align.cpp 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. #include <opencv2/opencv.hpp>
  2. #include "opencv2/xfeatures2d.hpp"
  3. #include "opencv2/features2d.hpp"
  4. using namespace std;
  5. using namespace cv;
  6. using namespace cv::xfeatures2d;
  7. const int MAX_FEATURES = 500;
  8. const float GOOD_MATCH_PERCENT = 0.15f;
  9. void alignImages(Mat &im1, Mat &im2, Mat &im1Reg, Mat &h)
  10. {
  11. // Convert images to grayscale
  12. Mat im1Gray, im2Gray;
  13. cvtColor(im1, im1Gray, cv::COLOR_BGR2GRAY);
  14. cvtColor(im2, im2Gray, cv::COLOR_BGR2GRAY);
  15. // Variables to store keypoints and descriptors
  16. std::vector<KeyPoint> keypoints1, keypoints2;
  17. Mat descriptors1, descriptors2;
  18. // Detect ORB features and compute descriptors.
  19. Ptr<Feature2D> orb = ORB::create(MAX_FEATURES);
  20. orb->detectAndCompute(im1Gray, Mat(), keypoints1, descriptors1);
  21. orb->detectAndCompute(im2Gray, Mat(), keypoints2, descriptors2);
  22. // Match features.
  23. std::vector<DMatch> matches;
  24. Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming");
  25. matcher->match(descriptors1, descriptors2, matches, Mat());
  26. // Sort matches by score
  27. std::sort(matches.begin(), matches.end());
  28. // Remove not so good matches
  29. const int numGoodMatches = matches.size() * GOOD_MATCH_PERCENT;
  30. matches.erase(matches.begin()+numGoodMatches, matches.end());
  31. // Draw top matches
  32. Mat imMatches;
  33. drawMatches(im1, keypoints1, im2, keypoints2, matches, imMatches);
  34. imwrite("matches.jpg", imMatches);
  35. // Extract location of good matches
  36. std::vector<Point2f> points1, points2;
  37. for( size_t i = 0; i < matches.size(); i++ )
  38. {
  39. points1.push_back( keypoints1[ matches[i].queryIdx ].pt );
  40. points2.push_back( keypoints2[ matches[i].trainIdx ].pt );
  41. }
  42. // Find homography
  43. h = findHomography( points1, points2, RANSAC );
  44. // Use homography to warp image
  45. warpPerspective(im1, im1Reg, h, im2.size());
  46. }
  47. int main(int argc, char **argv)
  48. {
  49. // Read reference image
  50. string refFilename("form.jpg");
  51. cout << "Reading reference image : " << refFilename << endl;
  52. Mat imReference = imread(refFilename);
  53. // Read image to be aligned
  54. string imFilename("scanned-form.jpg");
  55. cout << "Reading image to align : " << imFilename << endl;
  56. Mat im = imread(imFilename);
  57. // Registered image will be resotred in imReg.
  58. // The estimated homography will be stored in h.
  59. Mat imReg, h;
  60. // Align images
  61. cout << "Aligning images ..." << endl;
  62. alignImages(im, imReference, imReg, h);
  63. // Write aligned image to disk.
  64. string outFilename("aligned.jpg");
  65. cout << "Saving aligned image : " << outFilename << endl;
  66. imwrite(outFilename, imReg);
  67. // Print estimated homography
  68. cout << "Estimated homography : \n" << h << endl;
  69. }