简体   繁体   English

检测openCV中的圆圈

[英]Detect circles in openCV

I have a problem with choosing right parameters for HoughCircles function.我在为 HoughCircles 函数选择正确的参数时遇到问题。 I try to detect circles from video.我尝试从视频中检测圆圈。 This circles are made by me, and has almost the same dimension.这个圆圈是我做的,尺寸几乎一样。 Problem is that camera is in move.问题是相机在移动。

When I change maxRadius it still detect bigger circles somehow (see the right picture).当我更改 maxRadius 时,它仍然以某种方式检测到更大的圆圈(见右图)。 I also tried to change param1, param2 but still no success.我也尝试更改 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) 

Maybe Im using wrong function?也许我使用了错误的功能?

Instead of having to fiddle with choosing the right parameters with cv2.HoughCircles , here's an alternative approach using contour filtering.不必用cv2.HoughCircles选择正确的参数, cv2.HoughCircles使用轮廓过滤的替代方法。 The idea is to obtain a binary image with Otsu's threshold then perform morphological operations to isolate elliptical shaped contours.其思想是获得具有Otsu 阈值的二值图像,然后执行形态学操作以隔离椭圆形轮廓。 Finally we find contours and filter using aspect ratio and contour area .最后我们使用纵横比轮廓面积找到轮廓和过滤器。 Here's the results:结果如下:

在此处输入图片说明

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

The main problem in your code is 5th argument to HoughCircles function.您代码中的主要问题是HoughCircles函数的第 5 个参数。

According to documentation the argument list is:根据文档,参数列表是:

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

That means the 5th argument applies circles (it gives an option getting the output by reference, instead of using the returned value).这意味着第 5 个参数应用circles (它提供了一个通过引用获取输出的选项,而不是使用返回值)。

Because you are not passing circles argument, you must pass named arguments for all arguments after the 4th argument (like param1=param1 , param2=param2 ....).因为您没有传递circles参数,所以您必须为第 4 个参数之后的所有参数传递命名参数(如param1=param1 , param2=param2 ....)。

Parameter tuning issues:参数调优问题:

  • Reduce the value of param1 .减少param1的值。 param1 is the higher threshold passed to the Canny. param1是传递给 Canny 的较高阈值。
    In your case value should be about 30 .在你的情况下,价值应该是大约30
  • Reduce the value of param2 The documentation not so clear, but setting the value around 50 works.减少param2的值文档不太清楚,但将值设置为50左右有效。
  • Increase maxRadius value - radius 10 is much smaller than the radius of your circles.增加maxRadius值 - 半径10远小于圆的半径。

Here is the code:这是代码:

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

Result:结果:

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM