生活随笔
收集整理的這篇文章主要介紹了
SIFT原理与源码分析
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
SIFT簡介
Scale Invariant Feature Transform,尺度不變特征變換匹配算法,是由David G. Lowe在1999年(《Object Recognition from Local Scale-Invariant Features》)提出的高效區域檢測算法,在2004年(《Distinctive Image Features from Scale-Invariant Keypoints》)得以完善。
SIFT特征對旋轉、尺度縮放、亮度變化等保持不變性,是非常穩定的局部特征,現在應用很廣泛。而SIFT算法是將Blob檢測,特征矢量生成,特征匹配搜索等步驟結合在一起優化。我會更新一系列文章,分析SIFT算法原理及OpenCV 2.4.2實現的SIFT源碼:
DoG尺度空間構造(Scale-space extrema detection) 關鍵點搜索與定位(Keypoint localization) 方向賦值(Orientation assignment) 關鍵點描述(Keypoint descriptor) OpenCV實現:特征檢測器FeatureDetector SIFT中LoG和DoG的比較
OpenCV2.3之后實現了SIFT的代碼,2.4改掉了一些bug。本系列文章主要分析OpenCV 2.4.2SIFT函數源碼。
SIFT位于OpenCV nonfree的模塊,David G. Lowe申請了算法的版權,請尊重作者權力,務必在允許范圍內使用。
SIFT in OpenCV
OpenCV中的SIFT函數主要有兩個接口。
構造函數:
[cpp] ?view plaincopy
SIFT::SIFT( int ?nfeatures=0,? int ?nOctaveLayers=3,? double ?contrastThreshold=0.04,? double ?edgeThreshold=?? 10,?double ?sigma=1.6)?? nfeatures: 特征點數目(算法對檢測出的特征點排名,返回最好的nfeatures個特征點)。
nOctaveLayers: 金字塔中每組的層數(算法中會自己計算這個值,后面會介紹)。
contrastThreshold: 過濾掉較差的特征點的對閾值。contrastThreshold越大,返回的特征點越少。
edgeThreshold: 過濾掉邊緣效應的閾值。edgeThreshold越大,特征點越多(被多濾掉的越少)。
sigma: 金字塔第0層圖像高斯濾波系數,也就是σ。
重載操作符:
[cpp] ?view plaincopy
void ?SIFT::operator()(InputArray?img,?InputArray?mask,?vector<KeyPoint>&?keypoints,?OutputArray?? descriptors,?bool ?useProvidedKeypoints= false )?? img: 8bit灰度圖像
mask: 圖像檢測區域(可選)
keypoints: 特征向量矩陣
descipotors: 特征點描述的輸出向量(如果不需要輸出,需要傳cv::noArray())。
useProvidedKeypoints: 是否進行特征點檢測。ture,則檢測特征點;false,只計算圖像特征描述。
函數源碼
構造函數SIFT()主要用來初始化參數,并沒有特定的操作:
[cpp] ?view plaincopy
SIFT::SIFT(? int ?_nfeatures,? int ?_nOctaveLayers,?? ???????????double ?_contrastThreshold,? double ?_edgeThreshold,? double ?_sigma?)?? ????:?nfeatures(_nfeatures),?nOctaveLayers(_nOctaveLayers),?? ????contrastThreshold(_contrastThreshold),?edgeThreshold(_edgeThreshold),?sigma(_sigma)?? ?????? ?????? {?? }?? 主要操作還是利用重載操作符()來執行:
[cpp] ?view plaincopy
void ?SIFT::operator()(InputArray?_image,?InputArray?_mask,?? ??????????????????????vector<KeyPoint>&?keypoints,?? ??????????????????????OutputArray?_descriptors,?? ??????????????????????bool ?useProvidedKeypoints)? const ?? ?? ?? ?? ?? ?? {?? ????Mat?image?=?_image.getMat(),?mask?=?_mask.getMat();?? ?? ????if (?image.empty()?||?image.depth()?!=?CV_8U?)?? ????????CV_Error(?CV_StsBadArg,?"image?is?empty?or?has?incorrect?depth?(!=CV_8U)" ?);?? ?? ????if (?!mask.empty()?&&?mask.type()?!=?CV_8UC1?)?? ????????CV_Error(?CV_StsBadArg,?"mask?has?incorrect?type?(!=CV_8UC1)" ?);?? ?? ?????????? ?????? ????Mat?base?=?createInitialImage(image,?false ,?( float )sigma);?? ????vector<Mat>?gpyr,?dogpyr;?? ?????? ????int ?nOctaves?=?cvRound(log(?( double )std::min(?base.cols,?base.rows?)?)?/?log(2.)?-?2);?? ?? ?????? ?????? ?????? ?????? ????buildGaussianPyramid(base,?gpyr,?nOctaves);?? ?????? ????buildDoGPyramid(gpyr,?dogpyr);?? ?? ?????? ?????? ?????? ?????? ?????? ????if (?!useProvidedKeypoints?)?? ????{?? ?????????? ????????findScaleSpaceExtrema(gpyr,?dogpyr,?keypoints);?? ?????????? ????????KeyPointsFilter::removeDuplicated(?keypoints?);??? ?? ?????????? ????????if (?!mask.empty()?)?? ????????????KeyPointsFilter::runByPixelsMask(?keypoints,?mask?);?? ?? ?????????? ????????if (?nfeatures?>?0?)?? ????????????KeyPointsFilter::retainBest(keypoints,?nfeatures);?? ?????????? ?????????? ????}?? ????else ?? ????{?? ?????????? ?????????? ????}?? ?? ?????? ????if (?_descriptors.needed()?)?? ????{?? ?????????? ????????int ?dsize?=?descriptorSize();?? ????????_descriptors.create((int )keypoints.size(),?dsize,?CV_32F);?? ????????Mat?descriptors?=?_descriptors.getMat();?? ?? ????????calcDescriptors(gpyr,?keypoints,?descriptors,?nOctaveLayers);?? ?????????? ?????????? ????}?? }?? 函數中用到的構造金字塔:?buildGaussianPyramid(base, gpyr, nOctaves);等步驟請參見文章后續系列。
(轉載請注明作者和出處:http://blog.csdn.net/xiaowei_cqu?未經允許請勿用于商業用途)
總結
以上是生活随笔 為你收集整理的SIFT原理与源码分析 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。