使用OpenCV检测损坏的形状
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用OpenCV检测损坏的形状相关的知识,希望对你有一定的参考价值。
我试图检测4条内的方块。目标是比较他们的质心。在大多数情况下,我的方法(如下所述)正确识别大多数情况。在焦点不好或光线太低的图像中,处理后的图像有一个破碎或断开的正方形,其轮廓未使用Canny检测到。以下是一般方法流程:
- 使用模板匹配来查找“条形图”并创建ROI
- 在ROI上使用adaptiveThreshold和ADAPTIVE_THRESH_MEAN_C
- 通过将ROI的边缘设置为255(白色)来隔离正方形
- 使用PHYSEx和MORPH_OPEN以及(8,8)MORPH_RECT作为结构元素
- 通过imutils.auto_canny方法(由Adri Rosebrock在pyimagesearch.com上编写)使用优化的Canny来查找正方形
- 返回'bars'和'square'的中心,并在原始图像上显示它们的minAreaRect
以下是一个典型成功的例子:thresholded ROI,'bars' removed,morphology applied,original with detected shapes
这是一个破碎的,无法察觉的'正方形'的例子:thresholded ROI,'bars' removed,morphology applied,original with detected shapes
我试过的事情:
在第2步:
methods = ['cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)[1]',
'cv2.threshold(cv2.GaussianBlur(gray, (5, 5), 0), 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]',
'cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 51, 2)',
'cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 51, 2)']
全局阈值无法解释从图像到图像的不同亮度。 ADAPTIVE_THRESH_MEAN_C的成功率高于ADAPTIVE_THRESH_GAUSSIAN_C。两者中的'51'都是随意的;通过测试,似乎更高的数字产生了更清洁的形状。
在第4步:
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (8, 8))
roi = cv2.morphologyEx(roi, cv2.MORPH_OPEN, kernel)
对于结构元素,我使用了各种大小的RECT,ELLIPSE和CROSS。如果它们变得太大,我最终会在'square'中创建形状,auto.canny更喜欢检测它,并且不知何故再也无法找到外部'square'。使用RETR_EXTERNAL而不是RETR_LIST,RETR_CCOMP或RETR_TREE不能解决此问题。对于形态学操作,我已经尝试过MORPH_OPEN并分别扩张/侵蚀,以便在轮廓检测之前关闭破碎的“方形”形状。
在第5步:
auto_canny似乎运作良好。在所有这些处理之后我尝试了匹配'square'的模板,但它经常失败。
我正在寻找一种能够捕捉当前成功和一些更“可实现”失败的独特解决方案。我愿意接受你提供的任何智慧。我正在考虑的新方向:
- 在侧面使用线检测并找到它们连接的位置
- 我可以用approxPolyDP估算一个正方形吗?
- 为'square'编写我自己的检测算法。它将涉及在numpy数组中找到角点,在这些点之间创建一个正方形,并稍微扩展它。
虽然我希望有一种神奇的方法可以完全满足我的需求,但我花了几个时间来研究这个问题,并期待一个类似的困难答案。预先感谢您的帮助!
在找到中心之前尝试填充广场。我通过迭代行并连接最左边和最右边的黑色像素来做到这一点。
# Iterate through each row in the image
for row in range(img.shape[0]):
# Find the left-most and right-most pixel in the sqare
start, stop = 0, 0
for col in range(img.shape[1]):
# Find the left-most
if img[row,col] != 255 and start == 0: start = col, row
# Find the right-most
if img[row,col] != 255: stop = col, row
# If there was a pixel in that row, connect them with a line
if start != 0:
cv2.line(img, start, stop, 0, 1)
以上是关于使用OpenCV检测损坏的形状的主要内容,如果未能解决你的问题,请参考以下文章
pyhton—opencv直线检测(HoughLines)找到最长的一条线