Hough Circle Transform Parameter Tuning with Examples
Today we will try to understand how to choose the appropriate parameters by experimenting with hough circle transform in Python.
Let’s start with the image below:
First, we apply grayscale to the image. Then, let’s try to apply the hough circle method directly without any other action. Meanwhile, we need to decide on the values of the parameters. The parameters of our method were as follows.
circles = cv.HoughCircles(img, cv.HOUGH_GRADIENT, dp, minDist, param1, param2, minRadius, maxRadius)
When we look at the image, we can see that there are 12 circles on the horizontal. So the radius will be roughly width/24. We can give minRadius and maxRadius values close to this number, taking into account the margins. Since there are spaces in the upper left and right sides (Actually, we can think that one more circle would fit in those spaces, so our circle number would be 13.) minRadius would be smaller than width/24. That’s why I called its value width/26. If we look at the bottom line in the image, the 12 circles fit perfectly in the width, touching the right and left ends, and in terms of perspective, we cannot see a part where less circles fit into this width. So I thought maxRadius could be width/24. minDist represented the minimum distance between two circles. Since the arrangement of our circles is regular, we can roughly calculate the distance between our circles with the minimum radius directly. This would correspond to roughly 2 times the minRadius. So we can call minDist width/12. Let’s try with param1 = 50, param2 = 40 initially. I gave 1.5 to dp.
Our result was as follows:
Now let’s play around with our parameters a little, since we couldn’t get the result we wanted. First of all, we may have come to very definite judgments at first. Let’s leave some flexibility in our values. Let’s start with minDist to do this. Let’s make the minDist width/13 and try again:
Our result has improved considerably. There is only 1 circle left that we cannot detect. At this stage, I was able to detect all circles by trying different methods. For example, by applying a 2*2 morphological gradient or a 3*3 gaussian blur with sigma=1.5. In both, I got the following image as a result:
Now, let’s repeat our steps again by looking at another image:
First, let’s apply grayscale. Next, let’s set the parameters of our HoughCircles method. Thinking that there are about 30 circles on the horizontal, I gave minRadius the value of weight/64. For maxRadius, I tried values between 40–50 and decided on the final weight/45. I gave minDist the value weight/32 to be 2 times the minRadius. I gave the values 50 and 40 to param1 and param2 as in the first example. I wrote 1.5 to dp again. Now let’s look at our result:
While we have achieved a good result, now let’s give extreme values to our parameters and see what happens. For example, when I give param1 the value 5, the result is as follows:
It sees radii as oversized and skips some circles. Now let’s try the value 200 for param1:
Although it is not a very bad result, we can say that we were not very successful in determining the radii. Now let’s try a high value for param2 (120):
Our success rate has dropped considerably. We can take a lesson from here that we shouldn’t increase param2 too much.
Now let’s continue with a different image:
Since our image is a bit noisy this time, let’s blur it first. Here, after blurring, I applied it in canny edge detection to make the contours of the circles a little more specific. Then, while giving the parameters, I roughly calculated how many pieces would fit horizontally from the smallest circle and the largest circle, and thought that it would be 20 and 8. That’s why I gave minRadius and maxRadius the values weight/40 and weight/15, respectively. I gave minRadius the weight/20 value, again with the same logic as the previous examples. Again, let’s give the values param1=50, param2=40, dp=1.5 and look at the result:
As you can see, we got a bad result. Now let’s change the params and dp a bit. As we decrease Param2, we get more circles, and as we increase it, we get less circles. In other words, lowering this value can increase our false positives, while increasing it can increase our false negatives. Let’s try lowering this value a bit, as we already found less circle than we wanted. Let’s set param2 to 20 and see the result:
We got the result we wanted. Our code for this example was as follows:
img = cv.imread(“../input_pictures/input_patato.png”)
img2 = img.copy()
img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
img = cv.GaussianBlur(img, (7, 7), 1.5)
img = cv.Canny(img, 50, 120)
h, w = img.shape[:]
circles = cv.HoughCircles(img, cv.HOUGH_GRADIENT, 1.5, int(w / 20), param1=50, param2=20, minRadius=int(w / 40),
maxRadius=int(w / 15))
circles = np.uint16(np.around(circles))
for c in circles[0, :]:
cv.circle(img2, (c, c), c, (0, 255, 0), 2)
cv.circle(img2, (c, c), 1, (0, 0, 255), 1)
cv.imshow(“ output img”, img2)
We can roughly estimate minRadius and maxRadius by calculating the number of circles that can fit on the horizontal.
If our circles are next to each other touching each other, we can give minDist twice the value of minRadius.
If our circles are far apart, we need to give higher values.
If we detected less circle than we should, we can try to lower the param2 value.
Lowering dp causes false negatives, raising it causes false positives.
If we could not achieve a good result despite all our parameter settings, we may consider blurring, canny edge detection, etc. if we did not do it at the beginning.