平面对象的匹配与识别:

        在日常生活中,我们接触的照片经常会因为角度或者方向的问题,而导致图像中的文字倾斜或者角度偏转。

透视变换(Perspective Transformation)可以将图片进行校正。也可以通过透视变换进行图像的平面识别;

 主要是两个API:

 

 代码演示:

  1 #include <opencv2/opencv.hpp>
  2 #include <opencv2/xfeatures2d.hpp>
  3 #include <iostream>
  4 #include <math.h>
  5
  6 using namespace cv;
  7 using namespace std;
  8 using namespace cv::xfeatures2d;
  9
 10 int main(int argc, char** argv) {
 11     Mat img1 = imread("L:/opencv_picture/book1.jpg", IMREAD_GRAYSCALE);
 12     Mat img2 = imread("L:/opencv_picture/book2.jpg", IMREAD_GRAYSCALE);
 13     if (!img1.data || !img2.data) {
 14         return -1;
 15     }
 16     imshow("object image", img1);
 17     imshow("object in scene", img2);
 18
 19     // surf featurs extraction
 20     int minHessian = 400;
 21     Ptr<SURF> detector = SURF::create(minHessian);
 22     vector<KeyPoint> keypoints_obj;
 23     vector<KeyPoint> keypoints_scene;
 24     Mat descriptor_obj, descriptor_scene;
 25     detector->detectAndCompute(img1, Mat(), keypoints_obj, descriptor_obj);
 26     detector->detectAndCompute(img2, Mat(), keypoints_scene, descriptor_scene);
 27
 28     // matching
 29     FlannBasedMatcher matcher;
 30     vector<DMatch> matches;
 31     matcher.match(descriptor_obj, descriptor_scene, matches);
 32
 33     // find good matched points
 34     double minDist = 1000;
 35     double maxDist = 0;
 36     for (int i = 0; i < descriptor_obj.rows; i++) {
 37         double dist = matches[i].distance;
 38         if (dist > maxDist) {
 39             maxDist = dist;
 40         }
 41         if (dist < minDist) {
 42             minDist = dist;
 43         }
 44     }
 45     printf("max distance : %f\n", maxDist);
 46     printf("min distance : %f\n", minDist);
 47     vector<DMatch> goodMatches;
 48     for (int i = 0; i < descriptor_obj.rows; i++) {
 49         double dist = matches[i].distance;
 50         if (dist < max(3 * minDist, 0.02)) {
 51             goodMatches.push_back(matches[i]);
 52         }
 53     }
 54
 55     Mat matchesImg;
 56     drawMatches(img1, keypoints_obj, img2, keypoints_scene, goodMatches, matchesImg, Scalar::all(-1),
 57         Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS
 58     );
 59     //以上代码参考上一节内容:FLANN特征点匹配
 60     vector<Point2f> obj;
 61     vector<Point2f> objInScene;
 62     for (size_t t = 0; t < goodMatches.size(); t++) {
 63         obj.push_back(keypoints_obj[goodMatches[t].queryIdx].pt);
 64 //将keypoints_obj中goodMatches[t]中的queryIdx参数(左图索引)用指针.pt分别压入堆栈obj中
 65         objInScene.push_back(keypoints_scene[goodMatches[t].trainIdx].pt);
 66 //将keypoints_scene中goodMatches[t]中的trainIdx参数(右图索引)用指针.pt分别压入堆栈objScene中
 67     }
 68     Mat H = findHomography(obj, objInScene, RANSAC);
 69 //findHomography函数:计算多个二维点对之间的最优单映射变换矩阵 H
 70 //第三个参数:0 - 利用所有点的常规方法      RANSAC - 基于RANSAC的鲁棒算法
 71 //              LMEDS - 最小中值鲁棒算法      RHO    - 基于PROSAC的鲁棒算法
 72
 73     vector<Point2f> obj_corners(4);    //图一矩形四个顶点
 74     vector<Point2f> scene_corners(4);  //在图二中经过变换后的图一的四个顶点
 75     obj_corners[0] = Point(0, 0);
 76     obj_corners[1] = Point(img1.cols, 0);
 77     obj_corners[2] = Point(img1.cols, img1.rows);
 78     obj_corners[3] = Point(0, img1.rows);
 79     perspectiveTransform(obj_corners, scene_corners, H); //开始变换
 80     //perspectiveTransform函数采用H变换,将图一的四个顶点变换到图2中也就是scene_corners
 81
 82     // draw line   (每个点都要加上图1的横坐标,以为两张图一起显示)
 83     line(matchesImg, scene_corners[0] + Point2f(img1.cols, 0), scene_corners[1] + Point2f(img1.cols, 0), Scalar(0, 0, 255), 2, 8, 0);
 84     line(matchesImg, scene_corners[1] + Point2f(img1.cols, 0), scene_corners[2] + Point2f(img1.cols, 0), Scalar(0, 0, 255), 2, 8, 0);
 85     line(matchesImg, scene_corners[2] + Point2f(img1.cols, 0), scene_corners[3] + Point2f(img1.cols, 0), Scalar(0, 0, 255), 2, 8, 0);
 86     line(matchesImg, scene_corners[3] + Point2f(img1.cols, 0), scene_corners[0] + Point2f(img1.cols, 0), Scalar(0, 0, 255), 2, 8, 0);
 87
 88     //仅在dst原图(图二)上画出目标图像
 89     Mat dst;
 90     cvtColor(img2, dst, COLOR_GRAY2BGR);
 91     line(dst, scene_corners[0], scene_corners[1], Scalar(0, 0, 255), 2, 8, 0);
 92     line(dst, scene_corners[1], scene_corners[2], Scalar(0, 0, 255), 2, 8, 0);
 93     line(dst, scene_corners[2], scene_corners[3], Scalar(0, 0, 255), 2, 8, 0);
 94     line(dst, scene_corners[3], scene_corners[0], Scalar(0, 0, 255), 2, 8, 0);
 95
 96     imshow("find known object demo", matchesImg);
 97     imshow("Draw object", dst);
 98
 99     waitKey(0);
100     return 0;
101 }

 效果图:

02-11 18:11