3D点云目标检测——KITTI数据集读取与处理

一、 数据基本情况

KITTI数据集是由德国卡尔斯鲁厄理工学院和丰田美国技术研究院联合创建的一个大规模自动驾驶场景下的计算机视觉算法评测数据集。以下是关于它的详细介绍:

  1. 数据集背景:为评估自动驾驶中计算机视觉算法的性能而设计。自动驾驶汽车需在复杂道路环境中准确识别、跟踪和预测其他车辆、行人等交通参与者的行为,KITTI数据集就是为提供这样一个基准测试平台而产生的。
  2. 数据采集:使用安装在改装丰田普锐斯车上的两台彩色相机、两台灰度相机、一个3D激光扫描仪和一个高精度GPS/IMU系统,在德国卡尔斯鲁厄的市区、乡村和高速公路等不同环境下行驶6小时采集数据。
  3. 数据内容:包含大量图像序列及对应的3D物体标注信息,标注信息有物体的位置、大小、方向及类别等,还提供了激光雷达扫描得到的点云数据。
  4. 数据标注:每个物体都被仔细标注,标注信息包括边界框、3D尺寸、方向角、截断程度以及遮挡程度等。
  5. 应用场景:主要用于评估自动驾驶中的目标检测、目标跟踪、3D重建、场景理解等算法的性能,也可用于研究计算机视觉、机器学习、模式识别等领域的其他问题。
  6. 评估指标:提供了准确率、召回率、F1分数等一套评估指标,帮助研究人员了解算法表现并进行比较。
  7. 数据集影响:自发布以来,已成为自动驾驶和计算机视觉领域的重要基准测试平台,推动了相关算法发展,促进了学术界和工业界的合作与交流,为自动驾驶技术的实际应用奠定了基础。

KITTI 数据集采集自德国卡尔斯鲁厄市,涵盖了市区、郊区、高速公路等多种交通场景。数据采集时间为 2011 年 09 月 26 日、28 日、29 日、30 日及 10 月 03 日的白天。

KITTI 数据采集平台如下图所示:

该平台包含以下设备:

  • 2 个 140 万像素的黑白相机
  • 2 个 140 万像素的彩色相机
  • 4 个爱特蒙特光学镜头
  • 1 个 64 线 Velodyne 3D 激光扫描仪
  • 1 个 OXTS RT3003 惯导系统

从上图可以看出:

  • 相机的坐标系中,Z 轴朝前,Y 轴朝下,整个坐标系为右手坐标系。
  • 激光雷达的 X 轴朝向正前方,Z 轴竖直向上,Y 轴根据右手定则确定。
  • IMU/GPS 系统的坐标系朝向与激光雷达一致。

总结来说,KITTI 数据集由 4 个相机、1 个激光雷达、1 个 IMU/GPS 惯导系统共同组成。我们需要厘清这 6 个传感器之间的坐标系关系和时间同步信息。

关于传感器的尺寸参数可以参考下图:

[date]-drive-sync-[sequence] 目录下存放了 6 个传感器对应的采集数据文件夹,分别为:

- image_00
- image_01
- image_02
- image_03
- oxts
- velodyne-points
  • 时间戳:在 velodyne-points 文件夹下有三个时间戳文件:
    • timestamps_start.txt:激光扫描仪一周开始扫描的时间。
    • timestamps_end.txt:激光扫描仪一周扫描结束的时间。
    • timestamps.txt:激光扫描到正前方触发相机拍照的时间。
  • 图像数据
    • 图像是裁剪掉了引擎盖和天空之后的图像。
    • 图像是去畸变之后的数据。
  • OXTS 数据:每一帧存储了包括经纬度、速度、加速度等 30 个不同的字段值。
  • 雷达数据
    • 浮点数的二进制文件,每个点由 4 个浮点数组成,分别为雷达坐标系下的 x,y,z 坐标和激光的反射强度 r
    • 每扫描一次,大约得到 120000 个 3D 点。
    • 激光雷达绕垂直轴逆时针转动。

传感器标定及时间同步

