The Project Tango C API documentation says that the distortion of the TANGO_CALIBRATION_POLYNOMIAL_3_PARAMETERS lens TANGO_CALIBRATION_POLYNOMIAL_3_PARAMETERS modeled as:
x_corr_px = x_px (1 + k1 * r2 + k2 * r4 + k3 * r6) y_corr_px = y_px (1 + k1 * r2 + k2 * r4 + k3 * r6)
That is, undistorted coordinates are a power function of distorted coordinates. There is another definition in the Java API , but this description is not detailed enough to indicate in which direction the map is displayed.
I had a lot of problems in registering things correctly, and I suspect that the display may indeed go in the opposite direction, that is, the distorted coordinates are a power series of undistorted coordinates. If the camera was calibrated using OpenCV, the cause of the problem may be that the OpenCV documentation is self-contradictory. The easiest description to find and understand is the OpenCV Camera Calibration Guide , which is consistent with Project Tango docs:

But, on the other hand, the OpenCV API documentation indicates that the mapping happens differently:

My experiments with OpenCV show that its API documentation looks right and the tutorial is wrong. A positive k1 (with all other distortion parameters set to zero) means pincushion distortion, and a negative k1 means barrel distortion. This is consistent with what Wikipedia says about the Brown Conradi model and will be the opposite of the Tsai Model . Note that the distortion can be modeled anyway depending on what makes the math more convenient. I discovered an error against OpenCV for this mismatch.
So my question is: is the Project Tango lens distortion model the same as in OpenCV (despite the documentation)?
Here is the image that I captured from a color camera (apparently, slightly tinted):

And here is the camera calibration reported by the Tango service:
distortion = {double[5]@3402} [0] = 0.23019999265670776 [1] = -0.6723999977111816 [2] = 0.6520439982414246 [3] = 0.0 [4] = 0.0 calibrationType = 3 cx = 638.603 cy = 354.906 fx = 1043.08 fy = 1043.1 cameraId = 0 height = 720 width = 1280
Here, how inconvenient with OpenCV in python:
>>> import cv2 >>> src = cv2.imread('tango00042.png') >>> d = numpy.array([0.2302, -0.6724, 0, 0, 0.652044]) >>> m = numpy.array([[1043.08, 0, 638.603], [0, 1043.1, 354.906], [0, 0, 1]]) >>> h,w = src.shape[:2] >>> mDst, roi = cv2.getOptimalNewCameraMatrix(m, d, (w,h), 1, (w,h)) >>> dst = cv2.undistort(src, m, d, None, mDst) >>> cv2.imwrite('foo.png', dst)
And this produces this, which may be slightly corrected at the top edge, but much better than my attempts with the reverse model:
