[英]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:参数调优问题:
param1
.param1
的值。 param1
is the higher threshold passed to the Canny. param1
是传递给 Canny 的较高阈值。30
.30
。param2
The documentation not so clear, but setting the value around 50
works.param2
的值文档不太清楚,但将值设置为50
左右有效。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.