Matriz de transformación de puntos en sistema de coordenadas 2D (traslación, escalado, rotación, corte incorrecto)

1. Traducción

En el espacio 2D, a menudo necesitamos trasladar un punto a otro. Supongamos un punto P ( x , y ) P(x,y) en el espacioP ( x ,y ) ; dirígelo ax , yx, yx ,Traducirtx t_x en la dirección ytxty t_yty, suponiendo que las coordenadas del punto después de la traslación son ( x ′ , y ′ ) (x',y')( x ,y ), entonces la operación de traducción de los puntos anteriores se puede resumir en la siguiente fórmula:
x ′ = x + txy ′ = x + ty \begin{alignat}{2} &x'=x + t_x\\ &y'=x + t_y \end {alinear}X=X+txy=X+ty
Usando una matriz homogénea se expresa de la siguiente manera:
[ x ′ ​​​​y ′ 1 ] = [ 1 btx 0 1 ty 0 0 1 ] [ xy 1 ] \begin{bmatrix} x' \\ y' \\ 1 \ end{bmatrix} = \ begin{bmatrix} 1 & b & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \\ 1 \end{bmatrix } Xy1 = 100b10txty1 Xy1

import numpy as np


def translation():
    """
    原始数组a 三个点(1,1) (4,4) (7,7)
    构建齐次矩阵 P
    构建变换矩阵 T
    """
    a = np.array([[1, 1],
               [4, 4],
               [7, 7]])

    P = np.array([a[:, 0],
               a[:, 1],
               np.ones(len(a))])

    T = np.array([[1, 0, 2],
               [0, 1, 2],
               [0, 0, 1]])
    return np.dot(T, P)


print(translation())

"""
[[3. 6. 9.]
 [3. 6. 9.]
 [1. 1. 1.]]
"""

Demostración del efecto de animación

import matplotlib
import matplotlib.pyplot as plt
import numpy as np

X, Y = np.mgrid[0:1:5j, 0:1:5j]
x, y = X.ravel(), Y.ravel()

def trans_translate(x, y, tx, ty):
    T = [[1, 0, tx],
         [0, 1, ty],
         [0, 0, 1]]
    T = np.array(T)
    P = np.array([x, y, [1] * x.size])
    return np.dot(T, P)

fig, ax = plt.subplots(1, 4)
T_ = [[0, 0], [2.3, 0], [0, 1.7], [2, 2]]
for i in range(4):
    tx, ty = T_[i]
    x_, y_, _ = trans_translate(x, y, tx, ty)
    ax[i].scatter(x_, y_)
    ax[i].set_title(r'$t_x={0:.2f}$ , $t_y={1:.2f}$'.format(tx, ty))

    ax[i].set_xlim([-0.5, 4])
    ax[i].set_ylim([-0.5, 4])
    ax[i].grid(alpha=0.5)
    ax[i].axhline(y=0, color='k')
    ax[i].axvline(x=0, color='k')
plt.show()

Por favor agregue una descripción de la imagen.

2. Escalado

En el espacio 2D, un punto ( x , y ) (x,y)( X ,y ) relativo a otro punto( px , py ) (p_x,p_y)( pagx,pagy) para la operación de escala, también podríamos escalar el factor enx, yx, yLas direcciones x e y son respectivamente:sx, sy s_x, s_ysx,sy, entonces la operación de escala anterior se puede resumir como la siguiente fórmula:
x ′ = sx ( x − px ) + px = sxx + px ( 1 − sx ) y ′ = sy ( y − py ) + py = syy + py ( 1 − sy ) \begin{alignat}{2} &x'=s_x(x-p_x) + p_x &=s_xx + p_x(1-s_x)\\ &y'=s_y(y-p_y) + p_y &=s_yy + p_y( 1-s_y) \end{alignat}X=sx( xpagx)+pagxy=sy( ypagy)+pagy=sxX+pagx( 1sx)=syy+pagy( 1sy)
Usando una matriz homogénea se expresa de la siguiente manera:
[ x ′ ​​​​y ′ 1 ] = [ sx 0 px ( 1 − sx ) 0 sypy ( 1 − sy ) 0 0 1 ] [ xy 1 ] \begin{bmatrix} x' \\ y' \\ 1 \end{bmatrix} = \begin{bmatrix} s_x& 0 & p_x(1-s_x) \\ 0 & s_y& p_y(1-s_y)\\ 0 & 0& 1 \end{bmatrix } \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} Xy1 = sx000sy0pagx( 1sx)pagy( 1sy)1 Xy1

def trans_scale(x, y, px, py, sx, sy):
    T = [[sx, 0 , px*(1 - sx)],
         [0 , sy, py*(1 - sy)],
         [0 , 0 , 1          ]]
    T = np.array(T)
    P = np.array([x, y, [1]*x.size])
    return np.dot(T, P)

