在生产线质量检测中,圆形物体的识别是常见需求。比如检测瓶盖密封性、轴承尺寸、硬币真伪等场景。但实际拍摄的工业图像往往存在光照不均、金属反光、背景复杂等问题,直接使用cv2.HoughCircles可能会漏检或误检。
我处理过的一个典型案例是检测传送带上的金属垫片。车间环境光线不稳定,垫片表面有油污反光,相邻垫片经常出现粘连。最初直接用默认参数检测,结果要么把反光点误判为圆,要么漏掉实际存在的垫片。后来通过系统性的参数调优和图像预处理,最终实现了99%以上的识别准确率。
cv2.HoughCircles基于霍夫变换原理,通过投票机制检测圆形。其核心参数直接影响检测效果:
python复制circles = cv2.HoughCircles(
image, # 输入图像(单通道)
method, # 检测方法(目前仅支持HOUGH_GRADIENT)
dp, # 累加器分辨率(1=原始尺寸)
minDist, # 圆心间最小距离
param1=100, # Canny边缘检测高阈值
param2=30, # 圆心累加器阈值
minRadius=0, # 最小圆半径
maxRadius=0 # 最大圆半径
)
通过金属零件检测项目,我总结出这些参数的调整规律:
在检测电镀零件时,我发现直接处理原图效果很差。后来采用组合预处理:
python复制# 同态滤波补偿光照
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = cv2.equalizeHist(gray)
# 自适应阈值处理
thresh = cv2.adaptiveThreshold(
gray, 255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY_INV, 11, 2
)
# 形态学去噪
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
clean = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
对于贴合的瓶盖检测,先用距离变换分离物体:
python复制# 计算距离变换
dist = cv2.distanceTransform(thresh, cv2.DIST_L2, 5)
_, sure_fg = cv2.threshold(dist, 0.7*dist.max(), 255, 0)
# 寻找标记点
sure_fg = np.uint8(sure_fg)
_, markers = cv2.connectedComponents(sure_fg)
基于汽车零部件检测项目,我的标准处理流程是:
cv2.GaussianBlur)cv2.bilateralFilter)开发了根据图像质量自动调参的算法:
python复制def auto_params(img):
# 计算图像清晰度
blur = cv2.Laplacian(img, cv2.CV_64F).var()
# 根据清晰度调整param1
if blur > 100:
param1 = 150
param2 = 40
else:
param1 = 80
param2 = 25
# 根据ROI面积调整minDist
h, w = img.shape
minDist = min(h,w) // 4
return param1, param2, minDist
当检测到过多虚假圆时,可以:
对于漏检情况建议:
在PCB板定位孔检测中,通过以下代码验证圆的有效性:
python复制def validate_circle(img, circle):
x,y,r = circle
roi = img[y-r:y+r, x-r:x+r]
# 检查圆形区域对比度
contrast = roi.std()
if contrast < 30:
return False
# 检查边缘连续性
mask = np.zeros_like(img)
cv2.circle(mask, (x,y), r, 255, 1)
edge_pixels = cv2.countNonZero(cv2.bitwise_and(img, mask))
return edge_pixels > 0.6 * 2*np.pi*r
对于实时检测场景,我常用的优化手段包括:
处理4K图像时容易内存溢出,解决方法:
python复制# 分块处理大图
tile_size = 1024
for y in range(0, h, tile_size):
for x in range(0, w, tile_size):
tile = img[y:y+tile_size, x:x+tile_size]
circles = detect_circles(tile)
# 转换坐标到原图
circles[:,0] += x
circles[:,1] += y
在最近的一个药瓶检测项目中,遇到瓶身反光导致误检的问题。最终解决方案是组合使用偏振滤镜和特殊的照明方案,配合以下处理代码:
python复制# 偏振光补偿
def polar_correction(img):
img1 = capture_with_polarizer(0) # 0度偏振
img2 = capture_with_polarizer(90) # 90度偏振
return cv2.addWeighted(img1, 0.5, img2, 0.5, 0)
# 专用检测流程
polar_img = polar_correction(raw_img)
enhanced = contrast_stretch(polar_img)
circles = hough_detect(enhanced, min_r=50, max_r=80)
这个案例让我深刻体会到,工业视觉检测不能只依赖算法调优,需要硬件和算法的协同优化。