【问题标题】:Detecting Overlapping Circles in OpenCV在 OpenCV 中检测重叠的圆
【发布时间】:2016-05-03 04:44:46
【问题描述】:

我正在使用 Python 的 OpenCV 库来检测图像中的圆圈。作为测试用例,我使用的是下图:

罐底:

我写了下面的代码,它应该在检测之前显示图像,然后显示添加了检测到的圆圈的图像:

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()

我得到这个:结果图像

我觉得我的问题在于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) 而不是我猜)。

标签: python opencv


【解决方案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)

现在这个脚本产生了结果:

但是有一些权衡,例如,如果 block_sizeconstant_c 分别更改为 11 和 2,那么脚本会产生:

您应该尝试应用具有适当形状内核的腐蚀来分离阈值图像中的重叠圆圈

您可以查看以下链接以了解有关自适应阈值和轮廓的更多信息:

阈值示例: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

【讨论】:

  • 所以如果我根本无法完美检测每个环的确切尺寸,有没有办法检测整个图像?比如说,如果我使用网络摄像头并举起罐头的图像,程序会专门检测该图像吗?
  • 是的,您可以将图像转换为HSV,然后使用合适的阈值对图像进行阈值处理。对阈值图像应用关闭操作(腐蚀 + 膨胀)以去除由于背景而出现的不需要的噪声分量。然后使用 RETR_EXTERNAL 找到这个遮罩的外部轮廓。如果图像中没有噪声成分,那么您将得到外圈。再次,您可以使用轮廓区域来删除所有嘈杂的组件。如果你想要黑色背景中的罐子,那么按位和应用关闭原始 BGR 图像后获得的掩码。
  • 我非常感谢您的回复,但我不知道该怎么做。我是 OpenCV 的新手,我似乎找不到关于如何使用它的质量指南。你会推荐什么吗?你是怎么学的?
  • 网上有很多教程。文档本身很棒,opencv 文件夹中也有示例。
猜你喜欢
  • 2015-01-12
  • 2013-08-18
  • 1970-01-01
  • 2014-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-17
  • 2017-05-24
相关资源
最近更新 更多