Ask Your Question

Revision history [back]

Unexpected results from decomposeHomographyMat

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:

  1. getPerspectiveTransform
  2. decomposeHomographyMat
  3. 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()