二维变换矩阵

二维平面上常见的三种几何变换

  • 平移
  • 缩放
  • 旋转

平移

在二维平面上每个点可以用 ( x , y ) (x,y) (x,y)表示,假设有一点 P ( x , y ) P(x,y) P(x,y),它平移到 P ′ ( x ′ , y ′ ) P'(x',y') P(x,y),则相应的数学表达式子为:
P ′ = P + Δ P [ x ′ y ′ ] = [ x y ] + [ Δ x Δ y ] = [ x + Δ x y + Δ y ] P'=P+\Delta P\\ \left [ \begin{matrix} x' \\y' \end{matrix}\right]=\left [ \begin{matrix} x \\y \end{matrix}\right]+\left [ \begin{matrix} \Delta x \\ \Delta y \end{matrix}\right] =\left [ \begin{matrix} x+\Delta x \\ y + \Delta y \end{matrix}\right] P=P+ΔP[xy]=[xy]+[ΔxΔy]=[x+Δxy+Δy]
例如,点 ( 1 , 1 ) (1,1) (1,1) 平移到 ( 2 , 3 ) (2,3) (2,3 需要相应的 Δ P = [ 1 2 ] \Delta P =\left [ \begin{matrix} 1\\ 2\end{matrix}\right ] ΔP=[12]

缩放

假设有一点 P ( x , y ) P(x,y) P(x,y),它缩放到 P ′ ( x ′ , y ′ ) P'(x',y') P(x,y),则相应的数学表达式子为:
P ′ = S P [ x ′ y ′ ] = [ S x 0 0 S y ] [ x y ] = [ x S x y S y ] P'=SP\\ \left [ \begin{matrix} x' \\y' \end{matrix}\right]=\left [ \begin{matrix} S_x & 0 \\0 & S_y \end{matrix}\right]\left [ \begin{matrix} x \\ y \end{matrix}\right] =\left [ \begin{matrix} xS_x \\ yS_y \end{matrix}\right] P=SP[xy]=[Sx00Sy][xy]=[xSxySy]
其中, S S S代表缩放的矩阵。

旋转

二维平面是上的旋转矩阵如下,
R = [ c o s ( α ) s i n ( α ) − s i n ( α ) c o s ( α ) ] R = \left [ \begin{matrix} cos(\alpha) & sin(\alpha) \\-sin(\alpha) & cos(\alpha) \end{matrix}\right] R=[cos(α)sin(α)sin(α)cos(α)]
想要知道详细这个矩阵的详细推导可以看这篇博客;
那么,假设有一点 P ( x , y ) P(x,y) P(x,y),它绕着原点旋转到 P ′ ( x ′ , y ′ ) P'(x',y') P(x,y),则相应的数学表达式子为:
P ′ = R P [ x ′ y ′ ] = [ c o s ( α ) s i n ( α ) − s i n ( α ) c o s ( α ) ] [ x y ] = [ x c o s ( α ) + y s i n ( α ) − x s i n ( α ) + y c o s ( α ) ] P'=RP\\ \left [ \begin{matrix} x' \\y' \end{matrix}\right]=\left [ \begin{matrix} cos(\alpha) & sin(\alpha) \\-sin(\alpha) & cos(\alpha) \end{matrix}\right]\left [ \begin{matrix} x \\ y \end{matrix}\right] =\left [ \begin{matrix} xcos(\alpha)+ysin(\alpha) \\-xsin(\alpha) +ycos(\alpha) \end{matrix}\right] P=RP[xy]=[cos(α)sin(α)sin(α)cos(α)][xy]=[xcos(α)+ysin(α)xsin(α)+ycos(α)]

齐次坐标系的引入

在二维平面上,缩放和旋转通过乘法实现,平移是通过加法实现,这样计算是很麻烦地!为了规范二维平面上的几何变换,数学家们引入了齐次坐标的概念。
齐次坐标的是什么呢?直观上来讲就是在原来的维度上面再添加一个维度,且多出的维度一直是1,例如:
P = [ x y 1 ] P = \left[ \begin{matrix} x\\ y\\1 \end{matrix} \right] P=xy1

则上述平移过程中的 Δ P \Delta P ΔP在齐次坐标系的表达方式为:
Δ P = [ 1 0 Δ x 0 1 Δ y 0 0 1 ] \Delta P = \left[ \begin{matrix} 1 & 0 & \Delta x \\ 0 & 1 & \Delta y \\ 0 & 0 & 1\end{matrix} \right] ΔP=100010ΔxΔy1
利用齐次坐标系,平移过程的数学表达式为:
P ′ = Δ P × P [ x ′ y ′ 1 ] = [ 1 0 Δ x 0 1 Δ y 0 0 1 ] [ x y 1 ] = [ x + Δ x y + Δ y 1 ] P'=\Delta P \times P\\ \left [ \begin{matrix} x' \\y' \\ 1 \end{matrix}\right]=\left[ \begin{matrix} 1 & 0 & \Delta x \\ 0 & 1 & \Delta y \\ 0 & 0 & 1\end{matrix} \right] \left [ \begin{matrix} x \\ y \\ 1\end{matrix}\right] =\left [ \begin{matrix} x+\Delta x \\ y + \Delta y \\ 1 \end{matrix}\right] P=ΔP×Pxy1=100010ΔxΔy1xy1=x+Δxy+Δy1

上述缩放过程中, S S S在齐次坐标系中的表达方式为:
S = [ S x 0 0 0 S y 0 0 0 1 ] S = \left[ \begin{matrix} S_x & 0 & 0 \\ 0 & S_y & 0 \\ 0 & 0 & 1\end{matrix} \right] S=Sx000Sy0001
则缩放过程的数学表达式为:

P ′ = S × P [ x ′ y ′ 1 ] = [ S x 0 0 0 S y 0 0 0 1 ] [ x y 1 ] = [ x S x y S y 1 ] P'=S \times P\\ \left [ \begin{matrix} x' \\y' \\ 1 \end{matrix}\right]=\left[ \begin{matrix} S_x & 0 & 0 \\ 0 & S_y & 0 \\ 0 & 0 & 1\end{matrix} \right] \left [ \begin{matrix} x \\ y \\ 1\end{matrix}\right] =\left [ \begin{matrix} xS_x \\ y S_y \\ 1 \end{matrix}\right] P=S×Pxy1=Sx000Sy0001xy1=xSxySy1

同理,上述旋转过程中的旋转矩阵 R R R在其次坐标系统的表达方式为:
S = [ c o s ( α ) s i n ( α ) 0 − s i n ( α ) c o s ( α ) 0 0 0 1 ] S = \left[ \begin{matrix} cos(\alpha) & sin(\alpha) & 0 \\ -sin(\alpha) & cos(\alpha) & 0 \\ 0 & 0 & 1\end{matrix} \right] S=cos(α)sin(α)0sin(α)cos(α)0001
则旋转过程的数学表达式为:
P ′ = R × P [ x ′ y ′ 1 ] = [ c o s ( α ) s i n ( α ) 0 − s i n ( α ) c o s ( α ) 0 0 0 1 ] [ x y 1 ] = [ x c o s ( α ) + y s i n ( α ) − x s i n ( α ) + y c o s ( α ) 1 ] P'=R \times P\\ \left [ \begin{matrix} x' \\y' \\ 1 \end{matrix}\right]=\left[ \begin{matrix} cos(\alpha) & sin(\alpha) & 0 \\ -sin(\alpha) & cos(\alpha) & 0 \\ 0 & 0 & 1\end{matrix} \right] \left [ \begin{matrix} x \\ y \\ 1\end{matrix}\right] =\left [ \begin{matrix} xcos(\alpha) + ysin(\alpha) \\ -xsin(\alpha)+ycos(\alpha) \\ 1 \end{matrix}\right] P=R×Pxy1=cos(α)sin(α)0sin(α)cos(α)0001xy1=xcos(α)+ysin(α)xsin(α)+ycos(α)1

至此,二维平面上所有几何变换都可以通过乘法实现。比如,在二维平面上要实现绕着某个点 P ( x , y ) P(x,y) P(x,y)旋转,需要以下三个步骤完成:

  • 将图形平移到原点
  • 对图形进行旋转
  • 将图形平移回原来的位置

没有利用齐次坐标系的话,变换过程的数学公式为:
P ′ = R ( P + Δ P ) + ( − Δ P ) = [ c o s ( α ) s i n ( α ) − s i n ( α ) c o s ( α ) ] ( [ x y ] + [ Δ x Δ y ] ) − [ Δ x Δ y ] P' = R(P+\Delta P)+(-\Delta P) \\ = \left [ \begin{matrix} cos(\alpha) & sin(\alpha) \\-sin(\alpha) & cos(\alpha) \end{matrix}\right] \left( \left [ \begin{matrix} x \\ y \end{matrix}\right] + \left [ \begin{matrix} \Delta x \\ \Delta y \end{matrix}\right] \right) -\left [ \begin{matrix} \Delta x \\ \Delta y \end{matrix}\right] P=R(P+ΔP)+(ΔP)=[cos(α)sin(α)sin(α)cos(α)]([xy]+[ΔxΔy])[ΔxΔy]
利用齐次坐标系的话,变换过程的数学公式为:
P ′ = ( − Δ P ) × R × Δ P × P = − [ 1 0 Δ x 0 1 Δ y 0 0 1 ] [ c o s ( α ) s i n ( α ) 0 − s i n ( α ) c o s ( α ) 0 0 0 1 ] [ 1 0 Δ x 0 1 Δ y 0 0 1 ] [ x y 1 ] P' = (-\Delta P)\times R\times \Delta P\times P \\ =- \left[ \begin{matrix} 1 & 0 & \Delta x \\ 0 & 1 & \Delta y \\ 0 & 0 & 1\end{matrix} \right] \left[ \begin{matrix} cos(\alpha) & sin(\alpha) & 0 \\ -sin(\alpha) & cos(\alpha) & 0 \\ 0 & 0 & 1\end{matrix} \right]\left[ \begin{matrix} 1 & 0 & \Delta x \\ 0 & 1 & \Delta y \\ 0 & 0 & 1\end{matrix} \right] \left[ \begin{matrix} x\\ y\\1 \end{matrix} \right] P=(ΔP)×R×ΔP×P=100010ΔxΔy1cos(α)sin(α)0sin(α)cos(α)0001100010ΔxΔy1xy1

下面用根据本篇文章的知识,利用Python实现一个正方形绕着中心点旋转45度的例子。

import numpy as np
import matplotlib.pyplot as plt

def poly_gen(x0=(10,10),length = 20):
    poly = []
    x = x0[0]
    y = x0[1]
    for _ in range(length):
        y += 1
        poly.append(np.array([x,y,1]))

    x = x0[0]
    y = x0[1]
    for _ in range(length):
        x += 1
        poly.append(np.array([x,y,1]))
    x = x0[0]+length
    y = x0[1]
    for _ in range(length):
        y += 1
        poly.append(np.array([x,y,1]))

    x = x0[0]
    y = x0[1]+length
    for _ in range(length):
        x +=1
        poly.append(np.array([x,y,1]))

    center = np.array([x0[0]+length/2,x0[1]+length/2])

    return poly, center

def translation(poly,dx,dy):
    T = np.array([[1,0,dx],
                  [0,1,dy],
                  [0,0,1]])

    poly_trans = []
    for x in poly:
        poly_trans.append(np.dot(T,x))
    return poly_trans

def rotation(poly,theta):
    R = np.array([[np.cos(theta), np.sin(theta),0],
                  [-np.sin(theta),np.cos(theta),0],
                  [0,0,1]])
    poly_rotation = []
    for x in poly:
        poly_rotation.append(np.dot(R,x))
    return  poly_rotation

if __name__=='__main__':

    fig1=plt.figure()
    poly, center = poly_gen()
    for x in poly:
        plt.scatter(x[0],x[1])

    plt.xlim(0,50)
    plt.ylim(0,50)

    fig2=plt.figure()
    poly_trans = translation(poly,-center[0],-center[1])
    poly_rotation = rotation(poly_trans, np.pi / 4.)
    poly_trans = translation(poly_rotation,center[0],center[1])
    for x in poly_trans:
        plt.scatter(x[0],x[1])
    plt.xlim(0,50)
    plt.ylim(0,50)
    plt.show()

其运行的结果如下:
这里写图片描述 这里写图片描述

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页