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:
Definimos la matriz de puntos de destino como , y definimos la matriz de puntos de origen como .
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
cada par, se cumplen las siguientes ecuaciones,
por lo tanto, podemos obtener la fórmula (1) y multiplicarla
hacia arriba y hacia abajo, y continuar deduciéndola:
necesitamos encontrar , y la otra es la incógnita, y convertir la ecuación en una matriz AX = 0 AX=0una X=0
Hay 9 incógnitas en este momento, necesitamos usar 9 ecuaciones para resolver, para un par de puntos coincidentespodemos 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á.
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 obtener
Por lo tanto, podemos obtener
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.
El último dígito es un 1 constante, podemos modificar la fórmula como fórmula
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]]