日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

SIFT原理与源码分析

發(fā)布時間:2025/3/21 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SIFT原理与源码分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

SIFT簡介

Scale Invariant Feature Transform,尺度不變特征變換匹配算法,是由David G. Lowe在1999年(《Object Recognition from Local Scale-Invariant Features》)提出的高效區(qū)域檢測算法,在2004年(《Distinctive Image Features from Scale-Invariant Keypoints》)得以完善。

SIFT特征對旋轉、尺度縮放、亮度變化等保持不變性,是非常穩(wěn)定的局部特征,現(xiàn)在應用很廣泛。而SIFT算法是將Blob檢測,特征矢量生成,特征匹配搜索等步驟結合在一起優(yōu)化。我會更新一系列文章,分析SIFT算法原理及OpenCV 2.4.2實現(xiàn)的SIFT源碼:

  • DoG尺度空間構造(Scale-space extrema detection)
  • 關鍵點搜索與定位(Keypoint localization)
  • 方向賦值(Orientation assignment)
  • 關鍵點描述(Keypoint descriptor)
  • OpenCV實現(xiàn):特征檢測器FeatureDetector
  • SIFT中LoG和DoG的比較
  • OpenCV2.3之后實現(xiàn)了SIFT的代碼,2.4改掉了一些bug。本系列文章主要分析OpenCV 2.4.2SIFT函數(shù)源碼。 SIFT位于OpenCV nonfree的模塊,David G. Lowe申請了算法的版權,請尊重作者權力,務必在允許范圍內(nèi)使用。

    SIFT in OpenCV

    OpenCV中的SIFT函數(shù)主要有兩個接口。

    構造函數(shù):

    [cpp]?view plaincopy
  • SIFT::SIFT(int?nfeatures=0,?int?nOctaveLayers=3,?double?contrastThreshold=0.04,?double?edgeThreshold=??
  • 10,?double?sigma=1.6)??
  • nfeatures:特征點數(shù)目(算法對檢測出的特征點排名,返回最好的nfeatures個特征點)。
    nOctaveLayers:金字塔中每組的層數(shù)(算法中會自己計算這個值,后面會介紹)。
    contrastThreshold:過濾掉較差的特征點的對閾值。contrastThreshold越大,返回的特征點越少。
    edgeThreshold:過濾掉邊緣效應的閾值。edgeThreshold越大,特征點越多(被多濾掉的越少)。
    sigma:金字塔第0層圖像高斯濾波系數(shù),也就是σ。

    重載操作符:

    [cpp]?view plaincopy
  • void?SIFT::operator()(InputArray?img,?InputArray?mask,?vector<KeyPoint>&?keypoints,?OutputArray??
  • descriptors,?bool?useProvidedKeypoints=false)??

  • img:8bit灰度圖像
    mask:圖像檢測區(qū)域(可選)
    keypoints:特征向量矩陣
    descipotors:特征點描述的輸出向量(如果不需要輸出,需要傳cv::noArray())。
    useProvidedKeypoints:是否進行特征點檢測。ture,則檢測特征點;false,只計算圖像特征描述。

    函數(shù)源碼

    構造函數(shù)SIFT()主要用來初始化參數(shù),并沒有特定的操作: [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)??
  • ????//?sigma:對第0層進行高斯模糊的尺度空間因子。??
  • ????//?默認為1.6(如果是軟鏡攝像頭捕獲的圖像,可以適當減小此值)??
  • {??
  • }??

  • 主要操作還是利用重載操作符()來執(zhí)行: [cpp]?view plaincopy
  • void?SIFT::operator()(InputArray?_image,?InputArray?_mask,??
  • ??????????????????????vector<KeyPoint>&?keypoints,??
  • ??????????????????????OutputArray?_descriptors,??
  • ??????????????????????bool?useProvidedKeypoints)?const??
  • //?mask?:Optional?input?mask?that?marks?the?regions?where?we?should?detect?features.??
  • //?Boolean?flag.?If?it?is?true,?the?keypoint?detector?is?not?run.?Instead,??
  • //?the?provided?vector?of?keypoints?is?used?and?the?algorithm?just?computes?their?descriptors.??
  • //?descriptors?–?The?output?matrix?of?descriptors.??
  • //?Pass?cv::noArray()?if?you?do?not?need?them.??????????????
  • {??
  • ????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)"?);??
  • ??
  • ??????????
  • ????//?得到第1組(Octave)圖像??
  • ????Mat?base?=?createInitialImage(image,?false,?(float)sigma);??
  • ????vector<Mat>?gpyr,?dogpyr;??
  • ????//?每層金字塔圖像的組數(shù)(Octave)??
  • ????int?nOctaves?=?cvRound(log(?(double)std::min(?base.cols,?base.rows?)?)?/?log(2.)?-?2);??
  • ??
  • ????//?double?t,?tf?=?getTickFrequency();??
  • ????//?t?=?(double)getTickCount();??
  • ??????
  • ????//?構建金字塔(金字塔層數(shù)和組數(shù)相等)??
  • ????buildGaussianPyramid(base,?gpyr,?nOctaves);??
  • ????//?構建高斯差分金字塔??
  • ????buildDoGPyramid(gpyr,?dogpyr);??
  • ??
  • ????//t?=?(double)getTickCount()?-?t;??
  • ????//printf("pyramid?construction?time:?%g\n",?t*1000./tf);??
  • ??????
  • ????//?useProvidedKeypoints默認為false??
  • ????//?使用keypoints并計算特征點的描述符??
  • ????if(?!useProvidedKeypoints?)??
  • ????{??
  • ????????//t?=?(double)getTickCount();??
  • ????????findScaleSpaceExtrema(gpyr,?dogpyr,?keypoints);??
  • ????????//除去重復特征點??
  • ????????KeyPointsFilter::removeDuplicated(?keypoints?);???
  • ??
  • ????????//?mask標記檢測區(qū)域(可選)??
  • ????????if(?!mask.empty()?)??
  • ????????????KeyPointsFilter::runByPixelsMask(?keypoints,?mask?);??
  • ??
  • ????????//?retainBest:根據(jù)相應保留指定數(shù)目的特征點(features2d.hpp)??
  • ????????if(?nfeatures?>?0?)??
  • ????????????KeyPointsFilter::retainBest(keypoints,?nfeatures);??
  • ????????//t?=?(double)getTickCount()?-?t;??
  • ????????//printf("keypoint?detection?time:?%g\n",?t*1000./tf);??
  • ????}??
  • ????else??
  • ????{??
  • ????????//?filter?keypoints?by?mask??
  • ????????//?KeyPointsFilter::runByPixelsMask(?keypoints,?mask?);??
  • ????}??
  • ??
  • ????//?特征點輸出數(shù)組??
  • ????if(?_descriptors.needed()?)??
  • ????{??
  • ????????//t?=?(double)getTickCount();??
  • ????????int?dsize?=?descriptorSize();??
  • ????????_descriptors.create((int)keypoints.size(),?dsize,?CV_32F);??
  • ????????Mat?descriptors?=?_descriptors.getMat();??
  • ??
  • ????????calcDescriptors(gpyr,?keypoints,?descriptors,?nOctaveLayers);??
  • ????????//t?=?(double)getTickCount()?-?t;??
  • ????????//printf("descriptor?extraction?time:?%g\n",?t*1000./tf);??
  • ????}??
  • }??

  • 函數(shù)中用到的構造金字塔:?buildGaussianPyramid(base, gpyr, nOctaves);等步驟請參見文章后續(xù)系列。

    (轉載請注明作者和出處:http://blog.csdn.net/xiaowei_cqu?未經(jīng)允許請勿用于商業(yè)用途)

    總結

    以上是生活随笔為你收集整理的SIFT原理与源码分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。