前面我們對sift算法的流程進行簡要研究,那么在OpenCV中,sift是如何被調用的?又是如何被實現出來的了?
特別是到了3.0以后,OpenCV對特征點提取這個方面進行了系統重構,那么整個代碼結構變成了什么模樣?
在代碼中
可以看出目前的結構是基於hess的算法進行的重構。那么首先需要解決的是整體的調用和實現結構問題,然后是hess算法的結構問題,再然后才是具體的算法。需要做的事情很多,
一起來研究。
一、OpenCV中sift調用接口和例子
首先是一定要編譯使用contrib版本的OpenCV代碼,同時最后設置的時候需要注意,
頭文件和命名空間要選擇正確。
在最新版本的OpenCV中,已經對特征提取這塊的函數進行了統一接口:
Mat matSrc
=
imread(
"e:/template/lena.jpg"
);
Mat gray;
Mat draw;
cvtColor( matSrc, gray, CV_RGB2GRAY );
Mat descriptors;
std : :vector <KeyPoint > keypoints;
// 生產sift結構
Ptr <SiftFeatureDetector > siftFD = SiftFeatureDetector : :create();
siftFD - >detectAndCompute(gray,Mat(),keypoints,draw);
drawKeypoints(gray,keypoints,gray,Scalar( 0, 0, 255),DrawMatchesFlags : :DEFAULT);
Mat draw;
cvtColor( matSrc, gray, CV_RGB2GRAY );
Mat descriptors;
std : :vector <KeyPoint > keypoints;
// 生產sift結構
Ptr <SiftFeatureDetector > siftFD = SiftFeatureDetector : :create();
siftFD - >detectAndCompute(gray,Mat(),keypoints,draw);
drawKeypoints(gray,keypoints,gray,Scalar( 0, 0, 255),DrawMatchesFlags : :DEFAULT);
結果:
這里也只是簡單地把特征點給畫了出來,並沒有將方向等信息進行表示。下面我們具體看一看sift在OpenCV中是如何實現的。
OpenCV是開發源代碼的,所以這里的代碼都是可以自己看到的。那么聯調的方式為
二、sift的代碼結構解析
注意,sift的原始地址在
它的類結構為:
它的構建函數為:
直接返回的是本類的指針
我們去看代碼,基本了解結構以后,就直接從我們想要用的那個函數開始“順藤摸瓜”。我們想要的是
detectAndCompute 函數。
三、sift的代碼具體實現
step0: createInitialImage 將圖片轉換成為合適的大小
Mat base = createInitialImage(image, firstOctave < 0, (float)sigma);
最為簡單的一步,據說將輸入的圖片變化為規整的大小和格式:
//step1: buildGaussianPyramid 構建高斯金字塔
buildGaussianPyramid(base, gpyr, nOctaves);
//step2: buildDoGPyramid 構建高斯差分金字塔
buildDoGPyramid(gpyr, dogpyr);
//step3: findScaleSpaceExtrema removeDuplicated 尋找並篩選尺度空間特征值
findScaleSpaceExtrema(gpyr, dogpyr, keypoints);
注意這里將特征值的初略尋找和細化尋找放在了一起(一個循環)
其中
其中二
注意:
//step4: calcDescriptors 計算特征值
calcDescriptors(gpyr, keypoints, descriptors, nOctaveLayers, firstOctave);
三、簡單小結
這里也只是將sift的代碼挑了出來,簡單進行了分析。應該說OpenCV的代碼本身才是其最為精髓的地方,無論是代碼背后的理論,還是代碼實現的技術,以及各種提升速度的方法,都對於我們寫出出色的圖像處理算法和運用很有幫助。
而學習的最好方法就是去實現創造。OpenCV本身就是開源的項目,基於現有的這么多的資源,在圖像處理廣闊的領域去進行創新,不斷鞏固提升自己的能力。與大家共勉!
