【OpenCV3】角点检测——cv::goodFeaturesToTrack()与cv::cornerSubPix()详解
一提到角點檢測,最常用的方法莫過于Harris角點檢測,opencv中也提供了Harris角點檢測的接口,即cv::cornerHarris(),但是Harris角點檢測存在很多缺陷(如角點是像素級別的,速度較慢等),因此我們這里將介紹opencv中的另一個功能更為強大的函數——cv::goodFeaturesToTrack(),它不僅支持Harris角點檢測,也支持Shi Tomasi算法的角點檢測。但是,該函數檢測到的角點依然是像素級別的,若想獲取更為精細的角點坐標,則需要調用cv::cornerSubPix()函數進一步細化處理,即亞像素。
1、cv::goodFeaturesToTrack()角點檢測
cv::goodFeaturesToTrack()的具體調用形式如下:
void cv::goodFeaturesToTrack(cv::InputArray image, // 輸入圖像(CV_8UC1 CV_32FC1)cv::OutputArray corners, // 輸出角點vectorint maxCorners, // 最大角點數目double qualityLevel, // 質量水平系數(小于1.0的正數,一般在0.01-0.1之間)double minDistance, // 最小距離,小于此距離的點忽略cv::InputArray mask = noArray(), // mask=0的點忽略int blockSize = 3, // 使用的鄰域數bool useHarrisDetector = false, // false ='Shi Tomasi metric'double k = 0.04 // Harris角點檢測時使用);
第一個參數是輸入圖像(8位或32位單通道圖)。
第二個參數是檢測到的所有角點,類型為vector或數組,由實際給定的參數類型而定。如果是vector,那么它應該是一個包含cv::Point2f的vector對象;如果類型是cv::Mat,那么它的每一行對應一個角點,點的x、y位置分別是兩列。
第三個參數用于限定檢測到的點數的最大值。
第四個參數表示檢測到的角點的質量水平(通常是0.10到0.01之間的數值,不能大于1.0)。
第五個參數用于區分相鄰兩個角點的最小距離(小于這個距離得點將進行合并)。
第六個參數是mask,如果指定,它的維度必須和輸入圖像一致,且在mask值為0處不進行角點檢測。
第七個參數是blockSize,表示在計算角點時參與運算的區域大小,常用值為3,但是如果圖像的分辨率較高則可以考慮使用較大一點的值。
第八個參數用于指定角點檢測的方法,如果是true則使用Harris角點檢測,false則使用Shi Tomasi算法。
第九個參數是在使用Harris算法時使用,最好使用默認值0.04。
下面使用測試代碼,看一下實際的檢測效果。
測試代碼如下:
cv::Mat image_color = cv::imread("house.jpg", cv::IMREAD_COLOR);//使用灰度圖像進行角點檢測cv::Mat image_gray;cv::cvtColor(image_color, image_gray, cv::COLOR_BGR2GRAY);//設置角點檢測參數std::vector<cv::Point2f> corners;int max_corners = 200;double quality_level = 0.01;double min_distance = 3.0;int block_size = 3;bool use_harris = false;double k = 0.04;//角點檢測cv::goodFeaturesToTrack(image_gray, corners, max_corners, quality_level, min_distance, cv::Mat(), block_size, use_harris, k);//將檢測到的角點繪制到原圖上for (int i = 0; i < corners.size(); i++){cv::circle(image_color, corners[i], 1, cv::Scalar(0, 0, 255), 2, 8, 0);}cv::imshow("house corner", image_color);cv::waitKey(0);return;
實際檢測效果如下:
2、cv::cornerSubPix()亞像素角點檢測
前面已經提及,cv::goodFeaturesToTrack()提取到的角點只能達到像素級別,在很多情況下并不能滿足實際的需求,這時,我們則需要使用cv::cornerSubPix()對檢測到的角點作進一步的優化計算,可使角點的精度達到亞像素級別。
具體調用形式如下:
void cv::cornerSubPix(cv::InputArray image, // 輸入圖像cv::InputOutputArray corners, // 角點(既作為輸入也作為輸出)cv::Size winSize, // 區域大小為 NXN; N=(winSize*2+1)cv::Size zeroZone, // 類似于winSize,但是總具有較小的范圍,Size(-1,-1)表示忽略cv::TermCriteria criteria // 停止優化的標準);
第一個參數是輸入圖像,和 cv::goodFeaturesToTrack()中的輸入圖像是同一個圖像。
第二個參數是檢測到的角點,即是輸入也是輸出。
第三個參數是計算亞像素角點時考慮的區域的大小,大小為NXN; N=(winSize*2+1)。
第四個參數作用類似于winSize,但是總是具有較小的范圍,通常忽略(即Size(-1, -1))。
第五個參數用于表示計算亞像素時停止迭代的標準,可選的值有cv::TermCriteria::MAX_ITER 、cv::TermCriteria::EPS(可以是兩者其一,或兩者均選),前者表示迭代次數達到了最大次數時停止,后者表示角點位置變化的最小值已經達到最小時停止迭代。二者均使用cv::TermCriteria()構造函數進行指定。
下面就通過一個示例看看cv::cornerSubPix()亞像素角點檢測的具體效果。
cv::Mat image_color = cv::imread("image.jpg", cv::IMREAD_COLOR);//用于繪制亞像素角點cv::Mat image_copy = image_color.clone();//使用灰度圖像進行角點檢測cv::Mat image_gray;cv::cvtColor(image_color, image_gray, cv::COLOR_BGR2GRAY);//設置角點檢測參數std::vector<cv::Point2f> corners;int max_corners = 100;double quality_level = 0.01;double min_distance = 10;int block_size = 3;bool use_harris = false;double k = 0.04;//角點檢測cv::goodFeaturesToTrack(image_gray,corners,max_corners,quality_level,min_distance,cv::Mat(),block_size,use_harris,k);//將檢測到的角點繪制到原圖上for (int i = 0; i < corners.size(); i++){cv::circle(image_color, corners[i], 5, cv::Scalar(0, 0, 255), 2, 8, 0);}//指定亞像素計算迭代標注cv::TermCriteria criteria = cv::TermCriteria(cv::TermCriteria::MAX_ITER + cv::TermCriteria::EPS,40,0.01);//亞像素檢測cv::cornerSubPix(image_gray, corners, cv::Size(5, 5), cv::Size(-1, -1), criteria);//將檢測到的亞像素角點繪制到原圖上for (int i = 0; i < corners.size(); i++){cv::circle(image_copy, corners[i], 5, cv::Scalar(0, 255, 0), 2, 8, 0);}cv::imshow("corner", image_color);cv::imshow("sub pixel corner", image_copy);cv::imwrite("corner.jpg", image_color);cv::imwrite("corner_sub.jpg", image_copy);cv::waitKey(0);return;
直接角點檢測和亞像素角點檢測的結果分別如下:
從檢測的效果來看,使用亞像素角點檢測后角點的精細度確實得到了顯著的提升。
2017.04.07
總結
以上是生活随笔為你收集整理的【OpenCV3】角点检测——cv::goodFeaturesToTrack()与cv::cornerSubPix()详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【OpenCV3】直线拟合——cv::f
- 下一篇: 【OpenCV3】棋盘格角点检测与绘制—