【问题标题】:Detect circles in openCV在openCV中检测圆圈
【发布时间】:2020-03-11 13:24:14
【问题描述】:

我在为 HoughCircles 函数选择正确参数时遇到问题。我尝试从视频中检测圆圈。这个圆圈是我做的,尺寸几乎一样。问题是相机在移动。

当我更改 maxRadius 时,它仍然以某种方式检测到更大的圆圈(见右图)。我也尝试更改 param1、param2 但仍然没有成功。

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  blurred = cv2.medianBlur(gray, 25)#cv2.bilateralFilter(gray,10,50,50)


  minDist = 100
  param1 = 500
  param2 = 200#smaller value-> more false circles
  minRadius = 5
  maxRadius = 10
  circles = cv2.HoughCircles(blurred, cv2.HOUGH_GRADIENT, 1, minDist, param1, param2, minRadius, maxRadius)

  if circles is not None:
    circles = np.uint16(np.around(circles))
    for i in circles[0,:]:
        cv2.circle(blurred,(i[0], i[1]), i[2], (0, 255, 0), 2) 

也许我使用了错误的功能?

【问题讨论】:

  • 为什么 param1 和 param2 太高了?试试这些参数:param1=100, param2 = 30, minradius = 1, maxradius = 100
  • minDist=100 在您的图像中有意义吗?尝试根据这些圆圈的实际距离减小 minDist

标签: python opencv geometry detection shapes


【解决方案1】:

代码中的主要问题是 HoughCircles 函数的第 5 个参数。

根据documentation,参数列表为:

cv2.HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) → circles

这意味着第五个参数适用circles(它提供了一个通过引用获取输出的选项,而不是使用返回值)。

因为您没有传递circles 参数,所以您必须为第四个参数之后的所有参数传递命名参数(如param1=param1param2=param2....)。

参数调优问题:

  • 减少param1 的值。 param1 是传递给 Canny 的更高阈值。
    在您的情况下,值应该约为30
  • 减少param2的值 文档不是很清楚,但在50 附近设置值是可行的。
  • 增加maxRadius 值 - 半径10 远小于您的圆的半径。

代码如下:

import numpy as np
import cv2

img = cv2.imread('circles.png')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

blurred = cv2.medianBlur(gray, 25) #cv2.bilateralFilter(gray,10,50,50)

minDist = 100
param1 = 30 #500
param2 = 50 #200 #smaller value-> more false circles
minRadius = 5
maxRadius = 100 #10

# docstring of HoughCircles: HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) -> circles
circles = cv2.HoughCircles(blurred, cv2.HOUGH_GRADIENT, 1, minDist, param1=param1, param2=param2, minRadius=minRadius, maxRadius=maxRadius)

if circles is not None:
    circles = np.uint16(np.around(circles))
    for i in circles[0,:]:
        cv2.circle(img, (i[0], i[1]), i[2], (0, 255, 0), 2)

# Show result for testing:
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

【讨论】:

  • 谢谢,这正是我所需要的。你是最棒的:)
【解决方案2】:

不必费心用cv2.HoughCircles 选择正确的参数,这里有一种使用轮廓过滤的替代方法。这个想法是使用Otsu's threshold 获得二值图像,然后执行morphological operations 以隔离椭圆形轮廓。最后我们find contours 并使用aspect ratiocontour area 进行过滤。结果如下:

import cv2
import numpy as np

# Load image, grayscale, median blur, Otsus threshold
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.medianBlur(gray, 11)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

# Morph open 
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=3)

# Find contours and filter using contour area and aspect ratio
cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.04 * peri, True)
    area = cv2.contourArea(c)
    if len(approx) > 5 and area > 1000 and area < 500000:
        ((x, y), r) = cv2.minEnclosingCircle(c)
        cv2.circle(image, (int(x), int(y)), int(r), (36, 255, 12), 2)

cv2.imshow('thresh', thresh)
cv2.imshow('opening', opening)
cv2.imshow('image', image)
cv2.waitKey()     

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多