# OpenCV 单应矩阵应用：全景图像融合原理

#### 1.单应矩阵

X是空间中的一点，左右两边是射影平面（摄像头）

#### 2.与基础矩阵的区别

p'应映射到x2'，但被映射到了x2

#### 4.代码实现

/********************************************************************
* Created by 杨帮杰 on 10/12/18
* Right to use this code in any way you want without
* warranty, support or any guarantee of it working
* E-mail: yangbangjie1998@qq.com
* Association: SCAU 华南农业大学
********************************************************************/

#include <iostream>
#include <vector>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/features2d.hpp>
#include <opencv2/calib3d.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/stitching.hpp>

#define PARLIAMENT01 "/home/jacob/图片/images/parliament1.jpg"
#define PARLIAMENT02 "/home/jacob/图片/images/parliament2.jpg"

using namespace cv;
using namespace std;

int main()
{
if (!image1.data || !image2.data)
return 0;

imshow("Image 1",image1);
imshow("Image 2",image2);

vector<KeyPoint> keypoints1;
vector<KeyPoint> keypoints2;
Mat descriptors1, descriptors2;

//创建SIFT检测器
Ptr<Feature2D> ptrFeature2D = xfeatures2d::SIFT::create(74);

//检测SIFT特征并生成描述子
ptrFeature2D->detectAndCompute(image1, noArray(), keypoints1, descriptors1);
ptrFeature2D->detectAndCompute(image2, noArray(), keypoints2, descriptors2);

cout << "Number of feature points (1): " << keypoints1.size() << endl;
cout << "Number of feature points (2): " << keypoints2.size() << endl;

//使用欧氏距离和交叉匹配策略进行图像匹配
BFMatcher matcher(NORM_L2, true);
vector<DMatch> matches;
matcher.match(descriptors1,descriptors2,matches);

Mat imageMatches;
drawMatches(image1,keypoints1,  // 1st image and its keypoints
image2,keypoints2,  // 2nd image and its keypoints
matches,            // the matches
imageMatches,       // the image produced
Scalar(255,255,255),  // color of the lines
Scalar(255,255,255),  // color of the keypoints
vector<char>(),
2);

imshow("Matches (pure rotation case)",imageMatches);

//将keypoints类型转换为Point2f
vector<Point2f> points1, points2;
for (vector<DMatch>::const_iterator it= matches.begin();
it!= matches.end(); ++it)
{
float x= keypoints1[it->queryIdx].pt.x;
float y= keypoints1[it->queryIdx].pt.y;
points1.push_back(Point2f(x,y));

x= keypoints2[it->trainIdx].pt.x;
y= keypoints2[it->trainIdx].pt.y;
points2.push_back(Point2f(x,y));
}

cout << "number of points: " << points1.size() << " & " << points2.size() << endl;

//使用RANSAC算法估算单应矩阵
vector<char> inliers;
Mat homography= findHomography(
points1,points2, // corresponding points
inliers,         // outputed inliers matches
RANSAC,      // RANSAC method
1.);             // max distance to reprojection point

//画出局内匹配项
drawMatches(image1, keypoints1,  // 1st image and its keypoints
image2, keypoints2,  // 2nd image and its keypoints
matches,            // the matches
imageMatches,       // the image produced
Scalar(255, 255, 255),  // color of the lines
Scalar(255, 255, 255),  // color of the keypoints
inliers,
2);

imshow("Homography inlier points", imageMatches);

//用单应矩阵对图像进行变换
Mat result;
warpPerspective(image1, // input image
result,         // output image
homography,     // homography
Size(2*image1.cols,image1.rows)); // size of output image

//拼接
Mat half(result,Rect(0,0,image2.cols,image2.rows));
image2.copyTo(half);

imshow("Image mosaic",result);

waitKey();
return 0;
}


References:
SLAM入门之视觉里程计(5)：单应矩阵
Opencv Sift和Surf特征实现图像无缝拼接生成全景图像
opencv计算机视觉编程攻略（第三版） —— Robert Laganiere

+ 订阅