第1章:叶片图像预处理基础
各位工程师朋友,大家好。我是老张,在机器视觉领域摸爬滚打了十几年。今天咱们开始聊叶片裂纹识别的第一道工序——图像预处理。
说实话,很多人一上来就急着跑模型,结果效果惨不忍睹。为什么?因为原始图像太「脏」了。光照不均、噪声干扰、对比度差……这些问题不解决,再好的算法也白搭。
我个人习惯,预处理占整个项目时间的40%以上。别嫌多,这步做好了,后面事半功倍。
1.1 图像读取与显示——从硬盘到内存的第一步
先说说最基础的操作。用OpenCV读取图像,代码就两行:
import cv2
img = cv2.imread('leaf.jpg')
但这里有个坑,我刚开始做项目时栽过跟头。OpenCV默认读取的是BGR格式,不是我们熟悉的RGB。你用matplotlib直接显示,颜色就全乱了。
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
显示图像我习惯用matplotlib:
import matplotlib.pyplot as plt
plt.imshow(img_rgb)
plt.title('原始叶片图像')
plt.axis('off')
plt.show()
你想想看,这一步虽然简单,但却是所有后续操作的基础。图像没读对,后面全是白费功夫。
1.2 灰度化与直方图均衡化——让裂纹「显形」
彩色图像信息量大,但裂纹检测其实不需要颜色。灰度化能减少计算量,还能突出纹理特征。
gray = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2GRAY)
但问题来了——光照不均匀怎么办?比如叶片一半亮一半暗,裂纹在暗区根本看不清。
这时候直方图均衡化就派上用场了。说白了,就是把像素值的分布「拉平」,让暗的地方亮起来,亮的地方暗下去。
equ = cv2.equalizeHist(gray)
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
嗯,这里要注意:CLAHE的clipLimit参数需要调。我一般从2.0开始试,太大会出现伪影,太小又没效果。
1.3 高斯滤波与中值滤波去噪——给图像「美颜」
工业相机拍出来的叶片图像,多少都有噪声。椒盐噪声、高斯噪声……这些噪声会干扰裂纹的提取。
我个人习惯,先用高斯滤波去除高斯噪声:
gaussian = cv2.GaussianBlur(gray, (5,5), 1.0)
高斯滤波的原理,就是用邻域像素的加权平均来平滑图像。核大小我一般选5×5或7×7,太大细节就没了。
但高斯滤波对椒盐噪声效果不好。这时候要用中值滤波:
median = cv2.medianBlur(gray, 5)
中值滤波用邻域像素的中值代替中心像素,对椒盐噪声简直是「克星」。我在一个叶片表面缺陷检测项目里,就是靠中值滤波把噪声压下去的。
1.4 图像增强实战——让裂纹无处遁形
好了,前面都是热身。现在咱们来点真格的——图像增强实战。
我常用的增强组合拳是:CLAHE + 锐化 + 形态学操作。
第一步,CLAHE增强对比度:
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
enhanced = clahe.apply(gray)
第二步,锐化让裂纹边缘更清晰:
kernel = np.array([[-1,-1,-1],
[-1, 9,-1],
[-1,-1,-1]])
sharpened = cv2.filter2D(enhanced, -1, kernel)
第三步,形态学操作去除小噪点:
kernel = np.ones((3,3), np.uint8)
opening = cv2.morphologyEx(sharpened, cv2.MORPH_OPEN, kernel)
最后,把处理前后的图像放在一起对比:
plt.figure(figsize=(12,4))
plt.subplot(1,3,1); plt.imshow(gray, cmap='gray'); plt.title('原始灰度')
plt.subplot(1,3,2); plt.imshow(enhanced, cmap='gray'); plt.title('CLAHE增强')
plt.subplot(1,3,3); plt.imshow(opening, cmap='gray'); plt.title('锐化+去噪')
plt.show()
你看,裂纹是不是清晰多了?这就是预处理的魅力。
好了,第一章的内容就到这里。图像预处理是叶片裂纹识别的基础,每一步都有它的道理。别嫌麻烦,多调调参数,多看看效果,慢慢就有感觉了。
有什么问题,欢迎交流。我是老张,咱们下章见。