一,霍夫圆检测原理:

与霍夫直线检测相似
已知图像每一个像素对应极坐标坐标点为 ( x , y ) (x,y) (x,y)

x = a + R cos ⁡ ( θ ) x=a+R\cos(\theta) x=a+Rcos(θ)
y = b + R sin ⁡ ( θ ) y=b+R\sin(\theta) y=b+Rsin(θ)

a , b a,b a,b : 表示极坐标中的圆心 ,R : 表示半径 , θ \theta θ : 0° ~ 360°

在这里插入图片描述
假设 R(圆半径)固定不变, θ \theta θ从 0 ~ 360 推演计算,每次步长 1°,得出每一个 ( a , b ) (a,b) (a,b)坐标点。对图像上的每个像素点都进项推演计算。就会生成图中虚线表示的圆,累计它们的交点,交点次数最多的就可能是圆心(它们的坐标可能在同一个圆上面)。

在这里插入图片描述

  • 从平面坐标系到极坐标系转换三个参数 C ( x 0 , y 0 , r ) C(x_0,y_0,r) C(x0,y0,r),其中 x 0 , y 0 x_0,y_0 x0,y0 是圆心。
  • 假设平面坐标的任意一个圆上的点,转换到极坐标中: C ( x 0 , y 0 , r ) C(x_0,y_0,r) C(x0,y0,r) 处有最大值,霍夫变换正是使用这个原理实现圆检测。

二,API:

1:因为霍夫变换对噪声比较敏感,所以首先要对图像做中值滤波。
2:基于效率考虑,OpenCv中实现霍夫变换圆检测时基于图像梯度的实现,分为两步:
a ;检测边缘发现可能的圆心。
b ;基于第一步的基础上从候选圆心开始计算最佳半径大小。

Cv2.HoughCircles() : 使用霍夫变换查找灰度图像中的圆。

参数描述
InputArray image8位、单通道、灰度输入图像
HoughMethods method目前,唯一的实现方法是HoughCirclesMethod.Gradient
double dp累加器分辨率与图像分辨率的反比。dp=1
double minDist检测到的圆的中心之间的最小距离。可以分辨时两个圆还是同心圆
double param1 = 100第一个方法特定的参数。[默认值是100],边缘检测的低阈值
double param2 = 100第二个方法特定于参数。 [默认值是100],中心点累加器阈值,候选圆心
int minRadius = 0最小半径
int maxRadius = 0最大半径

三,代码:

 private static void HoughCircles(string path)
        {
            using (Mat src = new Mat(path, ImreadModes.AnyColor | ImreadModes.AnyDepth))
            using (Mat dst = new Mat())
            {

                //1:因为霍夫圆检测对噪声比较敏感,所以首先对图像做一个中值滤波或高斯滤波(噪声如果没有可以不做)
                Mat m1 = new Mat();
                Cv2.MedianBlur(src, m1, 3); //  ksize必须大于1且是奇数

                //2:转为灰度图像
                Mat m2 = new Mat();
                Cv2.CvtColor(m1, m2, ColorConversionCodes.BGR2GRAY);

                //3:霍夫圆检测:使用霍夫变换查找灰度图像中的圆。
                /*
                 * 参数:
                 *      1:输入参数: 8位、单通道、灰度输入图像
                 *      2:实现方法:目前,唯一的实现方法是HoughCirclesMethod.Gradient
                 *      3: dp      :累加器分辨率与图像分辨率的反比。默认=1
                 *      4:minDist: 检测到的圆的中心之间的最小距离。(最短距离-可以分辨是两个圆的,否则认为是同心圆-                            src_gray.rows/8)
                 *      5:param1:   第一个方法特定的参数。[默认值是100] canny边缘检测阈值低
                 *      6:param2:   第二个方法特定于参数。[默认值是100] 中心点累加器阈值 – 候选圆心
                 *      7:minRadius: 最小半径
                 *      8:maxRadius: 最大半径
                 * 
                 */
                CircleSegment[] cs=Cv2.HoughCircles(m2, HoughMethods.Gradient, 1, 80, 70, 30, 10, 60);
                src.CopyTo(dst);
               // Vec3d vec = new Vec3d();
                for (int i = 0; i < cs.Count(); i++)
                {
                    //画圆
                    Cv2.Circle(dst, (int)cs[i].Center.X, (int)cs[i].Center.Y, (int)cs[i].Radius, new Scalar(0, 0, 255), 2, LineTypes.AntiAlias);
                    //加强圆心显示
                    Cv2.Circle(dst, (int)cs[i].Center.X, (int)cs[i].Center.Y, 3, new Scalar(0, 0, 255), 2, LineTypes.AntiAlias);
                }
                using(new Window("OutputImage",WindowMode.AutoSize,dst))
                using (new Window("InputImage", WindowMode.AutoSize, src))
                {
                    Cv2.WaitKey(0);
                }
            }
        }

在这里插入图片描述

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