fig, ax = plt.subplots(1, 4)
S_ = [[1, 1], [1.8, 1], [1, 1.7], [2, 2]]
P_ = [[0, 0], [0, 0], [0.45, 0.45], [1.1, 1.1]]
for i in range(4):
    sx, sy = S_[i]; px, py = P_[i]
    x_, y_, _ = trans_scale(x, y, px, py, sx, sy)
    ax[i].scatter(x_, y_)
    ax[i].scatter(px, py)
    ax[i].set_title(r'$p_x={0:.2f}$ , $p_y={1:.2f}$'.format(px, py) + '\n'
                    r'$s_x={0:.2f}$ , $s_y={1:.2f}$'.format(sx, sy))
    
    ax[i].set_xlim([-2, 2])
    ax[i].set_ylim([-2, 2])
    ax[i].grid(alpha=0.5)
    ax[i].axhline(y=0, color='k')
    ax[i].axvline(x=0, color='k')

plt.show()

Por favor agregue una descripción de la imagen.

3. Rotación

En el espacio 2D, para un punto ( x , y ) (x,y)( X ,y ) relativo a otro punto( px , py ) (p_x,p_y)( pagx,pagy) para la operación de rotación, generalmente el sentido antihorario es positivo y el sentido horario es negativo, asumiendo que el ángulo de rotación esβ \betaβ , entonces los puntos anterioresx, yx,yx ,y relativo al puntopx, py p_x,p_ypagx,pagyEl ángulo de rotación β \betaDefina la función β como una función:
[ x ′ ​​​​y ′ 1 ] = [ cos ⁡ β − sin ⁡ β px ( 1 − cos ⁡ β ) + py sin ⁡ β sin ⁡ β cos ⁡ β py ( 1 − cos ⁡ β ) + px sen ⁡ β 0 0 1 ] [ xy 1 ] \begin{bmatrix} x' \\ y' \\ 1 \end{bmatrix} = \begin{bmatrix} \cos \beta& -\sin \beta & p_x(1-\cos \beta) + p_y \sin \beta \\ \sin \beta & \cos \beta& p_y(1-\cos \beta) + p_x \sin \beta \\ 0 & 0& 1 \end {bmatriz} \begin{bmatrix}x\\y\\1\end{bmatrix} Xy1 = porquebpecadob0pecadobporqueb0pagx( 1porquesegundo )+pagypecadobpagy( 1porquesegundo )+pagxpecadob1 Xy1

def trans_rotate(x, y, px, py, beta):
    beta = np.deg2rad(beta)
    T = [[np.cos(beta), -np.sin(beta), px*(1 - np.cos(beta)) + py*np.sin(beta)],
         [np.sin(beta),  np.cos(beta), py*(1 - np.cos(beta)) - px*np.sin(beta)],
         [0           ,  0           , 1                                      ]]
    T = np.array(T)
    P = np.array([x, y, [1]*x.size])
    return np.dot(T, P)

fig, ax = plt.subplots(1, 4)

R_ = [0, 225, 40, -10]
P_ = [[0, 0], [0, 0], [0.5, -0.5], [1.1, 1.1]]

for i in range(4):
    beta = R_[i]; px, py = P_[i]
    x_, y_, _ = trans_rotate(x, y, px, py, beta)
    ax[i].scatter(x_, y_)
    ax[i].scatter(px, py)
    ax[i].set_title(r'$\beta={0}°$ , $p_x={1:.2f}$ , $p_y={2:.2f}$'.format(beta, px, py))
    
    ax[i].set_xlim([-2, 2])
    ax[i].set_ylim([-2, 2])
    ax[i].grid(alpha=0.5)
    ax[i].axhline(y=0, color='k')
    ax[i].axvline(x=0, color='k')

plt.show()

Por favor agregue una descripción de la imagen.

4. esquila

En el espacio 2D, para un punto ( x , y ) (x,y)( X ,y ) relativo a otro punto( px , py ) (p_x,p_y)( pagx,pagy) para operaciones de corte incorrecto, que generalmente se utiliza para el procesamiento de deformación de objetos elásticos. Supongamos que los parámetros de corte incorrecto a lo largo de las direcciones x e y sonλ x , λ y \lambda _x, \lambda _yyox, yoy, entonces la operación de corte incorrecto se puede resumir y expresar como una matriz homogénea de la siguiente manera:

[ x ′ ​​​​y ′ 1 ] = [ 1 λ x − λ xpx λ y 1 − λ ypy 0 0 1 ] [ xy 1 ] \begin{bmatrix} x' \\ y' \\ 1 \end{bmatrix} = \begin{bmatrix} 1& \lambda _x & -\lambda _x p_x \\ \lambda _y & 1& -\lambda _y p_y \\ 0 & 0& 1 \end{bmatrix} \begin{bmatrix} x \\ y \\ 1\end{bmatriz} Xy1 = 1yoy0yox10yoxpagxyoypagy1 Xy1

import matplotlib.pyplot as plt
import numpy as np


X, Y = np.mgrid[0:1:5j, 0:1:5j]
x, y = X.ravel(), Y.ravel()

