OpenCV SIFT特征学习:(一)初识SIFT

SIFT  (Scale Invariant Feature Transform)

        sift,尺度不变特征,通过检测空间域与尺度域上的局部极大值作为特征,常于图像特征匹配,应用领域为目标识别(匹配),图像融合,图像拼接,图像检索等。假设对一幅图像进行sift特征提取,得到N个sift特征点,每个sift特征点的存储结构为128维的向量,则该图像的sift特征描述为N*128个向量。

       在OpenCV里,sift的提取主要使用一下语句:(注:头文件需包含#include 且在我的电脑上VS2012对于Opencv不是太友好,出现assertion fail***dbgheap.c***大概是堆的内存有问题之类的异常中断,后来换成VS2010就好了

 
    
cv::SiftFeatureDetector siftdtc; //构造sift检测器
std::vector<cv::KeyPoint> kp1; //存储sift特征keypoints的向量
siftdtc.detect(image,kp1); //检测image的sift特征,并将特征存于向量kp1中
drawKeypoints(image,kp1,out); //画特征点在cv::Mat out上
cv::imshow("out",out);

  生成这一图像是不是有些许成就感了?接下来分析下opencv的代码:
OpenCV SIFT特征学习:(一)初识SIFT_第1张图片

1.首先构造sift检测器使用的类SiftFeatureDetector的有两个重载函数,第二个重载中的参数double threshold,double edgeThreshold 分别代表特征的阈值和用于降低直线敏感度的阈值,后几个参数则是在在构造sift特征时使用图像金字塔构造DoG(difference of Gaussians)尺度空间的一些参数,即图像金字塔共分为nOctaves组,每组有nOctaveLayers层

 
    
SiftFeatureDetector(
const SIFT::DetectorParams& detectorParams=SIFT::DetectorParams(),
const SIFT::CommonParams& commonParams=SIFT::CommonParams() );
SiftFeatureDetector( double threshold, double edgeThreshold,
int nOctaves=SIFT::CommonParams::DEFAULT_NOCTAVES,
int nOctaveLayers=SIFT::CommonParams::DEFAULT_NOCTAVE_LAYERS,
int =SIFT::CommonParams::DEFAULT_FIRST_OCTAVE,
int angleMode=SIFT::CommonParams::FIRST_ANGLE );
2.如何存储sift特征?上述代码将sift特征存于vector这一类结构。keypoint是OpenCV自定义的一类数据结构,如下(参考某大神的博客):
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
angle:角度,表示关键点的方向,通过Lowe大神的论文可以知道,为了保证方向不变形,SIFT算法通过对关键点周围邻域进行梯度运算,求得该点方向。-1为初值。
class_id:当要对图片进行分类时,我们可以用class_id对每个特征点进行区分,未设定时为-1,需要靠自己设定
octave:代表是从金字塔哪一层提取的得到的数据。
pt:关键点点的坐标
response:响应程度,代表该点强壮大小,一开始我也理解不了,看到两位stackoverflow大大的原话(http://stackoverflow.com/questions/10328298/what-does-size-and-response-exactly-represent-in-a-surf-keypointhttp://stackoverflow.com/questions/24699495/opencv-keypoints-response-greater-or-less?lq=1)——response代表着该关键点how good,更确切的说,是该点角点的程度。瞬间明白。
size:该点直径的大小
来源: <opencv中keypoint数据结构分析 - 77695 - 博客园>
--------------------------------------------------------------------------------------------------------------------------------------------------------------------根据以上查看程序中的keypoint:图中共有1148个keypoint,
OpenCV SIFT特征学习:(一)初识SIFT_第2张图片

3.如何把特征点给画出来?使用drawKeypoints函数
 
    
void drawKeypoints(const Mat& image, const vector<KeyPoint>& keypoints, Mat& outImg, const Scalar& color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT )
Parameters:
image Source image.
keypoints Keypoints from the source image.
outImg Output image. Its content depends on the flags value defining what is drawn in the output image. See possible flags bit values below.
color Color of keypoints.
flags Flags setting drawing features. Possible flags bit values are defined by DrawMatchesFlags. See details above in drawMatches()
 
     
flags:
DEFAULT = 0, // 创建输出的图像;在画匹配时,两张图像,匹配线以及点都会画出;特征点之画出圆
//Output image matrix will be created (Mat::create), i.e. existing memory of output image may be reused.
// Two source images, matches, and single keypoints will be drawn.
// For each keypoint, only the center point will be drawn (without a circle around the keypoint with the
// keypoint size and orientation).
DRAW_OVER_OUTIMG = 1 , // Output image matrix will not be (不创建输出图像,匹配线在现存的output image中画出)
// created (using Mat::create). Matches will be drawn
// on existing content of output image.
NOT_DRAW_SINGLE_POINTS = 2 , // Single keypoints will not be drawn.
DRAW_RICH_KEYPOINTS = 4 // For each keypoint, the circle around (keypoint画出大小以及方向)
// keypoint with keypoint size and orientation will
// be drawn.
将运行代码例子的drawKeypoints函数改成: drawKeypoints (image,kp1,out,Scalar::all(-1),4);,得到下图,可以看到此时特征点已经有大小与向量了

   OpenCV SIFT特征学习:(一)初识SIFT_第3张图片 
4. 现在有一个问题,上文说sift特征点的向量是128维的,而cv::keyPoints只有6个维度,为什么呢?以下还是上面那个大神的回答: keypoint只是保存了opencv的sift库检测到的特征点的一些基本信息,但sift所提取出来的特征向量其实不是在这个里面,特征向量通过SiftDescriptorExtractor 提取,结果放在一个Mat的数据结构中。这个数据结构才真正保存了该特征点所对应的特征向量。( http://www.cnblogs.com/cj695/p/4041478.html )。代码示例如下:
 
     
SiftDescriptorExtractor extractor;
Mat descriptor1;
extractor.compute(image,kp1,descriptor1);
imshow("desc",descriptor1);
 OpenCV SIFT特征学习:(一)初识SIFT_第4张图片OpenCV SIFT特征学习:(一)初识SIFT_第5张图片

你可能感兴趣的:(图像特征,C++,CV)