I am getting unexpected results from decomposeHomographyMat. My use case is to find the pose and perspective of a square spanned by 4 coplanar points. It works fine most of the time with solvePNP, however sometimes it finds the incorrect pose. I want to find the 4 possible poses so I can further apply some heuristics to get the correct one. I thought this to be possible with decomposeHomographyMat, doing this:
- getPerspectiveTransform
- decomposeHomographyMat
- do some heuristics based on the normals
However, It doesn't seem to work the way I expect it, no tvec/rvec returns a sensible result that corresponds to the answer given by solvePNP. Have I understood decomposeHomographyMat incorrectly?
In the following small code snippet I would expect the pts3d to be projected back on top the src_points, however it it not close. (The side of the square is 70 pixel units) Python 3.5, opencv 3.1
import numpy as np
import cv2
import matplotlib.pyplot as plt
distCoeffs = np.array([-0.01598395733850265, 0.0161002782626507, 0.006006531041189746, 0.003478025937843327, -0.09145387764106144])
camMatrix = np.array([[803.5320342948786, 0, 329.0069671931076],
[0, 802.550899545886, 244.2624067660293],
[0, 0, 1]])
src_pts = np.array([[-35,-35], [-35,35], [35,35], [35,-35]],dtype=np.float32)
dst_pts = np.array([[411, 92],
[372, 110],
[348, 80],
[386, 63]], dtype=np.float32)
H = cv2.getPerspectiveTransform(src_pts, dst_pts)
_, Rs, Ts, Ns = cv2.decomposeHomographyMat(H, camMatrix)
pts3d = np.array([[-35,-35, 0], [-35,35,0], [35,35,0], [35,-35,0]],dtype=np.float32)
for i in range(len(Ts)):
projected_pts = cv2.projectPoints(pts3d, Rs[i], Ts[i], camMatrix, distCoeffs)[0][:,0,:]
plt.plot(*projected_pts.T)
plt.axis((0,640,0,480))
plt.plot(*dst_pts.T, 'o')
plt.show()
While the following works, and finds a pose:
_, rvec, tvec = cv2.solvePnP(pts3d, dst_pts, camMatrix, distCoeffs)
projected_pts2 = cv2.projectPoints(pts3d, rvec, tvec, camMatrix, distCoeffs)[0][:,0,:]
plt.axis((0,640,0,480))
plt.plot(*projected_pts2.T, 'o')
plt.show()