3. 图像处理基础:数字图像表示、OpenCV基础操作、图像增强与数据增强技术
做病虫害识别,说白了就是让算法学会「看」叶子。但算法看到的不是叶子,是一堆数字。这一章我们就来聊聊,怎么把一张照片变成算法能理解的东西,以及怎么让数据变得更丰富、更抗揍。
3.1 数字图像的本质:像素矩阵
一张图像在计算机眼里,就是一个二维数组。每个格子叫像素,每个像素存一个数值。灰度图是单通道,每个像素 0~255,0 是黑,255 是白。彩色图是三个通道叠加——R、G、B。
我记得刚入行时有个误区:以为图像越大越好。后来做水稻稻瘟病识别,一张 4000×3000 的图直接让训练显存爆了。你想想看,一张图就是 1200 万个像素,三个通道就是 3600 万个数值。模型要在这上面做卷积,计算量可想而知。
实际项目中,我们通常不会直接用原始分辨率。我习惯先做一次降采样,把长边缩到 1024 或 512。这样既保留纹理细节,又不会让训练太慢。
3.2 OpenCV 基础操作:读、写、显示、变换
OpenCV 是图像处理的瑞士军刀。我几乎每个项目都离不开它。下面这几个操作,是病虫害识别流水线里最常用的。
3.2.1 读取与显示
import cv2
# 读取图像,默认是 BGR 格式
img = cv2.imread('rice_leaf.jpg')
print(img.shape) # (H, W, 3)
# 转成 RGB(因为 matplotlib 用 RGB)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 显示
cv2.imshow('Rice Leaf', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
3.2.2 几何变换
病虫害识别中,叶子可能歪着、斜着、大小不一。我们需要用几何变换来对齐。
# 缩放
resized = cv2.resize(img, (512, 512))
# 旋转
(h, w) = img.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, 45, 1.0)
rotated = cv2.warpAffine(img, M, (w, h))
# 翻转
flipped = cv2.flip(img, 1) # 水平翻转
我个人习惯在数据预处理阶段,先把所有图片缩放到统一尺寸,比如 512×512。这样 batch 训练时不用动态 padding,效率高很多。
3.2.3 色彩空间转换
有时候 RGB 不是最好的特征空间。比如识别早期稻瘟病,病斑往往是黄褐色,在 HSV 空间里更容易分割。
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# 提取黄色区域
lower_yellow = np.array([20, 100, 100])
upper_yellow = np.array([30, 255, 255])
mask = cv2.inRange(hsv, lower_yellow, upper_yellow)
3.3 图像增强:让特征更明显
图像增强不是为了让图更好看,而是为了让算法更容易抓住关键特征。说白了,就是「把病斑凸显出来」。
3.3.1 直方图均衡化
如果一张图整体偏暗或偏亮,直方图均衡化可以把对比度拉开。
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
equalized = cv2.equalizeHist(gray)
但要注意,全局均衡化有时会放大噪声。我更喜欢用 CLAHE(对比度受限自适应直方图均衡化),它只在局部窗口内做均衡,不会把背景噪声也放大。
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
clahe_img = clahe.apply(gray)
3.3.2 锐化与去噪
病虫害识别中,病斑边缘往往是关键。锐化能让边缘更清晰。
kernel = np.array([[-1,-1,-1],
[-1, 9,-1],
[-1,-1,-1]])
sharpened = cv2.filter2D(img, -1, kernel)
但锐化也会放大噪声。我通常先做一次高斯模糊去噪,再做锐化。
blurred = cv2.GaussianBlur(img, (5,5), 0)
sharpened = cv2.addWeighted(img, 1.5, blurred, -0.5, 0)
3.4 数据增强:用有限数据训练无限泛化
这是我最想强调的部分。病虫害数据集通常很小——你可能只有几百张带病斑的叶子照片。直接训练,模型很容易过拟合。数据增强就是「用魔法打败魔法」。
3.4.1 几何增强
| 增强方式 | 适用场景 | 注意事项 |
|---|---|---|
| 随机旋转(±30°) | 叶子朝向不固定 | 旋转后黑边需裁剪或填充 |
| 水平/垂直翻转 | 对称性病害 | 文字类病害不要垂直翻转 |
| 随机裁剪 | 局部病斑检测 | 裁剪比例不要小于 50% |
| 缩放(0.8~1.2) | 不同拍摄距离 | 保持长宽比或等比缩放 |
3.4.2 色彩增强
光照变化是野外拍摄最大的干扰。我习惯用 HSV 空间的随机扰动来模拟不同光照。
def random_brightness_contrast(img):
alpha = 1.0 + random.uniform(-0.2, 0.2) # 对比度
beta = random.randint(-30, 30) # 亮度
return cv2.convertScaleAbs(img, alpha=alpha, beta=beta)
3.4.3 高级增强:MixUp 与 CutMix
这两个是近年来的「黑科技」。简单说,就是把两张图混合在一起,标签也按比例混合。
# MixUp 伪代码
lam = np.random.beta(1.0, 1.0)
mixed_img = lam * img1 + (1 - lam) * img2
mixed_label = lam * label1 + (1 - lam) * label2
我曾经在玉米叶斑病数据集上试过,只用原始 500 张图,加 MixUp 后验证集准确率从 78% 提升到 86%。效果非常明显。
3.5 本章知识体系总览
下面这张图,把本章的核心逻辑串起来了。从原始图像到模型输入,中间经历了什么,一目了然。
从原始像素矩阵开始,经过 OpenCV 的几何与色彩预处理,再到图像增强提升对比度,最后用数据增强扩充样本多样性。每一步都在为模型「喂」更好的数据。你想想看,如果输入的数据质量差、数量少,再好的算法也白搭。