【OpenCV入門指南】第七篇 線段檢測與圓檢測

【OpenCV入門指南】第七篇 線段檢測與圓檢測

在《OpenCV入門指南】第五篇輪廓檢測上》與《OpenCV入門指南】第六篇輪廓檢測下》講解了OpenCV的輪廓檢測。本篇將講解在OpenCV中使用線段檢測與圓檢測。編程

線段檢測與圓檢測主要運用Hough變換,Hough變換是一種利用圖像的全局特徵將特定形狀的邊緣鏈接起來,造成連續平滑邊緣的一種方法。它經過將源圖像上的點影射到用於累加的參數空間,實現對已知解析式曲線進行識別。windows

OpenCV編程中,線段檢測和圓檢測已經封裝成函數了,直接使用cvHoughLines2cvHoughCircles便可,下面來看看函數介紹和實際代碼。app

OpenCV入門指南》系列文章地址:http://blog.csdn.net/morewindows/article/category/863841函數

 

函數功能:檢測圖像中的線段編碼

函數原型:spa

CvSeqcvHoughLines2.net

  CvArrimage指針

  voidline_storageorm

  int method,blog

  double rho

  double theta

  int threshold,

  double param1=0, double param2=0 

);

參數說明:

第一個參數表示輸入圖像,必須爲二值圖像(黑白圖)。

第二個參數表示存儲容器,和上一篇的輪廓檢測同樣,能夠傳入CvMemStorage類型的指針。

第三個參數表示變換變量,能夠取下面的值:

  CV_HOUGH_STANDARD - 傳統或標準 Hough 變換每個線段由兩個浮點數 (ρ, θ) 表示,其中 ρ 是線段與原點(0,0) 之間的距離,θ 線段與 x-軸之間的夾角。

  CV_HOUGH_PROBABILISTIC - 機率 Hough 變換(若是圖像包含一些長的線性分割,則效率更高)。它返回線段分割而不是整個線段。每一個分割用起點和終點來表示。

  CV_HOUGH_MULTI_SCALE - 傳統 Hough 變換的多尺度變種。線段的編碼方式與 CV_HOUGH_STANDARD 的一致。

第四個參數表示與象素相關單位的距離精度。

第五個參數表示弧度測量的角度精度。

第六個參數表示檢測線段的最大條數,若是已經檢測這麼多條線段,函數返回。

第七個參數與第三個參數有關,其意義以下:

  對傳統 Hough 變換,不使用(0).

  對機率 Hough 變換,它是最小線段長度.

  對多尺度 Hough 變換,它是距離精度 rho 的分母 (大體的距離精度是 rho 而精確的應該是 rho / param1 ).

第八個參數與第三個參數有關,其意義以下:

  對傳統 Hough 變換,不使用 (0).

  對機率 Hough 變換,這個參數表示在同一條線段上進行碎線段鏈接的最大間隔值(gap), 即當同一條線段上的兩條碎線段之間的間隔小於param2時,將其合二爲一。

  對多尺度 Hough 變換,它是角度精度 theta 的分母 (大體的角度精度是 theta 而精確的角度應該是 theta / param2).

 

線段檢測的原理仍是有點複雜,有興趣請閱讀專業書籍,下面給一個份示例代碼:

[cpp] view plaincopy

  1. // 圖像中的線段檢測  

  2. //By MoreWindows (http://blog.csdn.net/MoreWindows)  

  3. #include <opencv2/opencv.hpp>  

  4. using namespace std;  

  5. #pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")  

  6. int main()  

  7. {     

  8.     const char *pstrWindowsSrcTitle = "原圖(http://blog.csdn.net/MoreWindows)";  

  9.     const char *pstrWindowsLineName = "線段檢測";  

  10.   

  11.     // 從文件中加載原圖  

  12.     IplImage *pSrcImage = cvLoadImage("201.jpg", CV_LOAD_IMAGE_UNCHANGED);  

  13.     // 灰度圖  

  14.     IplImage *pGrayImage =  cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);  

  15.     cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY);  

  16.     // 邊緣圖  

  17.     IplImage *pCannyImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);  

  18.     cvCanny(pGrayImage, pCannyImage, 30, 90);  

  19.     //cvSmooth(pCannyImage, pCannyImage);  

  20.   

  21.     // 線段檢測(只能針對二值圖像)  

  22.     CvMemStorage *pcvMStorage = cvCreateMemStorage();  

  23.     double fRho = 1;  

  24.     double fTheta = CV_PI / 180;  

  25.     int nMaxLineNumber = 50;   //最多檢測條直線  

  26.     double fMinLineLen = 50;   //最小線段長度  

  27.     double fMinLineGap = 10;   //最小線段間隔  

  28.     CvSeq *pcvSeqLines = cvHoughLines2(pCannyImage, pcvMStorage, CV_HOUGH_PROBABILISTIC, fRho, fTheta, nMaxLineNumber, fMinLineLen, fMinLineGap);  

  29.       

  30.     // 繪製線段  

  31.     IplImage *pColorImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 3);  

  32.     cvCvtColor(pCannyImage, pColorImage, CV_GRAY2BGR);  

  33.     int i;  

  34.     for(i = 0; i < pcvSeqLines->total; i++)  

  35.     {  

  36.         CvPoint* line = (CvPoint*)cvGetSeqElem(pcvSeqLines, i);  

  37.         cvLine(pColorImage, line[0], line[1], CV_RGB(255,0,0), 2);  

  38.     }  

  39.   

  40.     cvNamedWindow(pstrWindowsSrcTitle, CV_WINDOW_AUTOSIZE);  

  41.     cvShowImage(pstrWindowsSrcTitle, pSrcImage);  

  42.     cvNamedWindow(pstrWindowsLineName, CV_WINDOW_AUTOSIZE);  

  43.     cvShowImage(pstrWindowsLineName, pColorImage);  

  44.   

  45.     cvWaitKey(0);  

  46.   

  47.     cvReleaseMemStorage(&pcvMStorage);  

  48.     cvDestroyWindow(pstrWindowsSrcTitle);  

  49.     cvDestroyWindow(pstrWindowsLineName);  

  50.     cvReleaseImage(&pSrcImage);  

  51.     cvReleaseImage(&pGrayImage);  

  52.     cvReleaseImage(&pCannyImage);  

  53.     cvReleaseImage(&pColorImage);  

  54.     return 0;  

  55. }  

