1. 程式人生 > >SURF特徵點檢測(閾值和繪點方式均可通過滾動條調節)

SURF特徵點檢測(閾值和繪點方式均可通過滾動條調節)



       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"    );
}

程式效果如下:

提示資訊及原圖:

特徵檢測效果圖: