15.OpenCV透视变换

OpenCV透视变换

  本文是对上一篇的补充。透视变换(Perspective Transformation)是一种常见的几何变换,用于将图像从一种视角转换到另一种视角。它广泛应用于文档校正、车道检测、增强现实(AR)以及图像拼接等场景。本文将带你深入了解透视变换的数学原理、如何利用 OpenCV 实现透视变换,并通过示例代码展示实际应用。

1. 透视变换原理

透视变换基于投影变换理论,其数学表达式如下:

[ x ′ y ′ w ′ ] = [ M 11 M 12 M 13 M 21 M 22 M 23 M 31 M 32 M 33 ] [ x y 1 ] \begin{bmatrix} x' \\ y' \\ w' \end{bmatrix}=\begin{bmatrix} M_{11} & M_{12} & M_{13} \\ M_{21} & M_{22} & M_{23} \\ M_{31} & M_{32} & M_{33} \end{bmatrix}\begin{bmatrix} x \\ y \\ 1 \end{bmatrix} xyw = M11M21M31M12M22M32M13M23M33 xy1

通过将x′和y′分别除以w′得到最终映射到图像上的坐标:

x ′ ′ = x ′ w ′ x'' = \frac{x'}{w'} x′′=wx

y ′ ′ = y ′ w ′ y'' = \frac{y'}{w'} y′′=wy

这里的 3×3 变换矩阵(通常记为M)定义了原图到目标图的映射关系。在 OpenCV 中,我们可以利用两个点集来计算该矩阵。

2. OpenCV 中透视变换的实现

OpenCV 为透视变换提供了两个主要函数:

  • cv::getPerspectiveTransform

    根据原始点集和目标点集计算透视变换矩阵。

Mat cv::getPerspectiveTransform(const Point2f src[], const Point2f dst[]);
  • cv::warpPerspective

    根据计算得到的透视矩阵对图像进行变换,并输出变换后的图像。

void cv::warpPerspective(InputArray src, OutputArray dst, InputArray M, Size dsize);

这两个函数组合使用,可以实现从任意四边形到目标矩形(或其他四边形)的透视变换。

3. 示例代码

3.1 非交互式透视变换

在本示例中,我们手动指定原始图像中待变换区域的四个顶点,并将其映射到一个标准矩形。

适用于预先已知四个点坐标的场景,如文档校正。

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    // 读取图像(确保图像路径正确)
    Mat img = imread("E:/image/lena.png");
    if (img.empty()) {
        cerr << "无法加载图像!" << endl;
        return -1;
    }

    int img_height = img.rows;
    int img_width = img.cols;

    // 定义原始图像的四个角点(按顺时针或逆时针顺序)
    vector<Point2f> corners(4);
    corners[0] = Point2f(0, 0);
    corners[1] = Point2f(img_width - 1, 0);
    corners[2] = Point2f(0, img_height - 1);
    corners[3] = Point2f(img_width - 1, img_height - 1);

    // 定义目标图像中的四个点
    vector<Point2f> corners_trans(4);
    corners_trans[0] = Point2f(150, 250);
    corners_trans[1] = Point2f(771, 0);
    corners_trans[2] = Point2f(0, img_height - 1);
    corners_trans[3] = Point2f(650, img_height - 1);

    // 计算透视变换矩阵
    Mat transform = getPerspectiveTransform(corners, corners_trans);
    cout << "透视变换矩阵:" << endl << transform << endl;

    // 使用 warpPerspective 应用透视变换
    Mat img_trans;
    warpPerspective(img, img_trans, transform, img.size());

    imshow("原始图像", img);
    imshow("透视变换后图像", img_trans);
    waitKey(0);
    return 0;
}

在这里插入图片描述

3.2 交互式鼠标选择透视变换点

在交互式示例中,我们通过鼠标点击在图像上选取四个点,动态标记选取点,然后根据用户选择的点进行透视变换。该方法更灵活,适用于实际应用中无法预知准确点坐标的情况。

#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>

using namespace cv;
using namespace std;

Mat image;
vector<Point2f> selectedPoints;

// 鼠标回调函数:用于选取透视变换的四个点
void mouseHandler(int event, int x, int y, int flags, void* userdata) {
    if (event == EVENT_LBUTTONDOWN) {
        Point2f pt(x, y);
        selectedPoints.push_back(pt);
        cout << "选取点: (" << x << ", " << y << ")" << endl;
        circle(image, pt, 5, Scalar(0, 0, 255), -1);
        imshow("选择点", image);
    }
}

int main() {
    // 读取图像
    image = imread("E:/image/lena.png");
    if (image.empty()) {
        cerr << "无法加载图像!" << endl;
        return -1;
    }

    // 显示图像并绑定鼠标事件
    imshow("选择点", image);
    setMouseCallback("选择点", mouseHandler);

    cout << "请在图像上点击四个角点,然后按任意键进行透视变换" << endl;
    waitKey(0);

    if (selectedPoints.size() != 4) {
        cerr << "必须选择4个点!" << endl;
        return -1;
    }

    // 定义目标图像上的四个点,将转换为 500x400 的矩形
    vector<Point2f> dstPoints;
    dstPoints.push_back(Point2f(0, 0));
    dstPoints.push_back(Point2f(500, 0));
    dstPoints.push_back(Point2f(0, 400));
    dstPoints.push_back(Point2f(500, 400));

    // 计算透视变换矩阵
    Mat perspectiveMatrix = getPerspectiveTransform(selectedPoints, dstPoints);

    // 进行透视变换
    Mat warpedImage;
    warpPerspective(image, warpedImage, perspectiveMatrix, Size(500, 400));

    // 显示透视变换后的图像
    imshow("透视变换结果", warpedImage);
    waitKey(0);
    return 0;
}

在这个示例中:

  • 用户点击图像选取四个点后,通过鼠标回调函数将选取点绘制到图像上。
  • 当选取完毕后按任意键后,程序计算透视变换矩阵,并将选取的区域映射到预设目标矩形上,实现文档或目标区域的校正。

4. 透视变换的应用场景介绍

透视变换技术在实际项目中有着广泛应用,主要包括:

  • 文档校正:对手机拍摄的书页、名片、票据等图像进行校正,使其恢复为标准矩形,便于后续 OCR(光学字符识别)处理。
  • 车道检测:在自动驾驶系统中,将摄像头拍摄的道路图像透视变换为鸟瞰图,有助于车道线检测和车辆定位。
  • 增强现实(AR):通过透视变换将虚拟图像投影到真实物体表面,实现虚实结合的效果。
  • 图像拼接:在全景图制作过程中,对多个重叠图像进行透视变换,便于图像之间的无缝拼接。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值