3. 图像采集与预处理:让相机“看清”缺陷的第一步
做光学检测这么多年,我最大的体会就是——图像预处理做得好,后面算法省一半的力气。你想想看,如果相机拍出来的图本身就乱七八糟的,你再牛的检测算法也白搭。今天我就把这块的核心操作掰开揉碎了讲给你听。
3.1 用OpenCV读取图像:别小看这一步
读取图像,听起来简单吧?但我见过太多新手在这栽跟头。OpenCV读取图像默认是BGR格式,不是我们熟悉的RGB。这坑我踩过不止一次。
import cv2
import numpy as np
# 读取图像——我最常用的方式
img = cv2.imread('defect_sample.jpg')
# 检查是否读取成功
if img is None:
print("图像读取失败,检查路径或文件")
exit()
# 显示原始图像
cv2.imshow('Original Image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
读取相机流呢?我建议用VideoCapture。记得设置分辨率,不然默认的640x480有时候不够用。
cap = cv2.VideoCapture(0) # 0代表默认摄像头
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
ret, frame = cap.read()
if ret:
cv2.imwrite('captured_frame.jpg', frame)
cap.release()
3.2 灰度化:丢掉颜色,保留结构
为什么要灰度化?说白了,大部分光学缺陷(划痕、脏污、气泡)在灰度图上就能看得很清楚。颜色信息反而会干扰检测。我做过一个项目,检测手机玻璃盖板的划痕,彩色图跑算法要200ms,灰度图只要50ms,准确率还更高。
# 灰度化——三种方式,我常用第一种
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 或者直接以灰度模式读取
gray_img = cv2.imread('defect_sample.jpg', cv2.IMREAD_GRAYSCALE)
你可能会问:那什么时候保留彩色?嗯,当缺陷本身带有颜色特征时,比如PCB板上的氧化变色,这时候彩色信息就有用了。
3.3 直方图均衡化:让暗部细节“浮出水面”
直方图均衡化,说白了就是把图像的灰度分布“拉平”。我遇到过一批产品,因为打光角度问题,图像整体偏暗,缺陷几乎看不见。均衡化之后,那些细微的划痕立马显现出来。
# 全局直方图均衡化
equ = cv2.equalizeHist(gray)
# 对比显示
cv2.imshow('Original Gray', gray)
cv2.imshow('Equalized', equ)
但要注意——全局均衡化有时候会放大噪声。我建议你试试CLAHE(对比度受限自适应直方图均衡化),效果更细腻。
# CLAHE——我的首选
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
clahe_img = clahe.apply(gray)
3.4 高斯滤波去噪:平滑但不模糊边缘
高斯滤波,核心思想是用一个高斯核去卷积图像。每个像素的值由它周围像素加权平均得到,权重由高斯分布决定。这样做的好处是——去噪的同时尽量保留边缘。
# 高斯滤波——核大小和标准差是关键
blurred = cv2.GaussianBlur(gray, (5, 5), 1.5)
# 参数说明:
# (5,5) 是核大小,必须是奇数
# 1.5 是标准差σ,控制平滑程度
核大小怎么选?我一般遵循这个原则:
| 核大小 | 适用场景 | 我的经验 |
|---|---|---|
| (3, 3) | 轻微噪声,需要保留精细缺陷 | 检测微小划痕时用 |
| (5, 5) | 中等噪声,通用场景 | 我最常用的尺寸 |
| (7, 7) | 强噪声,大缺陷检测 | 注意会模糊小缺陷 |
3.5 完整流程:从相机到预处理
好了,我们把上面这些串起来,形成一个完整的预处理流水线。这是我做项目时的标准流程:
def preprocess_image(image_path):
# 1. 读取图像
img = cv2.imread(image_path)
if img is None:
return None
# 2. 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 3. CLAHE增强
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
enhanced = clahe.apply(gray)
# 4. 高斯滤波去噪
denoised = cv2.GaussianBlur(enhanced, (5, 5), 1.5)
return denoised
# 调用
result = preprocess_image('defect_sample.jpg')
cv2.imshow('Preprocessed', result)
这个流程我用了好几年,在玻璃、金属、塑料等多种材质上都验证过。当然,具体参数要根据你的实际图像微调。
3.6 知识体系总览
下面这张图,是我梳理的本章核心逻辑。你可以把它当作一个检查清单:
你看,整个流程其实就四个步骤。但每一步都有讲究——灰度化怎么选通道、均衡化用全局还是CLAHE、高斯滤波核多大合适。这些细节,决定了你最终检测算法的成败。