Transformación de perspectiva inversa: implementación de Python de la matriz de transformación

Referencia

La comprensión personal del principio de transformación de perspectiva y la implementación de Python de la matriz de transformación
puede ser incorrecta, bienvenido a discutir.
Para realizar la transformación de perspectiva, se deben seleccionar cuatro puntos. Estos puntos definen un rectángulo, pero en la imagen original, debido a problemas como los ángulos de la cámara, no parece ser un rectángulo. Para cambiar la perspectiva, necesitamos para realizar la transformación de perspectiva.
La transformación de perspectiva esencialmente convierte una imagen de una perspectiva a otra a través de una transformación lineal entre cuatro puntos.

Fórmula de cálculo

Matriz de transformación de perspectiva:

inserte la descripción de la imagen aquí
Definimos la matriz de puntos de destino como inserte la descripción de la imagen aquí, y definimos la matriz de puntos de origen como inserte la descripción de la imagen aquí.
Esto es un mapeo de coordenadas de píxeles bidimensionales a coordenadas mundiales tridimensionales. Nuestro objetivo principal aquí es mapear coordenadas de píxeles a otras coordenadas de píxeles.
Para inserte la descripción de la imagen aquí
cada par, inserte la descripción de la imagen aquíse cumplen las siguientes ecuaciones,
inserte la descripción de la imagen aquí
por lo tanto, podemos obtener la fórmula (1) y multiplicarla
inserte la descripción de la imagen aquí
hacia arriba y hacia abajo, y continuar deduciéndola:
inserte la descripción de la imagen aquí
necesitamos encontrar inserte la descripción de la imagen aquí, y la otra es la incógnita, y convertir la ecuación en una matriz AX = 0 AX=0una X=0
inserte la descripción de la imagen aquí
Hay 9 incógnitas en este momento, necesitamos usar 9 ecuaciones para resolver, para un par de puntos coincidentesinserte la descripción de la imagen aquípodemos obtener dos ecuaciones.
¿Por qué solo necesitamos 4 pares de puntos coincidentes para resolver la ecuación anterior?

8 incógnitas

Encontramos que para la fórmula (1) se puede escribir de la siguiente forma, el resultado no cambiará.
inserte la descripción de la imagen aquídonde α \alphaα es un número que no es 0.
En este punto, podemos mapear la fórmula anterior de nuevo a la forma matricial, y podemos obtenerinserte la descripción de la imagen aquí
Por lo tanto, podemos obtener
inserte la descripción de la imagen aquí
que solo hay 8 incógnitas en este punto, y solo necesitamos encontrar 4 conjuntos de puntos correspondientes para resolver la ecuación.
La reacción a la fórmula de la solución es la siguiente.
inserte la descripción de la imagen aquí
El último dígito es un 1 constante, podemos modificar la fórmula como fórmulainserte la descripción de la imagen aquí

Solución de código: hágalo usted mismo

# 此处的src是原坐标数组,dst是目标坐标数组
def WarpPerspectiveMatrix(src, dst):
    assert src.shape[0] == dst.shape[0] and src.shape[0] >= 4

    nums = src.shape[0]
    # 4组对应点,每组2行8列
    # 总共8行8列的数组,对应公式(3)中最左边的矩阵
    A = np.zeros((2 * nums, 8))
    # 4组对应点,每组2行1列
    # 总共8行1列,对应公式(3)中最右边的矩阵
    B = np.zeros((2 * nums, 1))
    # 矩阵赋值,0下标为x值,1下标为y值
    for i in range(0, nums):
        A_i = src[i,:]
        B_i = dst[i,:]
        A[2*i, :] = [A_i[0], A_i[1], 1, 0, 0, 0, -A_i[0]*B_i[0], -A_i[1]*B_i[0]]
        B[2*i] = B_i[0]

        A[2*i+1, :] = [0, 0 , 0, A_i[0], A_i[1], 1, -A_i[0]*B_i[1], -A_i[1]*B_i[1]]
        B[2*i+1] = B_i[1]

	# 转换为矩阵
    A = np.mat(A)
    # 求解未知数值,.I表示求逆
    warpMatrix = A.I * B

	# 矩阵后处理,主要是将a33的1值赋值回去
    warpMatrix = np.array(warpMatrix).T[0]
    warpMatrix = np.insert(warpMatrix, warpMatrix.shape[0], values=1.0, axis=0)
    warpMatrix = warpMatrix.reshape((3, 3))
    return warpMatrix

Solución de código: implementación de Opencv

# 注意,这里的src和dst,本人验证,使用np.float32()定义可以不出错
M = cv2.getPerspectiveTransform(src, dst)
src = np.float32([[34 * 720 / 160, 113 * 1280 / 288], [34 * 720 / 160, 186 * 1280 / 288], [157 * 720 / 160, 50 * 1280 / 288], [157 * 720 / 160, 244 * 1280 / 288]])
dst = np.float32([[150, 50], [150, 490], [780, 50], [780, 490]])


def WarpPerspectiveMatrix(src, dst):
    assert src.shape[0] == dst.shape[0] and src.shape[0] >= 4

    nums = src.shape[0]
    A = np.zeros((2 * nums, 8))
    B = np.zeros((2 * nums, 1))
    for i in range(0, nums):
        A_i = src[i,:]
        B_i = dst[i,:]
        A[2*i, :] = [A_i[0], A_i[1], 1, 0, 0, 0, -A_i[0]*B_i[0], -A_i[1]*B_i[0]]
        B[2*i] = B_i[0]

        A[2*i+1, :] = [0, 0 , 0, A_i[0], A_i[1], 1, -A_i[0]*B_i[1], -A_i[1]*B_i[1]]
        B[2*i+1] = B_i[1]

    A = np.mat(A)
    warpMatrix = A.I * B

    warpMatrix = np.array(warpMatrix).T[0]
    warpMatrix = np.insert(warpMatrix, warpMatrix.shape[0], values=1.0, axis=0)
    warpMatrix = warpMatrix.reshape((3, 3))
    return warpMatrix

M = WarpPerspectiveMatrix(src, dst)
print(M)
M = cv2.getPerspectiveTransform(src, dst)
print(M)
# 自己实现的
[[ 6.41178433e+00  0.00000000e+00 -7.04158205e+02]
 [ 1.54253726e+00  2.50298025e+00 -1.40077892e+03]
 [ 5.52700641e-03  0.00000000e+00  1.00000000e+00]]
# opencv官方的
[[ 6.41178433e+00  0.00000000e+00 -7.04158205e+02]
 [ 1.54253726e+00  2.50298025e+00 -1.40077892e+03]
 [ 5.52700641e-03 -1.08420217e-19  1.00000000e+00]]

Supongo que te gusta

Origin blog.csdn.net/REstrat/article/details/126987198
Recomendado
Clasificación