2026/3/31 17:31:12
网站建设
项目流程
外贸公司网站空间,青岛李沧建设局网站,建设网站便宜,wordpress多媒体不显示1. KITTI数据集calib.txt文件解析入门
第一次打开KITTI数据集的calib.txt文件时#xff0c;很多人都会被那一串串数字搞得一头雾水。这个文件其实就像自动驾驶汽车的体检报告#xff0c;记录了所有传感器的健康状况和相互位置关系。我刚开始接触时也花了不少时间…1. KITTI数据集calib.txt文件解析入门第一次打开KITTI数据集的calib.txt文件时很多人都会被那一串串数字搞得一头雾水。这个文件其实就像自动驾驶汽车的体检报告记录了所有传感器的健康状况和相互位置关系。我刚开始接触时也花了不少时间研究现在就把这些经验分享给大家。calib.txt文件主要包含三类关键信息相机内参、相机外参和传感器间的转换矩阵。其中P0-P3开头的四行对应四个相机的投影矩阵R0_rect是矫正旋转矩阵Tr_velo_to_cam和Tr_imu_to_velo则是激光雷达与相机、IMU与激光雷达之间的转换矩阵。举个例子KITTI数据集中00序列的calib.txt文件内容大致是这样的P0: 7.215377e02 0.000000e00 6.095593e02 0.000000e00 0.000000e00 7.215377e02 1.728540e02 0.000000e00 0.000000e00 0.000000e00 1.000000e00 0.000000e00 P1: 7.215377e02 0.000000e00 6.095593e02 -3.875744e02 0.000000e00 7.215377e02 1.728540e02 0.000000e00 0.000000e00 0.000000e00 1.000000e00 0.000000e00 R0_rect: 9.999239e-01 9.837760e-03 -7.445048e-03 -9.869795e-03 9.999421e-01 -4.278459e-03 7.402527e-03 4.351614e-03 9.999631e-01 Tr_velo_to_cam: 7.533745e-03 -9.999714e-01 -6.166020e-04 -4.069766e-03 1.480249e-02 7.280733e-04 -9.998902e-01 -7.631618e-02 9.998621e-01 7.523790e-03 1.480755e-02 -2.717806e-012. 相机参数详解与提取技巧2.1 相机内参矩阵解析相机内参矩阵就像相机的身份证包含了焦距、主点坐标等关键信息。在KITTI中P0-P3矩阵都是3×4的投影矩阵其中前3×3部分是内参矩阵。以P2矩阵为例P2: 7.215377e02 0.000000e00 6.095593e02 4.485728e01 0.000000e00 7.215377e02 1.728540e02 2.163791e-01 0.000000e00 0.000000e00 1.000000e00 2.745884e-03我们可以这样提取内参参数fx 721.5377 (x轴焦距)fy 721.5377 (y轴焦距)cx 609.5593 (主点x坐标)cy 172.8540 (主点y坐标)用Python提取这些参数非常方便import numpy as np P2 np.array([ [7.215377e02, 0.000000e00, 6.095593e02, 4.485728e01], [0.000000e00, 7.215377e02, 1.728540e02, 2.163791e-01], [0.000000e00, 0.000000e00, 1.000000e00, 2.745884e-03] ]) K P2[:3, :3] # 内参矩阵 fx, fy K[0,0], K[1,1] cx, cy K[0,2], K[1,2]2.2 相机外参与基线计算相机外参告诉我们相机在空间中的位置和朝向。KITTI数据集中相机之间的外参可以通过投影矩阵推算出来。比如P0和P1矩阵的第四列差值就包含了基线信息。计算两个相机之间的基线距离单位米b -(P1[0,3] - P0[0,3]) / P1[0,0] # 基线距离在KITTI数据中左右灰度相机的基线距离约为0.54米这个值对立体视觉深度计算非常关键。3. 3D点云投影实战指南3.1 坐标转换全流程将激光雷达点云投影到相机图像需要经过四个关键步骤将点云从激光雷达坐标系转换到相机坐标系应用矫正旋转矩阵R0_rect使用相机内参矩阵投影到图像平面过滤图像外的点和遮挡点这个过程的数学表达是y P2 * R0_rect * Tr_velo_to_cam * x3.2 Python实现详解下面是一个完整的点云投影代码示例def project_velo_to_image(pts_3d_velo, P, R0_rect, Tr_velo_to_cam): # 将点云从激光雷达坐标系转换到相机坐标系 pts_3d_cam np.dot(Tr_velo_to_cam, np.vstack([pts_3d_velo.T, np.ones((1, pts_3d_velo.shape[0]))])) # 应用矫正旋转 pts_3d_rect np.dot(R0_rect, pts_3d_cam[:3,:]) pts_3d_rect np.vstack([pts_3d_rect, np.ones((1, pts_3d_rect.shape[1]))]) # 投影到图像平面 pts_2d np.dot(P, pts_3d_rect) pts_2d[0,:] / pts_2d[2,:] pts_2d[1,:] / pts_2d[2,:] return pts_2d[:2,:].T实际使用时我们还需要考虑一些优化过滤掉相机后方的点z0移除超出图像边界的点根据深度值进行颜色映射方便可视化4. 常见问题与解决方案4.1 参数单位与坐标系问题KITTI数据集中的参数单位需要特别注意平移向量单位是米旋转矩阵是无量纲的图像坐标以像素为单位坐标系定义如下相机坐标系x向右y向下z向前激光雷达坐标系x向前y向左z向上4.2 实际应用中的坑在实际项目中我遇到过几个典型问题忘记扩展矩阵维度R0_rect是3×3矩阵需要扩展为4×4齐次坐标矩阵忽略了矫正旋转直接使用Tr_velo_to_cam会导致投影位置偏差基线计算符号错误忘记负号会导致深度计算完全错误解决方法也很简单# 正确扩展R0_rect矩阵 R0_rect_ext np.eye(4) R0_rect_ext[:3,:3] R0_rect # 正确计算投影 pts_2d P2.dot(R0_rect_ext).dot(Tr_velo_to_cam_ext).dot(pts_velo)5. 进阶应用与性能优化5.1 多传感器数据融合利用calib.txt中的参数我们可以实现激光雷达与相机的精确融合。比如将激光雷达检测的3D框投影到图像上def draw_3d_box(image, corners_3d, color(0,255,0), thickness2): # 将3D框的8个角点投影到图像 corners_2d project_velo_to_image(corners_3d, P2, R0_rect, Tr_velo_to_cam) # 绘制12条边 edges [(0,1),(1,2),(2,3),(3,0), # 底面 (4,5),(5,6),(6,7),(7,4), # 顶面 (0,4),(1,5),(2,6),(3,7)] # 侧面 for e in edges: cv2.line(image, tuple(corners_2d[e[0]].astype(int)), tuple(corners_2d[e[1]].astype(int)), color, thickness)5.2 批量处理与加速技巧处理整个KITTI序列时可以采用这些优化方法预计算所有变换矩阵的乘积避免重复计算使用多线程处理不同帧利用Numpy的向量化操作替代循环一个优化后的处理流程如下# 预计算变换矩阵 M P2.dot(R0_rect_ext).dot(Tr_velo_to_cam_ext) def fast_project(pts_velo, M): pts_hom np.hstack([pts_velo, np.ones((len(pts_velo),1))]) pts_2d_hom np.dot(M, pts_hom.T).T pts_2d pts_2d_hom[:,:2] / pts_2d_hom[:,2:3] return pts_2d