1. 程式人生 > >C# EMGU 3.4.1學習筆記(八)示例程式:霍夫圓變換HoughCircles函式

C# EMGU 3.4.1學習筆記(八)示例程式:霍夫圓變換HoughCircles函式

霍夫圓變換的基本思路是認為影象上每一個非零畫素點都有可能是一個潛在的圓上的一點,跟霍夫線變換一樣,也是通過投票,生成累積座標平面,設定一個累積權重來定位圓。

在笛卡爾座標系中圓的方程為:

其中(a,b)是圓心,r是半徑,也可以表述為:

即:

所以在abr組成的三維座標系中,一個點可以唯一確定一個圓。 而在笛卡爾的xy座標系中經過某一點的所有圓對映到abr座標系中就是一條三維的曲線:

經過xy座標系中所有的非零畫素點的所有圓就構成了abr座標系中很多條三維的曲線。

在xy座標系中同一個圓上的所有點的圓方程是一樣的,它們對映到abr座標系中的是同一個點,所以在abr座標系中該點就應該有圓的總畫素N0個曲線相交。通過判斷abr中每一點的相交(累積)數量,大於一定閾值的點就認為是圓。

以上是標準霍夫圓變換實現演算法,問題是它的累加面是一個三維的空間,意味著比霍夫線變換需要更多的計算消耗。Opencv霍夫圓變換對標準霍夫圓變換做了運算上的優化。它採用的是“霍夫梯度法”。它的檢測思路是去遍歷累加所有非零點對應的圓心,對圓心進行考量。如何定位圓心呢?圓心一定是在圓上的每個點的模向量上,即在垂直於該點並且經過該點的切線的垂直線上,這些圓上的模向量的交點就是圓心。

霍夫梯度法就是要去查詢這些圓心,根據該“圓心”上模向量相交數量的多少,根據閾值進行最終的判斷。

備註:以上霍夫圓變換的原理說明引用自:https://blog.csdn.net/dcrmg/article/details/52506538

以下是霍夫圓變換的示例,本示例是《OpenCV3程式設計入門》中7.2.9的示例程式的C# EMGU 3.4.1版。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Util;
using Emgu.CV.Structure;

namespace HoughCircles
{
    class Program
    {
        static void Main(string[] args)
        {
            //載入原始圖
            Mat srcImage = CvInvoke.Imread("moon.jpg");
            //定義臨時變數和目標圖
            Mat tempImage = new Mat(), dstImage = new Mat();

            //顯示原始圖
            CvInvoke.Imshow("OriginalImage", srcImage);

            //轉為灰度圖並進行影象平滑
            CvInvoke.CvtColor(srcImage, tempImage, ColorConversion.Rgb2Gray);
            CvInvoke.GaussianBlur(tempImage, tempImage, new Size(9, 9), 0, 0);

            //進行霍夫圓變換
            VectorOfPoint3D32F circles = new VectorOfPoint3D32F(); //定義vect儲存圓引數(中心點x、y座標和半徑)
            CvInvoke.HoughCircles(tempImage, circles, HoughType.Gradient, 2, 20, 200, 200, 0, 0);

            //依次在圖中繪製出圓
            for (int i = 0; i < circles.Size; i++)
            {
                //引數定義
                Point center = new Point((int)Math.Round(circles[i].X), (int)Math.Round(circles[i].Y)); //定義圓心
                int radius = (int)Math.Round(circles[i].Z);
                //繪製圓心(圓的thickness設定為-1)
                CvInvoke.Circle(srcImage, center, 3, new MCvScalar(0, 255, 0), -1);
                //繪製圓輪廓
                CvInvoke.Circle(srcImage, center, radius, new MCvScalar(155, 50, 255), 3);
            }

            //顯示最終效果圖
            CvInvoke.Imshow("HoughCircleTransformedImage", srcImage);

            CvInvoke.WaitKey(0);
        }
    }
}

程式執行截圖如下:

原始圖:

霍夫圓變換後的效果圖: