GGCNN实战:从深度相机数据采集到PyBullet仿真数据集构建

张开发
2026/4/19 2:49:51 15 分钟阅读

分享文章

GGCNN实战:从深度相机数据采集到PyBullet仿真数据集构建
1. 深度相机数据采集实战深度相机是机器人抓取研究中最关键的传感器之一它能够同时获取场景的RGB彩色信息和深度信息。在实际项目中我使用Intel RealSense D435i这款消费级深度相机进行数据采集实测下来性价比很高。这款相机采用主动红外立体视觉原理左侧两个镜头分别负责发射和接收红外点阵右侧则是常规RGB摄像头。安装驱动时最容易踩坑的就是USB接口问题。记得第一次调试时我用了手机Type-C数据线连接结果相机频繁掉线。后来才发现必须使用原装的USB 3.0线缆传输带宽才能满足深度数据流的需求。这里分享一个检查技巧在RealSense Viewer工具中如果深度帧率显示为6Hz而不是30Hz大概率就是线缆或接口不达标。数据采集的核心代码如下pipeline rs.pipeline() config rs.config() config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30) config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30) align rs.align(rs.stream.color) # 深度与彩色对齐 while True: frames pipeline.wait_for_frames() aligned_frames align.process(frames) depth_frame aligned_frames.get_depth_frame() color_frame aligned_frames.get_color_frame()实际采集时要注意几个细节首先环境光照不能太强否则红外点阵会被自然光干扰其次物体表面材质会影响深度质量比如反光金属、透明玻璃等特殊材质可能需要额外处理。我通常会在拍摄平台上铺哑光材质的背景布这样能获得更干净的深度图。2. PyBullet仿真环境搭建当真实数据不足时PyBullet物理引擎可以帮我们生成逼真的仿真数据。这个开源的物理引擎支持刚体动力学、碰撞检测等特性特别适合抓取任务的模拟。我在Ubuntu 18.04上配置时发现直接pip install pybullet就能用比Gazebo这类仿真工具简单多了。搭建抓取场景主要分三步首先是导入机器人模型比如UR5机械臂然后加载目标物体我常用YCB数据集中的日常物品最后设置物理参数比如摩擦系数、重力加速度等。这里有个实用技巧可以用p.loadURDF的flags参数控制物体是否自碰撞这在摆放密集物体时特别有用。仿真数据采集示例import pybullet as p p.connect(p.GUI) # 可视化模式 p.setGravity(0, 0, -9.8) robot p.loadURDF(ur5.urdf) obj p.loadURDF(ycb/003_cracker_box.urdf) # 随机撒放物体 for _ in range(50): pos [np.random.uniform(-0.5,0.5), np.random.uniform(-0.5,0.5), 0.2] p.resetBasePositionAndOrientation(obj, pos, random_orientation) p.stepSimulation() # 运行物理仿真仿真数据最大的优势是可以自动生成标注。通过PyBullet的API能直接获取物体位姿和抓取点坐标省去了手工标注的麻烦。不过要注意仿真与现实间的差距建议在材质纹理、光照条件等方面尽量贴近真实场景。3. 数据集构建与增强技巧将采集的数据整理成GGCNN可用的格式需要标准化处理。我的经验是建立这样的目录结构dataset/ ├── train/ │ ├── rgb/ # 存放RGB图像 │ ├── depth/ # 存放深度图(TIFF格式) │ └── label/ # 存放标注文件 └── test/ └── ... # 同上数据增强是提升模型泛化能力的关键。除了常规的旋转、缩放外针对抓取任务我推荐几种特殊增强方式深度噪声注入模拟深度相机的测量误差遮挡模拟随机添加遮挡物增强鲁棒性光照变换调整HSV通道模拟不同光照条件实现代码片段def add_depth_noise(depth_img): noise np.random.normal(0, 0.01, depth_img.shape) return np.clip(depth_img noise, 0, 1) def random_occlusion(img): h, w img.shape[:2] occ_size np.random.randint(50, 150) x np.random.randint(0, w-occ_size) y np.random.randint(0, h-occ_size) img[y:yocc_size, x:xocc_size] 0 return img4. GGCNN数据格式转换GGCNN需要将标注转换为特殊的MAT格式包含三个关键通道抓取点置信度标注抓取位置的二值掩码抓取角度用cos/sin值表示夹持器朝向抓取宽度归一化到[0,1]的夹持器开合程度转换工具的核心逻辑from scipy.io import savemat def save_grasp_label(grasp_points, grasp_angles, grasp_widths): grasp_map np.zeros((480, 640)) cos_map np.zeros((480, 640)) sin_map np.zeros((480, 640)) width_map np.zeros((480, 640)) # 填充标注点 for (y,x), angle, width in zip(grasp_points, grasp_angles, grasp_widths): grasp_map[y,x] 1 cos_map[y,x] np.cos(2*angle) sin_map[y,x] np.sin(2*angle) width_map[y,x] width / 150.0 # 归一化 savemat(grasp_label.mat, { points: grasp_map, cos: cos_map, sin: sin_map, width: width_map })在实际项目中我发现标注质量对模型性能影响极大。好的标注应该考虑物体重心附近的抓取点更稳定夹持器宽度要略大于物体厚度对称物体应标注多个可行抓取角度5. 联合训练策略将真实数据与仿真数据结合训练能显著提升模型性能。我的经验是采用7:3的比例混合两类数据同时要注意域适应使用Batch Normalization统计量对齐课程学习先易后难逐步增加数据复杂度数据平衡确保各类物体的样本分布均匀训练代码配置示例train_loader DataLoader( ConcatDataset([RealDataset(), SimDataset()]), batch_size32, shuffleTrue, num_workers4 ) model GGCNN() criterion GraspLoss() # 自定义多任务损失 optimizer Adam(model.parameters(), lr1e-4) for epoch in range(100): for rgb, depth, label in train_loader: pred model(rgb, depth) loss criterion(pred, label) optimizer.zero_grad() loss.backward() optimizer.step()在机械臂抓取实验中这种联合训练方式使抓取成功率从纯真实数据的68%提升到了83%。最关键的是仿真数据帮助模型学会了处理各种极端情况比如堆叠物体、部分遮挡等场景。

更多文章