ImageMosaic.h
#ifndef IMAGE_MOSAIC_H
#define IMAGE_MOSAIC_H
#include <iostream>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include <opencv2/opencv.hpp>
#include<opencv2/xfeatures2d.hpp>
#include<opencv2/core/core.hpp>
using namespace cv; //包含cv命名空间
using namespace std;
using namespace cv::xfeatures2d;//只有加上这句命名空间,SiftFeatureDetector and SiftFeatureExtractor才可以使用
typedef struct
{
Point2f left_top;
Point2f left_bottom;
Point2f right_top;
Point2f right_bottom;
}four_corners_t;
four_corners_t corners;
Mat ImageMosaic(Mat img_1, Mat img_2)
{
//创建SIFT 类指针
Ptr<Feature2D> f2d = xfeatures2d::SIFT::create();
//imshow("img_1", img_1);
//检测关键点
double t0 = getTickCount();
vector<KeyPoint> keypoints_1(0), keypoints_2(0);
f2d->detect(img_1, keypoints_1);
f2d->detect(img_2, keypoints_2);
//计算描述符 (特征向量)
Mat descriptors_1, descriptors_2;
f2d->compute(img_1, keypoints_1, descriptors_1);
f2d->compute(img_2, keypoints_2, descriptors_2);
//使用BF匹配器匹配描述符向量
BFMatcher matcher;
vector<DMatch> matches;
matcher.match(descriptors_1, descriptors_2, matches);
//绘制匹配出的关键点
Mat img_matches;
drawMatches(img_1, keypoints_1, img_2, keypoints_2, matches, img_matches);
//计算匹配结果中距离最大和距离最小值
double min_dist = matches[0].distance, max_dist = matches[0].distance;
for (int m = 0; m < matches.size(); m++)
{
if (matches[m].distance<min_dist)
{
min_dist = matches[m].distance;
}
if (matches[m].distance>max_dist)
{
max_dist = matches[m].distance;
}
}
//筛选出较好的匹配点
vector<DMatch> goodMatches;
for (int m = 0; m < matches.size(); m++)
{
if (matches[m].distance < 0.6*max_dist)
{
goodMatches.push_back(matches[m]);
}
}
//RANSAC匹配过程
vector<DMatch> m_Matches;
m_Matches = goodMatches;
/*int ptCount = goodMatches.size();
if (ptCount < 100)
{
cout << "Don't find enough match points" << endl;
return 0;
}*/
//坐标转换为float类型
vector <KeyPoint> RAN_KP1, RAN_KP2;
//size_t是标准C库中定义的,应为unsigned int,在64位系统中为long unsigned int,在C++中为了适应不同的平台,增加可移植性。
for (size_t i = 0; i < m_Matches.size(); i++)
{
RAN_KP1.push_back(keypoints_1[goodMatches[i].queryIdx]);
RAN_KP2.push_back(keypoints_2[goodMatches[i].trainIdx]);
//RAN_KP1是要存储img01中能与img02匹配的点
//goodMatches存储了这些匹配点对的img01和img02的索引值
}
//坐标变换
vector <Point2f> p01, p02;
for (size_t i = 0; i < m_Matches.size(); i++)
{
p01.push_back(RAN_KP1[i].pt);
p02.push_back(RAN_KP2[i].pt);
}
//求转换矩阵
Mat H;
vector<uchar> m;
H = findHomography(p01, p02, RANSAC);//寻找匹配图像
cout << "H矩阵" << H << endl;
//H矩阵变换后的图像
Mat image1;
warpPerspective(img_1, image1, H, Size(MAX(corners.right_top.x, corners.right_bottom.x), img_2.rows));
return image1;
}
#endif
main程序
#include "ImageMosaic.h"
int main(int argc, char*argv[])
{
Mat img_1 = imread("1.jpg");
Mat img_2 = imread("2.jpg");
Mat image1 = ImageMosaic(img_1, img_2);
imshow("img_2", img_2);
imshow("image1", image1);
waitKey(0);
}