KITTI 与 Waymo Open Dataset 2024:自动驾驶点云数据格式转换与预处理实战

自动驾驶技术的快速发展离不开高质量的数据集支持。作为该领域的两大标杆,KITTI和Waymo Open Dataset在2024年都进行了重要更新,为研究者提供了更丰富、更精确的感知数据。本文将深入探讨这两大数据集的最新特性,并手把手教你完成从数据下载到预处理的全流程操作。

1. 数据集概览与获取

2024年,KITTI和Waymo Open Dataset都迎来了重大版本更新。KITTI 2024版新增了夜间场景和极端天气条件下的采集数据,点云采样频率提升至20Hz,同时改进了标注精度。Waymo则开放了更多城市道路数据,单个场景的连续采集时长从20秒延长至60秒,显著提升了时序分析的价值。

数据集下载步骤:

  1. KITTI数据集获取
wget https://s3.eu-central-1.amazonaws.com/avg-kitti/raw_data/2024_kitty_raw_data.zip
unzip 2024_kitty_raw_data.zip -d ./kitti_data
  1. Waymo数据集获取
import waymo_open_dataset
dataset = waymo_open_dataset.WaymoOpenDataset()
dataset.download_and_prepare('waymo_data/')

关键差异对比:

特性 KITTI 2024 Waymo Open Dataset 2024
数据采集频率 20Hz 10Hz
单场景时长 15-30秒 60秒
标注类型 3D框+类别 3D框+类别+运动轨迹
天气条件 新增雨雾场景 多种光照条件
数据量 50小时 2000小时

2. 数据解析核心技术

2.1 KITTI数据解析

KITTI采用传统的二进制存储格式,每个点云文件包含约12万点。2024版改进了时间同步机制,使得激光雷达与摄像头数据对齐更精确。

Python解析示例:

import numpy as np

def read_kitti_bin(bin_path):
    """读取KITTI二进制点云文件"""
    points = np.fromfile(bin_path, dtype=np.float32).reshape(-1, 4)
    # 第4列为反射强度
    return points[:, :3], points[:, 3]

# 使用示例
points, intensity = read_kitti_bin('kitti_data/000000.bin')

2.2 Waymo数据解析

Waymo使用TFRecord格式存储数据,单个文件包含完整的场景信息。2024版新增了动态物体轨迹预测标注。

关键解析代码:

import tensorflow as tf
from waymo_open_dataset import dataset_pb2

def parse_waymo_tfrecord(tfrecord_path):
    dataset = tf.data.TFRecordDataset(tfrecord_path)
    for data in dataset:
        frame = dataset_pb2.Frame()
        frame.ParseFromString(data.numpy())
        yield frame

# 提取点云数据
for frame in parse_waymo_tfrecord('waymo_data/segment-123.tfrecord'):
    lidar_data = frame.lidar_data[0]  # 获取第一个激光雷达数据
    points = np.column_stack([
        lidar_data.range_image_returns[0].data,
        lidar_data.range_image_returns[0].data
    ])

3. 格式转换实战

实际项目中经常需要统一数据格式。下面展示将KITTI转换为通用PLY格式,以及Waymo到KITTI格式的转换方法。

3.1 KITTI转PLY格式

def kitti_to_ply(bin_path, ply_path):
    points, intensity = read_kitti_bin(bin_path)
    
    header = f"""ply
format ascii 1.0
element vertex {len(points)}
property float x
property float y
property float z
property float intensity
end_header
"""
    
    with open(ply_path, 'w') as f:
        f.write(header)
        for pt, i in zip(points, intensity):
            f.write(f"{pt[0]} {pt[1]} {pt[2]} {i}\n")

# 转换示例
kitti_to_ply('kitti_data/000000.bin', 'output/000000.ply')

3.2 Waymo转KITTI格式

def waymo_to_kitti(frame, output_dir, frame_id):
    """将Waymo帧转换为KITTI格式"""
    # 提取点云
    lidar = frame.lidar_data[0]
    points = np.array([[p.x, p.y, p.z, p.intensity] 
                      for p in lidar.returns])
    
    # 保存点云
    points.astype(np.float32).tofile(f'{output_dir}/{frame_id:06d}.bin')
    
    # 保存标注
    with open(f'{output_dir}/{frame_id:06d}.txt', 'w') as f:
        for label in frame.laser_labels:
            f.write(f"{label.type} 0 0 0 "
                   f"{label.box.center_x} {label.box.center_y} {label.box.center_z} "
                   f"{label.box.length} {label.box.width} {label.box.height} "
                   f"{label.box.heading} 1\n")

