变换矩阵概述
什么是变换矩阵?百度百科中的解释是:变换矩阵是数学线性代数中的一个概念,在线性代数中,线性变换能够用矩阵来表示;如果
T
{T}
T是一个把
R
n
{R_n}
Rn映射到
R
m
{R_m}
Rm的线性变换,且
x
{x}
x是一个具有
n
{n}
n个元素的列向量,那么我们把
m
×
n
{m \times n}
m×n的矩阵
A
{A}
A称为
T
{T}
T的变换矩阵。其中,
x
{x}
x是
R
n
{R_n}
Rn上的一个向量,经过和变换矩阵
A
{A}
A相乘之后,就能映射到
R
m
{R_m}
Rm空间中。
而在图形学中,变换矩阵举足轻重,一切物体的缩放、旋转、位移等操作都可以通过变换矩阵作用得到。下面介绍图形学中常用的几种变换矩阵,其中最为重要的是齐次坐标的应用。
2维线性变换
我们假设
[
a
1
a
2
a
3
a
4
]
\begin{bmatrix}a_1 & a_2 \\ a_3 & a_4\end{bmatrix}
[a1a3a2a4]是一个变换矩阵,则2D线性变换可以表示为:
[
a
1
a
2
a
3
a
4
]
[
x
y
]
=
[
a
1
x
a
2
y
a
3
x
a
4
y
]
\begin{bmatrix}a_1 & a_2 \\ a_3 & a_4\end{bmatrix} \begin{bmatrix}x \\ y\end{bmatrix} = \begin{bmatrix}a_1x & a_2y \\ a_3x & a_4y\end{bmatrix}
[a1a3a2a4][xy]=[a1xa3xa2ya4y]
缩放(Scale)
缩放是指将物体沿着坐标轴进行压缩或者拉伸的操作,假设有一个坐标
(
x
,
y
)
{(x, y)}
(x,y),经过缩放之后变成
(
x
′
,
y
′
)
{(x', y')}
(x′,y′),其中
x
′
=
s
x
x
,
y
′
=
s
y
y
{x'=s_xx,y'=s_yy}
x′=sxx,y′=syy,
s
x
{s_x}
sx和
s
y
{s_y}
sy称为缩放比例系数,当
s
x
=
s
y
{s_x=s_y}
sx=sy时称为等比例缩放,否则成为非等比例缩放。
为了使得
x
′
=
s
x
x
,
y
′
=
s
y
y
{x'=s_xx,y'=s_yy}
x′=sxx,y′=syy,我们可以将变换矩阵定义为:
s
c
a
l
e
(
s
x
,
s
y
)
=
[
s
x
0
0
s
y
]
scale(s_x, s_y)=\begin{bmatrix}s_x & 0 \\ 0 & s_y\end{bmatrix}
scale(sx,sy)=[sx00sy]
所以,原来的矩阵与它相乘后变成:
[
s
x
0
0
s
y
]
[
x
y
]
=
[
s
x
x
s
y
y
]
\begin{bmatrix}s_x & 0 \\ 0 & s_y\end{bmatrix} \begin{bmatrix}x \\ y\end{bmatrix} = \begin{bmatrix}s_xx \\ s_yy\end{bmatrix}
[sx00sy][xy]=[sxxsyy]
也就是说,除了原点不动外,其他点都变成了
(
s
x
x
,
s
y
y
)
T
{(s_xx, s_yy)^T}
(sxx,syy)T,即沿着坐标轴比例进行了缩放。下面举两个例子:
切变(Shearing)
切变是指把一体的一边固定,然后拉另外一边,比如下图:
那么切变的变换矩阵是怎么样的呢?按照前面缩放的经验,我们只需找出点与点之间的数量关系即可。从图中可以看出,此变换在
y
y
y轴上并没有做出任何改动,是
x
x
x轴在向右拉伸。再仔细观察发现,低端
y
=
0
y=0
y=0这条边也没有发生任何变换,而最上端的那条直线变化最大,我们假设此时
y
=
1
y=1
y=1,并向右移动了距离
a
a
a,则原本位于
(
0
,
1
)
(0, 1)
(0,1)的点变成了
(
a
,
1
)
(a, 1)
(a,1),因此我们不妨将切变的变换矩阵定义为:
s
h
e
a
r
=
[
1
a
0
1
]
shear = \begin{bmatrix}1 & a \\ 0 & 1\end{bmatrix}
shear=[10a1]
于是,原来的矩阵与它相乘后变成:
[
1
a
0
1
]
[
x
y
]
=
[
x
+
a
y
y
]
\begin{bmatrix}1 & a \\ 0 & 1\end{bmatrix} \begin{bmatrix}x \\ y\end{bmatrix} = \begin{bmatrix}x + ay \\ y\end{bmatrix}
[10a1][xy]=[x+ayy]
旋转(Rotation)
旋转是指物体的转动,这里我们默认与绕原点转动,并将其变换矩阵定义为:
r
o
t
a
t
e
(
θ
)
=
[
cos
θ
−
sin
θ
sin
θ
cos
θ
]
rotate(\theta)=\begin{bmatrix}\cos\theta & -\sin\theta \\ \sin\theta & \cos\theta\end{bmatrix}
rotate(θ)=[cosθsinθ−sinθcosθ]
怎么来的呢?按照前面的经验我们只需要找出点的变换关系即可,下面引用西电卢本伟同学的手写推导:
旋转前后的图像如下图:
齐次坐标
齐次坐标(Homogeneous coordinates)就是将一个原本是
n
n
n维的向量用一个
n
+
1
n+1
n+1维向量来表示,是指一个用于投影几何里的坐标系统,如同用于欧式几何里的笛卡尔坐标一般。
在齐次坐标下,对于点来说扩展为
(
x
,
y
,
1
)
T
(x, y, 1)^T
(x,y,1)T,对于向量来说扩展为
(
x
,
y
,
0
)
T
(x, y, 0)^T
(x,y,0)T,这样做是有道理的,比如向量相加减之后还是向量,点相加减之后还是点。
那么多余平移来说,就可以这样表示:
[
x
′
y
′
1
]
=
[
1
0
t
x
0
1
t
y
0
0
1
]
[
x
y
1
]
=
[
x
+
t
x
y
+
t
y
1
]
\begin{bmatrix}x' \\ y' \\ 1\end{bmatrix} = \begin{bmatrix}1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1\end{bmatrix}\begin{bmatrix}x \\ y \\ 1\end{bmatrix} = \begin{bmatrix}x + t_x \\ y + t_y \\ 1\end{bmatrix}
⎣
⎡x′y′1⎦
⎤=⎣
⎡100010txty1⎦
⎤⎣
⎡xy1⎦
⎤=⎣
⎡x+txy+ty1⎦
⎤
仿射变换
仿射变换又称为仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间。仿射变换包括缩放、旋转、反射、错切以及平移,原来的直线仿射变换后还是直线,原来的平行线经过仿射变换之后还是平行线。一个集合的仿射变换为:
f
(
x
)
=
A
x
+
b
,
x
∈
X
f(x) = Ax + b, x \in X
f(x)=Ax+b,x∈X特别地,在二维图像变换中,其一般表达式为:
[
x
′
y
′
1
]
=
[
R
0
R
1
t
x
R
2
R
3
t
y
0
0
1
]
[
x
y
1
]
\begin{bmatrix}x' \\ y' \\ 1\end{bmatrix} = \begin{bmatrix}R_0 & R_1 & t_x \\ R_2 & R_3 & t_y \\ 0 & 0 & 1\end{bmatrix}\begin{bmatrix}x \\ y \\ 1\end{bmatrix}
⎣
⎡x′y′1⎦
⎤=⎣
⎡R0R20R1R30txty1⎦
⎤⎣
⎡xy1⎦
⎤我们发现,在二维的变换矩阵中,最后一行是固定的
(
0
,
0
,
1
)
(0, 0, 1)
(0,0,1),而第一、第二行前两列是要进行的线性变换,最后一列是要平移的距离。
在仿射变换中,除了进行单一的平移、旋转等操作之外,我们还可以对变换进行组合与分解。
就组合而言,其变换的顺序从右往左看,例如我们定义一个变换矩阵:
M
=
[
1
0
t
x
0
1
t
y
0
0
1
]
[
cos
θ
−
sin
θ
0
sin
θ
cos
θ
0
0
0
1
]
M =\begin{bmatrix}1 & 0 & t_x \\ 0 & 1& t_y \\ 0 & 0 & 1\end{bmatrix} \begin{bmatrix}\cos \theta & -\sin\theta & 0 \\ \sin\theta & \cos\theta & 0 \\ 0 & 0 & 1\end{bmatrix}
M=⎣
⎡100010txty1⎦
⎤⎣
⎡cosθsinθ0−sinθcosθ0001⎦
⎤其作用是,先将二维图像逆时针旋转
θ
\theta
θ,然后平移
(
t
x
,
t
y
)
T
(t_x, t_y)^T
(tx,ty)T。
就分解而言,其实就是组合的逆过程,一种简单的做法是:先将左下点移动到原点之后再进行线性与平移操作。
3维变换
三维的变换跟二维的差不多,相当于增加了一个维度,下面给出反射变换在三维当中的一些常用变换矩阵(用齐次坐标表示)。
平移(Translation)
t r a n s l a t i o n ( t x , t y , t z ) = [ 1 0 0 t x 0 1 0 t y 0 0 1 t z 0 0 0 1 ] translation(t_x, t_y, t_z) = \begin{bmatrix}1 & 0 & 0 & t_x \\ 0 & 1 & 0 & t_y\\ 0 & 0 & 1 & t_z \\ 0 & 0 & 0 & 1\end{bmatrix} translation(tx,ty,tz)=⎣ ⎡100001000010txtytz1⎦ ⎤
缩放(Scale)
s c a l e ( s x , s y , s z ) = [ s x 0 0 0 0 s y 0 0 0 0 s z 0 0 0 0 1 ] scale(s_x, s_y, s_z) = \begin{bmatrix}s_x & 0 & 0 & 0 \\ 0 & s_y & 0 & 0\\ 0 & 0 & s_z & 0 \\ 0 & 0 & 0 & 1\end{bmatrix} scale(sx,sy,sz)=⎣ ⎡sx0000sy0000sz00001⎦ ⎤
旋转(Rotation)
- 绕 x x x轴旋转: R x ( α ) = [ 1 0 0 0 0 cos α − sin α 0 0 sin α cos α 0 0 0 0 1 ] R_x(\alpha) = \begin{bmatrix}1 & 0 & 0 & 0 \\ 0 & \cos\alpha & -\sin\alpha & 0\\ 0 & \sin\alpha & \cos\alpha & 0 \\ 0 & 0 & 0 & 1\end{bmatrix} Rx(α)=⎣ ⎡10000cosαsinα00−sinαcosα00001⎦ ⎤
- 绕 y y y轴旋转: R y ( α ) = [ cos α 0 sin α 0 0 1 0 0 − sin α 0 cos α 0 0 0 0 1 ] R_y(\alpha) = \begin{bmatrix}\cos\alpha & 0 & \sin\alpha & 0 \\ 0 & 1 & 0 & 0\\ -\sin\alpha & 0 & \cos\alpha & 0 \\ 0 & 0 & 0 & 1\end{bmatrix} Ry(α)=⎣ ⎡cosα0−sinα00100sinα0cosα00001⎦ ⎤
- 绕 z z z轴旋转: R z ( α ) = [ cos α − sin α 0 0 sin α cos α 0 0 0 0 1 0 0 0 0 1 ] R_z(\alpha) = \begin{bmatrix}\cos\alpha & -\sin\alpha & 0 & 0 \\ \sin\alpha & \cos\alpha & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1\end{bmatrix} Rz(α)=⎣ ⎡cosαsinα00−sinαcosα0000100001⎦ ⎤
- 绕任意轴旋转:我们把该轴给先旋转到任意的x,y,z轴上,然后就可以应用基本的旋转矩阵,最后再逆旋转回来即可。