# getPerspectiveTransform fails at 1 input point

Hey I am trying to compute a perspective transformation using openCV.
My code is as follows:

``````original_pts = np.array([[745, 1233], [1505, 1581], [1502, 1212], [855, 1229]], dtype=np.float32)
desired_pts = np.array([[46., 50.], [949., 490.], [949., 50.], [175., 50.]], dtype=np.float32)
M = cv2.getPerspectiveTransform(original_pts, desired_pts)
cv2.perspectiveTransform(np.float32(original_pts[None, :, :]), M)[0]
``````

The output is:

``````array([[  46.,   50.],
[   0.,    0.],
[ 949.,   50.],
[ 175.,   50.]], dtype=float32)
``````

For some reason the second point is just very wrong

Trying to debug I implemented the linear system myself:

``````x = original_pts[:, 0]
y = original_pts[:, 1]
xt = desired_pts[:, 0]
yt = desired_pts[:, 1]
A = []
for i in range(4):
equation = [x[i], y[i], 1, 0, 0, 0, 0, 0]
equation += [0] * i
equation += [-xt[i]]
equation += [0] * (3 - i)
A.append(equation)

equation = [0, 0, 0, x[i], y[i], 1, 0, 0]
equation += [0] * i
equation += [-yt[i]]
equation += [0] * (3 - i)
A.append(equation)

equation = [0, 0, 0, 0, 0, 0, x[i], y[i]]
equation += [0] * i
equation +=  [-1]
equation += [0] * (3 - i)
A.append(equation)

A = np.array(A)

b = np.array([0]*8 + [-1]*4)
res = np.linalg.solve(A, b)
my_M = np.array([[res[0], res[1], res[2]], [res[3], res[4], res[5]], [res[6], res[7], 1]])
cv2.perspectiveTransform(np.float32(original_pts[None, :, :]), my_M)[0]
``````

Which yields a better approximation:

``````array([[  47.653404,   51.79718 ],
[ 975.5118  ,  503.6889  ],
[ 949.      ,   50.      ],
[ 175.0361  ,   50.036106]], dtype=float32)
``````

Does anyone have any idea, whether I’m using `cv2.getPerspectiveTransfrom` wrongly or does it simply not work for some problems? I thought I’d basically reimplemented a non-optimized version of the function

the points:

`M` looks broken.

the problem here is that some of these points are (quasi-)colinear, meaning you don’t actually have enough equations to solve for eight unknowns. you tried to define a rectangle like this. that is no longer a proper perspective transform.

give `estimateAffine2D` or `estimateAffinePartial2D` a try

``````>>> (M1, inliers) = cv2.estimateAffine2D(original_pts[:,None,:], desired_pts[:,None,:]); M1
array([[    1.1938 ,    -0.00919,  -833.13482],
[    0.03246,     1.19188, -1443.22657]])
>>> cv.transform(original_pts[:,None,:], M1) - desired_pts[:,None,:]
array([[[-1.0849 ,  0.55139]],

[[ 0.00336, -0.00171]],

[[-0.18756,  0.09534]],

[[ 1.26947, -0.64526]]], dtype=float32)
``````
``````>>> (M2, inliers) = cv2.estimateAffinePartial2D(original_pts[:,None,:], desired_pts[:,None,:]); M2
array([[    1.19316,    -0.03249,  -803.94236],
[    0.03249,     1.19316, -1444.82473]])
>>> cv.transform(original_pts[:,None,:], M2) - desired_pts[:,None,:]
array([[[-1.09546,  0.55322]],

[[-8.59692,  0.46753]],

[[-0.18726,  0.09229]],

[[ 1.28259, -0.64551]]], dtype=float32)
``````

Thank you that’s very helpful ! However, what am I supposed to do if I don’t know a-priori if my points are quasi-colinear? Do I always have to check whether the perspective transform reproduces the given points before applying it to the larger point set? I won’t always have a affine transformation so switching to that is not an option