OpenCv之图像的仿射和透视变化

目录

一、仿射变换

[1.1. 核心原理](#1.1. 核心原理)

1.2.仿射变化核心函数

[1.3 仿射的一些应用](#1.3 仿射的一些应用)

[1.4 一个仿射应用实例代码](#1.4 一个仿射应用实例代码)

二、透视变化

[2.1 核心原理](#2.1 核心原理)

[2.2 计算透视矩阵](#2.2 计算透视矩阵)

[2.3 应用透视变换](#2.3 应用透视变换)

[2.4 应用场景](#2.4 应用场景)

2.5一个透视变化应用的实例代码


一、仿射变换

1.1. 核心原理

仿射变换是二维平面内的线性变换 + 平移 ,本质是:二维坐标 → 二维坐标 的线性映射,保持平直性平行性

  • 平直性:变换后直线依然是直线,不会弯曲。
  • 平行性:变换后平行线依然平行,点的顺序不变。
  • 包含的基础操作:平移、旋转、缩放、错切,以及它们的组合。

1.2.仿射变化核心函数

仿射变化函数

cpp 复制代码
void warpAffine(
    InputArray src,          // 输入图像
    OutputArray dst,         // 输出图像
    InputArray M,            // 2×3 仿射变换矩阵
    Size dsize,              // 输出图像尺寸
    int flags = INTER_LINEAR, // 插值方法
    int borderMode = BORDER_CONSTANT, // 边界填充方式
    const Scalar& borderValue = Scalar() // 边界填充值 默认0黑色不影响图片
);

图像旋转的仿射矩阵getRotationMatrix2D()

专门用于生成 绕某点旋转 + 等比例缩放的仿射矩阵(2×3),是最常用的图像旋转工具。

复制代码
Mat cv::getRotationMatrix2D(
    Point2f center,  // 旋转中心坐标 (x, y)
    double angle,    // 旋转角度(单位:度),正值=逆时针
    double scale     // 整体缩放因子(不缩放填1)
);

核心参数含义

  • center :图像旋转的中心点(比如图像中心 Point2f(cols/2, rows/2)),绕该点旋转不会让图像偏移。
  • angle :角度单位是正值为逆时针旋转 (比如 90 是逆时针转 90°,-90 是顺时针转 90°)。
  • scale :两个轴的统一缩放因子(scale=0.5 表示缩小一半,scale=2 表示放大一倍)。

三点对应法计算仿射变换矩阵getAffineTransform()

  • 计算矩阵 M:需要3 组不共线的对应点(原坐标 → 目标坐标),仿射变换有 6 个未知参数(2×3 矩阵),每组对应点提供 2 个方程,3 组点刚好解出 6 个参数。。

    Mat getAffineTransform(
    const Point2f src[], // 原图像3个点
    const Point2f dst[] // 目标图像3个对应点
    );

1.3 仿射的一些应用

  • 图像校正:将倾斜的文档 / 证件转正。
  • 数据增强:深度学习训练时,对图像做旋转 / 平移 / 缩放,扩充样本。
  • 图像拼接:对齐多张图像的视角。
  • UI 交互:图片拖动、旋转、拉伸等操作。

1.4 一个仿射应用实例代码

cpp 复制代码
void testFangShe()
{
	Mat ColorMat = imread(R"(D:\Study\OpenCvStudy\lean.jpg)", ImreadModes::IMREAD_COLOR);
	
	//图像旋转
	Mat rotaion0, img_wrap0;
	double angle = 30;
	Point2f center(ColorMat.rows/2,ColorMat.cols/2);
	rotaion0 = getRotationMatrix2D(center,angle,1);
	warpAffine(ColorMat, img_wrap0, rotaion0, Size(2*ColorMat.cols, 100+ColorMat.rows));
	namedWindow("逆时针旋转30度", WindowFlags::WINDOW_NORMAL);
	imshow("逆时针旋转30度",img_wrap0);

	//三点法确定仿射变化矩阵
	 // 1. 定义3组对应点(原坐标 → 目标坐标)
	Point2f srcPoints[3] = {
		Point2f(0, 0),          // 左上角
		Point2f(ColorMat.cols - 1, 0),  // 右上角
		Point2f(0, ColorMat.rows - 1)   // 左下角
	};
	Point2f dstPoints[3] = {
		Point2f(50, 50),                // 目标左上角
		Point2f(ColorMat.cols - 1 + 50, 50),     // 目标右上角
		Point2f(50, ColorMat.rows - 1 + 50)      // 目标左下角
	};

	Mat rotation1, img_warp1;
	rotation1 = getAffineTransform(srcPoints, dstPoints);
	warpAffine(ColorMat, img_warp1, rotation1, Size(ColorMat.cols+60, ColorMat.rows + 60));
	namedWindow("三点法变换", WindowFlags::WINDOW_NORMAL);
	imshow("三点法变换", img_warp1);
	waitKey();
}

二、透视变化

2.1 核心原理

透视变换是三维空间到二维平面的投影变换

透视变换本质是将三维空间投影到二维平面 的单应性变换(Homography),也叫四点变换(因为需要 4 组对应点求解矩阵)。

2.2 计算透视矩阵

getPerspectiveTransform()

复制代码
Mat cv::getPerspectiveTransform(
    const Point2f src[],  // 原图4个点(任意3点不共线)
    const Point2f dst[],  // 目标图4个对应点
    int solveMethod = DECOMP_LU  // 矩阵求解方法(默认LU分解)
);
  • 参数说明
    • src[] / dst[]:各 4 个点,必须一一对应,且任意 3 点不共线(否则矩阵不可逆)。

    • solveMethod:求解线性方程组的方法,常用选项:

      标志 含义 适用场景
      DECOMP_LU LU 分解(默认) 速度快,精度高
      DECOMP_SVD 奇异值分解 数值更稳定,适合点有噪声的情况
      DECOMP_EIG 特征值分解 特征值问题场景

2.3 应用透视变换

warpPerspective()

复制代码
void cv::warpPerspective(
    InputArray src,          // 输入图像
    OutputArray dst,         // 输出图像
    InputArray M,            // 3×3 透视变换矩阵
    Size dsize,              // 输出图像尺寸
    int flags = INTER_LINEAR, // 插值方法(同resize)
    int borderMode = BORDER_CONSTANT, // 边界填充方式
    const Scalar& borderValue = Scalar() // 边界填充值
);
  • 关键参数
    • M:必须是 3×3 的单应性矩阵。
    • flags:插值方法,推荐 INTER_LINEAR(默认)或 INTER_CUBIC(高清场景)。
    • borderMode:变换后超出图像区域的填充方式,默认黑色填充。

2.4 应用场景

  1. 文档 / 证件矫正:将倾斜拍摄的文档、身份证、发票转正为俯视视角(最常用场景)。
  2. AR 增强现实:将虚拟物体(如贴纸、模型)贴到真实平面上。
  3. 全景拼接:多张相邻图像通过单应性矩阵对齐,拼接成全景图。
  4. 视角转换:将斜视图、鸟瞰图转换为正视图(如自动驾驶的鸟瞰图)。
  5. 图像校正:纠正相机拍摄时的透视畸变(如广角镜头的边缘变形)。

2.5一个透视变化应用的实例代码

以下是通过透视变化矫正拍摄不正的二维码。

cpp 复制代码
void testPesPective()
{
	Mat ColorMat = imread(R"(D:\Study\OpenCvStudy\QRCode.png)", ImreadModes::IMREAD_COLOR);
	Point2f src_points[4],dst_points[4];
	src_points[0] = Point2f(58.0, 236.0);
	src_points[1] = Point2f(333.0, 0.0);
	src_points[2] = Point2f(264.0, 574.0);
	src_points[3] = Point2f(458.0, 322.0);

	dst_points[0] = Point2f(29.0,78.0);
	dst_points[1] = Point2f(473.0, 78.0);
	dst_points[2] = Point2f(29.0, 531.0);
	dst_points[3] = Point2f(473.0, 531.0);

	Mat T_Mat = getPerspectiveTransform(src_points, dst_points);
	Mat TransFormQRcode;
	warpPerspective(ColorMat, TransFormQRcode, T_Mat, Size(509, 575));
	imshow("未矫正二维码", ColorMat);
	imshow("透视矫正二维码",TransFormQRcode);
	waitKey();
}
相关推荐
码农垦荒笔记2 小时前
OpenClaw实战 #07:从 0 写一个自定义 Skill——让 AI 自动同步 Notion 待办到飞书(完整代码)
人工智能·飞书·notion
lpfasd1232 小时前
2026创业风向:做一款“AI陪伴成长”App,是风口还是雷区?
人工智能
ECT-OS-JiuHuaShan2 小时前
朱梁万有递归元定理,解构西方文明中心论幻觉
开发语言·人工智能·php
茗创科技2 小时前
JNeurosci|盲人与非盲人的枕叶皮层中阅读与言语的相似计算层级:来自 fMRI 与计时经颅磁刺激(TMS)的汇聚证据
机器学习·脑网络·神经科学
Aubrey-J2 小时前
练习开发Skill——网页内容抓取Skill(website-content-fetch)
开发语言·人工智能
超自然祈祷2 小时前
从gym到gymnasium的倒立摆
人工智能·机器学习
GEO_Huang2 小时前
企业智脑如何生成决策方案?数谷的AI定制化服务的深度在哪?
大数据·人工智能·rpa·geo·ai定制·企业ai智能体定制
星浩AI2 小时前
清华团队开源!我给孩子制作了 AI 互动课堂,手把手教你给孩子做一个
人工智能·后端·github
图图的点云库2 小时前
点云深度学习算法概述
人工智能·深度学习·算法