ORB-GMS-RANSAC图像对齐
1 #include <iostream> 2 #include <opencv2/core.hpp> //基础数据类型实现 3 #include <opencv2/highgui.hpp> //图像的输入输出 4 #include <opencv2/imgproc.hpp> //图像处理 5 #include <opencv2/flann.hpp> //快速最近邻匹配算法 6 #include <opencv2/calib3d.hpp> 7 #include <opencv2/features2d.hpp> //一些特征检测的算法库,如FAST 8 #include <opencv2/xfeatures2d.hpp>//一些算法,如GMS匹配算法(特征点细筛) 9 //#include <stdlib.h> 10 11 12 using namespace cv; 13 using namespace std; 14 using namespace cv::xfeatures2d; 15 16 17 int main() 18 { 19 Mat img_1 = imread("D:\\g.jpg"); 20 Mat img_2 = imread("D:\\dd.jpg"); 21 //Ptr<Feature2D> sift = xfeatures2d::SIFT::create(); 22 //Ptr<Feature2D> surf = xfeatures2d::SURF::create(); 23 Ptr<ORB> orb = ORB::create(5000); //定义了orb类对象并初始化 24 orb->setFastThreshold(0); //FAST焦点检测算法阈值设定,0最大限度的检出角点。 25 26 vector<KeyPoint> keypoints_1, keypoints_2;//定义了两个数组,未初始化 27 Mat descriptors_1, descriptors_2;//定义了两个结构变量,未初始化 28 29 //sift->detect(img_1, keypoints_1); 30 //sift->compute(img_1, keypoints_1, descriptors); 31 32 orb->detectAndCompute(img_1, Mat(), keypoints_1, descriptors_1); 33 orb->detectAndCompute(img_2, Mat(), keypoints_2, descriptors_2); 34 35 //orb ->detect(img_1, keypoints_1); 36 //orb ->compute(img_1, keypoints_1, descriptors_1); 关键点->描述子 37 38 //orb->detect(img_2, keypoints_2); 39 //orb->compute(img_2, keypoints_2, descriptors_2); 40 41 Mat ShowKeypoints1, ShowKeypoints2; //定义了两个结构化类型变量 42 drawKeypoints(img_1, keypoints_1, ShowKeypoints1); //调用函数画出检测到的关键点 43 drawKeypoints(img_2, keypoints_2, ShowKeypoints2); 44 imshow("Result_1", ShowKeypoints1); //设置显示窗口名称 45 imshow("Result_2", ShowKeypoints2); 46 47 vector<DMatch> matchesAll, matchesGMS; //定义两个数组对象 48 BFMatcher matcher(NORM_HAMMING);//定义一个类对象,暴力匹配算法-第一轮,得到gms的输入。 49 50 matcher.match(descriptors_1, descriptors_2, matchesAll); //针对前面生成的描述子暴力匹配,这个matchAll是被匹配的点构成的数组。 51 cout << "matchesAll: " << matchesAll.size() << endl; //输出orb完全匹配的特征点对数 52 matchGMS(img_1.size(), img_2.size(), keypoints_1, keypoints_2, matchesAll, matchesGMS);//GMS网格运动统计继续筛选匹配特征点 53 std::cout << "matchesGMS: " << matchesGMS.size() << std::endl;//输出gms筛选后匹配的特征点对数 54 55 std::vector<Point2f> points1, points2; 56 for (size_t i = 0; i < matchesGMS.size(); i++) //这里是暴力匹配作剔除后剩下的点 57 { 58 //queryIdx是对齐图像的描述子和特征点的下标。 59 points1.push_back(keypoints_1[matchesGMS[i].queryIdx].pt); 60 //queryIdx是是样本图像的描述子和特征点的下标。 61 points2.push_back(keypoints_2[matchesGMS[i].trainIdx].pt); 62 } 63 Mat im1Reg, h; 64 // Find homography 计算Homography,RANSAC随机抽样一致性算法 65 h = findHomography(points1, points2, RANSAC);//这个函数参数远比这个多,很多参数缺省取了默认值,输入两张图片各自匹配点的矩阵,和匹配方法 66 67 // Use homography to warp image 映射 68 warpPerspective(img_1, im1Reg, h, img_2.size()); 69 70 Mat finalMatches; 71 drawMatches(img_1, keypoints_1, img_2, keypoints_2, matchesGMS, finalMatches, Scalar::all(-1), Scalar::all(-1),//匹配的点及连接线的颜色随机;未被匹配的单点颜色随机。 72 std::vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);//画出匹配示意图,参数中有GMS运动估计筛选后的匹配点 73 imshow("Matches GMS", finalMatches);//显示 74 //system("pause"); 75 imwrite("MatchesGMS.jpg", finalMatches);//保存 76 //看matchGMS的结构,将其分为两个新的keypoints,然后直接配对 77 78 string outFilename("aligned.jpg"); 79 cout << "Saving aligned image : " << outFilename << endl; 80 imwrite(outFilename, im1Reg); //校准后图像 81 imshow("aligned ", im1Reg); 82 83 waitKey(0); 84 return 0; 85 }
算法存在的问题:只能对齐两个特征完全一样的图,只是因为类似拍摄角度产生的差别,换句话说这种基于特征的对齐对于特征变化非常敏感。在此项目中很多位置的特征是不固定的,比如器件上的标码,比如线的形态不同,而且器件的缺失也会影响。不适用于接线盒项目。