opencv學習之路(18)、霍夫變換


一、簡介

在圖像處理和計算機視覺領域中,如何從當前的圖像中提取所需要的特征信息是圖像識別的關鍵所在。在許多應用場合中需要快速准確地檢測出直線或者圓。其中一種非常有效的解決問題的方法是霍夫(Hough)變換。

二、霍夫線變換

霍夫線變換的原理

 

 以上原理部分,轉自http://blog.csdn.net/poem_qianmo/article/details/26977557

 

 1 #include "opencv2/opencv.hpp"
 2 using namespace cv;
 3 
 4 void main()
 5 {
 6     Mat src=imread("E://1.png");
 7     Mat dst;
 8     imshow("src", src);
 9     
10     Canny(src, src, 50, 200);
11     imshow("Canny", src);
12     //cvtColor(src, dst, CV_BGR2GRAY);//彩色圖轉灰度圖:該語句不能放在canny邊緣檢測后(canny檢測后,圖像變為了灰度圖)
13     cvtColor(src, dst, CV_GRAY2BGR);//灰度圖轉彩色圖
14     
15     //進行霍夫線變換
16     vector<Vec2f> lines;  //定義矢量結構lines用於存放得到的線段矢量集合
17     HoughLines(src, lines, 1, CV_PI/180, 150);//超過150的線段才被檢測到
18 
19     //依次在圖中繪制出每條線段
20     for (size_t i = 0; i < lines.size(); i++)
21     {
22         float rho=lines[i][0],theta=lines[i][1];
23         Point pt1,pt2;
24         double a=cos(theta),b=sin(theta);
25         double x0=a*rho,y0=b*rho;
26         pt1.x=cvRound(x0+1000*(-b));//cvRound(double value) 函數:對一個double型數字四舍五入,返回一個整數
27         pt1.y=cvRound(y0+1000*(a));
28         pt2.x = cvRound(x0 - 1000*(-b));  
29         pt2.y = cvRound(y0 - 1000*(a));  
30         line(dst,pt1,pt2,Scalar(55,100,195),2,8);
31     }
32     
33     imshow("dst", dst);
34     waitKey(0);
35     destroyAllWindows();
36 }

三、累計概率霍夫變換

 1 #include "opencv2/opencv.hpp"
 2 using namespace cv;
 3 
 4 void main()
 5 {
 6     //HoughLinesP()用法
 7     Mat src = imread("E://1.png");
 8     Mat dstImg = src.clone();
 9     imshow("src", src);
10 
11     cvtColor(src, src, CV_BGR2GRAY);
12     Canny(src,src, 50, 200);
13     vector<Vec4i> lines;  //定義矢量結構lines用於存放得到的線段矢量集合
14     HoughLinesP(src, lines, 1, CV_PI/180, 150, 50, 10);
15     //依次在圖中繪制出每條線段
16     for(size_t i = 0; i<lines.size(); i++)
17     {
18         Vec4i p = lines[i];
19         line(dstImg, Point(p[0], p[1]), Point(p[2], p[3]), Scalar(0, 255, 0), 2, 8);20     }
21     imshow("dst", dstImg);
22     waitKey(0);
23     destroyAllWindows();
24 }

四、霍夫圓變換

霍夫圓變換的基本原理和上面講的霍夫線變化大體上是很類似的,只是點對應的二維極徑極角空間被三維的圓心點x, y還有半徑r空間取代。說“大體上類似”的原因是,如果完全用相同的方法的話,累加平面會被三維的累加容器所代替:在這三維中,一維是x,一維是y,另外一維是圓的半徑r。這就意味着需要大量的內存而且執行效率會很低,速度會很慢。

對直線來說, 一條直線能由參數極徑極角表示. 而對圓來說, 我們需要三個參數來表示一個圓, 也就是:

這里的(Xcenter,Ycenter)表示圓心的位置 (下圖中的綠點) ,而 r 表示半徑, 這樣我們就能唯一的定義一個圓了, 見下圖:

在OpenCV中,我們一般通過一個叫做“霍夫梯度法”的方法來解決圓變換的問題。

  • 第一個參數,InputArray類型的image,輸入圖像,即源圖像,需為8位的灰度單通道圖像。
  • 第二個參數,InputArray類型的circles,經過調用HoughCircles函數后此參數存儲了檢測到的圓的輸出矢量,每個矢量由包含了3個元素的浮點矢量(x, y, radius)表示。
  • 第三個參數,int類型的method,即使用的檢測方法,目前OpenCV中就霍夫梯度法一種可以使用,它的標識符為CV_HOUGH_GRADIENT,在此參數處填這個標識符即可。
  • 第四個參數,double類型的dp,用來檢測圓心的累加器圖像的分辨率於輸入圖像之比的倒數,且此參數允許創建一個比輸入圖像分辨率低的累加器。上述文字不好理解的話,來看例子吧。例如,如果dp= 1時,累加器和輸入圖像具有相同的分辨率。如果dp=2,累加器便有輸入圖像一半那么大的寬度和高度。
  • 第五個參數,double類型的minDist,為霍夫變換檢測到的圓的圓心之間的最小距離,即讓我們的算法能明顯區分的兩個不同圓之間的最小距離。這個參數如果太小的話,多個相鄰的圓可能被錯誤地檢測成了一個重合的圓。反之,這個參數設置太大的話,某些圓就不能被檢測出來了。
  • 第六個參數,double類型的param1,有默認值100。它是第三個參數method設置的檢測方法的對應的參數。對當前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示傳遞給canny邊緣檢測算子的高閾值,而低閾值為高閾值的一半。
  • 第七個參數,double類型的param2,也有默認值100。它是第三個參數method設置的檢測方法的對應的參數。對當前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示在檢測階段圓心的累加器閾值。它越小的話,就可以檢測到更多根本不存在的圓,而它越大的話,能通過檢測的圓就更加接近完美的圓形了。
  • 第八個參數,int類型的minRadius,有默認值0,表示圓半徑的最小值。
  • 第九個參數,int類型的maxRadius,也有默認值0,表示圓半徑的最大值。

需要注意的是,使用此函數可以很容易地檢測出圓的圓心,但是它可能找不到合適的圓半徑。我們可以通過第八個參數minRadius和第九個參數maxRadius指定最小和最大的圓半徑,來輔助圓檢測的效果。或者,我們可以直接忽略返回半徑,因為它們都有着默認值0,單單用HoughCircles函數檢測出來的圓心,然后用額外的一些步驟來進一步確定半徑。

 

 1 #include "opencv2/opencv.hpp"
 2 using namespace cv;
 3 
 4 void main()
 5 {
 6     Mat src = imread("E://C.jpg");
 7     Mat dst = src.clone();
 8     imshow("src", src);
 9 
10     cvtColor(src, src, CV_BGR2GRAY);
11     GaussianBlur(src,src,Size(9,9),2);
12 
13     vector<Vec3f> circles;
14     HoughCircles(src, circles, CV_HOUGH_GRADIENT,1.5, 10, 200, 100);
15     for(size_t i = 0; i<circles.size(); i++)
16     {
17         Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
18         int radius = cvRound(circles[i][2]);
19         circle(dst, center, 3, Scalar(0, 0, 255), -1, 8,0);//設置為-1時,畫實心圓
20         circle(dst, center, radius, Scalar(0, 255, 0), 3, 8,0);//畫空心圓
21     }
22     imshow("dst", dst);
23     waitKey(0);
24 }

五、其他

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM