Affine Transformations仿射变换

news2024/9/28 21:24:33

在这里插入图片描述

什么是仿射变换

仿射变换(Affine Transformation)是数学和计算机图形学中的一种线性变换,它包括了平移、旋转、缩放、剪切等操作。仿射变换保留了几何图形的“仿射性质”,即平行线在变换后仍然平行,线性组合在变换后仍然是线性组合,并且保持点的相对顺序和比例关系,但不一定保持角度和距离。

在二维空间中,仿射变换可以用一个 2 × 2 2 \times 2 2×2 的矩阵和一个 2 × 1 2 \times 1 2×1 的平移向量来表示。具体来说,如果我们有一个点 ( x , y ) (x, y) (x,y),其变换后的新位置 ( x ′ , y ′ ) (x', y') (x,y)

可以通过以下公式得到:

在这里插入图片描述

其中,矩阵 ( a b c d ) \begin{pmatrix} a & b \\ c & d \end{pmatrix} (acbd) 描述了旋转、缩放和剪切,向量 ( e f ) \begin{pmatrix} e \\ f \end{pmatrix} (ef)描述了平移。

在更高维的空间中,仿射变换的概念类似。对于三维空间,变换可以表示为一个 3 × 3 3 \times 3 3×3 的矩阵加上一个 3 × 1 3 \times 1 3×1 的平移向量。

仿射变换广泛应用于计算机视觉、图像处理、计算机图形学、地理信息系统(GIS)、机器人学等领域。

如何进行仿射变换

我们可以通过对某些矩阵进行点积来执行对任何图像的转换。在下面,您可以看到一些使用的转换和矩阵。

在这里插入图片描述
下面是使用矩阵对图像进行仿射变换的函数。

def warpAffine(image, M, output_shape):
    rows, cols, *_ = image.shape
    out_rows, out_cols, *_ = output_shape

    output = np.zeros(output_shape, dtype=image.dtype)

    for out_row in range(out_rows):
        for out_col in range(out_cols):
            # Calculate the corresponding pixel coordinates in the input image
            in_col, in_row, _ = np.dot(M, [out_col, out_row, 1]).astype(int)

            # Check if the pixel coordinates are within the bounds of the input image
            if 0 <= in_row < rows and 0 <= in_col < cols:
                output[out_row, out_col, :] = image[in_row, in_col, :]

    return output

if __name__ == '__main__':
    img = cv2.imread('./panda.jpg')
    th = np.radians(45)
    M = np.float32([[np.cos(th), np.sin(th), -400], [-np.sin(th), np.cos(th), 250], [0, 0, 0]])
    shape = (img.shape[0] + 400, img.shape[1] + 400, img.shape[2])
    res = warpAffine(img, M, shape)

    plt.subplot(121)
    plt.title("Original")
    plt.imshow(img)
    plt.subplot(122)
    plt.title("Transformed")
    plt.imshow(res)
    plt.tight_layout()
    plt.show()

在这里插入图片描述
好吧,这样做很好,但如果我们不知道使用什么矩阵,又如何进行转换呢?

如果您可以通过给出三个 (x, y) 点(如 src 和 dst)来表达您的转换,那么我们可以轻松完成该转换。

如果您的输入如下所示,

在这里插入图片描述
你想要解的方程如下所示,

在这里插入图片描述
由于 SRC 是方阵,因此我们可以通过将 inv(SRC) 与 DST 进行矩阵乘法来计算矩阵 M 。

下面是 python 函数。

def getAffineTransform(src, dst):
    src = np.array([[x, y, 1] for (x, y) in src])

    M = np.linalg.inv(src) @ dst
    ''' or '''
    # M = np.linalg.solve(src, dst)

    return M.T

if __name__ == '__main__':
    def r():
        return (random.random() - 0.5) * .3 * cols

    _from = np.float32([[0, 0], [cols, rows], [0, rows]])
    _to = np.float32([[r(), r()], [cols + r(), rows + r()], [r(), rows + r()]])

    M = getAffineTransform(_from, _to)
    M = np.vstack([M, [0, 0, 0]])
    dst = warpAffine(img, M, img.shape)

    plt.figure(figsize=(20, 10))
    plt.subplot(121)
    plt.title("Original")
    plt.imshow(img)
    plt.subplot(122)
    plt.title("Transformed")
    plt.imshow(dst)
    plt.tight_layout()
    plt.show()

在这里插入图片描述
好了,现在我们知道如何变换了,但是我们如何反转变换呢?

我们可以使用仿射矩阵的逆对图像执行 warpAffine,请记住,只有当变换后的图像具有原始形式的所有数据时,我们才能将图像反转为精确的原始形式。

下面是 invertAffineTransform 的代码块,

