SURF特徵點檢測(閾值和繪點方式均可通過滾動條調節)
阿新 • • 發佈:2019-01-04
SURF的原理我不再敘述,網上資料比較多。在計算視覺領域,尺度空間被象徵性的表述為一個影象金字塔,向下降取樣一般用高斯金字塔。其中,輸入影象函式反覆與高斯函式的核卷積並反覆對其進行二次抽樣,這種方法主要用於SIFT演算法的實現,但每層影象依賴於原影象,並且影象需要重設尺寸,因此,這種計算方法運算量較大。SURF角點檢測演算法是對SIFT的一種改進,主要體現在速度上,效率更高。它和SIFT的主要區別是影象多尺度空間的構建方法不同。SURF演算法對積分影象進行操作,卷積只和前一幅影象有關,其降取樣的方法是申請增加影象核的尺寸,這也是SIFT演算法與SURF演算法在使用金字塔原理方面的不同。SURF演算法允許尺度空間多層影象同時被處理,不需對影象進行二次抽樣,從而提高演算法效能。
在此我參考《OpenCV3程式設計入門》配套示例程式:SURF特徵點檢測,對該程式進行了一些修改,在原程式的SURF特徵點檢測的基礎上,添加了兩個滾動條來實現hessian閾值和繪點方式的動態調節。
程式碼如下:
//--------------------------------------【程式說明】------------------------------------------- // 程式說明:參考《OpenCV3程式設計入門》配套示例程式89 // 程式描述:SURF特徵點檢測 // 開發測試所用作業系統: Windows 7 32bit // 開發測試所用IDE版本:Visual Studio 2010 // 開發測試所用OpenCV版本: 2.4.10 //------------------------------------------------------------------------------------------------ //---------------------------------【標頭檔案、名稱空間包含部分】---------------------------- // 描述:包含程式所使用的標頭檔案和名稱空間 //------------------------------------------------------------------------------------------------ #include "opencv2/opencv.hpp" #include "opencv2/nonfree/nonfree.hpp" #include<opencv2/legacy/legacy.hpp> #include <iostream> using namespace cv; //-----------------------------------【全域性函式宣告部分】-------------------------------------- // 描述:全域性函式的宣告 //----------------------------------------------------------------------------------------------- static void ShowHelpText( );//輸出幫助文字 void on_surf(int,void*);//回撥函式 //-----------------------------------【全域性變數宣告部分】-------------------------------------- Mat srcImage1,srcImage2; int g_minHessian = 40;//定義SURF中的hessian閾值特徵點檢測運算元,閾值為:g_minHessian*10 int g_flags=0; //-----------------------------------【main( )函式】-------------------------------------------- // 描述:控制檯應用程式的入口函式,我們的程式從這裡開始執行 //----------------------------------------------------------------------------------------------- int main( int argc, char** argv ) { //【0】改變console字型顏色 system("color 2F"); //【0】顯示幫助文字 ShowHelpText( ); //【1】載入源圖片並顯示 srcImage1 = imread("1.jpg", 1 ); srcImage2 = imread("2.jpg", 1 ); if( !srcImage1.data || !srcImage2.data )//檢測是否讀取成功 { printf("讀取圖片錯誤,請確定目錄下是否有imread函式指定名稱的圖片存在~! \n"); return false; } imshow("原始圖1",srcImage1); imshow("原始圖2",srcImage2); createTrackbar("閾值/10","原始圖1",&g_minHessian,100,on_surf); createTrackbar("繪點方式","原始圖1",&g_flags,2,on_surf); on_surf(0,0); waitKey(0); return 0; } void on_surf(int,void*) { //【2】定義需要用到的變數和類 SurfFeatureDetector detector( g_minHessian*10 );//定義一個SurfFeatureDetector(SURF) 特徵檢測類物件 std::vector<KeyPoint> keypoints_1, keypoints_2;//vector模板類是能夠存放任意型別的動態陣列,能夠增加和壓縮資料 //【3】呼叫detect函式檢測出SURF特徵關鍵點,儲存在vector容器中 detector.detect( srcImage1, keypoints_1 ); detector.detect( srcImage2, keypoints_2 ); //【4】繪製特徵關鍵點. Mat img_keypoints_1; Mat img_keypoints_2; drawKeypoints( srcImage1, keypoints_1, img_keypoints_1, Scalar::all(-1), g_flags*2 ); drawKeypoints( srcImage2, keypoints_2, img_keypoints_2, Scalar::all(-1), g_flags*2 ); //【5】顯示效果圖 imshow("特徵點檢測效果圖1", img_keypoints_1 ); imshow("特徵點檢測效果圖2", img_keypoints_2 ); } //-----------------------------------【ShowHelpText( )函式】---------------------------------- // 描述:輸出一些幫助資訊 //---------------------------------------------------------------------------------------------- void ShowHelpText() { //輸出OpenCV版本 printf("\t\t\t 當前使用的OpenCV版本為:" CV_VERSION ); //輸出一些幫助資訊 printf("\n\n\t【SURF特徵點檢測】程式\n\n"); printf("\n\t該程式帶有兩個滾動條\n\n"); printf("\n\t滾動條1:SURF的hessian的閾值(實際閾值為該值的10倍)\n\n"); printf("\n\t滾動條2:繪製關鍵點的不同方式:\n\n" "\t\t0——對應DEFAULT方式\n\n" "\t\t1——對應NOT_DRAW_SINGLE_POINTS方式\n\n" "\t\t2——對應DRAW_RICH_KEYPOINTS方式\n\n"); printf( "\n\t按鍵操作說明: \n\n" "\t\t鍵盤按鍵任意鍵- 退出程式\n\n" ); }
程式效果如下:
提示資訊及原圖:
特徵檢測效果圖: