HoughCircles Doesn't detect circles correctly in OpenCV
See the question and my original answer on StackOverflowHere is a solution (based on OpenCvSharp, not on emgucv, which allows C# code to be very close to all OpenCV code that you can find in C++ or Python, but you can easily convert it back to emgucv).
I've removed the Erode and Dilate step (which in this case just destroy the original image too much).
What I used is a loop on hough circle calls (varying the inverse ratio to accumulator resolution) to ensure that I detect more than one circle, and not the circles I'm not interested in.
int blurSize = 5;
using (var src = new Mat("2Okrv.jpg"))
using (var gray = src.CvtColor(ColorConversionCodes.BGR2GRAY))
using (var blur = gray.GaussianBlur(new Size(blurSize, blurSize), 0))
using (var dst = src.Clone())
{
// this hashset will automatically store all "unique" detected circles
// circles are stored modulo some "espilon" value, set to 5 here (half of min size of hough circles below)
var allCircles = new HashSet<CircleSegment>(new CircleEqualityComparer { Epsilon = 5 });
// vary inverse ratio of accumulator resolution
// depending on image, you may vary start/end/step
for (double dp = 1; dp < 5; dp += 0.2)
{
// we use min dist = 1, to make sure we can detect concentric circles
// we use standard values for other parameters (canny, ...)
// we use your min max values (the max may be important when dp varies)
var circles = Cv2.HoughCircles(blur, HoughMethods.Gradient, dp, 1, 100, 100, 10, 128);
foreach (var circle in circles)
{
allCircles.Add(circle);
}
}
// draw final list of unique circles
foreach (var circle in allCircles)
{
Cv2.Circle(dst, circle.Center, (int)circle.Radius, Scalar.FromRgb(235, 20, 30), 1);
}
// display images
using (new Window("src image", src))
using (new Window("dst image", dst))
{
Cv2.WaitKey();
}
}
public class CircleEqualityComparer : IEqualityComparer<CircleSegment>
{
public double Epsilon { get; set; }
public bool Equals(CircleSegment x, CircleSegment y) => x.Center.DistanceTo(y.Center) <= Epsilon && Math.Abs(x.Radius - y.Radius) <= Epsilon;
// bit of a hack... we return a constant so only Equals is used to compare two circles
// since we have only few circles that's ok, we don't play with millions...
public int GetHashCode(CircleSegment obj) => 0;
}
Here is the result: