使用OpenCV检测重叠的圆形

3
我将使用OpenCV库来检测图像中的圆形。作为测试案例,我使用以下图像:
罐底部:

enter image description here

我写了以下代码,应该会先显示未检测到圆的图片,然后显示检测到圆的图片:
import cv2
import numpy as np

image = cv2.imread('can.png')
image_rgb = image.copy()
image_copy = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
grayscaled_image = cv2.cvtColor(image_copy, cv2.COLOR_GRAY2BGR)

cv2.imshow("confirm", grayscaled_image)
cv2.waitKey(0)

cv2.destroyAllWindows()


circles = cv2.HoughCircles(image_copy, cv2.HOUGH_GRADIENT, 1.3, 20, param1=60, param2=33, minRadius=10,maxRadius=28)


if circles is not None:
    print("FOUND CIRCLES")
    circles = np.round(circles[0, :]).astype("int")
    print(circles)
    for (x, y, r) in circles:
        cv2.circle(image, (x, y), r, (255, 0, 0), 4)
        cv2.rectangle(image, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)
    cv2.imshow("Test", image + image_rgb)
    cv2.waitKey(0)

cv2.destroyAllWindows()

我得到了这个:结果图像

enter image description here

我觉得我的问题在于使用 HoughCircles() 函数。其用法为: cv2.HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) 其中 minDist 是一个大于 0 的值,要求检测到的圆之间必须有一定距离。由于这个要求,我无法正确检测罐底上所有的圆,因为每个圆的中心都在同一个位置。轮廓是否是解决方案?如何将轮廓转换为圆形,以便我可以使用它们的中心点坐标?为了最好地检测罐底上每个环中的圆形对象,我应该怎么做?

不是你的问题,但是以后需要注意:image_copy = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) 应该改为 image_copy = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) - Micka
1个回答

1

通过自适应阈值处理图像,找到轮廓并为面积大于阈值的轮廓拟合最小包围圆,可以检测出大多数圆。

import cv2
import numpy as np

block_size,constant_c ,min_cnt_area = 9,1,400
img = cv2.imread('viMmP.png')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
thresh = cv2.adaptiveThreshold(img_gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,block_size,constant_c)
thresh_copy = thresh.copy()
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
    if cv2.contourArea(cnt)>min_cnt_area:
        (x,y),radius = cv2.minEnclosingCircle(cnt)
        center = (int(x),int(y))
        radius = int(radius)
        cv2.circle(img,center,radius,(255,0,0),1)
cv2.imshow("Thresholded Image",thresh_copy)
cv2.imshow("Image with circles",img)
cv2.waitKey(0)

现在这个脚本产生的结果是:

enter image description here

enter image description here

但是有一些权衡,比如,如果将block_sizeconstant_c分别更改为11和2,则脚本产生的结果为:

enter image description here

enter image description here

您应该尝试使用适当形状的内核应用腐蚀操作,以分离阈值图像中重叠的圆形。

您可以查看以下链接了解更多关于自适应阈值和轮廓的内容:

阈值化示例:http://docs.opencv.org/3.1.0/d7/d4d/tutorial_py_thresholding.html

阈值化参考:http://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html

轮廓示例:http://docs.opencv.org/3.1.0/dd/d49/tutorial_py_contour_features.html


如果我无法完美地检测每个环的确切尺寸,那么有没有一种方法可以将整个图像作为整体进行检测?比如,如果我使用网络摄像头并举起一个罐子的图像,程序会特别检测到该图像吗? - user5705019
是的,您可以将图像转换为HSV,然后使用适当的阈值对图像进行阈值处理。对阈值化的图像应用闭合操作(腐蚀+膨胀),以消除由于背景而出现的不需要的噪声组件。然后使用RETR_EXTERNAL查找此掩码的外部轮廓。如果图像中没有噪声组件,则会得到外圆。再次使用轮廓面积来删除所有噪声组件。如果您想要黑色背景中的罐子,则可以对原始BGR图像应用闭合后获得的掩码进行位与运算。 - Akhilesh Sreedharan
我非常感谢您的回复,但是我不知道如何做任何这些事情。我是OpenCV的新手,似乎找不到一个质量好的指南来使用它。您有什么推荐吗?您是如何学习它的? - user5705019
有很多在线教程。文档本身很棒,而且在OpenCV文件夹中还有示例。 - Akhilesh Sreedharan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接