前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >五分钟学会如何利用矩阵进行平面坐标系转换

五分钟学会如何利用矩阵进行平面坐标系转换

作者头像
阿利民
发布2022-05-16 12:55:12
2.4K0
发布2022-05-16 12:55:12
举报
文章被收录于专栏:阿利民

背景

在图形图像领域,矩阵是一个应用广泛,且极其重要的工具。简单的,我们在OpenGL的Shader中,可以利用矩阵进行视图变换,比如透视、投影等。但本文不打算讨论这些内容,而是聚焦在如何利用矩阵把坐标从一个坐标系变换到另一个坐标系,并且保证坐标的相对位置不变,即计算一个坐标系上的点在另一个坐标系的投影。本文只探讨平面坐标系的问题,并且假设读者对矩阵知识有一定的了解,如果对矩阵比较陌生,建议先复习一下这部分知识。

通常,一个成熟的图像处理软件会(比如大名鼎鼎的Photoshop)引入这些概念,图层、画布和窗口。图层是软件的直接处理对象,简单的一张图片就可以作为一个图层,图层通常不止一个,并且会有各种各样的操作,比如缩放、旋转和位移;画布则是所有图层的载体,对图层的各种处理结果会直接表现在画布上,简单说画布就是图像的最终处理结果;而窗口则是画布的载体,只是简单的显示画布,不会直接和图层进行耦合,但是操作图层的坐标通常源于窗口。

这种分层结构使得图像的处理逻辑变得清晰,但同时也变得更为复杂。一个典型的问题,点击窗口上的点P,然后在图层上绘制一个点P`,使得点P与点P`在窗口上重合(点P在图层上的投影)。注意,由于图层会缩放、旋转和位移,所以点P与点P`的坐标通常不会相等,点P需要通过一系列计算才能得出点P`的坐标,而矩阵就是可以进行这种关系计算的数学工具。

定义问题

上面提到了图层、画布、窗口三种结构,实际上对应着一个三层嵌套坐标系统,它们有这样的关系,窗口坐标系作为整个坐标系统的根,是画布坐标系的直接父级坐标系,同样的画布坐标系是图层坐标系的直接父级坐标系。三个坐标系的转换计算看起来很复杂,但实际上我们只要找出其中两个坐标系的矩阵计算方法,即可推广到所有坐标系,不管坐标系统有多少层级。

如下图,坐标系统由xOy、x`O`y`两个坐标系组成,分别对应画布坐标系、图层坐标系,那么容易得出坐标系转换问题的数学定义。

已知O(0, 0)、O`(0, 0)分别是两个坐标系的原点,点O`在坐标系xOy中的坐标为(1, 3),P(3, 4)是xOy上的一点,∠α=30°,求点P在x`O`y`上的投影P`的坐标值。这是一个典型的矩阵运算问题。

我们知道,对坐标系上的点进行缩放、旋转和位移,使用4x4矩阵表示如下。由于本文只探讨平面坐标系中的问题,但是为了表示第三维的存在,所以在单位矩阵中z轴的值为1。矩阵的第四维是为了解决位移无法使用3x3矩阵表示的问题而引入的齐次坐标。

假设缩放、旋转和位移矩阵分别为Ms、Mr、Mt,那么总的变换矩阵M可以表示如下。交换律不适用于矩阵乘法,所以顺序很重要。注意,矩阵表示的顺序和实际的变换顺序是相反的。

解决问题

了解变换矩阵后,我们重新回到坐标变换的问题,这里为了简化问题,暂且忽略坐标系的缩放,那么解决问题可以分为以下两步:

  1. 第一步,只考虑位移不考虑旋转,此时两个坐标系的状态如图一,设旋转前的x`O`y`上有一点P`,坐标值与点P(3, 4)相等,已知点O`在xOy上点坐标值为(1, 3),若P`向x`轴位移-1,向y`轴位移-3,即位移向量为(-1, -3),那么x`O`y`上的P`将与xOy上的点P重合 。
  2. 第二步,在第一步的基础上接着考虑旋转问题,让x`O`y`绕点O`旋转∠α=30°。如图二,此时点P`与点P不再重合。如果让P`反向旋转∠α,P`与点P将再次重合,最终算得P在x`O`y`上的投影,如图3。

至此,我们容易得出下面的坐标变换矩阵计算式,点P(3, 4)位移(-1, -3) 后,反向旋转∠α,最终点P`坐标约为(1.232, 1.866)。

接下来考虑坐标系的缩放的问题,设x`O`y`的x`和y`缩放系数分别为sx、sy,同理可以得出缩放矩阵。同旋转位移一样,所求坐标的缩放系数与x`O`y`的相反。代入公式容易得出以下计算式。

到这里我们就可以在保持相对位置不变的前提下,把坐标从一个坐标系变换到另一个坐标系了。这类应用还有很多,如已知窗口上一个裁剪框的坐标,要求对画布上的图层进行裁剪,再比如画笔等。需要注意的是,OpenGL坐标系都是归一化的,需要利用投影矩阵再计算一次才能实际应用到Shader中,当然也可以把矩阵放到Shader计算,只是和CPU同步比较困难。最终源码参考Al2DCoordinate.cpp实现。

hwvc项目:

https://github.com/imalimin/hwvc/tree/develop

Al2DCoordinate源码:https://github.com/imalimin/hwvc/blob/develop/src/al_common/math/Al2DCoordinate.cpp

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 阿利民 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 定义问题
  • 解决问题
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档