def invertAffineTransform(M):
    # Extract the rotation and translation components of the affine matrix
    R = M[:2, :2]
    t = M[:2, 2]

    # Compute the inverse of the rotation matrix
    R_inv = np.linalg.inv(R)

    # Compute the inverse affine transformation matrix
    M_inv = np.zeros((2, 3), dtype=np.float32)
    M_inv[:2, :2] = R_inv
    M_inv[:2, 2] = -np.dot(R_inv, t)

    return M_inv

if __name__ == '__main__':
    M_inv = invertAffineTransform(M)
    M_inv = np.vstack([M_inv, [0, 0, 0]])

    res_inv = warpAffine(res, M_inv, img.shape)

    plt.figure(figsize=(20, 10))
    plt.subplot(121)
    plt.title("Transformed")
    plt.imshow(res)
    plt.subplot(122)
    plt.title("InvTransformed")
    plt.imshow(res_inv)
    plt.tight_layout()
    plt.show()

在这里插入图片描述

结论

我希望您现在对仿射变换及其背后的数学有了清晰的了解。

当您处理现实世界的项目时,您不必做所有这些努力,您可以使用 OpenCV 等库来满足您的需求。在使用 OpenCV 的 Python 中,您可以执行如下所示的解释算法:

img = cv2.imread('<path-to-img>')

th = np.radians(20)
M = np.float32([[np.cos(th), np.sin(th), 100], [-np.sin(th), np.cos(th), 250]])
shape = (img.shape[0] + 400, img.shape[1] + 400)
rows, cols, _ = img.shape

def r():
    return (random.random() - 0.5) * .3 * cols


res = cv2.warpAffine(img, M, shape)


_from = np.float32([[0, 0], [cols, rows], [0, rows]])
_to = np.float32([[r(), r()], [cols + r(), rows + r()], [r(), rows + r()]])

M = cv2.getAffineTransform(_from, _to)
dst = cv2.warpAffine(img, M, shape)

M_inv = cv2.invertAffineTransform(M)
res_inv = cv2.warpAffine(res, M_inv, (img.shape[0], img.shape[1]))

参考

https://github.com/OlehOnyshchak/ImageTransformations/blob/master/AffineTransformation.ipynb

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2052391.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电机预测性维护模组

设备简介 本模组为了对电机进行预测性运维而开发&#xff0c;可以采集电机的 3 路加速度振动传感器、3 路电流&#xff08;电机供电互感器输出信号&#xff09;、1 路转速&#xff08;电机转速&#xff09;、8 路温度&#xff08;PT100 温度传感器&#xff09;。 模组计算振动…

一文带你看懂安全生产管理系统

通过集成多种先进技术和设备&#xff0c;实现对企业安全生产全过程的智能化、精细化管理。系统分为五个核心层面&#xff0c;各层面相互协作&#xff0c;共同确保企业的安全生产。 1. 数据采集层 设备终端&#xff1a;利用防爆终端、防爆平板、无线传感器、电子标签、定位设备、…

WinForm DataGridView整行选中并且checkbox勾选

