Hi, I am having problem with solvePNP
providing drastically different result given essentially same input. The function I am testing is as following
def pose_estimation(image_points, object_points, camera_matrix, dist_coeffs=np.zeros((4, 1))):
print(image_points)
print(object_points)
print(camera_matrix)
print(dist_coeffs)
res = cv2.solvePnP(object_points, image_points, camera_matrix, dist_coeffs)
image_points_ref = np.array([[413.00486363, 217.74341906],
[413.15650142, 220.25746512],
[407.77718261, 220.02347556],
[407.6519472 , 220.75548504],
[396.93019839, 220.29270531],
[396.14034602, 219.52147414],
[390.79016357, 219.29020324],
[391.74411038, 220.06815504],
[418.80503339, 216.85660952],
[418.69262068, 216.17264099],
[374.06361682, 214.25686018],
[375.19012835, 214.98173447],
[422.9617814 , 216.32101234],
[371.79359441, 214.12534426]])
assert np.linalg.norm(image_points-image_points_ref)<1e-7
print(f"Diff between image_points {np.linalg.norm(image_points-image_points_ref)}")
assert type(image_points) == type(image_points_ref)
assert type(image_points.dtype) == type(image_points_ref.dtype)
res_ref = cv2.solvePnP(object_points, image_points_ref, camera_matrix, dist_coeffs)
print(res)
print(res_ref)
return res
The only difference between two calls to the solvePNP
is I am using image_points_ref
, which I copied after printing our image_points
in the terminal, instead of image_points
. However, the two calls to the solvePNP
function is generating drastically different results. For the first one I am getting (which is close to ground truth) is
(True, array([[2.55860807],
[2.46640239],
[2.34886843]]), array([[ 225.93103637],
[ -31.06022884],
[3151.231523 ]]))
and for the second one
(True, array([[ 1.20061489],
[ 1.27656775],
[-1.21488959]]), array([[ 39.15125973],
[ 21.73380486],
[242.05403987]]))
I am wondering if it’s normal to get such a different result for small difference in the input? For reference, I am on Ubuntu 20.04, Python3.8, opencv-python 4.7.0.72 and 4.8.0.76. The number of image/object points is 14. The full output from this function is shown below.
[[413.00486363 217.74341906]
[413.15650142 220.25746512]
[407.77718261 220.02347556]
[407.6519472 220.75548504]
[396.93019839 220.29270531]
[396.14034602 219.52147414]
[390.79016357 219.29020324]
[391.74411038 220.06815504]
[418.80503339 216.85660952]
[418.69262068 216.17264099]
[374.06361682 214.25686018]
[375.19012835 214.98173447]
[422.9617814 216.32101234]
[371.79359441 214.12534426]]
[[-1221.370483 16.052534 0. ]
[-1279.224854 16.947235 5. ]
[-1279.349731 8.911615 5. ]
[-1221.505737 8.033512 5. ]
[-1221.43811 -8.496282 5. ]
[-1279.302002 -8.493725 5. ]
[-1279.315796 -16.504263 5. ]
[-1221.462402 -16.498976 5. ]
[-1520.81 26.1257 5. ]
[-1559.122925 26.101082 5. ]
[-1559.157471 -30.753305 5. ]
[-1520.886353 -30.761044 5. ]
[-1561.039063 31.5222 5. ]
[-1561.039795 -33.577713 5. ]]
[[1.25322156e+03 0.00000000e+00 3.20500000e+02]
[0.00000000e+00 1.25322156e+03 2.40500000e+02]
[0.00000000e+00 0.00000000e+00 1.00000000e+00]]
[[0.]
[0.]
[0.]
[0.]]
Diff between image_points 1.7516194186395812e-08
(True, array([[2.55860807],
[2.46640239],
[2.34886843]]), array([[ 225.93103637],
[ -31.06022884],
[3151.231523 ]]))
(True, array([[ 1.20061489],
[ 1.27656775],
[-1.21488959]]), array([[ 39.15125973],
[ 21.73380486],
[242.05403987]]))