opencv 影象拼接
阿新 • • 發佈:2019-01-03
左右圖單應性變換原理圖
1.SURF特徵點提取
#include "pch.h" #include <opencv2\opencv.hpp> #include <opencv2\xfeatures2d.hpp> #include <iostream> #include "StitcherTest.h" using namespace cv; using namespace cv::xfeatures2d; using namespace std; int main() { Mat image_1 = imread("1.jpg"); Mat image_2 = imread("2.jpg"); Mat gray_image_1; Mat gray_image_2; cvtColor(image_1, gray_image_1, CV_RGB2GRAY); cvtColor(image_2, gray_image_2, CV_RGB2GRAY); // Check if image files can be read if (!gray_image_1.data) { std::cout << "Error Reading Image 1" << std::endl; return 0; } if (!gray_image_2.data) { std::cout << "Error Reading Image 2" << std::endl; return 0; } imshow("bag1 image", image_1); imshow("bag2 image", image_2); // Detect the keypoints using SURF Detector // Based from Anna Huaman's 'Features2D + Homography to find a known object' Tutorial int minHessian = 50; Ptr<SurfFeatureDetector> detector = SurfFeatureDetector::create(minHessian);; std::vector <KeyPoint> keypoints_2, keypoints_1; detector->detect(gray_image_2, keypoints_2); detector->detect(gray_image_1, keypoints_1); // Calculate Feature Vectors (descriptors) // Based from Anna Huaman's 'Features2D + Homography to find a known object' Tutorial Ptr < SurfDescriptorExtractor> extractor = SurfDescriptorExtractor::create(); Mat descriptors_2, descriptors_1; extractor->compute(gray_image_2, keypoints_2, descriptors_2); extractor->compute(gray_image_1, keypoints_1, descriptors_1); // Matching descriptor vectors using FLANN matcher // Based from Anna Huaman's 'Features2D + Homography to find a known object' Tutorial FlannBasedMatcher matcher; std::vector <DMatch> matches; matcher.match(descriptors_2, descriptors_1, matches); double max_dist = 0; double min_dist = 100; // Quick calculation of max and min distances between keypoints // Based from Anna Huaman's 'Features2D + Homography to find a known object' Tutorial for (int i = 0; i < descriptors_2.rows; i++) { double dist = matches[i].distance; if (dist < min_dist) { min_dist = dist; } } // Use matches that have a distance that is less than 3 * min_dist std::vector <DMatch> good_matches; for (int i = 0; i < descriptors_2.rows; i++) { if (matches[i].distance < 3 * min_dist) { good_matches.push_back(matches[i]); } } std::vector <Point2f> points2; std::vector <Point2f> points1; for (int i = 0; i < good_matches.size(); i++) { // Get the keypoints from the good matches points2.push_back(keypoints_2[good_matches[i].queryIdx].pt); points1.push_back(keypoints_1[good_matches[i].trainIdx].pt); } //以左邊的圖片為準,從右邊進行拼接,變換原理見上圖 // Find the Homography Matrix Mat H = findHomography(points2, points1, CV_RANSAC); // Use the Homography Matrix to warp the images cv::Mat resultRight; warpPerspective(image_2, resultRight, H, cv::Size(2 * image_2.cols, image_2.rows)); cv::Mat half(resultRight, cv::Rect(0, 0, image_1.cols, image_1.rows)); image_1.copyTo(half); imshow("resultRight", resultRight); //以右邊的圖片為準,從左邊進行拼接,變換原理見上圖 Mat homo = findHomography(points1, points2); //需要向右平移image_1的寬度 Mat shftMat = (Mat_<double>(3, 3) << 1.0, 0, image_1.cols, 0, 1.0, 0, 0, 0, 1); Mat resultLeft; warpPerspective(image_1, resultLeft, shftMat * homo, Size(2 * image_2.cols, image_2.rows)); image_2.copyTo(Mat(resultLeft, Rect(image_1.cols, 0, image_2.cols, image_2.rows))); // Write image imshow("resultLeft", resultLeft); waitKey(0); return 0; }
2.ORB特徵點提取
#include "pch.h" #include <opencv2\opencv.hpp> #include <opencv2\xfeatures2d.hpp> #include <iostream> #include "StitcherTest.h" using namespace cv; using namespace cv::xfeatures2d; using namespace std; int main() { cv::Mat image1 = cv::imread("1.jpg", 1); cv::Mat image2 = cv::imread("2.jpg", 1); if (!image1.data || !image2.data) return 0; imshow("image1", image1); imshow("image2", image2); std::vector<cv::KeyPoint> keypoints1, keypoints2; //尋找ORB特針點對 Ptr<DescriptorMatcher> descriptorMatcher; vector<DMatch> matches; vector<KeyPoint> keyImg1, keyImg2; Mat descImg1, descImg2; //建立ORB物件 Ptr<Feature2D> b = ORB::create(); //兩種方法尋找特徵點 b->detectAndCompute(image1, Mat(), keyImg1, descImg1, false); b->detectAndCompute(image2, Mat(), keyImg2, descImg2, false); //匹配特徵點 descriptorMatcher = DescriptorMatcher::create("BruteForce"); descriptorMatcher->match(descImg1, descImg2, matches, Mat()); Mat index; int nbMatch = int(matches.size()); Mat tab(nbMatch, 1, CV_32F); for (int i = 0; i < nbMatch; i++) { tab.at<float>(i, 0) = matches[i].distance; } sortIdx(tab, index, cv::SORT_EVERY_COLUMN + cv::SORT_ASCENDING); vector<DMatch> bestMatches; for (int i = 0; i < 60; i++) { bestMatches.push_back(matches[index.at<int>(i, 0)]); } Mat result; drawMatches(image1, keyImg1, image2, keyImg2, bestMatches, result); std::vector<Point2f> obj; std::vector<Point2f> scene; for (int i = 0; i < (int)bestMatches.size(); i++) { obj.push_back(keyImg1[bestMatches[i].queryIdx].pt); scene.push_back(keyImg2[bestMatches[i].trainIdx].pt); } //直接呼叫ransac,計算單應矩陣 Mat H = findHomography(scene, obj, CV_RANSAC); cv::Mat resultRight; warpPerspective(image2, resultRight, H, cv::Size(image1.cols + image2.cols, max(image1.rows, image2.rows))); cv::Mat half(resultRight, cv::Rect(0, 0, image1.cols, image1.rows)); image1.copyTo(half); imshow("resultRight", resultRight); waitKey(0); return 0; }