SIFT特征提取步骤:
http://blog.csdn.net/abcjennifer/article/details/7639681
(1)构建金字塔尺度图
(2)获取特征点(极值点)
(3)去除不好的特征点
(4)对每个特征点计算128维参数
(5)特征点match
1.首先需要介绍一下DOG(高斯差分卷积)
2.极值点:若像素点是其相邻像素点(相邻层的像素点也算,一共28个)的极大值或者极小值,则该点位特征点。
3.不好的点的去除:这里使用Harris Corners检测器
1)根据泰勒展开式求极值点,根据阈值判断是否可以留下来
2)边界响应的去除:根据Hessian矩阵去除。
4.计算内个特征点周围16*16矩阵内的像素点的梯度方向和梯度模,再将该16*16矩阵划分为4*4的子矩阵,共16个。
这样就可以对每个feature形成一个4*4*8=128维的描述子,每一维都可以表示4*4个格子中一个的scale/orientation. 将这个向量归一化之后,就进一步去除了光照的影响。
- match :根据来那个户图像特征点的欧氏距离进行匹配。
c代码实现
// FeatureDetector.cpp : Defines the entry point for the console application.
//
// Created by Rachel on 14-1-12.
// Copyright (c) 2013年 ZJU. All rights reserved.
//
#include "stdafx.h"
#include "highgui.h"
#include "cv.h"
#include "vector"
#include "opencv\cxcore.hpp"
#include "iostream"
#include "opencv.hpp"
#include "nonfree.hpp"
#include "showhelper.h"
using namespace cv;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
//Load Image
Mat c_src1 = imread( "..\\Images\\3.jpg");
Mat c_src2 = imread("..\\Images\\4.jpg");
Mat src1 = imread( "..\\Images\\3.jpg", CV_LOAD_IMAGE_GRAYSCALE);
Mat src2 = imread( "..\\Images\\4.jpg", CV_LOAD_IMAGE_GRAYSCALE);
if( !src1.data || !src2.data )
{ std::cout<< " --(!) Error reading images " << std::endl; return -1; }
//sift feature detect
SiftFeatureDetector detector;
std::vector<KeyPoint> kp1, kp2;
detector.detect( src1, kp1 );
detector.detect( src2, kp2 );
SiftDescriptorExtractor extractor;
Mat des1,des2;//descriptor
extractor.compute(src1,kp1,des1);
extractor.compute(src2,kp2,des2);
Mat res1,res2;
int drawmode = DrawMatchesFlags::DRAW_RICH_KEYPOINTS;
drawKeypoints(c_src1,kp1,res1,Scalar::all(-1),drawmode);//在内存中画出特征点
drawKeypoints(c_src2,kp2,res2,Scalar::all(-1),drawmode);
cout<<"size of description of Img1: "<<kp1.size()<<endl;
cout<<"size of description of Img2: "<<kp2.size()<<endl;
//write the size of features on picture
CvFont font;
double hScale=1;
double vScale=1;
int lineWidth=2;// 相当于写字的线条
cvInitFont(&font,CV_FONT_HERSHEY_SIMPLEX|CV_FONT_ITALIC, hScale,vScale,0,lineWidth);//初始化字体,准备写到图片上的
// cvPoint 为起笔的x,y坐标
IplImage* transimg1 = cvCloneImage(&(IplImage) res1);
IplImage* transimg2 = cvCloneImage(&(IplImage) res2);
char str1[20],str2[20];
sprintf(str1,"%d",kp1.size());
sprintf(str2,"%d",kp2.size());
const char* str = str1;
cvPutText(transimg1,str1,cvPoint(280,230),&font,CV_RGB(255,0,0));//在图片中输出字符
str = str2;
cvPutText(transimg2,str2,cvPoint(280,230),&font,CV_RGB(255,0,0));//在图片中输出字符
//imshow("Description 1",res1);
cvShowImage("descriptor1",transimg1);
cvShowImage("descriptor2",transimg2);
BFMatcher matcher(NORM_L2);
vector<DMatch> matches;
matcher.match(des1,des2,matches);
Mat img_match;
drawMatches(src1,kp1,src2,kp2,matches,img_match);//,Scalar::all(-1),Scalar::all(-1),vector<char>(),drawmode);
cout<<"number of matched points: "<<matches.size()<<endl;
imshow("matches",img_match);
cvWaitKey();
cvDestroyAllWindows();
return 0;
}