您的位置:首页 > 运维架构

OpenCV2.4.4中调用SIFT特征检测器进行图像匹配

2015-01-16 22:51 537 查看
OpenCV中一些相关结构说明:

特征点类:

查看文本打印?

class KeyPoint

{

Point2f pt; //坐标

float size; //<strong>特征</strong>点邻域直径

float angle; //<strong>特征</strong>点的方向,值为[0,360),负值表示不使用

float response; //

int octave; //<strong>特征</strong>点所在的<strong>图像</strong>金字塔的组

int class_id; //用于聚类的id

}

存放匹配结果的结构:

查看文本打印?

struct DMatch

{

//三个构造函数

DMatch(): queryIdx(-1), trainIdx(-1),imgIdx(-1),distance(std::numeric_limits<float>::max()) {}

DMatch(int _queryIdx, int _trainIdx, float _distance ) :

queryIdx( _queryIdx),trainIdx( _trainIdx), imgIdx(-1),distance( _distance) {}

DMatch(int _queryIdx, int _trainIdx, int _imgIdx, float _distance ) :

queryIdx(_queryIdx), trainIdx( _trainIdx), imgIdx( _imgIdx),distance( _distance) {}

intqueryIdx; //此<strong>匹配</strong>对应的查询<strong>图像</strong>的<strong>特征</strong>描述子索引

inttrainIdx; //此<strong>匹配</strong>对应的训练(模板)<strong>图像</strong>的<strong>特征</strong>描述子索引

intimgIdx; //训练<strong>图像</strong>的索引(若有多个)

float distance; //两个<strong>特征</strong>向量之间的欧氏距离,越小表明<strong>匹配</strong>度越高。

booloperator < (const DMatch &m) const;

};

说明:以两个特征点描述子(特征向量)之间的欧氏距离作为特征匹配的相似度准则,假设特征点对p和q的

特征描述子分别为Desp和Desq,则其欧氏距离定义为:



所以每个匹配分别对应训练图像(train)和查询图像(query)中的一个特征描述子(特征向量)。

查看文本打印?

#include "opencv2/highgui/highgui.hpp"

#include "opencv2/imgproc/imgproc.hpp"

#include "opencv2/nonfree/nonfree.hpp"

#include "opencv2/nonfree/features2d.hpp"

#include <iostream>

#include <stdio.h>

#include <stdlib.h>

using namespace cv;

using namespace std;

int main()

{

initModule_nonfree();//初始化模块,使用SIFT或SURF时用到

Ptr<FeatureDetector> detector = FeatureDetector::create( "SIFT" );//创建SIFT<strong>特征</strong><strong>检测器</strong>

Ptr<DescriptorExtractor> descriptor_extractor = DescriptorExtractor::create( "SIFT" );//创建<strong>特征</strong>向量生成器

Ptr<DescriptorMatcher> descriptor_matcher = DescriptorMatcher::create( "BruteForce" );//创建<strong>特征</strong><strong>匹配</strong>器

if( detector.empty() || descriptor_extractor.empty() )

cout<<"fail to create detector!";

//读入<strong>图像</strong>

Mat img1 = imread("desk.jpg");

Mat img2 = imread("desk_glue.jpg");

//<strong>特征</strong>点检测

double t = getTickCount();//当前滴答数

vector<KeyPoint> keypoints1,keypoints2;

detector->detect( img1, keypoints1 );//检测img1中的SIFT<strong>特征</strong>点,存储到keypoints1中

detector->detect( img2, keypoints2 );

cout<<"<strong>图像</strong>1<strong>特征</strong>点个数:"<<keypoints1.size()<<endl;

cout<<"<strong>图像</strong>2<strong>特征</strong>点个数:"<<keypoints2.size()<<endl;

//根据<strong>特征</strong>点计算<strong>特征</strong>描述子矩阵,即<strong>特征</strong>向量矩阵

Mat descriptors1,descriptors2;

descriptor_extractor->compute( img1, keypoints1, descriptors1 );

descriptor_extractor->compute( img2, keypoints2, descriptors2 );

t = ((double)getTickCount() - t)/getTickFrequency();

cout<<"SIFT算法用时:"<<t<<"秒"<<endl;

cout<<"<strong>图像</strong>1<strong>特征</strong>描述矩阵大小:"<<descriptors1.size()

<<",<strong>特征</strong>向量个数:"<<descriptors1.rows<<",维数:"<<descriptors1.cols<<endl;

cout<<"<strong>图像</strong>2<strong>特征</strong>描述矩阵大小:"<<descriptors2.size()

<<",<strong>特征</strong>向量个数:"<<descriptors2.rows<<",维数:"<<descriptors2.cols<<endl;

//画出<strong>特征</strong>点

Mat img_keypoints1,img_keypoints2;

drawKeypoints(img1,keypoints1,img_keypoints1,Scalar::all(-1),0);

drawKeypoints(img2,keypoints2,img_keypoints2,Scalar::all(-1),0);

//imshow("Src1",img_keypoints1);

//imshow("Src2",img_keypoints2);

//<strong>特征</strong><strong>匹配</strong>

vector<DMatch> matches;//<strong>匹配</strong>结果

descriptor_matcher->match( descriptors1, descriptors2, matches );//<strong>匹配</strong>两个<strong>图像</strong>的<strong>特征</strong>矩阵

cout<<"Match个数:"<<matches.size()<<endl;

//计算<strong>匹配</strong>结果中距离的最大和最小值

//距离是指两个<strong>特征</strong>向量间的欧式距离,表明两个<strong>特征</strong>的差异,值越小表明两个<strong>特征</strong>点越接近

double max_dist = 0;

double min_dist = 100;

for(int i=0; i<matches.size(); i++)

{

double dist = matches[i].distance;

if(dist < min_dist) min_dist = dist;

if(dist > max_dist) max_dist = dist;

}

cout<<"最大距离:"<<max_dist<<endl;

cout<<"最小距离:"<<min_dist<<endl;

//筛选出较好的<strong>匹配</strong>点

vector<DMatch> goodMatches;

for(int i=0; i<matches.size(); i++)

{

if(matches[i].distance < 0.31 * max_dist)

{

goodMatches.push_back(matches[i]);

}

}

cout<<"goodMatch个数:"<<goodMatches.size()<<endl;

//画出<strong>匹配</strong>结果

Mat img_matches;

//红色连接的是<strong>匹配</strong>的<strong>特征</strong>点对,绿色是未<strong>匹配</strong>的<strong>特征</strong>点

drawMatches(img1,keypoints1,img2,keypoints2,goodMatches,img_matches,

Scalar::all(-1)/*CV_RGB(255,0,0)*/,CV_RGB(0,255,0),Mat(),2);

imshow("MatchSIFT",img_matches);

waitKey(0);

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: