透视变换 c++实现

一. 场景说明

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

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

二. 代码实现

#include <iostream>
#include <string>
#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;
}

三. 效果展示

原图:
在这里插入图片描述
坐标显示:
在这里插入图片描述
透视变换后的图:
在这里插入图片描述

欢迎技术交流:
在这里插入图片描述

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值