Revision history [back]

Omnidir undistort vs projectPoints

I work with fisheye images (~180°FOV) and want to be able to convert forth and back between distorted and undistorted image coordinates. With the fisheye camera model I already have this running as expected, but wanted to have a look at the omnidirectional camera model. However, trying to do a coordinate roundtrip in python using

out1 = cv2.omnidir.projectPoints(points, rvec, tvec, K, xi, D)


followed by

out2 = cv2.omnidir.undistortPoints(out1, K, D, xi, None)


results in out2 differ from points (also apart from the obvious difference in dimension). Only in case of manually set xi = 0 I obtain concordance in points and out2. Am I just wrong, having bug in my code or ist this an issue within the opencv_contrib implementation?

I already had a look at the source of these functions and the corresponding paper, but couldn't definitely figure out, whether there might be something wrong. However, comparing https://github.com/opencv/opencv_contrib/blob/master/modules/ccalib/src/omnidir.cpp#L152 and https://github.com/opencv/opencv_contrib/blob/master/modules/ccalib/src/omnidir.cpp#L333 puzzles me a bit. Shouldn't one of them be the inverse operation or am I totally wrong?

Doing the same with fisheye camera model (using both, projectPoints and distortPoints basically interchangeable) leads to expected results.

I would be very thankful if anyone would have a hint for me regarding this.

code for reproducibility:

import numpy as np
import cv2

K = np.array([[ 1.24440479e+03, -1.22794708e-01,  9.60388731e+02],
[ 0.00000000e+00,  1.24469754e+03,  9.59437737e+02],
[ 0.00000000e+00,  0.00000000e+00,  1.00000000e+00]])
D = np.array([[-2.68369102e-01,  3.37814230e-02,  2.31238441e-04,
-2.66100513e-04]])
xi = np.array([1.])   # works with np.array([0.])

x = np.array([500])
y = np.array([500])

x = (x - K[0, 2]) / K[0, 0]
y = (y - K[1, 2]) / K[1, 1]
points = np.array([x, y, np.ones_like(x)]).T
rvec = np.zeros((3, 1))
tvec = np.zeros((3, 1))
out1, _ = cv2.omnidir.projectPoints(points.reshape(-1, 1, 3), rvec, tvec, K, xi, D)
out2 = cv2.omnidir.undistortPoints(out1, K, D, xi, None)