Project Tango C API documentation表示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 camera calibration tutorial,它与Project Tango文档一致:
但另一方面,OpenCV API documentation指定映射的另一种方式:
我使用OpenCV进行的实验表明,其API文档显示正确且教程错误。正k1
(所有其他失真参数设置为零)表示枕形失真,负k1
表示桶形失真。这与Wikipedia says about the Brown-Conrady model相匹配,与Tsai model相反。请注意,失真可以是modeled either way,具体取决于使数学更方便的原因。我针对这种不匹配对OpenCV开了一个bug。
所以我的问题是: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)
这产生了这个,这可能在顶部边缘有点过度修正,但比我对反向模型的尝试要好得多:
答案 0 :(得分:0)
也许它不适合发布,但我真的想分享OpenCV中使用的可读代码版本,以实际纠正失真。
我确信我不是唯一一个需要x_corrected
和y_corrected
且未能找到一个简单易懂的公式的人。
我在Python中重写了cv2.undistortPoints
的基本部分,您可能会注意到纠正是迭代执行的。这很重要,因为9次幂的多项式解不存在,我们所能做的就是多次应用它的尊重版本来得到数值解。
def myUndistortPoint((x0, y0), CM, DC):
[[k1, k2, p1, p2, k3, k4, k5, k6]] = DC
fx, _, cx = CM[0]
_, fy, cy = CM[1]
x = x_src = (x0 - cx) / fx
y = y_src = (y0 - cy) / fy
for _ in range(5):
r2 = x**2 + y**2
r4 = r2**2
r6 = r2 * r4
rad_dist = (1 + k4*r2 + k5*r4 + k6*r6) / (1 + k1*r2 + k2*r4 + k3*r6)
tang_dist_x = 2*p1 * x*y + p2*(r2 + 2*x**2)
tang_dist_y = 2*p2 * x*y + p1*(r2 + 2*y**2)
x = (x_src - tang_dist_x) * rad_dist
y = (y_src - tang_dist_y) * rad_dist
x = x * fx + cx
y = y * fy + cy
return x, y
为了加快速度,您只能使用三次迭代,在大多数相机上,这将提供足够的精度来适应像素。