opencv eleven Hough circle detection principles and advanced use cases (including optimization steps)

Hough circle detection can detect circles existing in the target image, but in actual use, parameter adjustment is very difficult. Therefore, in this blog post, the principle, parameter list, and optimization experience of Hough circle detection are analyzed and summarized. The adjustment basis for each parameter is listed in detail to achieve Hough circle detection in complex backgrounds.

1. Principle introduction

1.1 Basic principles

相关知识:
Hough circle detection is closely related to the Hough transform. The Hough transform is based on the mutual transformation between the polar coordinate system (a coordinate system described by the radius and the angle) and the Cartesian coordinate system (an ordinary plane coordinate system). realized. A point on the Cartesian coordinate system becomes a line when transformed into the polar coordinate system; and vice versa.
Insert image description here

However, the Hough circle detection method based on Hough transform is extremely computationally intensive and is not suitable for practical applications. In the implementation of opencv, the Hough gradient algorithm is used for circle detection.
Reference link: https://www.cnblogs.com/bjxqmy/p/12333022.html

1.2 The principle of Hough gradient method

1. Perform Canny edge detection on the original image to obtain the edge-detected binary image.
2. Execute the Sobel operator once on the original image to calculate the neighborhood gradient values ​​of all pixels.
3. Initialize the center space N(a,b) and make all N(a,b)=0. If the center of the circle is required to be in the image, the range of a and b values ​​corresponds to the width and height of the image respectively, and N(a,b) means there are a*b in total.
4. Traverse all non-zero pixels in the Canny edge binary image, draw lines along the gradient direction (the vertical direction of the tangent, based on the vertical gradient and horizontal gradient calculated by the Sobel operator) within a fixed search radius range, and divide the line segments N(a,b)+=1 for all points (a,b) in the accumulator passed through.
Insert image description here

5. Statistically sort N(a,b) to get the possible center of the circle (the larger N(a,b) is, the more likely it is the center of the circle).
Insert image description here
Reference link: https://zhuanlan.zhihu.com/p/427270299

1.3 Disadvantages of Hough gradient method

1. In the Hough gradient method, the Sobel derivative is used to calculate the local gradient, and the subsequent assumption is that it can be regarded as equivalent to a tangent line based on several local points, and this is not a numerically stable approach. In most cases, this will give correct results, but may produce some noise in the output.

2. The entire set of non-zero pixels in the edge image is regarded as a candidate part of each center. If the search radius range of the gradient direction is not properly set, it will lead to a huge amount of calculation.

3. Because the Hough gradient algorithm performs circle center accumulation detection through the vertical line of the arc tangent, when there are concentric circles, they will accumulate to the same circle center, which results in only selecting the circle with the largest accumulated value.

1.4 Parameter details

The code used for Hough circle detection is as follows

method=cv2.HOUGH_GRADIENT
circles=cv2.HoughCircles(image, method, dp=1, minDist=10, param1=None, param2=None, minRadius=None, maxRadius=None)

The details of its parameter list are as follows:

Circles:used to store the results of HoughCircles, the type is list, the object format in the list is x, y, r; the
image:input image, that is, the source image, an 8-bit single-channel image, if a color image is used, it needs to be converted to Grayscale image;
method:defines a method for detecting circles in an image. The only method currently implemented is cv2.HOUGH_GRADIENT;
dp:the ratio of the image pixel resolution to the parameter space resolution (the official document writes the ratio of the image resolution to the accumulator resolution, which considers the parameter space to be an accumulator, after all What is stored in it is the number of passing pixels), dp=1, then the parameter space is as large as the image pixel space (resolution), dp=2, the resolution of the parameter space is only half the size of the pixel space; #By setting dp can reduce the computational effort
minDist:of detecting the minimum distance between the (x, y) coordinates of the center of a circle. If minDist is too small, most circles with similar centers will be retained. If minDist is too large, circles with similar centers will be merged (if the distance between the centers of the two circles is < minDist, they are considered to be the same circle).
param1:canny The high threshold of edge detection. The low threshold is automatically set to half of the high threshold. The default is 100. ;
param2:The threshold for determining whether a point on the accumulation plane is the center of a circle. It is judged as a circle if it is greater than the threshold. When the value is set to a small value, more circles are detected. The default value is 100;
minRadius:the minimum size of the radius (in pixels) defaults to 0;
maxRadius:the maximum size of the radius (in pixels) defaults to 0.

2. Practical application

2.1 Basic running code

The following code implements reading the image for Hough circle detection, trying to detect the wheels in the vehicle in the picture below. But its parameter settings need to be adjusted and optimized.

import cv2
import numpy as np
import time
if __name__ == "__main__":
    name="test.jpg"
    img = cv2.imread(name)
    t1=time.time()
    GrayImage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    circles = cv2.HoughCircles(GrayImage, cv2.HOUGH_GRADIENT, 1, 40, param1=70, param2=30, minRadius=0,maxRadius=0)
    t2=time.time()
    print("运行时间:",t2-t1)

    circles = np.uint16(np.around(circles))
    for i in circles[0,:]:
        x,y,r=i[0],i[1],i[2]
        #draw the outer circle
        cv2.circle(img,(x,y),r,(0,255,0),2)
        cv2.circle(img,(x,y),2,(0,0,255),3)
    cv2.imshow("img",img)
    cv2.waitKey()

