我通过tof camera
收到了MATLAB
的深度图片。用于计算深度图像中x,y,z坐标的tof相机的交付驱动程序正在使用openCV
函数,该函数通过mex文件在MATLAB
中实现。
但是后来我不能再使用这些驱动程序,也不能使用openCV
函数,因此我需要自己实现2d到3d的映射,包括径向失真的补偿。我已经掌握了相机参数,并且深度图像的每个像素的x,y,z坐标的计算正在工作。到目前为止,我正在通过牛顿法解决非正畸的隐式方程(这不是很快......)。但我想实现openCV
函数的不失真。
...我的问题是:我真的不明白它,我希望你能帮助我。它是如何实际工作的?我试图在论坛中搜索,但没有找到任何有关此案例的有用线索。
问候!
答案 0 :(得分:8)
documentation page related to camera calibration上提供了3D点[X; Y; Z]
投影到2D图像点[u; v]
的方程式:
在镜头失真的情况下,方程是非线性的并且取决于3到8个参数(k1到k6,p1和p2)。因此,通常需要非线性求解算法(例如Newton方法,Levenberg-Marquardt算法等)来反演这样的模型并估计来自失真的未失真坐标。这就是函数undistortPoints
背后的用法,调整参数使得优化速度快但有点不准确。
然而,在图像镜头校正的特定情况下(与点校正相反),基于众所周知的图像重新采样技巧,存在更有效的方法。这个技巧是,为了获得目标图像的每个像素的有效强度,您必须将目标图像中的坐标转换为源图像中的坐标,而不是直观地期望的相反。在镜头失真校正的情况下,这意味着您实际上不必反转非线性模型,而只是应用它。
基本上,函数undistort
背后的算法如下。对于目标镜头校正图像的每个像素,请执行以下操作:
(u_dst, v_dst)
将像素坐标(x', y')
转换为标准化坐标K
,(x'', y'')
,(x'', y'')
将(u_src, v_src)
转换为失真像素坐标K
,(u_src, v_src)
关联的强度/深度,并将此强度/深度指定给当前目标像素。请注意,如果您对深度图图像失真感兴趣,则应使用最近邻插值,否则几乎可以肯定在对象边界处插入深度值,从而产生不必要的伪像。
答案 1 :(得分:0)
以上答案是正确的,但请注意,UV坐标位于屏幕空间中,并且以(0,0)为中心,而不是“实际” UV坐标。
来源:使用Python / OpenGL自己重新实现。代码:
def correct_pt(uv, K, Kinv, ds):
uv_3=np.stack((uv[:,0],uv[:,1],np.ones(uv.shape[0]),),axis=-1)
xy_=uv_3@Kinv.T
r=np.linalg.norm(xy_,axis=-1)
coeff=(1+ds[0]*(r**2)+ds[1]*(r**4)+ds[4]*(r**6));
xy__=xy_*coeff[:,np.newaxis]
return (xy__@K.T)[:,0:2]