Halcon中对应的例子为inspect_bottle_mouth.hdev,用于检测酒瓶瓶口是否出现破损等缺陷情形,检测效果如下:
(1) 正常情瓶口完整,无破损
(2) 异常情况包含不同情况的破损
Halcon实例主要步骤包含五步,分别是:
- 使用阈值处理和形态学粗定位品口位置;
- XLD轮廓拟合最近似的圆形区域作为瓶口的轮廓;
- 极坐标变换,转换到水平或垂直方向进行处理;
- 均值滤波图与原图做差分,根据阈值提取;
- 将绘制的缺陷部分通过反极坐标变换投影到原图上。
具体的实现代码大家有兴趣看下Halcon的实例代码,这里有几个重要步骤需要对比说明:
(1) 瓶口轮廓粗定位,OpenCV实现是根据瓶口部分区域为黑色且明显易于提取所以选择了HSV提取黑色轮廓的方法,然后通过计算轮廓的最小外接圆来近似,大部分效果还可以,如下:
但有一些情况圆边上多出一部分杂讯,如下:
Halcon中通过拟合圆算子可以过滤,OpenCV中需要自己写
(2) 所以,第一步和第二步这里直接同霍夫圆变换来替换(最重要的就是参数要设置合适):
代码语言:javascript复制gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
gray = cv2.medianBlur(gray,3)
circles = cv2.HoughCircles(gray,cv2.HOUGH_GRADIENT,1,100,
param1=200,param2=30,minRadius=150,maxRadius=500)
我测试了一下,16张测试图,效果都不错,暂时采用它。 (3) 第三步,极坐标变换。这里的重点就是基于上一步骤要准确找到圆,将圆心作为极坐标变换的中心。
代码语言:javascript复制x = circles[0][i][0] - circles[0][i][2]
y = circles[0][i][1] - circles[0][i][2]
w = h = 2 * circles[0][i][2]
center = (circles[0][i][0], circles[0][i][1])
radius = circles[0][i][2]
ROI = img[y:y h,x:x w].copy()
cv2.imshow('ROI',ROI)
trans_center = (center[0]-x, center[1]-y)
polarImg = cv2.warpPolar(ROI,(300,600),trans_center,radius,cv2.INTER_LINEAR cv2.WARP_POLAR_LINEAR)
cv2.imshow('polarImg',polarImg)
变换前:
变换后:
(3) 均值滤波做差分,注意这里的均值滤波核大小,一般我们都是设置(3,3)或(5,5)等,这里物体垂直方向较长,参考Halcon例子中设置为(3, 501),看效果:
代码语言:javascript复制blur = cv2.blur(gray,(3,501))
cv2.imshow('blur',blur)
diff = cv2.absdiff(gray,blur)
cv2.imshow('diff',diff)
cv2.imwrite("diff.png",diff)
ret,thres = cv2.threshold(diff,55,255,cv2.THRESH_BINARY)
thres = cv2.medianBlur(thres, 3)
contours2,hierarchy2 = cv2.findContours(thres, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
for cnt2 in contours2:
(x2, y2, w2, h2) = cv2.boundingRect(cnt2)
#print(x, y, w, h)
if w2 > 13:
cv2.drawContours(polarImg,cnt2,-1,(0,0,255),2)
isNG = True
然后做差分,阈值处理,绘制轮廓:
(4) 反极坐标变换,结果投影到原图:
(5) 最后把ROI图贴到结果图中:
完整测试效果见下面视频:
核心代码上面已展示,如果对完整源码感兴趣,欢迎加入知识星球获取和讨论,感谢。