The original image content is as follows:
Please add image description

2.2 Optimization plan

When running the above code, the computer freezes due to the huge amount of calculation. (Reason 1: Lack of image processing optimization, Reason 2: Unreasonable Hough circle parameters,)

2.2.1 Image optimization

Image optimization is to reduce interference points in the Hough circle detection process, because 3 points can form a circle.

Edge noise filtering

1. Perform median | mean filtering optimization on the image to reduce edge noise existing in the image.
The added code is as follows, and the result was finally produced within 16 seconds.

    #GrayImage= cv2.medianBlur(GrayImage,7)#中值滤波 滤除背景噪声
    GrayImage= cv2.blur(GrayImage,(7,7))#均值滤波 滤除背景噪声

Insert image description here

Computation reduction

2. Optimize the image size, because when performing Hough circle detection, the image size has little impact on the detection accuracy. But downsampling (reducing) the image can greatly reduce the amount of calculations.
The added code is as follows. The result is obtained within 0.76s, but it is not very accurate.若缩放到0.25倍,则可在0.06秒内跑出结果

    GrayImage=cv2.resize(GrayImage,None,fx=0.5,fy=0.5)

Insert image description here

Keep a perfect circle

This step is optional.
In some special cases, such as the center detection of steel coils, due to gravity, the side circle of the steel coil is pressed into an ellipse, and it needs to be stretched in the y direction (vertical direction). As shown in the following code, the image is stretched by 1.2 times in the y direction. At this time, the side ellipse of the steel coil is stretched into a perfect circle.
img=cv2.resize(img,None,fx=1,fy=1.2)

2.2.2 Detection parameter optimization

Search radius optimization

By analyzing the above image, it is found that there are too many circles detected, and the preliminary estimate of the wheel's pixel radius range is 20-80 ( 通过多次设置范围,确定车轮像素在20~80之间).
The Hough circle detection parameters at this time are as follows:minRadius=20,maxRadius=80

circles = cv2.HoughCircles(GrayImage, cv2.HOUGH_GRADIENT, 1, minDist=40, param1=70, param2=30, minRadius=20,maxRadius=80)

At this time, the detection effect is as follows. The code only ran out the results in 0.03 seconds (20 times faster than the original), so the Hough circle search radius was limited.
Insert image description here

Circle center accumulation optimization

After the optimization in the previous step, circles that do not exist in reality are still detected. This is caused by the unreasonable setting of the accumulated circle center (the accumulated value on the arc at the center. If the accumulated value exceeds this threshold, it is considered a circle).
The Hough circle detection parameters at this time are as follows:param2=50, minRadius=20,maxRadius=80

circles = cv2.HoughCircles(GrayImage, cv2.HOUGH_GRADIENT, 1, minDist=4, param1=70, param2=50, minRadius=20,maxRadius=80)

At this time, the detection effect is as follows. The result is only run out in 0.03 seconds (same as the previous step), so the Hough circle search radius is limited.
Insert image description here

Circle center distance optimization

After going through the above steps, it was found that for some circles, multiple circles with very close centers would be detected. 原先的圆心距设置很合理,但为了出优化效果,故将上一步的圆心距离设置的很小. This is caused by the unreasonable setting of the minimum circle center distance in the detection step.
The Hough circle detection parameters at this time are as follows: minDist=20, param2=50, minRadius=20,maxRadius=80
The detection effect at this time is as follows, and the wheel area can be well positioned.
Insert image description here

Best complete code

额外说明:若对检测到的圆效果存在疑惑时,可以自行对原图进行cany求边缘,以校验参数param1设置的是否合理, the value of param1 is adjusted according to the effect of cany operation (which is the high threshold of canny edge detection). Usually, this value does not need to be adjusted, because this value has little impact on the effect.

import cv2
import numpy as np
import time
if __name__ == "__main__":
    name="test.jpg"
    img = cv2.imread(name)
    t1=time.time()
    img=cv2.resize(img,None,fx=0.5,fy=0.5)
    GrayImage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    #GrayImage= cv2.medianBlur(GrayImage,7)#中值滤波 滤除背景噪声
    GrayImage= cv2.blur(GrayImage,(7,7))#均值滤波 滤除背景噪声
    circles = cv2.HoughCircles(GrayImage, cv2.HOUGH_GRADIENT, 1, minDist=20, param1=70, param2=50, minRadius=20,maxRadius=80)
    t2=time.time()
    print("运行时间:",t2-t1)#只统计霍夫圆检测时间
	
	#这里进行圆绘制
    circles = np.uint16(np.around(circles))
    for i in circles[0,:]:
        x,y,r=i[0],i[1],i[2]
        #draw the outer circle
        cv2.circle(img,(x,y),r,(0,255,0),2)
        cv2.circle(img,(x,y),2,(0,0,255),3)
    cv2.imshow("img1",img)
    cv2.waitKey()

Guess you like

Origin blog.csdn.net/m0_74259636/article/details/132655935