整个系统以激光雷达旋转一周为 1 帧。激光雷达旋转到某个特定位置时,通过一个弹簧片的物理接触触发相机拍照。IMU 无法通过这种触发方式采集数据,但 IMU 数据采集的频率达到了 100Hz,通过对 IMU 采集的数据记录时间戳,选择与相机采集时间最接近的作为当前帧的数据,最大时间误差为 5ms。

相机标定:相机内外参标定使用的方法是 A toolbox for automatic calibration of range and camera sensors using a single shot。所有相机的中心都已对齐,即它们都在相同的 XY 平面上,这便于图像的校正(去除天空和引擎盖)。

每天开始采集数据前,都会对整个数据采集系统进行标定,以避免传感器间位置的偏移。

在每天的 date_calib.zip 文件夹下,有 3 个文本文件,用于记录传感器之间的坐标转换关系等信息。

二、 用于 3D 目标检测

最初,KITTI 数据集支持的任务包括双目、光流和里程计。后来,陆续支持了深度估计、2D 目标检测、3D 目标检测、BEV 目标检测、语义分割、实例分割、多目标追踪等任务。

在目标检测中,定义的类别有 8 种:Car/Van/Truck/Pedestrian/Person_sitting/Cyclist/Tram/Misc(其他)

对 3D 对象的标注是在激光雷达坐标系下进行的。需要注意的是,目前 3D 目标检测只由检测框中心点坐标 xyz、检测框的长宽高 length/width/height 和检测框的偏航角 yaw 这 7 个自由度组成。

在这里插入图片描述

不过这里有一个容易引起歧义的问题:length/width/height 分别对应 xyz 的哪个轴呢?从下图可以看出,length 对应 dxwidth 对应 dyheight 对应 dz。整个 3D 框的标注在激光雷达坐标系下。

KITTI 3D 目标检测数据集包括 7481 张训练数据和 7518 张测试数据。尽管 KITTI 数据集中包含了标注了 8 种对象,但只有 Car/Pedestrian 标注得比较充分,KITTI 官方用来评估算法。在 KITTI BenchMark 中使用的 3D 检测框类别有 3 个,分别是 Car/Pedestrian/Cyclist

下载的 3D 目标检测数据集包含以下文件夹:

  • image_02:左目彩色 png 格式的图像。
  • label_02:左目彩色图像中标注的对象标签。
  • calib:传感器之间的坐标转换关系。
  • velodyne:激光点云数据。
  • plane:在激光坐标系下,路面的平面方程。

标签文件中每一行内容如下:

Pedestrian 0.00 0 -0.20 712.40 143.00 810.73 307.92 1.89 0.48 1.20 1.84 1.47 8.41 0.01

包含的字段有:

  • type:目标的类型,如 Car/Van 等,1 个字段。
  • truncated:浮点数 0-1,目标对象离开相机视野的比例,1 个字段。
  • occluded:整数 0,1,2,30 表示全部可见,1 表示部分遮挡,2 表示大部分未遮挡,3 表示未知,1 个字段。
  • alpha:对象的观测角,1 个字段。
  • bbox:2D 检测框像素坐标,x1,y1,x2,y2,4 个字段。
  • dimensions:3D 对象的尺寸,height,width,length,单位是米,3 个字段。
  • location:3D 对象在相机坐标系下的中心坐标 xyz,单位是米。
  • rotation_yyaw 角,偏航角。
  • score:目标对象的评分,用来计算 ROC 曲线或 MAP。

相机坐标系中的点可以通过 calib 中的变换矩阵变换到图像像素坐标中。

rotation_yalpha 的区别在于:alpha 度量的是相机中心到对象中心的角度。rotation_y 度量的是对象绕相机坐标系 y 轴的转角 yaw。以汽车为例,当一辆车在相机坐标系下位于 x 轴方向时,其 rotation_y 角为零,无论这辆车在 x,z 平面的哪个位置。而对于 alpha 角来说,仅当汽车在相机坐标系下 z 轴上时,alpha 角为零,偏离 z 轴时,alpha 角都不为零。

将激光点云投影到左目彩色图像中可以使用的公式为:X = P2 * R0_rect * Tr_vel_to_cam * Y

