天天看點

opencv使用霍夫圓算法HoughCircles進行圓檢測霍夫梯度法的原理霍夫圓變換:HoughCircles 函數

 原理介紹:

opencv —— HoughCircles 霍夫圓變換原理及圓檢測

霍夫變換(Hough Transform)

霍夫變換 - 圓檢測 (Hough Circle transform)

霍夫圓算法是一種用于檢測圖像中圓形區域的算法。OpenCV 霍夫圓變換對标準霍夫圓變換做了運算上的優化。它采用的是 “霍夫梯度法”。

霍夫梯度法的原理

第一步:估計圓心

  1. 把原圖做一次 Canny 邊緣檢測,得到邊緣檢測的二值圖。
  2. 對原始圖像執行一次 Sobel 算子,計算出所有像素的鄰域梯度值。
  3. 初始化圓心空間 N(a,b),令所有的 N(a,b)=0。
  4. 周遊 Canny 邊緣二值圖中的所有非零像素點,沿着梯度方向 ( 切線的垂直方向 )畫線,将線段經過的所有累加器中的點 (a,b) 的 N(a,b)+=1。統計排序 N(a,b),得到可能的圓心(N(a,b) 越大,越有可能是圓心)。   

第二步:估計半徑(針對某一個圓心 (a,b))

  1. 計算 Canny 圖中所有非 0 點距離圓心的距離。
  2. 距離從小到大排序,根據門檻值,選取合适的可能半徑(比如 3 和 3.5 都被劃為半徑值 3 中)。
  3. 初始化半徑空間 r, N(r)=0。
  4. 周遊 Canny 圖中的非 0 點,N( 距離 )+=1。
  5. 統計得到可能的半徑值(N(r) 越大,說明這個距離值出現次數越多,越有可能是半徑值)。

霍夫梯度法缺點

  1. 在霍夫梯度法中,我們使用 Sobel 導數來計算局部梯度,那麼随之而來的假設是,其可以視作等同于一條局部切線,并這個不是一個數值穩定的做法。在大多數情況下,這樣做會得到正确的結果,但或許會在輸出中産生一些噪聲。
  2. 在邊緣圖像中的整個非0像素集被看做每個中心的候選部分。是以,如果把累加器的門檻值設定偏低,算法将要消耗比較長的時間。
  3. 因為每一個中心隻選擇一個圓,如果有同心圓,就隻能選擇其中的一個。
  4. 因為中心是按照其關聯的累加器值的升序排列的,并且如果新的中心過于接近之前已經接受的中心的話,就不會被保留下來。且當有許多同心圓或者是近似的同心圓時,霍夫梯度法的傾向是保留最大的一個圓。可以說這是一種比較極端的做法,因為在這裡預設Sobel導數會産生噪聲,若是對于無窮分辨率的平滑圖像而言的話,這才是必須的。

霍夫圓變換:HoughCircles 函數

HoughCircles 函數可以利用霍夫變換算法檢測出灰階圖中的圓。

函數原型:

CV_EXPORTS_W void HoughCircles( InputArray image, OutputArray circles,

                               int method, double dp, double minDist,

                               double param1 = 100, double param2 = 100,

                               int minRadius = 0, int maxRadius = 0 );
           

 @brief Finds circles in a grayscale image using the Hough transform.使用霍夫變換在灰階圖中檢測圓

The function finds circles in a grayscale image using a modification of the Hough transform.

@note Usually the function detects the centers of circles well. However, it may fail to find correct radii. You can assist to the function by specifying the radius range ( minRadius and maxRadius ) if you know it. Or, in the case of #HOUGH_GRADIENT method you may set maxRadius to a negative number to return centers only without radius search, and find the correct radius using an additional procedure.

此函數可以很容易地檢測出圓心,但是可能找不到合适地圓半徑。我們可以通過 minRadius 和 maxRadius 兩個參數指定最大和最小圓半徑,來輔助圓檢測的結果。或者可以直接忽略傳回半徑,讓二者均為預設值,隻用 HoughCircles 函數檢測出圓心,用額外步驟進一步确定半徑。

It also helps to smooth image a bit unless it's already soft. For example,GaussianBlur() with 7x7 kernel and 1.5x1.5 sigma or similar blurring may help.

除非圖像已經很柔和,否則還可以使圖像稍微平滑一些 例如,具有7x7核心和1.5x1.5 sigma或類似模糊效果的GaussianBlur()可能會有所幫助

@param image 8-bit, single-channel, grayscale input image.

@param circles Output vector of found circles. Each vector is encoded as  3 or 4 element

floating-point vector

opencv使用霍夫圓算法HoughCircles進行圓檢測霍夫梯度法的原理霍夫圓變換:HoughCircles 函數

.

@param method Detection method, see #HoughModes. The available methods are #HOUGH_GRADIENT and #HOUGH_GRADIENT_ALT.

@param dp Inverse ratio of the accumulator resolution to the image resolution. For example, if dp=1 , the accumulator has the same resolution as the input image. If dp=2 , the accumulator has half as big width and height. For #HOUGH_GRADIENT_ALT the recommended value is dp=1.5, unless some small very circles need to be detected.

累加器分辨率與圖像分辨率的反比 例如,如果 dp = 1,累加器具有與輸入圖像相同的分辨率 如果dp = 2,則累加器具有 寬度和高度的一半 對于#HOUGH GRADIENT ALT,建議值為dp = 1.5, 除非需要檢測到一些很小的圓圈

