【问题标题】:How to detect circle in a binary image如何检测二值图像中的圆圈
【发布时间】:2017-10-06 01:49:39
【问题描述】:

是原图:

以及预处理后的图片

  • 变灰
  • 做精明的边缘
  • 扩张
  • 侵蚀
  • bitwise_not

结果如下:

现在我想检测上图中所有的实心圆圈,结果是我 想要:

我尝试过这样的事情:

MatOfPoint2f approxCurve = new MatOfPoint2f();
matOfPoint2f.fromList(contour.toList());
Imgproc.approxPolyDP(matOfPoint2f, approxCurve, Imgproc.arcLength(matOfPoint2f, true) * 0.02, true);
long total = approxCurve.total();
// now check the total if it was greater than 6, then it can be a circle

结果是这样的:这不是我想要的

更新: (包括更多示例图片)

【问题讨论】:

  • 请记住,由于透视,您实际上并不是在寻找圆圈。在您的“我想要的”图像中,您标记了多个看起来不像圆圈的对象。而其他类似的形状还没有填充红色。考虑使用更适合您的目的的图片
  • 是的,目的是检测和统计图像中有多少个管道?那是我在问题中提到的解决方案,我只是看看是否有更好的解决方案可以克服我的解决方案所存在的问题。
  • 您是否尝试过应用霍夫圆变换?
  • @TiagoCunha 是的,我试过了,结果连上图都没有。

标签: java c++ opencv image-processing


【解决方案1】:

更新:使用轮廓更新我的解决方案。你可以找到解决方案 在下面使用霍夫圆。


使用轮廓法。

我今天再次尝试寻找轮廓来标记管道。结果我得到了轮廓。我已经根据轮廓长度和面积过滤了结果。但是您可以根据您拥有的图像应用更多约束。似乎我已经过度拟合了这张图片的解决方案,但这是我唯一可以访问的图片。您还可以使用 laplacian/canny 代替自适应阈值。希望这会有所帮助:)

import cv2 as cv2

img_color = cv2.imread('yNxlz.jpg')
img_gray = cv2.cvtColor(img_color, cv2.COLOR_BGR2GRAY)

image = cv2.GaussianBlur(img_gray, (5, 5), 0)

thresh = cv2.adaptiveThreshold(image,255,cv2.ADAPTIVE_THRESH_MEAN_C,\
            cv2.THRESH_BINARY_INV,11,2)

contours,hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnt = contours

contour_list = []
for contour in contours:
    approx = cv2.approxPolyDP(contour,0.01*cv2.arcLength(contour,True),True)
    area = cv2.contourArea(contour)
    # Filter based on length and area
    if (7 < len(approx) < 18) & (900 >area > 200):
        # print area
        contour_list.append(contour)

cv2.drawContours(img_color, contour_list,  -1, (255,0,0), 2)
cv2.imshow('Objects Detected',img_color)
cv2.waitKey(5000)

霍夫圆法

我尝试拍摄您的图像并应用霍夫圆(opencv)。我没有Java设置,因此我使用了python。这是我得到的代码和对应的结果。

在此之前,有一些技巧可以对此进行微调。

  • 重要的是预处理,一个简单的 Gaussianblur 让我得到了很好的改进,所以使用高斯过滤器大小。
  • 既然您已经知道管道半径/直径,请利用该信息。也就是说,在 Houghcircles 中使用 minradius 和 maxradius 参数。
  • 如果您知道管道之间的最小距离,您也可以使用 mindist param。
  • 如果您知道可能存在管道的区域,则可以忽略在该区域以外检测到的误报管道。

希望这会有所帮助:)

我使用的代码

import cv2 as cv2

img_color = cv2.imread('yNxlz.jpg')
img_gray = cv2.cvtColor(img_color, cv2.COLOR_BGR2GRAY)

img_gray = cv2.GaussianBlur(img_gray, (7, 7), 0)

#Hough circle
circles = cv2.HoughCircles(img_gray, cv2.cv.CV_HOUGH_GRADIENT, 1, minDist=15,
                     param1=50, param2=18, minRadius=12, maxRadius=22)

if circles is not None:
    for i in circles[0, :]:
        # draw the outer circle
        cv2.circle(img_color, (i[0], i[1]), i[2], (0, 255, 0), 2)
        # draw the center of the circle
        cv2.circle(img_color, (i[0], i[1]), 2, (0, 0, 255), 3)

cv2.imwrite('with_circles.png', img_color)

cv2.imshow('circles', img_color)
cv2.waitKey(5000)

这是我得到的结果。

【讨论】:

  • 感谢先生的回复!在收到您的回复之前,我也尝试了霍夫圈,它给出的结果与您的测试结果相似,但有两个问题。第一个问题很慢实时不好,第二个问题是情况,例如:当我给另一个图像时,它不会很好,所以我寻找可以用来检测的算法它自己的轮廓中的椭圆形或圆形,可能比霍夫圆形快得多。无论如何,你的答案是好的。投票吧!!
  • 欢迎,为了提高速度,尽量缩小图片尺寸。但这确实会导致一些信息丢失。好的,findcontours 也可能会有所帮助。祝你好运。将看看我是否尝试使用 findcontour 并在当天晚些时候发布另一个答案
  • @BahramdunAdil 可能会找到一种自动调整带有霍夫圆的管道的方法。您可能希望提供更多与您提供的样本不同的样本,以便人们考虑数据中可能存在的变化。
  • 我已经用轮廓更新了解决方案。看一看。我没有考虑速度,我认为你可以更好地判断这一点。
  • @m3h0w +1 同意你的看法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-01
  • 1970-01-01
  • 2020-04-09
  • 1970-01-01
  • 2011-12-04
  • 1970-01-01
相关资源
最近更新 更多