其中,R0_rect 是 3x3 的校正矩阵,Tr_vel_to_cam 是 3x4 的雷达变换到相机坐标系下的变换矩阵。

三、代码实战

使用 open3d 读取点云

import numpy as np
import struct
import open3d as o3d

def convert_kitti_bin_to_pcd(binFilePath):
    size_float = 4
    list_pcd = []
    with open(binFilePath, "rb") as f:
        byte = f.read(size_float * 4)
        print(byte)
        while byte:
            x, y, z, intensity = struct.unpack("ffff", byte)
            list_pcd.append([x, y, z])
            byte = f.read(size_float * 4)
    np_pcd = np.asarray(list_pcd)
    pcd = o3d.geometry.PointCloud()
    pcd.points = o3d.utility.Vector3dVector(np_pcd)
    return pcd

bs = "/xx/xx/data/code/mmdetection3d/demo/data/kitti/000008.bin"
pcds = convert_kitti_bin_to_pcd(bs)
o3d.visualization.draw_geometries([pcds])

# save
o3d.io.write_point_cloud('000008.pcd', pcds, write_ascii=False, compressed=False, print_progress=False)

通过 numpy 读取:

def load_bin(bin_file):
    data = np.fromfile(bin_file, np.float32).reshape((-1, 4))
    data = data[:, :-1]
    pcd = o3d.geometry.PointCloud()
    pcd.points = o3d.utility.Vector3dVector(data)
    return pcd

上述代码可以读取并可视化点云数据,并将其保存为 pcd 格式的点云。

选取的 3D 目标检测任务数据集中的 training/image_02/000008.png,对应的标签文件为 000008.txt,内容如下:

Car 0.88 3 -0.69 
### 使用 KITTI 点云数据集进行 SLAM 建图 #### 数据准备 为了利用KITTI点云数据集进行SLAM建图,需先下载所需的数据子集。通常选用的是KITTI里程计数据集中特定编号的数据序列,如07号数据集[^1]。 #### 加载点云数据 加载激光雷达点云文件是第一步操作。这些文件通常是二进制格式存储的,并且每一行代表一个测量点的空间坐标(x, y, z)以及反射强度(intensity),可以使用Python中的`numpy`库来高效处理这类数据: ```python import numpy as np def load_velo_scan(velo_filename): scan = np.fromfile(velo_filename, dtype=np.float32) return scan.reshape((-1, 4)) ``` 此函数能够读取指定路径下的.bin文件并返回一个形状为(N×4)的数组,其中N表示点的数量。 #### 座标变换配准 对于连续两帧之间的点云匹配问题,可以通过应用已知的姿态变化矩阵(来自GPS/IMU传感器提供的ground truth信息)来进行初步校正。这一步骤有助于减少累积误差的影响,使后续迭代最近点(ICP)算法或其他精确实现更加容易收敛于正确解。姿态转换可通过如下方式实现: ```python from scipy.spatial.transform import Rotation as R def transform_point_cloud(points, rotation_matrix, translation_vector): r = R.from_matrix(rotation_matrix) transformed_points = points.copy() transformed_points[:, :3] = (r.apply(transformed_points[:, :3]) + translation_vector).astype(np.float32) return transformed_points ``` 这里假设输入参数`points`是一个包含所有待转换点坐标的二维数组;而`rotation_matrix`和`translation_vector`则分别对应着旋转和平移分量。 #### 构建全局地图 随着车辆沿轨迹移动收集更多观测值,可逐步积累局部扫描结果形成更大范围内的环境模型——即所谓的“全局地图”。这一过程涉及到将每一对相邻时刻获取到的新旧视景关联起来,并更新整体结构以反映最新感知情况。具体来说,就是在每次接收到新的LiDAR扫面之后执行上述提到过的刚体运动补偿步骤,再将其加入现有集合之中完成增量式的扩展。 #### 融合语义信息 除了传统的几何特征外,还可以考虑引入额外维度的信息源辅助定位绘图任务。例如,在某些研究工作中已经展示了如何结合视觉识别技术赋予场景内各组成部分更丰富的描述属性,从而提高系统的鲁棒性和准确性。特别是当面对复杂多变的城市道路状况时,这种方法显得尤为重要[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知来者逆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值