第三节 变换
这里先来简单看一个场景,左边的人在向向外看,右边的是他看到的图像。这里有个明显的区别就是从一个3d的世界变成了2d的图片,这一切就是通过变换完成的。
3d场景变成2d图片
1缩放变换
缩放变换这里我们先对这个图像进行缩放变换,横轴和纵轴都缩放0.5倍,我们可以先用图上下方的方式来表达这个变换。而结合我们之前学过的矩阵,我们可以把它写作这样一个形式.
矩阵形式的表达
上面的缩放是一个均匀的缩放。而如果我们进行一个非均匀的缩放,就会有这样的结果
只对x轴进行缩放这时,我们只要将Sx为1 Sy为0.5 即可表达。
2.反射变换
我们先看一个简单的 沿着y轴变换
反射变换3.切变
切变这里我们来稍微仔细推到下,之后省略此步骤,大同小异。 首先这个变换是只针对于x轴的变换,也就是说对于任何点来说他只发生了x轴方向的变换y轴值没发生变动。而具体x轴变动了多少 需要看这个点的y值是多少。当y值为1时x轴变动了+a也就是说从原来的点 (0,1) 变动到了 (0 + a(1 * a), 0) 也就是说y轴上的每个单位会给x轴带来a的的值变化。同理可推导出来,当x值为0.5时,带来的时 a/2 的值变换 也就是说 x的值会变换 y*a 。
经过上面的我们可以稍微梳理下矩阵的大体含义。
这里我们只看变换矩阵的第一行(红色的)和原来的坐标矩阵。
变换后的值 X' = x * 1 + y * a 也就是说对于这个变换的每个x ,他并不会进行一个倍率的缩放变换(例如*2 放大一倍 或者 0.5 缩小一倍)而是根据y的值进行一个线性的增加
如果在这里我们吧1 变换成2 那么结果就会变成是一个 先对x轴进行一倍的拉伸(拉宽) 然后再统一根据y的值像右拽 ya 个值.。
4.旋转变换s
这我们有个约定俗称
1:在没规定的情况下默认认为沿着原点旋转
2:在没说方向的情况下默认为逆时针
旋转变换
这里矩阵的推导其实和上面类似,我们找到一个点 来看他的
x' 变为了 a * x + b * y
y' 变味了 c * x + d * z
那么找出的
就是我们要的旋转矩阵了。
带入到上面的图中,我们以原图中的 (1,0) 点来看
x轴的值变味了 1 * cosθ y轴的值变成了 1 * sinθ 这两个值就是我们的 a b
而c d 同理,我们吧 (0,1)点带入,即可找到对应的 c d 的值 这就是整体的推导过程。
这里我们可以发现,上面的4种变换都可以写作如下的方式
线性变换我们吧所有可以这样推导的矩阵变换叫做线性变换。而什么是非线性变换呢?我们来看下面的
5.平移变换 & 齐次坐标
这里我们发现我们都是用的相同维度的矩阵乘以对应的变量。那我们能否使用不同维度的相乘呢?
接下来我们就需要引入齐次坐标。
首先我们要明白为什么我们要引入齐次坐标这个概念。我们来看下面的一个变换
平移变换
这里我们可以简单的写出对应的方程:
方程
但这里我们可以发现,我们已经无法用刚才的 ax+by来表示上面的式子了。因为ax+by只能表示变换和xy都是线性相关的变换,而这里我们是一个固定值 tx,之前的方法无法加上一个固定值。
我们只能把它写作如下形式:
先对坐标进行一个线性变换,然后再在此基础上加上偏移量。
然而这个式子直觉上看着就略微。。。不够优雅,并且我们不希望用这么复杂的式子来表示平移这种很简单的变换。所以我们需要会找到一个方法 让他在不同维度下也可以相乘。
于是我们就找到了下面这种解决办法:
对于任何2维的点 我们由原来的 (x,y) ==> (x,y,1)
对于任何2维的向量 我们由原来的 (x,y) ==> (x,y,0)
这里的0和1取决于你是为了表示这个点 还是说代表的是一个向量。
这样对于之前的平移,我们便可以由如下操作来决绝之前的问题
平移矩阵
多出了这个1,我们便可以让他来进行一个常量的变换(平移变换)。而对于其他线性变换,我们可以吧 tx ty变为0 便不会影响线性变换的结果
这里我们思考下为何向量的结尾是0。
我们知道对于一个向量来说,他只有两个关键信息:方向和长度。他无所谓起始点和终止点,只要方向和长度相同,我们便认为两个向量相同。而平移变换他只改变了起始点和终止点的位置,并未改变向量的方向和大小。所以对于向量而言,如果结尾是1 那经过平移计算后的向量便和原向量不相等了。
而在另一方面,对于平面内的一些计算 我们有下面类型
引入其次坐标后的向量与点的计算
例如 点 - 点 = 向量,而这样剪完之后心引入的其次坐标为也会有 1-1 变成0,正好是向量的齐次坐标补充结尾
其他三种我们都可以很简单的理解而对于 点 + 点 我们如何理解呢?
这里对于这种运算有一个扩充:
点+点的扩充
如图,当w为0时,他代表一个向量。而当他不为0时, (x,y,w)他真正代表的点为 (x/w, y/w, 1),也就是说这两种表达时等价的
例如我们举个例子 (1,1,1) + (3,3,1) 的运算结果 为 (4,4,2) <==> (2,2,1) 正好是前两者的中点。也就在引入齐次坐标后,两个点相加的结果时他们的中点。
而对于下面方式可以表示的变换,我们称为放射变换( = 线性变换 + 平移)。
我们可以发现对于二位的仿射变换在引入齐次坐标后,他的最后一行永远是 (0,0,1)(这里只针对二维仿射变换)
tx,ty代表平移的值。
仿射变换
接下来我们把之前的线性变换矩阵引入齐次坐标,就会有
引入齐次坐标之后的线性变换
5.逆变换
逆变换例如我们有个变换矩阵 M 在经过 M 矩阵变换后到了如下位置, 我们可以再经过 M的逆矩阵运算后悔恢复原位。
推导大致如下
A M M(逆) = A (M M(逆))
矩阵 * 自己的逆矩阵 = 单位矩阵
矩阵 * 单位矩阵 = 不变
6.组合变换
例如有如下一个变换,那么我么你是怎么得到的呢?或许我们可以先平移之后再进行旋转(绕原点)
这里我们发现和结果明显不对看来这次常识是失败的。
但我们或许可以这样:
我们先进行一个旋转的操作,再进行平移。这次我们发现结果时正确的。这里我们发现了两个事情很关键:
1:复杂的变换可以拆分为多个简单的变换
2:变换的顺序很关键,顺序不同结果也会不同。
对于第二点,其实矩阵的乘法告诉了我们 因为有
A B != B A
矩阵乘法不满足交换律
这里因为我们是列向量,所以记得是要从右往左乘
这里加入我们要对一个点进行很多个变换 A1,A2,A3......
那么我们就会有这样一个算式
矩阵满足结合律
虽然我们可以通过左边的式子,一个一个的应用变换从右向左
但我们也可以利用矩阵的结合律,现将 An ~ A1 所有的变换结合在一起 最后再乘上我们的点。
我们发现 最后我们只用了1个矩阵,可能就表示刻一个非常非常复杂的变换(只要 An ~ A1所有的矩阵均为 3* 3) 这其实是结合律很好的一个性质,我们可以把一个很复杂的变换用一种很简单的形式表现出来。
6.变换的分解
之前我们的旋转默认都是沿原点旋转,这其实很大幅度上限制了我们的操作空间,那么我们如何能让他沿着任意一点旋转呢?
绕图形左下角点进行旋转
虽然现在我们不会对任意点的旋转,但我们了解对原点的旋转。我们可以先将它平移到原点,旋转θ角度,再平移回去
7.三维变换
那么我们可以想到 三维空间中也会有平移变换,我们依然是需要引入齐次坐标,规则和二维是相同的,各种运算定义也是相同的
三维空间中的齐次坐标引入同样对于三维空间的矩阵,变换引入齐次坐标后如下
三维空间中的仿射变换我们发现对于三维空间中的仿射变换,最后一行还是 0,0,0,1 平移还是在最后一列,左边的3*3任然是代表旋转、缩放等变换。
这里我们思考下 一直说可以把平移和线性变换两种写成一个矩阵,例如上图的矩阵,那么他是先平移还是线性变换呢?
*留白思考
其实是先进行线性变换后平移。因为在我们现在使用的列向量的情况中,运算是左乘 所以其实上面的运算矩阵可以拆分为
平移矩阵(坐上角线性部分为单位矩阵) * 线性变换矩阵 * 要变换的点,例如下图
如果顺序相反由于矩阵不适用结合律 会有错误结果。