運行結果以下:

 

圓檢測函數要用到cvHoughCircles這個函數的函數原形以下:

CVAPI(CvSeq*) cvHoughCircles

  CvArrimagevoidcircle_storage,

  int method

  double dp

  double min_dist,

  double param1 CV_DEFAULT(100),

  double param2 CV_DEFAULT(100),

  int min_radius CV_DEFAULT(0),

  int max_radius CV_DEFAULT(0)

);

能夠看出cvHoughCircles與上面的cvHoughLines2函數比較相似,所以講下部分參數的意思就能夠了:

第二個參數表示Hough變換方式,目前只能用CV_HOUGH_GRADIENT

第三個參數表示尋找圓弧圓心的累計分辨率,一般設置成1就能夠了。

第四個參數表示兩個不一樣圓之間的最小距離,因爲是按圓心來計算距離的,所以對同心圓的檢測就無能爲力了。

注意,圓檢測函數可使用灰度圖。

 

圓檢測的代碼以下:

[cpp] view plaincopy

  1. // 圖像中的圓檢測  

  2. //By MoreWindows (http://blog.csdn.net/MoreWindows)  

  3. #include <opencv2/opencv.hpp>  

  4. using namespace std;  

  5. #pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")  

  6. int main()  

  7. {     

  8.     const char *pstrWindowsSrcTitle = "原圖(http://blog.csdn.net/MoreWindows)";  

  9.     const char *pstrWindowsLineName = "圓檢測";  

  10.   

  11.     // 從文件中加載原圖  

  12.     IplImage *pSrcImage = cvLoadImage("201.jpg", CV_LOAD_IMAGE_UNCHANGED);  

  13.     // 灰度圖  

  14.     IplImage *pGrayImage =  cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);  

  15.     cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY);  

  16.     //cvSmooth(pGrayImage, pGrayImage);  

  17.   

  18.     // 圓檢測(灰度圖)  

  19.     CvMemStorage *pcvMStorage = cvCreateMemStorage();  

  20.     double fMinCircleGap = pGrayImage->height / 10;  

  21.     CvSeq *pcvSeqCircles = cvHoughCircles(pGrayImage, pcvMStorage, CV_HOUGH_GRADIENT, 1, fMinCircleGap);  

  22.     //每一個圓由三個浮點數表示:圓心座標(x,y)和半徑  

  23.   

  24.     // 繪製直線  

  25.     IplImage *pColorImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 3);  

  26.     cvCvtColor(pGrayImage, pColorImage, CV_GRAY2BGR);  

  27.     int i;  

  28.     for (i = 0; i < pcvSeqCircles->total; i++)  

  29.     {  

  30.         float* p = (float*)cvGetSeqElem(pcvSeqCircles, i);  

  31.         cvCircle(pColorImage, cvPoint(cvRound(p[0]), cvRound(p[1])), cvRound(p[2]), CV_RGB(255, 0, 0), 2);  

  32.     }  

  33.   

  34.     cvNamedWindow(pstrWindowsSrcTitle, CV_WINDOW_AUTOSIZE);  

  35.     cvShowImage(pstrWindowsSrcTitle, pSrcImage);  

  36.     cvNamedWindow(pstrWindowsLineName, CV_WINDOW_AUTOSIZE);  

  37.     cvShowImage(pstrWindowsLineName, pColorImage);  

  38.   

  39.     cvWaitKey(0);  

  40.   

  41.     cvReleaseMemStorage(&pcvMStorage);  

  42.     cvDestroyWindow(pstrWindowsSrcTitle);  

  43.     cvDestroyWindow(pstrWindowsLineName);  

  44.     cvReleaseImage(&pSrcImage);  

  45.     cvReleaseImage(&pGrayImage);  

  46.     cvReleaseImage(&pColorImage);  

  47.     return 0;  

  48. }  

運行結果以下,能夠看出圓的檢測準確度不高。

 

OpenCV入門指南】第五篇輪廓檢測上》、《OpenCV入門指南】第六篇輪廓檢測下》及《【OpenCV入門指南】第七篇線段檢測與圓檢測》介紹了圖像的輪廓檢測,線段檢測及圓檢測。

下面幾篇將介紹圖像的直方圖,這對統計圖像的信息以及根據這些信息來加強圖像很是有幫助。歡迎繼續瀏覽《【OpenCV入門指南】第八篇灰度直方圖》、《【OpenCV入門指南】第九篇灰度直方圖均衡化》與《【OpenCV入門指南】第十篇彩色直方圖均衡化》。

相關文章
相關標籤/搜索