@param minDist Minimum distance between the centers of the detected circles. If the parameter is too small, multiple neighbor circles may be falsely detected in addition to a true one. If it is too large, some circles may be missed.

被檢測圓的中心之間的最小距離。如果參數太小,可能會錯誤地檢測到多個鄰居圓,而不是一個真鄰居圓。如果太大,可能會漏掉一些圓圈。

@param param1 First method-specific parameter. In case of #HOUGH_GRADIENT and #HOUGH_GRADIENT_ALT, it is the higher threshold of the two passed to the Canny edge detector (the lower one is twice smaller).

Note that #HOUGH_GRADIENT_ALT uses #Scharr algorithm to compute image derivatives, so the threshold value shough normally be higher, such as 300 or normally exposed and contrasty images.

第一個method-specific參數。在#HOUGH GRADIENT和#HOUGH ALT的情況下,它是傳遞給Canny邊緣檢測器的兩個較高的門檻值(較低的那個小1 / 2)。注意,#HOUGH梯度ALT使用#Scharr算法來計算圖像導數,是以門檻值通常會更高,例如300或正常曝光和對比度圖像。

@param param2 Second method-specific parameter. In case of #HOUGH_GRADIENT, it is the accumulator threshold for the circle centers at the detection stage. The smaller it is, the more false circles may be detected. Circles, corresponding to the larger accumulator values, will be returned first. In the case of #HOUGH_GRADIENT_ALT algorithm, this is the circle "perfectness" measure. The closer it to 1, the better shaped circles algorithm selects. In most cases 0.9 should be fine.

If you want get better detection of small circles, you may decrease it to 0.85, 0.8 or even less. But then also try to limit the search range [minRadius, maxRadius] to avoid many false circles.

第二種方法特定的參數; 如果是#HOUGH GRADIENT,則為 圓的累加器門檻值在檢測階段居中 越小越多 可能會檢測到錯誤的圓圈 與較大的累加器值相對應的圓将是 首先傳回 在#HOUGH GRADIENT ALT算法的情況下,這是圈 perfectness 度量 它越接近1,則選擇的形狀更好的圓形算法 在大多數情況下,0.9應該可以 如果要更好地檢測小圓圈,可以将其降低到0.85 0.8甚至更低 但是,然後還要嘗試限制搜尋範圍[minRadius,maxRadius],以避免出現許多錯誤的圓圈

@param minRadius Minimum circle radius.

@param maxRadius Maximum circle radius. If <= 0, uses the maximum image dimension. If < 0, #HOUGH_GRADIENT returns centers without finding the radius. #HOUGH_GRADIENT_ALT always computes circle radiuses.

  • image,輸入圖像,即源圖像,需要為 8 位的灰階單通道圖像。
  • circles,調用 HoughCircles 函數後此參數存儲了檢測到的圓的輸出矢量,每個矢量由包含了 3 個元素的浮點矢量(x,y,radius)表示。
  • method,使用的檢測方法,目前 OpenCV 中就霍夫梯度法一種可以使用,辨別符為 HOUGH_GRADIENT。
  • dp,累加面分辨率(大小) = 原始圖像分辨率(大小) × 1/dp。預設 dp = 1 時,兩者分辨率相同。
  • minDist,兩個圓心之間的最小距離。若兩圓心距離 < minDist,則認為是同一個圓。
  • param1,Canny 邊緣檢測的高門檻值,低門檻值被自動置為高門檻值的一半,預設為 100。
  • param2,累加平面某點是否是圓心的判定門檻值。它越大,能通過檢測的圓就更接近完美的圓形,預設為 100。
  • minRadius,圓半徑的最小值。預設為 0。
  • maxRadius,圓半徑的最大值,預設為 0。
參數 描述
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 最大半徑
#include<opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int hough_value = 55;
Mat src, gray;
void hough_change(int, void*) {
	vector<Vec3f>circles;    //minDist 和 param2 數值的設定是關鍵
	HoughCircles(gray, circles, HOUGH_GRADIENT, 1, 10, 110, hough_value, 0, 0);
	Mat show = src.clone();
	for (int i = 0; i < circles.size(); i++) {
		circle(show, Point(circles[i][0], circles[i][1]), circles[i][2], Scalar(0, 0, 255), 2);
	}
	imshow("show", show);
}
int main() {
	src = imread("circles.bmp");
	GaussianBlur(src, src, Size(3, 3), 0, 0);
	imshow("原圖", src);
	cvtColor(src, gray, COLOR_BGR2GRAY);
	namedWindow("show");
	createTrackbar("hough_value", "show", &hough_value, 200, hough_change);
	hough_change(0, 0);

	waitKey(0);
}
           
opencv使用霍夫圓算法HoughCircles進行圓檢測霍夫梯度法的原理霍夫圓變換:HoughCircles 函數
opencv使用霍夫圓算法HoughCircles進行圓檢測霍夫梯度法的原理霍夫圓變換:HoughCircles 函數

 使用HoughCircles()函數進行圓檢測,其中參數的選擇很關鍵,尤其是minDist 和 param2 兩個參數的數值選擇,決定着圓檢測效果的好壞。

繼續閱讀