OpenCV学习(二十四 ):角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack()
OpenCV學習(二十四 ):角點檢測(Corner Detection):cornerHarris(),goodFeatureToTrack()
參考博客:
Harris角點檢測原理詳解
Harris角點檢測原理及C++實現
OpenCV亞像素角點cornerSubPixel()源代碼分析
Taylor公式(泰勒公式)通俗+本質詳解
如何理解最小二乘法?
一、概述
1、角點定義:
角點沒有明確的數學定義,但人們普遍認為角點是二維圖像亮度變化劇烈的點或圖像邊緣曲線上曲率極大值的點。這些點在保留圖像圖形重要特征的同時,可以有效地減少信息的數據量,使其信息的含量很高,有效地提高了計算的速度,有利于圖像的可靠匹配,使得實時處理成為可能。其在三維場景重建、運動估計、目標跟蹤、目標識別、圖像配準與匹配等計算機視覺領域起著非常重要的作用。
2、角點檢測:
計算機視覺子系統中用來捕獲圖像特征的一種方法,廣泛應用于運動檢測,圖相匹配,視頻跟蹤,三維重建和目標識別等領域,也稱為特征點檢測。我不再觀測整幅圖,二十選擇某些特殊的點,然后對他們進行局部 有的放矢(有明確的目的性和針對性)地分析。
圖像的特征類型包括有:
1)邊緣
2)角點(感興趣的關鍵點)
3)斑點(感興趣的區域)
關于角點的具體描述有:
1)一階導數(既灰度的梯度)的局部最大所對應的像素點
2)兩條既兩條以上邊緣的交點
3)圖像中梯度值和梯度方向的變化速率都很高的點
4)角點處得一階導數最大,二階導數為零,它指示了物體邊緣變化不連續的方向
在當前的圖像處理領域中,角點檢測算法可以歸納為:
1)基于灰度圖像的角點檢測(基于灰度圖像的角點檢測又可分三類,見下)
2)基于二值圖像的角點檢測
3)基于輪廓曲線的角點檢測
基于灰度圖像的角點檢測:
1)基于梯度:
其中基于梯度的方法是通過計算邊緣的曲率來判斷角點的存在性,角點計算數值的大小不僅與邊緣強度有關,而且與邊緣方向的變化率有關,該方法對噪聲比基于模板的角點檢測方法對噪聲更為敏感。
2)基于模板:
其中基于模板的方法主要考慮像素領域點的灰度變化,即圖像亮度的變化,將與鄰點亮度對比足夠大的點定義為角點。常見的基于模板的角點檢測算法有Kitchen-Rosenfeld角點檢測算法,Harris角點檢測算法、KLT角點檢測算法及SUSAN角點檢測算法。和其他角點檢測算法相比,SUSAN角點檢測算法具有算法簡單、位置準確、抗噪聲能力強等特點。
3)基于模板+梯度組合
二、harris角點檢測,cornerHarris()函數
harris角點檢測是一種直接基于灰度圖像的角點提取算法,穩定性高,尤其對L型角點檢測精度高。但由于
該函數在圖像上運行Harris角探測器。與cornerMinEigenVal()和cornerEigenValsAndVecs()函數類似,對于每個像素(x,y),它計算 blockSize×blockSize 鄰域上的2×2梯度協方差矩陣M(x,y)。然后計算如下特征
:
圖像中的角點可以作為此響應映射的局部最大值。即找出角點。
在用cornerHarris函數時要用單通道的圖像,要配合閾值操作函數一起threshold()對角點檢測之后的圖像進行顯示操作,確定圖像的強角點:goodFeatureToTrack()函數。
三、cornerMinEigenVal(),cornerEigenValsAndVecs()函數
作用:計算圖像塊的特征值和特征向量用于角點檢測。
void cornerEigenValsAndVecs( InputArray src, // 輸入單通道8位或浮點圖像 OutputArray dst, // 用來存儲結果的圖像;它有src相同的大小和類型為CV_32FC(6) int blockSize, // 領域尺寸 int ksize, // Sobel()算子的孔徑參數 int borderType=BORDER_DEFAULT // 圖像像素的邊界模式有默認值BORDER_DEFAULT );作用:計算梯度矩陣的最小特征值用于角點檢測。
void cornerMinEigenVal( InputArray src, // 輸入單通道8位或浮點圖像; OutputArray dst, // 用來存儲最小特征值的圖像;它有src相同的大小和類型為CV_32FC1; int blockSize, // 領域尺寸; int ksize=3, // Sobel()算子的孔徑參數; int borderType=BORDER_DEFAULT // 像素外推方式; );三、確定圖像強角點:Shi-Tomasi角點檢測,goodFeaturesToTrack()函數
goodFeatureToTrack()函數結合了Shi-Tomasi算子,用于確定圖像的強角點:
void goodFeaturesToTrack( InputArray image, // 輸入圖像,需要8位的或者浮點型32位單通道圖像 OutputArray corners, // 檢測到角點的輸出向量 int maxCorners, // 角點的最大數量 double qualityLevel, // 角點檢測可接受的最小特征值:其實實際用于過濾角點的最小特征值// 是 qualityLevel 與圖像中最大特征值得乘積。// 通常不超過1(常用0.10和0.01)。檢測完所有角點后,// 還要剔除一些距離較近的角點 double minDistance, // 角點之間的最小距離,單位為像素 InputArray mask=noMask(), // 用于指定感興趣區域的角點檢測,默認是noArray() int blockSize=3, // 是計算導數自相關矩陣時指定的鄰域范圍 bool useHarrisDetector=false, // 指示是否使用Harris角點檢測 double k=0.04 // 為了用于設置Hessian 自相關矩陣行列式 的相對權重的權重系數 );四、亞像素級角點檢測:cornerSubPix()函數
原理見上:
cornerSubPix()函數用于尋找亞像素級角點位置(更精確的浮點類型位置)
五示例一:harris角點檢測
#include <opencv2/opencv.hpp>using namespace cv; using namespace std;#define WINDOW_NAME1 "【程序窗口1】" //為窗口標題定義的宏 #define WINDOW_NAME2 "【程序窗口2】" //為窗口標題定義的宏Mat g_srcImage, g_srcImage1,g_grayImage; int thresh = 30; //當前閾值 int max_thresh = 175; //最大閾值int main() {// 1、載入原始圖并進行克隆保存g_srcImage = imread("F:/C++/2. OPENCV 3.1.0/TEST/corner.jpg", 1 );if(!g_srcImage.data ) { printf("讀取圖片錯誤,請確定目錄下是否有imread函數指定的圖片存在~! \n"); return false; }imshow("原始圖",g_srcImage);g_srcImage1=g_srcImage.clone( );// 2、存留一張灰度圖cvtColor( g_srcImage1, g_grayImage, COLOR_BGR2GRAY );// 3、創建窗口和滾動條namedWindow( WINDOW_NAME1, WINDOW_AUTOSIZE );createTrackbar( "閾值: ", WINDOW_NAME1, &thresh, max_thresh, on_CornerHarris );on_CornerHarris( 0, 0 );waitKey(0);return 0; } void on_CornerHarris( int, void* ) {// 1、定義一些局部變量Mat dstImage;//目標圖Mat normImage;//歸一化后的圖Mat scaledImage;//線性變換后的八位無符號整型的圖// 2、初始化//置零當前需要顯示的兩幅圖,即清除上一次調用此函數時他們的值dstImage = Mat::zeros( g_srcImage.size(), CV_32FC1 );g_srcImage1=g_srcImage.clone( );// 3、正式檢測// 進行角點檢測// 領域大小為 2// sobel 算子孔徑 3// harris 參數cornerHarris( g_grayImage, dstImage, 2, 3, 0.04, BORDER_DEFAULT );// 歸一化與轉換normalize( dstImage, normImage, 0, 255, NORM_MINMAX, CV_32FC1, Mat() );convertScaleAbs( normImage, scaledImage ); //將歸一化后的圖線性變換成8位無符號整型// 4、進行繪制// 將檢測到的,且符合閾值條件的角點繪制出來int corner_count = 0;for( int j = 0; j < normImage.rows ; j++ )for( int i = 0; i < normImage.cols; i++ ){if( (int) normImage.at<float>(j,i) > thresh+80 ) // 設定閾值{circle( g_srcImage1, Point( i, j ), 5, Scalar(10,10,255), 2, 8, 0 );circle( scaledImage, Point( i, j ), 5, Scalar(0,10,255), 2, 8, 0 );}}cout<<"角點個數="<<corner_count<<endl;// 4、顯示最終效果imshow( WINDOW_NAME1, g_srcImage1 );imshow( WINDOW_NAME2, scaledImage ); }結果:
六、示例二:確定圖像強角點:Shi-Tomasi角點檢測,亞像素級角點檢測:cornerSubPix()函數
#include <opencv2/opencv.hpp>using namespace cv; using namespace std;#define WINDOW_NAME "【Shi-Tomasi角點檢測】" //為窗口標題定義的宏Mat g_srcImage, g_grayImage; int g_maxCornerNumber = 50; // 角點的最大數量 int g_maxTrackbarNumber = 500; int g_minDistance =10; RNG g_rng(12345);//初始化隨機數生成器int main() {// 1、載入原始圖并進行克隆保存 // g_srcImage = imread("F:/C++/2. OPENCV 3.1.0/TEST/corner2.jpg", 1 );g_srcImage = imread("F:/C++/2. OPENCV 3.1.0/TEST/test1.png", 1 );if(!g_srcImage.data ) { printf("讀取圖片錯誤,請確定目錄下是否有imread函數指定的圖片存在~! \n"); return false; }cvtColor( g_srcImage, g_grayImage, COLOR_BGR2GRAY );// 2、創建窗口和滑動條,并進行顯示和回調函數初始化namedWindow( WINDOW_NAME, WINDOW_AUTOSIZE );createTrackbar( "最大角點數", WINDOW_NAME, &g_maxCornerNumber, g_maxTrackbarNumber, on_GoodFeaturesToTrack );createTrackbar( "最小距離", WINDOW_NAME, &g_minDistance, 100, on_GoodFeaturesToTrack );imshow( "原始圖", g_srcImage );on_GoodFeaturesToTrack( 0, 0 );waitKey(0);return 0; } void on_GoodFeaturesToTrack( int, void* ) {// 1、對變量小于等于1時的處理if( g_maxCornerNumber <= 1 ){g_maxCornerNumber = 1;}// 2、Shi-Tomasi算法(goodFeaturesToTrack函數)的參數準備vector<Point2f> corners;double qualityLevel = 0.01;//角點檢測可接受的最小特征值int blockSize = 3;//計算導數自相關矩陣時指定的鄰域范圍double k = 0.04;//權重系數Mat copy = g_srcImage.clone(); //復制源圖像到一個臨時變量中,作為感興趣區域// 3、進行Shi-Tomasi角點檢測goodFeaturesToTrack( g_grayImage, // 輸入圖像corners, // 檢測到的角點的輸出向量g_maxCornerNumber, // 角點的最大數量qualityLevel, // 角點檢測可接受的最小特征值g_minDistance, // 角點之間的最小距離Mat(), // 感興趣區域blockSize, // 計算導數自相關矩陣時指定的鄰域范圍false, // 不使用Harris角點檢測k ); // 權重系數// 4、輸出文字信息cout<<"\t>此次檢測到的角點數量為:"<<corners.size()<<endl;// 5、繪制檢測到的角點int r = 4;for( int i = 0; i < corners.size(); i++ ){//以隨機的顏色繪制出角點circle( copy, corners[i], r, Scalar(g_rng.uniform(0,255), g_rng.uniform(0,255),g_rng.uniform(0,255)), -1, 8, 0 );}// 6、顯示(更新)窗口imshow( WINDOW_NAME, copy );// 7、亞像素角點檢測的參數設置Size winSize = Size( 5, 5 );Size zeroZone = Size( -1, -1 );// TermCriteria術語標準TermCriteria criteria = TermCriteria( TermCriteria::EPS + TermCriteria::MAX_ITER, 40, 0.001 );// 8、計算出亞像素角點位置vector<Point2f> corners_sub=corners;cornerSubPix( g_grayImage, corners_sub, winSize, zeroZone, criteria );// 9、輸出角點信息for( int i = 0; i < corners.size(); i++ ){cout<<" \t>>亞像素級/像素級 角點坐標["<<i<<"] ("<<corners_sub[i]<<")"<<" ("<<corners[i].x<<","<<corners[i].y<<")"<<endl;} }結果:
總結
以上是生活随笔為你收集整理的OpenCV学习(二十四 ):角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack()的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 有道翻译接口问题
- 下一篇: MATLAB(四)在高等数学中的应用