一、霍夫圓檢測原理:
與霍夫直線檢測相似,從平面座標系到極座標系轉換三個參數 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