Opencv3中特征点检测有很多与opencv2不同的地方,特别是在特征点检测这一块
想要用opencv3进行特征点检测,有很多前期的准备工作要做有一大堆的配置,
参见:http://blog.csdn.net/linshuhe1/article/details/51221015
实验代码如下:
/***************************************************************************
*检测候选特征点周围一圈的像素值,如果候选点周围领域内有足够多的像素点与该候选点的灰度值差别够大,则认为该候选点为一个特征点。
*如果测试了候选点周围每隔90度角的4个点,应该至少有3个和候选点的灰度值差足够大,否则则不用再计算其他点,直接认为该候选点不是特征点。候选点周围的圆的选取半径是一个很重要的参数,
*http://www.tuicool.com/articles/NzE77nB
*http://blog.sina.com.cn/s/blog_a98e39a201017pgn.html
*http://www.xuebuyuan.com/582341.html
*http://blog.csdn.net/poem_qianmo/article/details/33320997
***************************************************************************/
#include <iostream>
#include<opencv2\opencv.hpp>
#include"opencv2/xfeatures2d.hpp"
using namespace cv;
using namespace std;
using namespace cv::xfeatures2d;
using namespace cv::ml;
int main()
{
Mat a = imread( "1.jpg" , 0 ); //读取灰度图像
Mat b = imread( "2.jpg" , 0 );
Ptr<SURF> surf; //创建方式和opencv2中的不一样
// Ptr<SIFT> sift;
surf = SURF::create( 800 ); //阈值
BFMatcher matcher; //匹配器
Mat c , d;
vector<KeyPoint> key1 , key2;
vector<DMatch> matches;
//结果为一个Mat矩阵,它的行数与特征点向量中元素个数是一致的。每行都是一个N维描述子的向量
surf->detectAndCompute( a , Mat() , key1 , c ); //检测关键点和匹配描述子
surf->detectAndCompute( b , Mat() , key2 , d );
matcher.match( c , d , matches ); // 匹配,得到匹配向量
sort( matches.begin() , matches.end() ); // 匹配点排序
vector< DMatch > good_matches; // 匹配两幅图像的描述子
int ptsPairs = min( 50 , ( int ) ( matches.size() * 0.15 ) );
cout << ptsPairs << endl;
for( int i = 0; i < ptsPairs; i++ ) // 将匹配较好的特征点存入good_matches中
{
good_matches.push_back( matches[i] );
}
Mat outimg;
drawMatches( // 绘制匹配点
a , // 原图像1
key1 , // 原图像1的特征点
b , // 原图像2
key2 , // 原图像2的特征点
good_matches , // 原图像1的特征点匹配原图像2的特征点[matches[i]]
outimg , // 输出图像具体由flags决定
Scalar::all( -1 ) , // 匹配的颜色(特征点和连线),若matchColor==Scalar::all(-1),颜色随机
Scalar::all( -1 ) , // 单个点的颜色,即未配对的特征点,若matchColor==Scalar::all(-1),颜色随机
vector<char>() , // Mask决定哪些点将被画出,若为空,则画出所有匹配点
DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS ); //Fdefined by DrawMatchesFlags
imshow( "匹配图" , outimg );
waitKey();
vector<Point2f> obj;
vector<Point2f> scene;
for( size_t i = 0; i < good_matches.size(); i++ )
{
good_matches[i].queryIdx保存着第一张图片匹配点的序号,keypoints_1[good_matches[i].queryIdx].pt.x 为该序号对应的点的x坐标
obj.push_back( key1[good_matches[i].queryIdx].pt );
scene.push_back( key2[good_matches[i].trainIdx].pt );
}
vector<Point2f> scene_corners( 4 );
vector<Point2f> obj_corners( 4 );
obj_corners[0] = Point( 0 , 0 );
obj_corners[1] = Point( a.cols , 0 );
obj_corners[2] = Point( a.cols , a.rows );
obj_corners[3] = Point( 0 , a.rows );
Mat H = findHomography( // 在两个平面之间寻找单映射变换矩阵
obj , // 在原平面上点的坐标
scene , // 在目标平面上点的坐标
RANSAC ); // 用于计算单映射矩阵的方法
perspectiveTransform( // 向量组的透视变换
obj_corners , // 输入两通道或三通道的浮点数组,每一个元素是一个2D/3D 的矢量转换
scene_corners , // 输出和src同样的size和type
H ); // 3x3 或者4x4浮点转换矩阵
// 绘制
line( outimg , scene_corners[0] + Point2f( ( float ) a.cols , 0 ) , scene_corners[1] + Point2f( ( float ) a.cols , 0 ) , Scalar( 0 , 255 , 0 ) , 2 , LINE_AA );
line( outimg , scene_corners[1] + Point2f( ( float ) a.cols , 0 ) , scene_corners[2] + Point2f( ( float ) a.cols , 0 ) , Scalar( 0 , 255 , 0 ) , 2 , LINE_AA );
line( outimg , scene_corners[2] + Point2f( ( float ) a.cols , 0 ) , scene_corners[3] + Point2f( ( float ) a.cols , 0 ) , Scalar( 0 , 255 , 0 ) , 2 , LINE_AA );
line( outimg , scene_corners[3] + Point2f( ( float ) a.cols , 0 ) , scene_corners[0] + Point2f( ( float ) a.cols , 0 ) , Scalar( 0 , 255 , 0 ) , 2 , LINE_AA );
imshow( "匹配图" , outimg );
waitKey( 0 );
}