1. 程式人生 > >霍夫變換檢測圓形原理分析

霍夫變換檢測圓形原理分析

上一篇部落格中簡要描述了一下自己對霍夫變換檢測直線的原理理解,現在說一下檢測圓形的原理。

其實檢測圓形和檢測直線的原理差別不大,只不過直線是在二維空間,因為y=kx+b,只有k和b兩個自由度。而圓形的一般性方程表示為(x-a)²+(y-b)²=r²。那麼就有三個自由度圓心座標a,b,和半徑r。這就意味著需要更多的計算量,而OpenCV中提供的cvHoughCircle()函式裡面可以設定半徑r的取值範圍,相當於有一個先驗設定,在每一個r來說,在二維空間內尋找a和b就可以了,能夠減少計算量。

具體步驟如下:

1.對輸入影象進行邊緣檢測,獲取邊界點,即前景點。

2.假如影象中存在圓形,那麼其輪廓必定屬於前景點(此時請忽略邊緣提取的準確性)。

3.同霍夫變換檢測直線一樣,將圓形的一般性方程換一種方式表示,進行座標變換。由x-y座標系轉換到a-b座標系。寫成如下形式(a-x)²+(b-y)²=r²。那麼x-y座標系中圓形邊界上的一點對應到a-b座標系中即為一個圓。

4.那x-y座標系中一個圓形邊界上有很多個點,對應到a-b座標系中就會有很多個圓。由於原影象中這些點都在同一個圓形上,那麼轉換後a,b必定也滿足a-b座標系下的所有圓形的方程式。直觀表現為這許多點對應的圓都會相交於一個點,那麼這個交點就可能是圓心(a, b)。

5.統計區域性交點處圓的個數,取每一個區域性最大值,就可以獲得原影象中對應的圓形的圓心座標(a,b)。一旦在某一個r下面檢測到圓,那麼r的值也就隨之確定。

以下面的圖片為例,呼叫OpenCV中的cvHoughCircles()進行圓形的檢測,左邊為原圖,右邊為檢測結果,圓形都被圈出。

              

附上程式碼:

#include"cv.h"
#include"highgui.h"
#include<math.h>
using namespace cv;

void main()
{
	IplImage* srcImg=cvLoadImage("img.jpg", CV_LOAD_IMAGE_GRAYSCALE);

	CvMemStorage* storage= cvCreateMemStorage(0);
	cvSmooth(srcImg, srcImg, CV_GAUSSIAN, 5, 5);
	
	//函式範圍值為指向影象序列的指標
	CvSeq* results=cvHoughCircles(srcImg, storage, CV_HOUGH_GRADIENT, 2,srcImg->width/10);

	for (int i=0; i<results->total; i++)
	{
		float* p=(float*) cvGetSeqElem(results, i);  //依次獲取影象序列中的影象資料
		CvPoint pt=cvPoint(cvRound(p[0]), cvRound(p[1]));  //獲取圓心座標
		cvCircle(srcImg, pt, cvRound(p[2]), CV_RGB(0xff, 0xff, 0xff), 3, 8);  //在圖片中將圓形畫出來
	}

	cvNamedWindow("Img", 1);
	cvShowImage("Img", srcImg);

	cvWaitKey(-1);

	cvReleaseImage(&srcImg);
	cvDestroyAllWindows();
}