1. 从停车场到三维世界:AVP场端感知的起点
大家好,我是老张,在AI和智能硬件这行摸爬滚打了十几年,最近几年深度参与了几个自动代客泊车(AVP)的场端感知项目。今天想和大家聊聊一个非常具体、也非常“硬核”的实战环节:当你拿到停车场里几十个摄像头同步采集回来的一堆“Bag”数据包时,如何一步步把它们变成一个完整、干净、带标签的三维点云世界。这个过程,就像是把一堆杂乱无章的乐高零件,拼成一幅能看清每个行人、每辆车的立体地图,是后续所有高级感知任务(比如我们想做的行人骨架提取)的基石。
很多刚接触这个领域的朋友,一听到“多相机融合”、“3D重建”、“点云标注”这些词就有点发怵,觉得背后是深不可测的数学和复杂的系统。其实不然,只要你把流程拆解开,每一步都有非常明确的工程化做法。我刚开始做的时候也踩了不少坑,比如坐标系统没对齐导致点云“飘”在天上,或者深度图转换后噪声多得没法看。这篇文章,我就结合最近一个真实的停车场项目,把从Bag数据拆解,到深度图生成点云、多视角融合,再到最终点云标注的完整流水线,掰开揉碎了讲给你听。我们的目标很明确:不空谈理论,只分享能直接上手的代码、能复现的步骤,以及那些只有踩过坑才知道的注意事项。
简单来说,这个流程可以概括为三步:“读”、“算”、“标”。“读”是把原始的ROS Bag数据包,解析成我们熟悉的图像和点云文件;“算”是利用相机参数,将每个相机的深度图转换并融合到一个统一的三维世界里;“标”则是为这个融合后的三维点云中的每个点(比如行人、车辆、柱子)打上标签,为后续的模型训练提供“标准答案”。下面,我们就一步步来。
2. 数据准备:拆解神秘的Bag数据包
拿到数据,第一步永远是先搞清楚手里有什么。在这个AVP场端项目中,我们通常会拿到一个数据包,里面通常包含这么几样东西:多个相机同步采集的原始数据(以ROS Bag格式存储)、所有相机的内参文件、所有相机的外参文件。Bag文件是机器人操作系统(ROS)中常用的数据记录格式,你可以把它理解成一个“容器”,里面按时间顺序打包存储了各个传感器(这里是深度相机)发布的话题(Topic)数据。
2.1 读懂相机参数文件:内参和外参
在动手写代码读数据之前,我们必须先理解两个关键文件:相机内参(Intrinsics) 和 相机外参(Extrinsics)。这是将2D图像信息映射到3D世界的“密码本”。
相机内参文件(比如 camera_info_depth_list_K.txt),通常是一个 N x 9 的矩阵(N是相机数量,比如75个)。每一行代表一个相机的内参矩阵 K,它描述了相机自身的成像几何特性。这个3x3的矩阵通常写成以下形式:
[Fx, 0, Cx]
[0, Fy, Cy]
[0, 0, 1 ]
这里,Fx 和 Fy 是以像素为单位的焦距,Cx 和 Cy 是图像的主点坐标(通常接近图像中心)。这个矩阵的作用是建立图像像素坐标 (u, v) 和相机坐标系下的归一化坐标 (Xc/Zc, Yc/Zc) 之间的关系。我习惯用一个简单的比喻:内参就像你的眼睛的“出厂设置”,决定了你看东西的视野范围和成像的扭曲程度(虽然这里通常已校正为无畸变)。
相机外参文件(比如 depth2global.txt),通常是一个 N x 7 的矩阵。每一行代表一个相机相对于某个世界坐标系(比如停车场地图坐标系)的位姿。这7个数通常是:平移向量 (tx, ty, tz) 和旋转四元数 (rw, rx, ry, rz)。四元数是一种非常高效且无奇异的表示3D旋转的方式。外参矩阵(一个4x4的变换矩阵)可以由这7个数计算得到。它的作用是把点在相机坐标系下的坐标,变换到世界坐标系下。继续用眼睛的比喻:外参就是你脑袋的位置和朝向,决定了你从哪个角度、哪个位置观察世界。
在实际操作中,我强烈建议你写个小脚本,加载这些参数文件,并可视化检查一下。比如,把75个相机的外参平移向量 (tx, ty, tz) 用三维散点图画出来,看看它们在停车场空间中的分布是否合理(是不是均匀覆盖了停车场区域),这能提前避免因为文件错位或格式误解导致的后续灾难性错误。
2.2 解析Bag文件:提取深度图与点云
接下来就是对付Bag文件了。我们一般会有两个Bag文件:一个专门记录所有相机的深度图像,另一个可能直接记录某些相机或融合后的点云。深度图像是每个像素值代表该点到相机距离的灰度图,它是生成点云的原材料。
首先,我们需要用ROS的命令行工具“侦察”一下Bag包里有什么。打开终端,依次执行:
# 启动ROS核心(如果还没运行的话)
roscore
# 查看bag文件的信息,包括包含哪些话题(topic)、消息类型、时间跨度等
rosbag info 2024-06-22-18-59-05.bag
这个 info 命令非常关键,它会告诉你这个Bag包里记录了哪些话题,比如可能是 /realsense001/depth/image_rect_raw, /realsense002/depth/image_rect_raw 等等。知道了话题名称和消息类型,我们才能编写正确的读取程序。
读取深度图Bag的Python代码核心是使用 rosbag 和 cv_bridge 库。下面是我在项目中实际使用的代码,加了详细的注释:
import numpy as np
import rosbag
from cv_bridge import CvBridge
import cv2
import os
print('开始读取深度图Bag...')
bridge = CvBridge()
camera_num = 75
# 替换为你的bag文件路径
bag = rosbag.Bag('../data/2024-06-22-18-59-05.bag')
for i in range(1, camera_num + 1):
# 为每个相机创建单


93

被折叠的 条评论
为什么被折叠?



