Project Tango C API 文档说TANGO_CALIBRATION_POLYNOMIAL_3_PARAMETERS
镜头失真建模为:
x_corr_px = x_px (1 + k1 * r2 + k2 * r4 + k3 * r6) y_corr_px = y_px (1 + k1 * r2 + k2 * r4 + k3 * r6)
也就是说,未失真坐标是失真坐标的幂级数函数。Java API中还有另一个定义,但该描述不够详细,无法说明函数映射的方向。
我在正确注册事物时遇到了很多麻烦,而且我怀疑映射实际上可能朝相反的方向发展,即失真坐标是未失真坐标的幂级数。如果相机校准是使用 OpenCV 生成的,那么问题的原因可能是 OpenCV 文档自相矛盾。最容易找到和理解的描述是OpenCV 相机校准教程,它与 Project Tango 文档一致:
但另一方面,OpenCV API 文档指定映射采用另一种方式:
我对 OpenCV 的实验表明,它的 API 文档看起来是正确的,而教程是错误的。正数k1
(所有其他失真参数设置为零)表示枕形失真,负数k1
表示桶形失真。这与Wikipedia 关于 Brown-Conrady 模型的说法相吻合,并且与Tsai 模型相反。请注意,失真可以通过任何一种方式建模,具体取决于使数学更方便的方式。我针对这种不匹配打开了一个针对 OpenCV的错误。
所以我的问题是:Project Tango 镜头失真模型是否与 OpenCV 中实现的模型相同(尽管有文档)?
这是我从彩色相机拍摄的图像(可以看到轻微的枕形):
以下是 Tango 服务报告的相机校准:
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
以下是如何在 python 中使用 OpenCV 去扭曲:
>>> 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)
这会产生这个,这可能在顶部边缘有点过度校正,但比我使用反向模型的尝试要好得多: