透视变换 c++实现

一. 场景说明

已知某个物体的四个角点(比如:车牌、表格等)坐标和对应的图片,如何通过透视变换获得矫正的图片。
原理解析:

  1. 对四个点进行排序(四个点可能是乱序的);
  2. 获得透视变换矩阵;
  3. 获得矫正的图片;

二. 代码实现

#include 
#include 
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"

int sort_points(cv::Point2f points[])
{
    cv::Point2f tempPoint;
    // 按照x轴坐标从小到大排序
    for(int i=0; i<3; i++)
    {
        for(int j=i+1; j<4; j++)
        {
            if(points[i].x > points[j].x)
            {
                tempPoint = points[i];
                points[i] = points[j];
                points[j] = tempPoint;
            }
        }
    }

    // 按照纵坐标排序,坐标顺序为:0左下角 1左上角 2右上角 3右下角
    if(points[0].y < points[1].y)
    {
        tempPoint = points[0];
        points[0] = points[1];
        points[1] = tempPoint;
    }
    if(points[2].y > points[3].y)
    {
        tempPoint = points[2];
        points[2] = points[3];
        points[3] = tempPoint;
    }
    return 0;
}

cv::Mat warp_img(cv::Point2f points[], const cv::Mat image)
{
    cv::Point2f pts_src[4] = {points[0], points[1], points[2], points[3]};
    int img_crop_height = int(sqrt(pow(pts_src[0].x - pts_src[1].x, 2) +
                                   pow(pts_src[0].y - pts_src[1].y, 2)));
    int img_crop_width = int(sqrt(pow(pts_src[1].x - pts_src[2].x, 2) +
                                  pow(pts_src[1].y - pts_src[2].y, 2)));
    cv::Point2f pts_dst[4];
    pts_dst[0] = cv::Point2f(0, img_crop_height - 1);
    pts_dst[1] = cv::Point2f(0, 0);
    pts_dst[2] = cv::Point2f(img_crop_width - 1, 0);
    pts_dst[3] = cv::Point2f(img_crop_width - 1, img_crop_height - 1);
    cv::Mat M = cv::getPerspectiveTransform(pts_src, pts_dst);
    cv::Mat crop_image;
    cv::warpPerspective(image, crop_image, M,
                        cv::Size(img_crop_width, img_crop_height),
                        cv::BORDER_REPLICATE);
    return crop_image;
}

int main()
{
    std::string img_path = "../test.jpg";
    cv::Mat image = cv::imread(img_path);
    cv::Mat image2 = image.clone();

    cv::Point2f points[4];
    points[0] = cv::Point2f(464, 2862);
    points[1] = cv::Point2f(2697, 2925);
    points[2] = cv::Point2f(2706, 3566);
    points[3] = cv::Point2f(431, 3487);
    sort_points(points);

    for(int i=0; i<4; i++)
    {
        cv::circle(image, points[i], 20, cv::Scalar(0,0,255), cv::FILLED, 0);
        std::cout << "points:" << points[i] << std::endl;
    }
    cv::imwrite("../result.jpg", image);

    cv::Mat crop_img = warp_img(points, image2);
    cv::imwrite("../crop_img.jpg", crop_img);
    return 0;
}

三. 效果展示

原图:
透视变换 c++实现_第1张图片
坐标显示:
透视变换 c++实现_第2张图片
透视变换后的图:
透视变换 c++实现_第3张图片

欢迎技术交流:
透视变换 c++实现_第4张图片

你可能感兴趣的:(OpenCV,c++,计算机视觉,opencv)