在计算机图像学中常常涉及到对图像的进行各种变换,包括平移、旋转、缩放、剪切等操作,它们被称为坐标变换或仿射变换。本篇文章将由浅到深,详细地讨论关于图像坐标变换的原理。
在本篇文章中,我们重点来讨论二维图像和三维图像的坐标变换。为了更好去理解三维坐标变换,我们先讨论二维坐标变换。
在图(1)中,把 P P P点分别向 x x x和 y y y方向平移 t x t_x tx和 t y t_y ty个单位:
点 P P P经过上述的平移之后,得到 P ′ P' P′:
P ′ = p + t = ( x + t x , y + t y ) . (1) P'=p+t=(x+t_x,y+t_y).\tag{1} P′=p+t=(x+tx,y+ty).(1)
如果我们将点 P ′ P' P′的坐标用矩阵的方式来表示,则可以得到:
P ′ = [ x + t x y + t y ] (2) P'= \begin{bmatrix} x+t_x \\ y+t_y \end{bmatrix} \tag{2} P′=[x+txy+ty](2)
我们是否可以将式子(2)拆开成为原坐标向量和平移变换矩阵的乘法?然而,根据线性代数的基础知识可知,无法将(2)进行拆分。(读者可以动手试一试,看能不能拆开。至于为什么要拆开,我们将在后面讨论)
为了将式子(2)拆开,我们就必须引入齐次坐标。齐次坐标无非就是将二维的矩阵变为三维,并在第三维用数字1来填充:
P ′ = [ x + t x y + t y 1 ] (3) P'= \begin{bmatrix} x+t_x \\ y+t_y \\ 1 \end{bmatrix} \tag{3} P′=⎣ ⎡x+txy+ty1⎦ ⎤(3)
此时我们就可以拆开式子(3)用矩阵和向量的乘法来表示:
P ′ = [ x + t x y + t y 1 ] = [ 1 0 t x 0 1 t y 0 0 1 ] ⋅ [ x y 1 ] (4) P'= \begin{bmatrix} x+t_x \\ y+t_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} \tag{4} P′=⎣ ⎡x+txy+ty1⎦ ⎤=⎣ ⎡100010txty1⎦ ⎤⋅⎣ ⎡xy1⎦ ⎤(4)
为了更加简便,我们将(4)继续化简:
= [ I t 0 1 ] ⋅ [ x y 1 ] (5) =\begin{bmatrix} I & t \\ 0 & 1 \end{bmatrix} · \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} \tag{5} =[I0t1]⋅⎣ ⎡xy1⎦ ⎤(5)
其中 I I I为单位矩阵, t t t为平移的向量 [ t x , t y ] T [t_x,t_y]^T [tx,ty]T。任意一点坐标 [ x , y , 1 ] T [x,y,1]^T [x,y,1]T左乘平移矩阵就可以得到平移后的位置 P ′ P' P′。
在图(2)中,我们沿 P P P点的 x , y x,y x,y轴分别缩放 S x 、 S y S_x、S_y Sx、Sy倍:
在图(2)中,我们为了与平移的矩阵形式统一也采用了齐次坐标,则 P ′ P' P′坐标的向量形式:
p ′ → [ S x x S y y 1 ] (6) p'\to \begin{bmatrix} S_xx \\ S_yy \\ 1 \end{bmatrix} \tag{6} p′→⎣ ⎡SxxSyy1⎦ ⎤(6)
将(6)拆分为坐标向量和缩放矩阵的乘法:
= [ S x 0 0 0 S y 0 0 0 1 ] ⋅ [ x y 1 ] = [ S ′ 0 0 1 ] ⋅ [ x y 1 ] = S ⋅ [ x y 1 ] . (7) =\begin{bmatrix} S_x & 0 & 0 \\ 0 & S_y & 0 \\ 0 & 0 & 1 \end{bmatrix} · \begin{bmatrix} x \\ y \\ 1 \end{bmatrix}\\ =\begin{bmatrix} S' & 0 \\ 0 & 1 \end{bmatrix} · \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} \quad\quad\, \\= S· \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} \quad\quad\quad\quad\quad .\tag{7} =⎣ ⎡Sx000Sy0001⎦ ⎤⋅⎣ ⎡xy1⎦ ⎤=[S′001]⋅⎣ ⎡xy1⎦ ⎤=S⋅⎣ ⎡xy1⎦ ⎤.(7)
其中 S S S为缩放矩阵, P P P点的位置向量左乘缩放矩阵 S S S便可得到缩放后的点 P ′ P' P′。
如图(3)所示,我们将 O P OP OP向量旋转 β \beta β角度到 O P ′ OP' OP′:
根据三角函数关系以及极坐标系的机制,我们可以将 P P P和 P ′ P' P′表示为:
P ( x , y ) = { x = r ⋅ c o s α y = r ⋅ s i n α P ′ ( x ′ , y ′ ) = { x ′ = r ⋅ c o s ( α + β ) y ′ = r ⋅ s i n ( α + β ) (8) P(x,y)= \begin{cases} x=r·cos\alpha \\ y=r·sin\alpha \end{cases} \\ \\ P'(x',y')= \begin{cases} x'=r·cos(\alpha+\beta) \\ y'=r·sin(\alpha+\beta) \end{cases} \tag{8} P(x,y)={x=r⋅cosαy=r⋅sinαP′(x′,y′)={x′=r⋅cos(α+β)y′=r⋅sin(α+β)(8)
在(8)中, r r r就是向量 ∣ O P ∣ |OP| ∣OP∣的长度。
我们将式子(8)的 P ′ ( x ′ , y ′ ) P'(x',y') P′(x′,y′)展开:
{ x ′ = r ⋅ c o s α c o s β − r ⋅ s i n α s i n β = x c o s β − y s i n β y ′ = r ⋅ s i n α c o s β + r ⋅ c o s α s i n β = x s i n β + y c o s β (9) \begin{cases} x'=r·cos\alpha\,cos\beta-r·sin\alpha\,sin\beta=xcos\beta-ysin\beta \\ y'=r·sin\alpha\,cos\beta+r·cos\alpha\,sin\beta=xsin\beta+ycos\beta \end{cases} \tag{9} {x′=r⋅cosαcosβ−r⋅sinαsinβ=xcosβ−ysinβy′=r⋅sinαcosβ+r⋅cosαsinβ=xsinβ+ycosβ(9)
将上述表达式用矩阵来表示:
[ x ′ y ′ 1 ] = [ c o s β − s i n β 0 s i n c o s β 0 0 0 1 ] ⋅ [ x y 1 ] (10) \begin{bmatrix} x' \\ y' \\ 1 \end{bmatrix} =\begin{bmatrix} cos\beta & -sin\beta & 0 \\ sin & cos\beta & 0 \\ 0 & 0 & 1 \end{bmatrix} · \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} \tag{10} ⎣ ⎡x′y′1⎦ ⎤=⎣ ⎡cosβsin0−sinβcosβ0001⎦ ⎤⋅⎣ ⎡xy1⎦ ⎤(10)
这就是二维旋转的基本形式,中间的矩阵即二维旋转的旋转矩阵,坐标向量左乘该矩阵后,即得到这个向量旋转 β \beta β角度后的新坐标。
读者可能会注意到,上述的旋转只是二维坐标围绕着坐标原点进行旋转,那关于任意点旋转应该如何表示?其实关于任意点的旋转操作可以拆分为以下步骤:①将旋转点移动到坐标原点;②按绕原点的旋转规律进行旋转;③再将旋转点移回原处。
图(5)中,点 P P P向 x 、 y 、 z x、y、z x、y、z三个方向分别平移 T x 、 T y 、 T z T_x、T_y、T_z Tx、Ty、Tz个单位:
点 P P P的平移向量为:
T ′ = [ T x T y T z ] (11) T'= \begin{bmatrix} T_x \\ T_y \\ T_z \end{bmatrix} \tag{11} T′=⎣ ⎡TxTyTz⎦ ⎤(11)
为了拆分平移操作为向量和矩阵的乘法,我们仍然引入了齐次坐标。那么 P ′ P' P′可表示为:
P ′ → [ I T ′ 0 1 ] 4 × 4 ⋅ [ x y z 1 ] → T ⋅ [ x y z 1 ] (12) P'\to \begin{bmatrix} I & T' \\ 0 & 1 \end{bmatrix}_{4×4} · \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} \to\,T· \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} \tag{12} P′→[I0T′1]4×4⋅⎣ ⎡xyz1⎦ ⎤→T⋅⎣ ⎡xyz1⎦ ⎤(12)
(12)便是三维坐标的平移操作,其中 T T T为平移矩阵。
三维坐标的缩放与二维类似,当点 P P P向 x 、 y 、 z x、y、z x、y、z三个方向分别缩放 S x 、 S y 、 S z S_x、S_y、S_z Sx、Sy、Sz倍时, P ′ P' P′坐标的向量形式为:
P ′ → [ S x x S y y S z z 1 ] (13) P'\to \begin{bmatrix} S_xx \\ S_yy \\ S_zz \\ 1 \end{bmatrix} \tag{13} P′→⎣ ⎡SxxSyySzz1⎦ ⎤(13)
将(12)进行拆分:
= [ S x 0 0 0 0 S y 0 0 0 0 S z 0 0 0 0 1 ] ⋅ [ x y z 1 ] = [ S ′ 0 0 1 ] ⋅ [ x y z 1 ] = S ⋅ [ x y z 1 ] (14) =\begin{bmatrix} S_x & 0 & 0 & 0 \\ 0 & S_y & 0 & 0 \\ 0 & 0 & S_z & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} · \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} \\ =\begin{bmatrix} S' & 0\\ 0 & 1 \end{bmatrix} · \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} \quad\quad\quad\quad\, \\= S· \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} \quad\quad\quad\quad\quad\quad\quad\, \tag{14} =⎣ ⎡Sx0000Sy0000Sz00001⎦ ⎤⋅⎣ ⎡xyz1⎦ ⎤=[S′001]⋅⎣ ⎡xyz1⎦ ⎤=S⋅⎣ ⎡xyz1⎦ ⎤(14)
(14)中的 S S S就是缩放矩阵,任意三维坐标左乘 S S S就可以得到缩放之后的新坐标 P ’ P’ P’。
在三维旋转中,我们遵守右手准则,即 x x x指向右方, y y y指向上方, z z z指向前方,如图(6)所示:
三维旋转可借助二维旋转来理解,由于三维空间中可以任意轴旋转,为方便分析与使用,在本节我们考虑绕X、Y、Z轴的旋转。
绕 X X X轴旋转,则把图(6)中的整个坐标系向右旋转,让 X X X轴指向前方。绕 X X X轴旋转,则不用考虑 X X X轴的坐标变化,三维坐标变为了二维坐标, Y O Z YOZ YOZ就构成了一个二维平面( O O O为坐标原点):
根据图(7)可知, Y Y Y轴就是原来的 X X X轴, Z Z Z轴也就是原来的 Y Y Y轴,因此根据二维坐标的旋转可得:
P ( x , y , z ) = { x = x y = r ⋅ c o s α z = r ⋅ s i n α P ′ ( x ′ , y ′ , z ′ ) = { x ′ = x y ′ = r ⋅ c o s ( α + β ) = r c o s α c o s β − r s i n α s i n β z ′ = r ⋅ s i n ( α + β ) = r s i n α c o s β + r c o s α s i n β (15) P(x,y,z)= \begin{cases} x=x \\ y=r·cos\alpha \\ z=r·sin\alpha \end{cases} \\ \\ P'(x',y',z')= \begin{cases} x'=x \\ y'=r·cos(\alpha+\beta)=rcos\alpha\,cos\beta-rsin\alpha\,sin\beta \\ z'=r·sin(\alpha+\beta)=rsin\alpha\,cos\beta+rcos\alpha\,sin\beta \end{cases} \tag{15} P(x,y,z)=⎩ ⎨ ⎧x=xy=r⋅cosαz=r⋅sinαP′(x′,y′,z′)=⎩ ⎨ ⎧x′=xy′=r⋅cos(α+β)=rcosαcosβ−rsinαsinβz′=r⋅sin(α+β)=rsinαcosβ+rcosαsinβ(15)
(15)的矩阵形式:
[ x ′ y ′ z ′ 1 ] = [ 1 0 0 0 0 c o s β − s i n β 0 0 s i n β c o s β 0 0 0 0 1 ] ⋅ [ x y z 1 ] = R ⋅ [ x y z 1 ] (16) \begin{bmatrix} x' \\ y' \\ z' \\ 1 \end{bmatrix} =\begin{bmatrix} 1 & 0 & 0 & 0\\ 0 & cos\beta & -sin\beta & 0 \\ 0 & sin\beta & cos\beta & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} · \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} =R· \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} \tag{16} ⎣ ⎡x′y′z′1⎦ ⎤=⎣ ⎡10000cosβsinβ00−sinβcosβ00001⎦ ⎤⋅⎣ ⎡xyz1⎦ ⎤=R⋅⎣ ⎡xyz1⎦ ⎤(16)
注意:为了与平移的矩阵形式相同,旋转矩阵也采用了齐次坐标。
绕 Y Y Y轴旋转,则把图(6)中的整个坐标系向左旋转,让 Y Y Y轴指向前方。绕 Y Y Y轴旋转,则不用考虑 Y Y Y轴的坐标变化,三维坐标变为了二维坐标, Z O X ZOX ZOX就构成了一个二维平面( O O O为坐标原点):
根据图(8)可知, Z Z Z轴就是原来的 X X X轴, X X X轴也就是原来的 Y Y Y轴,因此根据二维坐标的旋转可得:
P ( x , y , z ) = { x = r ⋅ s i n α y = y z = r ⋅ c o s α P ′ ( x ′ , y ′ , z ′ ) = { x ′ = r ⋅ s i n ( α + β ) = r s i n α c o s β + r c o s α s i n β y ′ = y z ′ = r ⋅ c o s ( α + β ) = r c o s α c o s β − r s i n α s i n β = { x ′ = x c o s β + z s i n β y ′ = y z ′ = − x s i n β + z c o s β (17) P(x,y,z)= \begin{cases} x=r·sin\alpha \\ y=y \\ z=r·cos\alpha \end{cases} \\ \\ P'(x',y',z')= \begin{cases} x'=r·sin(\alpha+\beta)=rsin\alpha\,cos\beta+rcos\alpha\,sin\beta \\ y'=y \\ z'=r·cos(\alpha+\beta)=rcos\alpha\,cos\beta-rsin\alpha\,sin\beta \end{cases} \\ \\= \begin{cases} x'=xcos\beta+zsin\beta \\ y'=y \\ z'=-xsin\beta+zcos\beta \end{cases} \tag{17} P(x,y,z)=⎩ ⎨ ⎧x=r⋅sinαy=yz=r⋅cosαP′(x′,y′,z′)=⎩ ⎨ ⎧x′=r⋅sin(α+β)=rsinαcosβ+rcosαsinβy′=yz′=r⋅cos(α+β)=rcosαcosβ−rsinαsinβ=⎩ ⎨ ⎧x′=xcosβ+zsinβy′=yz′=−xsinβ+zcosβ(17)
用矩阵形式来表示式子(16):
[ x ′ y ′ z ′ 1 ] = [ c o s β 0 s i n β 0 0 1 0 0 − s i n β 0 c o s β 0 0 0 0 1 ] ⋅ [ x y z 1 ] = R ⋅ [ x y z 1 ] (18) \begin{bmatrix} x' \\ y' \\ z' \\ 1 \end{bmatrix} =\begin{bmatrix} cos\beta & 0 & sin\beta & 0\\ 0 & 1 & 0 & 0 \\ -sin\beta & 0 & cos\beta & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} · \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} =R· \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} \tag{18} ⎣ ⎡x′y′z′1⎦ ⎤=⎣ ⎡cosβ0−sinβ00100sinβ0cosβ00001⎦ ⎤⋅⎣ ⎡xyz1⎦ ⎤=R⋅⎣ ⎡xyz1⎦ ⎤(18)
绕 Z Z Z轴旋转,则让 Z Z Z轴指向前方。绕 Z Z Z轴旋转,则不用考虑 Z Z Z轴的坐标变化,三维坐标变为了二维坐标, X O Y XOY XOY就构成了一个二维平面( O O O为坐标原点):
根据图(8)可知,绕 Z Z Z轴旋转,其实就是二维坐标绕原点旋转,因此可推出:
P ( x , y , z ) = { x = r ⋅ c o s α y = r ⋅ s i n α z = z P ′ ( x ′ , y ′ , z ′ ) = { x ′ = r ⋅ c o s ( α + β ) = r c o s α c o s β − r s i n α s i n β y ′ = r ⋅ s i n ( α + β ) = r s i n α c o s β + r c o s α s i n β z ′ = z = { x ′ = x c o s β − y s i n β y ′ = = x s i n β + y c o s β z ′ = z (19) P(x,y,z)= \begin{cases} x=r·cos\alpha \\ y=r·sin\alpha \\ z=z \end{cases} \\ \\ P'(x',y',z')= \begin{cases} x'=r·cos(\alpha+\beta)=rcos\alpha\,cos\beta-rsin\alpha\,sin\beta \\ y'=r·sin(\alpha+\beta)=rsin\alpha\,cos\beta+rcos\alpha\,sin\beta \\ z'=z \end{cases} \\ \\ = \begin{cases} x'=xcos\beta-ysin\beta \\ y'==xsin\beta+ycos\beta \\ z'=z \end{cases} \tag{19} P(x,y,z)=⎩ ⎨ ⎧x=r⋅cosαy=r⋅sinαz=zP′(x′,y′,z′)=⎩ ⎨ ⎧x′=r⋅cos(α+β)=rcosαcosβ−rsinαsinβy′=r⋅sin(α+β)=rsinαcosβ+rcosαsinβz′=z=⎩ ⎨ ⎧x′=xcosβ−ysinβy′==xsinβ+ycosβz′=z(19)
(19)用矩阵表示:
[ x ′ y ′ z ′ 1 ] = [ c o s β − s i n β 0 0 s i n β c o s β 0 0 0 0 1 0 0 0 0 1 ] ⋅ [ x y z 1 ] = R ⋅ [ x y z 1 ] (20) \begin{bmatrix} x' \\ y' \\ z' \\ 1 \end{bmatrix} =\begin{bmatrix} cos\beta & -sin\beta & 0 & 0 \\ sin\beta & cos\beta & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} · \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} =R· \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} \tag{20} ⎣ ⎡x′y′z′1⎦ ⎤=⎣ ⎡cosβsinβ00−sinβcosβ0000100001⎦ ⎤⋅⎣ ⎡xyz1⎦ ⎤=R⋅⎣ ⎡xyz1⎦ ⎤(20)
在图像处理中,我们往往不是单一地对某一坐标进行变换操作,而是会对大量的坐标进行一系列的变换操作。如果直接使用表达式的形式来进行变换操作也是可行的,但是这其中涉及大量的计算,而叠加各种变换系数后的表达式将变得十分臃肿且会降低程序的计算效率。
解决办法就是将各种变换操作用一个单独的矩阵来进行表示,列如:
R ⋅ S ⋅ T ⋅ [ x y z 1 ] (21) R·S·T· \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} \tag{21} R⋅S⋅T⋅⎣ ⎡xyz1⎦ ⎤(21)
(21)表示对三维坐标先进行平移,然后缩放,最后再旋转等一系列操作,其中 R R R是旋转矩阵, S S S是缩放矩阵, T T T是平移矩阵。
采用矩阵形式来表达变换操作有如下好处:①可以更简便地表示变换操作;②矩阵形式非常利于计算机处理,可以加快计算效率。
正是基于以上的原因,所以我们需要将变换操作都统一用矩阵的形式来表示。
读者可以发现:无论是二维坐标的平移还是三维坐标的平移都无法直接用矩阵形式来表示,这也是为什么我们要引入齐次坐标的原因。二维坐标通过引入齐次坐标变成三维坐标,从而可以很轻松地使用矩阵形式来表示平移操作;三维坐标则通过引入齐次坐标变为四维坐标,用四维坐标方式来描述三维的平移操作。
在2.3节中,从 ( α + β ) (\alpha+\beta) (α+β)可以看出,我们只考虑了向正方向进行旋转,想要考虑负方向的旋转则只需要 − β -\beta −β即可,可以表示为 ( α − β ) (\alpha-\beta) (α−β),然后再化解表达式,求出沿负方向的变换矩阵。
我们在讨论二维坐标变换的基本原理之后,将二维坐标变换的理论迁移到三维坐标变换,并深入讨论关于三维坐标变换的基础原理。我们细致地解释了用变换矩阵的形式来代替变换表达式以及引入齐次坐标的原因。在最后,我们探讨了如何用矩阵形式来表示沿坐标轴的负方向进行旋转变换。
1、2.2 坐标转换基础_哔哩哔哩_bilibili
2、3维旋转矩阵推导与助记 - 哔哩哔哩 (bilibili.com)
3、旋转变换(一)旋转矩阵 - 莫水千流 - 博客园 (cnblogs.com)
4、齐次坐标_子胤的博客-CSDN博客_齐次坐标