FeatureDetetor是opencv中的一个虚类,其在opencv中类的定义如下:
class CV_EXPORTS FeatureDetector
{
public:
virtual ~FeatureDetector();
void detect( const Mat& image, vector & keypoints,
const Mat& mask=Mat() ) const;
void detect( const vector & images,
vector<vector >& keypoints,
const vector & masks=vector () ) const;
virtual void read(const FileNode&);
virtual void write(FileStorage&) const;
static Ptr create( const string& detectorType );
protected:
...
};
通过定义FeatureDetector的对象可以使用多种特征检测方法。通过create()函数调用:
Ptr FeatureDetector::create(const string& detectorType);
/*
其中特征点类型有以下几种。"FAST" – "STAR" – "SIFT" – "SURF" – "ORB" – "BRISK" – "MSER" – "GFTT" – "HARRIS" – "Dense" – "SimpleBlob"
*/
也可以直接用单独的类名定义:
Ptr detector = 单独的类名::create();
/*
单独的类名有:FastFeatureDetector、StarFeatureDetector、SIFT (nonfree module)、SURF (nonfree module)、ORB、BRISK、MSER、GoodFeaturesToTrackDetector、GoodFeaturesToTrackDetector with Harris detector enabled、DenseFeatureDetector、SimpleBlobDetector
*/
其中生成的keypoint数据结构
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-keypoint,http://stackoverflow.com/questions/24699495/opencv-keypoints-response-greater-or-less?lq=1)——response代表着该关键点how good,更确切的说,是该点角点的程度。瞬间明白。
size:该点直径的大小 注意一个问题:keypoint只是保存了opencv的sift库检测到的特征点的一些基本信息,也就上面所说的这些,但sift所提取出来的特征向量其实不是在这个里面,特征向量通过SiftDescriptorExtractor 提取,结果放在一个Mat的数据结构中。这个数据结构才真正保存了该特征点所对应的特征向量。具体见后文对SiftDescriptorExtractor 所生成的对象的详解。
DescriptorExtractor
同上一个类一样,定义方法如下:
Ptr=DescriptorExtractor:: create("ExtractorType");
/*
ExtractorType有"SIFT" – "SURF" – "BRIEF" – "BRISK" – "ORB" – "FREAK"
*/
同上一个类一样,它也可直接调用每种类型的类名。方法如下:
Ptr<DescriptorExtractor> descriptor = 类名::create();
/*
类名有:FREAK、ORB、BRISK、SURF、BriefDescriptorExtractor、SIFT
*/
DescriptorMatcher是匹配特征向量的抽象类,在OpenCV2中的特征匹配方法都继承自该类(例如:BFmatcher,FlannBasedMatcher)。该类主要包含了两组匹配方法:图像对之间的匹配以及图像和一个图像集之间的匹配。
(1) 用于图像对之间匹配的方法的声明
// Find one best match for each query descriptor (if mask is empty).
CV_WRAP void match( const Mat& queryDescriptors, const Mat& trainDescriptors,
CV_OUT vector & matches, const Mat& mask=Mat() ) const;
// Find k best matches for each query descriptor (in increasing order of distances).
// compactResult is used when mask is not empty. If compactResult is false matches
// vector will have the same size as queryDescriptors rows. If compactResult is true
// matches vector will not contain matches for fully masked out query descriptors.
CV_WRAP void knnMatch( const Mat& queryDescriptors, const Mat& trainDescriptors,
CV_OUT vector<vector >& matches, int k,const Mat& mask=Mat(), bool compactResult=false ) const;
// Find best matches for each query descriptor which have distance less than
// maxDistance (in increasing order of distances).
void radiusMatch( const Mat& queryDescriptors, const Mat& trainDescriptors,
vector<vector >& matches, float maxDistance,const Mat& mask=Mat(), bool compactResult=false ) const;
(2) 方法重载,用于图像和图像集匹配的方法声明
CV_WRAP void match( const Mat& queryDescriptors, CV_OUT vector & matches,const vector & masks=vector () );
CV_WRAP void knnMatch( const Mat& queryDescriptors, CV_OUT vector<vector >& matches, int k,const vector & masks=vector (), bool compactResult=false );
void radiusMatch( const Mat& queryDescriptors, vector<vector >& matches, float maxDistance,const vector & masks=vector (), bool compactResult=false );
定义方式如下:
Ptr matcher = DescriptorMatcher::create("matchType");
/*
BruteForce (it uses L2 )
BruteForce-L1
BruteForce-Hamming
BruteForce-Hamming(2)
FlannBased
*/
struct CV_EXPORTS_W_SIMPLE DMatch
{
//默认构造函数,FLT_MAX是无穷大
//#define FLT_MAX 3.402823466e+38F
/* max value */
CV_WRAP DMatch() : queryIdx(-1), trainIdx(-1), imgIdx(-1), distance(FLT_MAX) {}
//DMatch构造函数
CV_WRAP DMatch( int _queryIdx, int _trainIdx, float _distance ) : queryIdx(_queryIdx), trainIdx(_trainIdx), imgIdx(-1), distance(_distance) {}
//DMatch构造函数
CV_WRAP DMatch( int _queryIdx, int _trainIdx, int _imgIdx, float _distance ) :queryIdx(_queryIdx), trainIdx(_trainIdx), imgIdx(_imgIdx), distance(_distance) {}
//queryIdx为query描述子的索引,match函数中前面的那个描述子
CV_PROP_RW int queryIdx;
//trainIdx为train描述子的索引,match函数中后面的那个描述子
CV_PROP_RW int trainIdx;
//imgIdx为进行匹配图像的索引
//例如已知一幅图像的sift描述子,与其他十幅图像的描述子进行匹配,找最相似的图像,则imgIdx此时就有用了。
CV_PROP_RW int imgIdx;
//distance为两个描述子之间的距离
CV_PROP_RW float distance;
//DMatch比较运算符重载,比较的是DMatch中的distance,小于为true,否则为false
bool operator<( const DMatch &m ) const
{
return distance < m.distance;
}
};
void drawKeypoints(const Mat& image, const vector & keypoints, Mat& outImg, const Scalar& color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT )
//例如:drawKeypoints( img_1, keypoints_1, outimg1, Scalar::all(-1), DrawMatchesFlags::DEFAULT )
其中有 : image – 原图像、keypoints – 原图像的关键点、outImg – 输出图像、color – 关键点的颜色、flags – 设置绘图功能
void drawMatches(const Mat& img1, const vector & keypoints1, const Mat& img2, const vector & keypoints2, const vector & matches1to2, Mat& outImg, const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1), const vector<char>& matchesMask=vector<char>(), int flags=DrawMatchesFlags::DEFAULT )
//例如:drawMatches ( img_1, keypoints_1, img_2, keypoints_2, matches, img_match );
其中参数如下:img1 –第一幅图
keypoints1 – 第一幅图的关键点
img2 – 第二幅图
keypoints2 – 第二幅图的关键点
matches – 正确匹配
outImg – 输出图
matchColor – 匹配的颜色(连接线)
如果 matchColor==Scalar::all(-1) , 颜色随机
singlePointColor – 无匹配的点的颜色(圆圈)
如果 singlePointColor==Scalar::all(-1) ,颜色随机
matchesMask – 决定哪些匹配要画出来,若空,则全画
flags – 标志位