3、Python基础回顾:Python环境配置、NumPy与OpenCV基础、图像读写与预处理
各位同学,欢迎来到第三讲。说实话,很多搞算法的朋友,模型写得飞起,但一到部署就卡壳。为啥?环境没配好,或者图像读写那几步出了幺蛾子。今天这堂课,我就带大家把Python部署环境、NumPy和OpenCV的基础操作,以及图像预处理这些“地基”给夯实了。
我个人习惯,在开始任何项目前,先把环境理清楚。你想想看,如果连图像都读不对,后面的模型推理再牛也是白搭。所以,咱们从最基础的开始。
3.1 Python环境配置:别让环境坑了你
做工业部署,我强烈建议你用 Anaconda 或者 Miniconda 来管理环境。为什么?因为工业现场的环境往往很“脏”,各种依赖版本打架是常事。Conda能帮你隔离出一个干净的空间。
创建一个新环境,很简单:
# 创建一个名为 defect_detection 的环境,指定Python版本为3.8
conda create -n defect_detection python=3.8
# 激活环境
conda activate defect_detection
# 安装核心库
pip install numpy opencv-python matplotlib
这里要注意,opencv-python 是基础包,包含了大部分常用功能。如果你需要用到一些扩展模块(比如SIFT算法),可能需要安装 opencv-contrib-python。嗯,这里要提醒一下,工业场景下,尽量用稳定版本,别追新。
3.2 NumPy基础:图像的“骨架”
在OpenCV里,图像本质上就是一个NumPy数组。你想想看,一张640x480的彩色图,就是一个形状为 (480, 640, 3) 的三维数组。所以,搞懂NumPy,你就搞懂了图像的数据结构。
我给大家列几个最常用的操作,这些在预处理中天天见:
| 操作 | 代码示例 | 说明 |
|---|---|---|
| 创建数组 | np.zeros((480, 640, 3), dtype=np.uint8) |
创建一张全黑的图像 |
| 切片操作 | roi = img[100:200, 150:250] |
提取感兴趣区域(ROI),这是缺陷定位的基础 |
| 数据类型转换 | img_float = img.astype(np.float32) / 255.0 |
模型输入前,通常要归一化到0~1 |
| 维度变换 | img_transposed = np.transpose(img, (2, 0, 1)) |
将HWC转为CHW,很多深度学习框架需要这种格式 |
uint8 类型,我直接除以255后变成了整数0。正确的做法是先转成 float32 再除。
3.3 OpenCV基础:图像读写的“瑞士军刀”
OpenCV在工业视觉中的地位,不用我多说。它稳定、高效,而且接口非常统一。咱们先看最核心的读写操作。
3.3.1 读取与显示图像
import cv2
# 读取图像,默认是BGR格式
img = cv2.imread('defect_sample.jpg')
# 检查是否读取成功
if img is None:
print("图像读取失败,请检查路径")
exit()
# 显示图像
cv2.imshow('Defect Image', img)
cv2.waitKey(0) # 等待按键
cv2.destroyAllWindows()
这里有个坑,大家一定要注意:OpenCV默认读取的是BGR格式,而不是我们常见的RGB。很多同学第一次用的时候,直接用matplotlib显示,结果颜色全乱了。为什么会这样?因为matplotlib用的是RGB。
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)。否则模型学到的特征全是错的。
3.3.2 保存图像
# 保存处理后的图像
cv2.imwrite('result.jpg', img_processed)
保存时,OpenCV会根据文件后缀名自动选择编码格式。我个人习惯用PNG格式保存中间结果,因为它是无损压缩,不会丢失细节。
3.4 图像预处理:模型推理前的“必修课”
模型不是万能的,它需要输入特定尺寸、特定范围的数值。预处理的目的,就是把原始图像“喂”成模型喜欢的样子。
3.4.1 尺寸调整
工业相机拍出来的图,分辨率可能很高(比如500万像素)。但模型输入通常是固定的,比如224x224或416x416。所以第一步就是缩放。
# 缩放到模型输入尺寸
resized_img = cv2.resize(img, (224, 224), interpolation=cv2.INTER_LINEAR)
插值方法怎么选?我一般这样用:
- 缩小图像:用
cv2.INTER_AREA,能避免出现摩尔纹。 - 放大图像:用
cv2.INTER_LINEAR或cv2.INTER_CUBIC,效果更平滑。
3.4.2 归一化
归一化是让模型训练和推理更稳定的关键。说白了,就是把像素值从0~255映射到0~1或者-1~1。
# 简单的归一化到 [0, 1]
normalized_img = img.astype(np.float32) / 255.0
# 更常用的方式:减去均值,除以标准差
mean = [0.485, 0.456, 0.406] # ImageNet的均值
std = [0.229, 0.224, 0.225] # ImageNet的标准差
normalized_img = (normalized_img - mean) / std
3.4.3 数据增强(推理时也要做)
很多人以为数据增强只在训练时用。其实在推理时,为了提升鲁棒性,我们也会做一些简单的预处理。比如:
- 亮度调整:模拟产线上光照变化。
- 高斯模糊:模拟镜头轻微失焦。
- 仿射变换:校正拍摄角度偏差。
# 高斯模糊,去除传感器噪声
blurred = cv2.GaussianBlur(img, (5, 5), 1.5)
# 直方图均衡化,增强对比度
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
equalized = cv2.equalizeHist(gray)
这些操作看似简单,但在实际项目中,往往能带来几个点的准确率提升。你想想看,产线上的工件位置、光照不可能完全一致,预处理就是帮模型“抗干扰”。
3.5 一个完整的预处理流水线
最后,我给大家展示一个我在项目中常用的预处理函数。它把上面讲的内容串起来了:
def preprocess_for_inference(image_path, input_size=(224, 224)):
"""
工业缺陷检测模型的标准预处理流程
"""
# 1. 读取图像
img = cv2.imread(image_path)
if img is None:
raise ValueError(f"无法读取图像: {image_path}")
# 2. 转为RGB
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 3. 缩放
img_resized = cv2.resize(img_rgb, input_size, interpolation=cv2.INTER_AREA)
# 4. 归一化
img_normalized = img_resized.astype(np.float32) / 255.0
# 5. 标准化(使用ImageNet参数)
mean = np.array([0.485, 0.456, 0.406])
std = np.array([0.229, 0.224, 0.225])
img_standardized = (img_normalized - mean) / std
# 6. 转为CHW格式并增加batch维度
img_chw = np.transpose(img_standardized, (2, 0, 1))
img_batch = np.expand_dims(img_chw, axis=0)
return img_batch
这个函数,你直接复制到你的部署代码里,稍微改改路径和尺寸就能用。我每次做新项目,都是从这个模板开始的。
好了,这一讲的内容就到这里。环境配好了,图像能读能写了,预处理也搞定了。下一讲,咱们就要开始真正接触模型了——把训练好的模型加载进来,跑一次推理试试看。