一、理论知识
Scale Invariant Feature Transform,尺度不变特征变换匹配算法,对于算法的理论介绍,可以参考这篇文章http://blog.csdn.net/qq_20823641/article/details/51692415,里面很详细,可以更好的学习。这里就不多介绍。后面就挑选重点的来说
二、SIFT 主要思想
SIFT算法是一种提取局部特征的算法,在尺度空间寻找极值点,提取位置,尺度,旋转不变量。
三、SIFT算法的主要特点:
a) SIFT特征是图像的局部特征,其对旋转、尺度缩放、亮度变化保持不变性,对视角变化、仿射变换、噪声也保持一定程度的稳定性。
b) 独特性(Distinctiveness)好,信息量丰富,适用于在海量特征数据库中进行快速、准确的匹配[23]。
c) 多量性,即使少数的几个物体也可以产生大量SIFT特征向量。
d) 高速性,经优化的SIFT匹配算法甚至可以达到实时的要求。
e) 可扩展性,可以很方便的与其他形式的特征向量进行联合。
四、SIFT算法步骤:
1)检测尺度空间极值点
2)精确定位极值点
3)为每个关键点指定方向参数
4)关键点描述子的生成
五、程序过程
- 使用SiftFeatureDetector的detect方法检测特征存入一个向量里,并使用drawKeypoints在图中标识出来
- SiftDescriptorExtractor 的compute方法提取特征描述符,特征描述符是一个矩阵
- 使用匹配器matcher对描述符进行匹配,匹配结果保存由DMatch的组成的向量里
- 设置距离阈值,使得匹配的向量距离小于最小距离的2被才能进入最终的结果,用DrawMatch可以显示
六、函数简介
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层图像高斯滤波系数,也就是σ。
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,只计算图像特征描述
<p>class keyPoint{<span style="font-family: Arial;">Point2f pt;</span><span style="font-family: Arial;">float size;</span><span style="font-family: Arial;">float angle;</span><span style="font-family: Arial;">float response;i</span><span style="font-family: Arial;">nt octave;</span><span style="font-family: Arial;">int class_id;</span><span style="font-family: Arial;">}</span></p>
<span style="font-size:18px;">void drawMatches(const Mat&img1, const vector<KeyPoint>&keypoints1, const Mat&img2, const vector<KeyPoint>&keypoints2, const vector<DMatch>&matches1to2, Mat&outImg, const Scalar&matchColor=Scalar::all(-1), const Scalar&singlePointColor=Scalar::all(-1), const vector<char>&matchesMask=vector<char>(), intflags=DrawMatchesFlags::DEFAULT)</span>
Parameters: |
|
---|
七、函数注意事项
1.生成一个SiftFeatureDetector的对象,这个对象顾名思义就是SIFT特征的探测器,用它来探测衣服图片中SIFT点的特征,存到一个KeyPoint类型的vector中,keypoint只是保存了opencv的sift库检测到的特征点的一些基本信息,但sift所提取出来的特征向量其实不是在这个里面,特征向量通过SiftDescriptorExtractor
提取,结果放在一个Mat的数据结构中。这个数据结构才真正保存了该特征点所对应的特征向量。
2.keypoint只是达到了关键点的位置,方向等信息,并无该特征点的特征向量,要想提取得到特征向量就还要进行SiftDescriptorExtractor 的工作,建立了SiftDescriptorExtractor 对象后,通过该对象,对之前SIFT产生的特征点进行遍历,找到该特征点所对应的128维特征向量
八、示例
<span style="font-size:18px;">#include <opencv2/opencv.hpp> #include <opencv2/features2d/features2d.hpp> #include<opencv2/nonfree/nonfree.hpp> #include<opencv2/legacy/legacy.hpp> #include<vector> using namespace std; using namespace cv; int main(int argc,uchar* argv[]) { const char* imagename = "hand1.jpg"; //从文件中读入图像 Mat img = imread(imagename); Mat img2=imread("hand3.jpg"); //如果读入图像失败 if(img.empty()) { fprintf(stderr, "Can not load image %s\n", imagename); return -1; } if(img2.empty()) { fprintf(stderr, "Can not load image %s\n", imagename); return -1; } //显示图像 imshow("image before", img); imshow("image2 before",img2); //sift特征检测 SiftFeatureDetector siftdtc; vector<KeyPoint>kp1,kp2; siftdtc.detect(img,kp1); Mat outimg1; drawKeypoints(img,kp1,outimg1); imshow("image1 keypoints",outimg1); KeyPoint kp; siftdtc.detect(img2,kp2); Mat outimg2; drawKeypoints(img2,kp2,outimg2); imshow("image2 keypoints",outimg2); SiftDescriptorExtractor extractor; Mat descriptor1,descriptor2; BruteForceMatcher<L2<float>> matcher; vector<DMatch> matches; Mat img_matches; extractor.compute(img,kp1,descriptor1); extractor.compute(img2,kp2,descriptor2); matcher.match(descriptor1,descriptor2,matches); drawMatches(img,kp1,img2,kp2,matches,img_matches); imshow("matches",img_matches); //此函数等待按键,按键盘任意键就返回 waitKey(); return 0; }</span>
九、matlab
Demo Software: SIFT Keypoint Detector 代码参考大牛的,网址如下
http://www.cs.ubc.ca/~lowe/keypoints/
i1=imread('hand1.jpg'); i2=imread('hand3.jpg'); i11=rgb2gray(i1); i22=rgb2gray(i2); imwrite(i11,'v1.jpg','quality',80); imwrite(i22,'v2.jpg','quality',80); match('v1.jpg','v2.jpg');
http://www.cnblogs.com/cj695/p/4041478.html
http://blog.csdn.net/xiaowei_cqu/article/details/8069548
图像识别算法交流 QQ群:145076161,欢迎图像识别与图像算法,共同学习与交流