def trans_shear(x, y, px, py, lambdax, lambday):
    T = [[1      , lambdax, -lambdax*px],
         [lambday, 1      , -lambday*py],
         [0      , 0      ,  1         ]]
    T = np.array(T)
    P = np.array([x, y, [1]*x.size])
    return np.dot(T, P)

fig, ax = plt.subplots(1, 4)

L_ = [[0, 0], [2, 0], [0, -2], [-2, -2]]
P_ = [[0, 0], [0, 0], [0, 1.5], [1.1, 1.1]]

for i in range(4):
    lambdax, lambday = L_[i]; px, py = P_[i]
    x_, y_, _ = trans_shear(x, y, px, py, lambdax, lambday)
    ax[i].scatter(x_, y_)
    ax[i].scatter(px, py)
    ax[i].set_title(r'$p_x={0:.2f}$ , $p_y={1:.2f}$'.format(px, py) + '\n'
                    r'$\lambda_x={0:.2f}$ , $\lambda_y={1:.2f}$'.format(lambdax, lambday))

    ax[i].set_xlim([-3, 3])
    ax[i].set_ylim([-3, 3])
    ax[i].grid(alpha=0.5)
    ax[i].axhline(y=0, color='k')
    ax[i].axvline(x=0, color='k')

plt.show()

inserte la descripción de la imagen aquí

5. Reflexión

Para reflejar, el vector normal v del eje de simetría ( vx , vy ) v(v_x,v_y)v ( vx,vy) , la matriz espejoT m T_{m}tmEjemplo:
[ 1 − 2 xv 2 − 2 xvyv 0 − 2 xvyv 1 − 2 yv 2 0 0 0 1 ] \left[ \begin{array}{ccc} 1-2 x_{v}{ }^{2} & -2 x_{v} y_{v} & 0 \\ -2 x_{v} y_{v} & 1-2 y_{v}{ }^{2} & 0 \\ 0 & 0 & 1 \end {matriz} \derecha] 12x _v2−2x _ _vyv0−2x _ _vyv12 añosv20001
Además, se necesita un punto para representar la posición del eje de simetría (cualquier punto entre los 2 puntos del eje de simetría), expresado como M ( xm , ym ) M\left(x_{\mathrm{m}}, y_ {m}\derecha)METRO( xm,ym) , matriz de transformaciónH = T t ∗ T m ∗ T t − 1 H = T_{t}*T_{m}*T_{t}^{-1}h=tttmtt 1:
H = [ 1 0 0 0 1 0 xmym 1 ] [ 1 − 2 xv 2 − 2 xvyv 0 − 2 xvyv 1 − 2 yv 2 0 0 0 1 ] [ 1 0 0 0 1 0 − xm − ym ] H = \left[\begin{array}{ccc}1&0&0\\0&1&0\\x_{\mathrm{m}}&y_{m}&1\end{array}\right ] \left[\begin{array}{ccc}1 -2x_{v}{}^{2}&-2x_{v}y_{v}&0\\-2x_{v}y_{v} &1-2 y_{v}{}^{2}&0\\0&0&1 \end{array}\right]\left[\begin{array}{ccc}1&0&0\\0 &1&0\\-x_{\mathrm{m}}&-y_{m}&1\end{array}\right]h= 10Xm01ym001 12x _v2−2x _ _vyv0−2x _ _vyv12 añosv20001 10−x _m01ym001
Las coordenadas después de la duplicación son T o ∗ T t ∗ T m ∗ T t − 1 T_{o}*T_{t}*T_{m}*T_{t}^{-1}totttmtt 1

Matriz de espejo para reflejar a lo largo del eje X
: [ 1 0 0 0 − 1 0 1 0 1 ] \left[ \begin{array}{ccc} 1 & 0 & 0 \\ 0 & -1 & 0 \\ 1 & 0 & 1 \end{array} \right] 101010001
Matriz de espejo para reflejar a lo largo del
eje Y: [ − 1 0 0 0 1 0 0 1 1 ] \left[ \begin{array}{ccc} -1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 1 & 1 \end{array} \right] 100011001

import numpy as np


a = np.array([[1, 2],
              [2, 2],
              [3, 5],
              [4, 6]])
a = np.array([a[:,0], a[:,1], np.ones(len(a))])
print("\n",a)
print("--------------------------------")

T_x = np.array( [[ 1,  0,  0],
                 [ 0, -1,  0],
                 [ 1,  0,  1]])
print("\n",np.dot(T_x, a))
print("=================================")
T_y = np.array( [[-1,  0,  0],
                 [ 0,  1,  0],
                 [ 0,  1,  1]])
print("\n",np.dot(T_y, a))

Referencia:
https://zhuanlan.zhihu.com/p/387578291
https://zhuanlan.zhihu.com/p/187411029
https://blog.csdn.net/Akiyama_sou/article/details/122144415

Supongo que te gusta

Origin blog.csdn.net/wsp_1138886114/article/details/131888684
Recomendado
Clasificación