It shows my problem, I cannot get a better result than this one where there are detected circles (red) left and right on the lines.
I use HoughCircles(src_gray, circles, cv::HOUGH_GRADIENT, dp, minDistVal, cannyThreshold, accumulatorThreshold, minRadiusVal, maxRadiusVal)
Can I improve the detection somehow? Maybe some other algorithms is better suited?
Thanx!
PS: The green circles on the image are drawn by the user to precalculate radius and distance.
I’m not a fan of the Hough transform. It tends to produce a lot of false positives, has limitations related to how you set up the (discrete) parameter space (poor precision, or multiple results for a single feature), and runtime performance issues, particularly as the number of parameters increases.
I think it is a good teaching tool (easy to understand) and has some use as a way to generate candidates (first pass), but isn’t very useful on its own for getting high location accuracy results. (Circle detection, maybe, but circle position estimation, not so much).
If you are so inclined you could write your own circle fitting routine which you can apply to the output of houghCircles.
I wrote one based on this paper:
I chose the “Modified Least Squares” method, and it works very well for my use case. Equations II.8 through II.15 are the relevant ones.
I would share my code, but I don’t own it so I’m not able to. The function I wrote operates on contours returned by CV::findContours(), and is less than 100 lines of code.
For it to work well in your case you would have to isolate the circles somehow so you end up with individual contours for each circle. Some morphology operations might be all you need?
If your images are always of that form (circles appear to always be centered over the intersections of the lines, and the circles are always the same size) I might try to find all the lines in the image and then find all of the intersection points of the lines. Those intersection points would be the candidates for fitting a circle.
And if the circles are always the same size, maybe just make a template for the circle and convolve it with the image.
if you have this manual step anyway, you could just take that piece of the picture as a template and run matchTemplate().
a more involved scheme uses the initial template to find good instances, then averages over them, to suppress variations in background/surroundings, yielding a new and improved template.