1. 程式人生 > >Opencv學習---霍夫變換檢測圓的基本原理

Opencv學習---霍夫變換檢測圓的基本原理

為了方便以後檢視,將基本筆記收藏到這裡!

原博文:http://blog.csdn.net/yizhaoyanbo/article/details/59172991    

其實檢測圓形和檢測直線的原理差別不大,只不過直線是在二維空間,因為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();
}