WinForm DataGridView选中行设置 文章目录 WinForm DataGridView选中行设置添加checkbox列列和选中行效果选中行代码 添加checkbox列 列和选中行效果 选中行代码 public Basic_configuration(){InitializeComponent();...........//添加鼠标事件this.dataGridView_basic.CellMo…

node.js: mssql2019 sequelize6 es6+ ORM in vscode and WebStorm 2023.1

mssql: insert into [dbo].[tutorials]([title],[description],[published],[createdAt],[updatedAt]) values(N涂聚文,N涂聚文,0,2025-05-04,2025-05-04); go insert into [dbo].[tutorials]([title],[description],[published],[createdAt],[updatedAt]) values(Ngeovindu,N…

实战OpenCV之图像的属性

基础入门 图像的属性指的是描述图像基本信息的数据&#xff0c;包括但不限于&#xff1a;图像的尺寸、颜色通道数、像素数据类型等。这些属性对于图像处理非常重要&#xff0c;因为它们直接关系到如何正确地读取、处理和存储图像。常见的图像属性包括&#xff1a; 尺寸&#xf…

WandB 简明教程【Weights Bias】

在机器学习实验领域&#xff0c;调整超参数类似于微调复杂机器的旋钮和刻度盘。这些参数通常很微妙但至关重要&#xff0c;能够显著影响我们模型的性能和行为。WandB&#xff08;权重和偏差 ) 是一个强大的在线工具集&#xff0c;旨在简化模型训练、评估和分析的过程。 随着我…

TCP shutdown 之后~

目录 摘要 1 API 2 shutdown(sockfd, SHUT_WR) 3 shutdown(sockfd, SHUT_WR) 4 kernel 是怎么做的&#xff1f; 附 摘要 通过 shutdown() 关闭读写操作&#xff0c;会发生什么&#xff1f;具体点呢&#xff0c;考虑两个场景&#xff1a; 场景一&#xff1a;C 发送数据完毕…

VBA技术资料MF184:图片导入Word添加说明文字设置格式

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

C ++初阶:C++入门级知识点

&#x1f37a;0.前言 言C之言&#xff0c;聊C之识&#xff0c;以C会友&#xff0c;共向远方。各位博友的各位你们好啊&#xff0c;这里是持续分享C知识的小赵同学&#xff0c;今天要分享的C知识是C入门知识点&#xff0c;在这一章&#xff0c;小赵将会向大家展开聊聊C入门知识…

基于Mediapipe的手势识别系统 | OpenCV | Mediapipe | C++ | QT | Python | C# | Unity

基于Mediapipe的手势识别系统 OpenCV、Mediapipe C (QT)、Python (PyCharm)、C# (Visual Studio) Unity 3D 登录界面 图片手势识别 视频文件手势识别 摄像头实时手势识别 演示视频 基于Mediapipe的手势识别系统

UDP和TCP协议段格式分析

目录 UDP协议 特点 UDP协议的缓冲区 UDP协议段格式 TCP协议 特点 如何理解TCP是传输控制协议&#xff1f; TCP协议段格式 四位首部长度 16位窗口大小 32位序号 32位确认序号 TCP/IP四层模型&#xff1a; UDP协议 UDP&#xff08;User Datagram Protocol &#xff…

十大护眼落地灯品牌哪款好?十大护眼落地灯品牌

十大护眼落地灯品牌哪款好&#xff1f;根据国际市场的研究数据表明&#xff0c;我国在日常生活中对电子产品的依赖度极高&#xff0c;每天看电子产品的时间超过8小时&#xff0c;出现眼睛酸痛、干涩、视觉疲劳的人群也不再少数&#xff0c;而给眼睛带来伤害的除了电子产品中所含…

界面控件DevExpress ASP.NET Web Forms v24.1最新版本系统环境配置要求

本文档包含有关安装和使用 DevExpress ASP.NET Web Forms控件的系统要求的信息。 点击获取DevExpress v24.1正式版 .NET Framework DevExpress ASP.NET Web Forms控件支持以下.NET框架版本。 如果您需要 DevExpress 产品的早期版本&#xff0c;请直接戳这里联系我>> …

MySQL中的EXPLAIN的详解

一、介绍 官网介绍&#xff1a; https://dev.mysql.com/doc/refman/5.7/en/explain-output.htmlhttps://dev.mysql.com/doc/refman/8.0/en/explain-output.htmlexplain&#xff08;执行计划&#xff09;&#xff0c;使用explain关键字可以模拟优化器执行sql查询语句&#xff…

爆火的本地知识库项目是什么?什么是RAG?本地知识库与大模型的关系

“ 本地知识库就相当于大模型的外部资料库。” 很多人应该都听过本地知识库项目&#xff0c;它是当今人工智能领域爆火的项目之一&#xff0c;那么到底什么是本地知识库&#xff1f;它和大模型有什么关系&#xff1f;怎么构建本地知识库&#xff1f; 01 — 为什么需要本地知…

Docker的介绍、保姆级安装和使用

一、Docker简介 1.1、Docker是什么 Docker是一个用于开发、发布和运行应用程序的开放平台;使您能够将应用程序与基础设施分离,以便您可以快速交付软件。不像虚拟机那样笨重(比如:我需要将一个安装好nginx环境的内容分享给其他人: 方式一【使用虚拟】(应用程序Nginx与基…

系统架构设计师 - 软件工程(2)

软件工程 软件工程&#xff08;13-22分&#xff09;非常重要软件系统建模系统设计界面设计 ★★软件设计结构化设计 ★★面向对象设计 ★★★★★基本过程设计原则设计模式创建型模式&#xff1a;创建对象结构型模式&#xff1a;更大的结构行为型模式&#xff1a;交互及职责分配…

四川财谷通信息技术有限公司抖音小店优势解析

在数字经济蓬勃发展的今天&#xff0c;电商平台如雨后春笋般涌现&#xff0c;其中&#xff0c;四川财谷通信息技术有限公司旗下的抖音小店凭借其独特的优势和强大的实力&#xff0c;在众多竞争者中脱颖而出&#xff0c;成为消费者和商家信赖的优选平台。本文将详细解析四川财谷…

Windows键快捷键大全

Windows键快捷键大全 Windows键结合其他键可以执行多种快捷操作&#xff0c;以下是一些常用的Windows键快捷键&#xff1a; Windows键 D: 显示或隐藏桌面。Windows键 E: 打开文件资源管理器。Windows键 L: 锁定电脑。Windows键 R: 打开运行对话框。Windows键 I: 打开Win…

Java中JDK动态代理

参考&#xff1a;疯狂Java讲义 第18章 文章目录 前言复杂度与耦合的矛盾 使用JDK动态代理总结 前言 复杂度与耦合的矛盾 开发实际应用的软件系统时&#xff0c;通常会存在相同代码段重复出现的情况&#xff0c;在这种情况下&#xff0c;一般都提取为一个方法&#xff0c;在不…