特征点匹配于图像拼接的应用——基于Opencv3.4的SURF算法图像拼接

最近一直在学习关于特征点和图像拼接这一块的知识,相比说道特征点匹配,大家能想到的最最经典的便是1999年由David Lowe提出的SIFT(尺度不变特征变换Scale-invariant feature transform),虽然这种算法对于特征点的匹配程度最高,效果较好,然而由于其对于计算量的问题,难以实现高效率的描述生成,所以为满足实时条件的需求,针对SIFT的改进算法SURF应运而生。个人认为,SURF方面对于SIFT的较大改进是特征点检测阶段,使用了Hessian矩阵代替了SIFT中的高斯变换,获取极值点。当然在方向定位和对特征的描述子的定义方面,也有一定的出入。

当SURF用于图像拼接过程中,单一的SURF算法,仅仅能够获取图像的特征点,方向,及其对应的描述子,而在这个过程中,需要有一个误匹配点筛选过程,这里我们使用常用的RANSAC算法来对误匹配点进行筛选,这个算法的大概原理就是,随机抽取一定的特征点进行数学建模,再用模型评估其他匹配点,如此迭代直到得到的模型符合绝大多数的匹配点为止。而在映射拼接后,我们需要对拼接线进行优化处理,这里用到了加权平均的方法。

程序如下:

#include  
#include  
#include
#include"opencv2\opencv.hpp"
#include"opencv2\core\core.hpp"
#include"opencv2\xfeatures2d.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
using namespace std;


int main(int argc, char** argv) {
Mat src1 = imread("1.jpg");
Mat src2 = imread("2.jpg");


if (src1.data == NULL || src2.data == NULL)
{
cout << "No exist" << endl;
return -1;
}


Ptr surf = xfeatures2d::SURF::create();
vector pic1key, pic2key;
Mat des1, des2;
surf->detectAndCompute(src1,Mat(),pic1key,des1);
surf->detectAndCompute(src2,Mat(),pic2key,des2);
//drawKeypoints(src1,pic1key,src1);

FlannBasedMatcher  matcher;//不使用暴力匹配,改成Fast Library for Approximate Nearest Neighbors匹配(近似算法,比暴力匹配更快)
vector matches;
matcher.match(des1,des2,matches);


vectorpic1, pic2;//滤掉误匹配点
for (int i = 0; i < matches.size(); i++)
{
pic1.push_back(pic1key[matches[i].queryIdx].pt);
pic2.push_back(pic2key[matches[i].trainIdx].pt);
}
vectormark(pic1.size());
Mat transM = findHomography(pic1,pic2,CV_RANSAC,5,mark,500);
cout << "变换矩阵为:" << endl;
cout << transM;
vectoroptimizeMatch;
for (int i = 0; i < matches.size(); i++)
{
if (mark[i])
optimizeMatch.push_back(matches[i]);
}
//开始拼接
Mat tempP;
warpPerspective(src1,tempP,transM,Size(src1.cols*2,src1.rows));
Mat matchP(src1.cols*2,src1.rows,CV_8UC3);
tempP.copyTo(matchP);
src2.copyTo(matchP(Rect(0,0,src2.cols,src2.rows)));
imshow("compare",tempP);
imshow("compare1",matchP);


//优化拼接线
double lefttop[3] = {0,0,1};
double leftbottom[3] = {0,src1.rows,1};
double transLT[3];
double transLB[3];
Mat _lefttop = Mat(3,1,CV_64FC1,lefttop);
Mat _leftbottom = Mat(3,1,CV_64FC1,leftbottom);
Mat _transLT = Mat(3,1,CV_64FC1,transLT);
Mat _transLB = Mat(3,1,CV_64FC1,transLB);
_transLT = transM*_lefttop;
_transLB = transM*_leftbottom;
double weight = 1;
int leftline = MIN(transLT[0],transLB[0]);
double width = src2.cols - leftline;
for (int i = 0; i < src2.rows; i++)
{
uchar* src = src2.ptr(i);
uchar* trans = tempP.ptr(i);
uchar* match = matchP.ptr(i);
for (int j = leftline; j < src2.cols; j++)
{
if (trans[j * 3] == 0 && trans[j * 3 + 1] == 0 && trans[j * 3 + 2] == 0)
{
weight = 1;
}
else {
weight = (double)(width - (j - leftline)) / width;
}
match[j * 3] = src[j * 3] *  weight+ trans[j * 3] * (1 - weight);
match[j * 3 + 1] = src[j * 3 + 1] *  weight+ trans[j * 3 + 1] * (1 - weight);
match[j * 3 + 2] = src[j * 3 + 2] *  weight+ trans[j * 3 + 2] * (1 - weight);
}
}


imshow("output",matchP);
waitKey(0);
return 0;

}

其匹配拼接结果如下:

特征点匹配于图像拼接的应用——基于Opencv3.4的SURF算法图像拼接_第1张图片

特征点匹配于图像拼接的应用——基于Opencv3.4的SURF算法图像拼接_第2张图片

特征点匹配于图像拼接的应用——基于Opencv3.4的SURF算法图像拼接_第3张图片


你可能感兴趣的:(特征点匹配于图像拼接的应用——基于Opencv3.4的SURF算法图像拼接)