C#:霍夫變換圓檢測

一、霍夫圓檢測原理:

  • 與霍夫直線檢測相似,從平面座標系到極座標系轉換三個參數 C( x0,y0,r ) 只是參數方程有變化,而且參數空間增加了一個維度(圓心座標x,y和半徑r)

  • 已知圖像每一個像素對應極座標座標點爲( x , y ):
    x = a + R cos ⁡ ( θ )
    y = b + R sin ⁡ ( θ )
    a , b : 表示極座標中的圓心 ,R : 表示半徑 ,θ : 0° ~ 360°



    假設 R(圓半徑)固定不變,θ 從 0 ~ 360 推演計算,每次步長 1°,得出每一個 ( a , b ) 座標點。對圖像上的每個像素點都進項推演計算。就會生成圖中虛線表示的圓,累計它們的交點,交點次數最多的就可能是圓心(它們的座標可能在同一個圓上面)。

  • 從平面座標系到極座標系轉換三個參數 C( x0,y0,r ) ,x0 ,y0是圓心。

  • 假設平面座標的任意一個圓上的點,轉換到極座標中:C( x0,y0,r ) 處有最大值,霍夫變換正是使用這個原理實現圓檢測。

二、實現

  • 1:因爲霍夫變換對噪聲比較敏感,所以首先要對圖像做中值濾波。
  • 2:基於效率考慮,OpenCv中實現霍夫變換圓檢測時基於圖像梯度的實現,分爲兩步:
    a )檢測邊緣發現可能的圓心。
    b)基於第一步的基礎上從候選圓心開始計算最佳半徑大小。
  • Cv2.HoughCircles() : 使用霍夫變換查找灰度圖像中的圓。
參數 描述
InputArray image 8位、單通道、灰度輸入圖像
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 void uiButton2_Click(object sender, EventArgs e)
        {
            // using (Mat src = new Mat(path, ImreadModes.AnyColor | ImreadModes.AnyDepth))
            //  using (Mat dst = new Mat())
            {
                //1:因爲霍夫圓檢測對噪聲比較敏感,所以首先對圖像做一箇中值濾波或高斯濾波(噪聲如果沒有可以不做)
                Mat m1 = new Mat();
                Cv2.MedianBlur(src_img, m1, 3); //  ksize必須大於1且是奇數

                //2:轉爲灰度圖像
                Mat m2 = new Mat();
                Cv2.CvtColor(m1, m2, ColorConversionCodes.BGR2GRAY);

                //3:霍夫圓檢測:使用霍夫變換查找灰度圖像中的圓。
                CircleSegment[] cs = Cv2.HoughCircles(m2, HoughMethods.Gradient, 1, 80, 70, 60, 30, 100);
                src_img.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), 5, LineTypes.AntiAlias);
                    //加強圓心顯示
                    Cv2.Circle(dst, (int)cs[i].Center.X, (int)cs[i].Center.Y, 3, new Scalar(0, 0, 255), 3, LineTypes.AntiAlias);
                }
                //using (new Window("OutputImage", WindowMode.AutoSize, dst))
                picBoxShowDel.Image = dst.ToBitmap();
            }

四、參考

「haixin-561」的博客https://blog.csdn.net/weixin_41049188/article/details/92422241

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章