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 }
算法存在的問題:只能對齊兩個特征完全一樣的圖,只是因為類似拍攝角度產生的差別,換句話說這種基於特征的對齊對於特征變化非常敏感。在此項目中很多位置的特征是不固定的,比如器件上的標碼,比如線的形態不同,而且器件的缺失也會影響。不適用於接線盒項目。