4. 预处理关键技术与常见问题

4.1 点云滤波与降采样

高质量预处理能显著提升模型性能。以下是基于体素网格的降采样方法:

from sklearn.neighbors import KDTree

def voxel_downsample(points, voxel_size=0.1):
    """体素网格降采样"""
    voxel_grid = {}
    for point in points:
        voxel = tuple((point // voxel_size).astype(int))
        if voxel not in voxel_grid:
            voxel_grid[voxel] = []
        voxel_grid[voxel].append(point)
    
    # 取每个体素中心点
    downsampled = []
    for voxel in voxel_grid.values():
        downsampled.append(np.mean(voxel, axis=0))
    return np.array(downsampled)

4.2 数据增强技巧

典型增强操作:

  • 随机旋转(±10度)
  • 随机平移(±0.5米)
  • 随机缩放(0.9-1.1倍)
  • 点丢弃(随机丢弃5%点)
def augment_pointcloud(points):
    # 随机旋转
    angle = np.random.uniform(-10, 10)
    rot_mat = np.array([
        [np.cos(angle), -np.sin(angle), 0],
        [np.sin(angle), np.cos(angle), 0],
        [0, 0, 1]
    ])
    points = points @ rot_mat
    
    # 随机平移
    points += np.random.uniform(-0.5, 0.5, 3)
    
    # 随机缩放
    points *= np.random.uniform(0.9, 1.1)
    
    # 随机丢弃
    if np.random.rand() < 0.05:
        mask = np.random.rand(len(points)) > 0.05
        points = points[mask]
    
    return points

4.3 常见问题排查

问题1:Waymo数据加载缓慢

解决方案:使用TFRecord的并行加载功能

dataset = tf.data.TFRecordDataset(tfrecord_path)
dataset = dataset.prefetch(buffer_size=10)  # 预加载10个样本
dataset = dataset.map(parse_function, num_parallel_calls=4)

问题2:KITTI点云坐标不一致

注意:KITTI使用相机坐标系(x向前,y向左,z向上),而Waymo使用激光雷达坐标系。转换关系:

def kitti_to_waymo_coords(points):
    """KITTI坐标转Waymo坐标"""
    # x->x, y->-z, z->y
    return np.column_stack([points[:,0], points[:,2], -points[:,1]])

问题3:内存不足

处理大型Waymo文件时,建议使用生成器逐帧处理:

def process_large_waymo_file(tfrecord_path):
    dataset = tf.data.TFRecordDataset(tfrecord_path)
    for data in dataset:
        frame = dataset_pb2.Frame()
        frame.ParseFromString(data.numpy())
        yield process_frame(frame)  # 逐帧处理

5. 实战案例:构建统一数据处理流水线

最后,我们整合上述技术构建完整的处理流水线:

class UnifiedDataPipeline:
    def __init__(self, config):
        self.voxel_size = config.get('voxel_size', 0.1)
        self.augment = config.get('augment', False)
    
    def process_kitti(self, bin_path):
        points, intensity = read_kitti_bin(bin_path)
        points = voxel_downsample(points, self.voxel_size)
        if self.augment:
            points = augment_pointcloud(points)
        return points
    
    def process_waymo(self, frame):
        points = extract_waymo_points(frame)
        points = voxel_downsample(points, self.voxel_size)
        if self.augment:
            points = augment_pointcloud(points)
        return points
    
    def run(self, input_path, output_path):
        if input_path.endswith('.bin'):  # KITTI格式
            points = self.process_kitti(input_path)
            np.save(output_path, points)
        elif input_path.endswith('.tfrecord'):  # Waymo格式
            for i, frame in enumerate(parse_waymo_tfrecord(input_path)):
                points = self.process_waymo(frame)
                np.save(f'{output_path}_{i:04d}.npy', points)

在实际项目中,这套处理流程可以帮助我们快速统一不同来源的数据,为后续的模型训练打下坚实基础。根据具体任务需求,还可以添加更多定制化的预处理步骤,如地面去除、点云分割等操作。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