1 //#include "pch.h" //opencv4.0要去掉
2 #include <iostream>
3 #include <stdlib.h>
4 #include <opencv2/imgproc.hpp>
5 #include <opencv2/opencv.hpp>
6 #include "opencv2/xfeatures2d.hpp"
7 #include "opencv2/features2d.hpp"
8
9 using namespace std;
10 using namespace cv;
11 using namespace cv::xfeatures2d;
12
13 //最大特征点数
14 const int MAX_FEATURES = 500;
15 //好的特征点数
16 const float GOOD_MATCH_PERCENT = 0.15f;
17
18 /**
19 * @brief 图像对齐
20 *
21 * @param im1 对齐图像
22 * @param im2 模板图像
23 * @param im1Reg 输出图像
24 * @param h
25 */
26 void alignImages(Mat &im1, Mat &im2, Mat &im1Reg, Mat &h) //引用传递,传入是实参的的别名,实际是实参的地址,因此调用被调函数后,实参会被间接修改。,这么看:Mat& arg
27 //和函数的 值传递 相反。
28 {
29 // Convert images to grayscale
30 Mat im1Gray, im2Gray;
31 //转换为灰度图
32 cvtColor(im1, im1Gray, COLOR_BGR2GRAY); //opencv4.0这里CV_BGR2GRAY要改成COLOR_BGR2GRAY
33 cvtColor(im2, im2Gray, COLOR_BGR2GRAY);
34
35 // Variables to store keypoints and descriptors
36 //关键点
37 std::vector<KeyPoint> keypoints1, keypoints2;//定义装有KeyPoint数据类型的的数组变量, keypoints1, keypoints2。如:vector<int> x,y
38 //特征描述符
39 Mat descriptors1, descriptors2;
40
41 // Detect ORB features and compute descriptors. 计算ORB特征和描述子
42 Ptr<Feature2D> orb = ORB::create(MAX_FEATURES);//opencv中ORB函数是纯虚函数,继承自feature2D,无法通过实例化对象调用,只能通过指针调用。
43 orb->detectAndCompute(im1Gray, Mat(), keypoints1, descriptors1);
44 orb->detectAndCompute(im2Gray, Mat(), keypoints2, descriptors2);
45
46 // Match features. 特征点匹配
47 std::vector<DMatch> matches;
48 //汉明距离进行特征点匹配
49 Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming");//虚函数调用
50 matcher->match(descriptors1, descriptors2, matches, Mat());
51
52 // Sort matches by score 按照特征点匹配结果从优到差排列
53 std::sort(matches.begin(), matches.end());
54
55 // Remove not so good matches 移除不好的特征点
56 const int numGoodMatches = matches.size() * GOOD_MATCH_PERCENT;
57 matches.erase(matches.begin() + numGoodMatches, matches.end());//0.15*matchPoints_size
58
59 // Draw top matches
60 Mat imMatches;
61 //画出特征点匹配图
62 drawMatches(im1, keypoints1, im2, keypoints2, matches, imMatches);
63 imwrite("matches.jpg", imMatches); //暴力匹配后剔除差的匹配点后 打印的特征点匹配关系图
64
65 // Extract location of good matches
66 std::vector<Point2f> points1, points2;
67
68 //保存对应点
69 for (size_t i = 0; i < matches.size(); i++) //这里是暴力匹配作剔除后剩下的点
70 {
71 //queryIdx是对齐图像的描述子和特征点的下标。
72 points1.push_back(keypoints1[matches[i].queryIdx].pt);
73 //queryIdx是是样本图像的描述子和特征点的下标。
74 points2.push_back(keypoints2[matches[i].trainIdx].pt);
75 }
76
77 // Find homography 计算Homography,RANSAC随机抽样一致性算法
78 h = findHomography(points1, points2, RANSAC);//这个函数参数远比这个多,很多省略了,输入两张图片各自匹配点的矩阵,和匹配方法
79
80 // Use homography to warp image 映射
81 warpPerspective(im1, im1Reg, h, im2.size()); //弯曲视角,(待配准图,结果图,单应矩阵,)
82 }
83
84 int main()
85 {
86 // Read reference image 读取参考图像
87 string refFilename("D://aa.jpg"); //基准图像
88 cout << "Reading reference image : " << refFilename << endl;
89 Mat imReference = imread(refFilename);
90
91 // Read image to be aligned 读取对准图像
92 string imFilename("D://a.jpg"); //待校准图像
93 cout << "Reading image to align : " << imFilename << endl;
94 Mat im = imread(imFilename);
95
96 // Registered image will be resotred in imReg.
97 // The estimated homography will be stored in h.
98 //结果图像,单应性矩阵
99 Mat imReg, h;
100
101 // Align images
102 cout << "Aligning images ..." << endl;
103 alignImages(im, imReference, imReg, h);//(待配准图,参照图,结果图,单应矩阵)
104
105 // Write aligned image to disk.
106 string outFilename("aligned.jpg");
107 cout << "Saving aligned image : " << outFilename << endl;
108 imwrite(outFilename, imReg); //校准后图像
109
110 /* Print estimated homography
111 [0.4260230318277862, 2.205599317460628, 7.436838081684622;
112 -0.8418214464779903, 1.649310552258939, 1202.559886226323;
113 0.0003634828675145606, 0.001245337973396314, 1]*/
114 cout << "Estimated homography : \n" << h << endl; //这里输出到控制台了,要想保存需要输出重定向
115 system("pause");
116 return 0;
117 }
118