Я отображаю 2d точки из исходного прямоугольника в целевой прямоугольник.Я хотел бы иметь возможность сделать это, не требуя OpenCV.Я уже реализовал getPerspectiveTransform
, но у меня проблемы с поиском источника математики, требуемой для perspectiveTransform
.Все, что я нашел, это либо об использовании cv2.perspectiveTransform
, либо о том, как реализовать cv2.getPerspectiveTransform
.
. Пока у меня есть это, и оно работает:
import numpy as np
import cv2
def getPerspectiveTransform(sourcePoints, destinationPoints):
"""
Calculates the 3x3 matrix to transform the four source points to the four destination points
Comment copied from OpenCV:
/* Calculates coefficients of perspective transformation
* which maps soruce (xi,yi) to destination (ui,vi), (i=1,2,3,4):
*
* c00*xi + c01*yi + c02
* ui = ---------------------
* c20*xi + c21*yi + c22
*
* c10*xi + c11*yi + c12
* vi = ---------------------
* c20*xi + c21*yi + c22
*
* Coefficients are calculated by solving linear system:
* a x b
* / x0 y0 1 0 0 0 -x0*u0 -y0*u0 \ /c00\ /u0\
* | x1 y1 1 0 0 0 -x1*u1 -y1*u1 | |c01| |u1|
* | x2 y2 1 0 0 0 -x2*u2 -y2*u2 | |c02| |u2|
* | x3 y3 1 0 0 0 -x3*u3 -y3*u3 |.|c10|=|u3|,
* | 0 0 0 x0 y0 1 -x0*v0 -y0*v0 | |c11| |v0|
* | 0 0 0 x1 y1 1 -x1*v1 -y1*v1 | |c12| |v1|
* | 0 0 0 x2 y2 1 -x2*v2 -y2*v2 | |c20| |v2|
* \ 0 0 0 x3 y3 1 -x3*v3 -y3*v3 / \c21/ \v3/
*
* where:
* cij - matrix coefficients, c22 = 1
*/
"""
if sourcePoints.shape != (4,2) or destinationPoints.shape != (4,2):
raise ValueError("There must be four source points and four destination points")
a = np.zeros((8, 8))
b = np.zeros((8))
for i in range(4):
a[i][0] = a[i+4][3] = sourcePoints[i][0]
a[i][1] = a[i+4][4] = sourcePoints[i][1]
a[i][2] = a[i+4][5] = 1
a[i][3] = a[i][4] = a[i][5] = 0
a[i+4][0] = a[i+4][1] = a[i+4][2] = 0
a[i][6] = -sourcePoints[i][0]*destinationPoints[i][0]
a[i][7] = -sourcePoints[i][1]*destinationPoints[i][0]
a[i+4][6] = -sourcePoints[i][0]*destinationPoints[i][1]
a[i+4][7] = -sourcePoints[i][1]*destinationPoints[i][1]
b[i] = destinationPoints[i][0]
b[i+4] = destinationPoints[i][1]
x = np.linalg.solve(a, b)
x.resize((9,), refcheck=False)
x[8] = 1 # Set c22 to 1 as indicated in comment above
return x.reshape((3,3))
if __name__ == "__main__":
# Create a transform to change table coordinates in inches to projector coordinates
sourceCorners = np.array([[0.0, 0.0],[120.0,0.0],[120.0,63.0],[0.0,63.0]])
destinationCorners = np.array([[4095.0,0],[3071,4095],[1024,4095],[0,0]])
perspectiveTransform = getPerspectiveTransform(sourceCorners, destinationCorners)
points = np.array([0,0,120,63,120,0,0,63,120,63,0,0,120,0], dtype=float).reshape(-1,1,2)
perspectivePoints = cv2.perspectiveTransform(points, perspectiveTransform)
print(perspectivePoints)
Результат:
[[[4095. 0.]]
[[1024. 4095.]]
[[3071. 4095.]]
[[ 0. 0.]]
[[1024. 4095.]]
[[4095. 0.]]
[[3071. 4095.]]]
Графики:
![Source](https://i.stack.imgur.com/3yimS.png)
![Destination](https://i.stack.imgur.com/b1vtb.png)
Источник OpenCV C для perspectiveTransform
имеет загадочные имена переменных, без комментариев и довольно нечитаем.
Может кто-нибудь указать мне хороший источник о том, как реализовать perspectiveTransform
?