新手避坑指南:用Python+ROS搞定AVP项目中的.bag数据读取与深度图转点云
从零开始处理AVP项目中的.bag数据深度图与点云实战解析停车场里75个RealSense相机同时工作产生的.bag数据像一座未经开采的金矿——但当你第一次打开这些文件时可能会感到无从下手。作为刚接触ROS和点云处理的新手我清楚地记得自己面对海量数据时的茫然该从哪里开始为什么我的Python脚本总是报错深度图和点云到底有什么区别1. 理解AVP数据的基本构成在自主代客泊车(AVP)系统中多相机协同工作产生的数据量往往令人望而生畏。我们拿到的数据集通常包含以下几种关键信息相机参数文件camera_info_depth_list_K.txt75个相机的内参矩阵depth2global.txt75个相机的外参(位姿)数据ROS bag文件2024-06-22-18-59-05.bag深度图像序列2024-06-25-21-47-20.bag点云数据序列提示在开始处理前务必确认文件完整性。我曾经因为漏看一个参数文件浪费了两天时间调试错误的点云转换结果。1.1 相机参数解析相机内参矩阵的9个参数按以下顺序排列[Fx, 0, Cx, 0, Fy, Cy, 0, 0, 1]其中Fx和Fy代表焦距Cx和Cy是光学中心坐标。理解这些参数对后续的深度图转点云至关重要。外参数据则包含7个值[tx, ty, tz, rw, rx, ry, rz]前三个是平移向量后四个构成旋转四元数。这些参数将帮助我们把相机坐标系下的点云转换到统一的世界坐标系。2. ROS bag数据处理实战2.1 初步探索bag文件在编写处理脚本前先用ROS命令探查bag文件内容rosbag info 2024-06-22-18-59-05.bag这个命令会列出bag中包含的所有话题(topic)。在我的案例中深度图像话题的命名模式是/realsenseXXX/depth/image_rect_raw其中XXX是三位数的相机编号。2.2 深度图读取与保存使用Python读取深度图像的完整流程import rosbag from cv_bridge import CvBridge import cv2 import numpy as np bridge CvBridge() bag rosbag.Bag(2024-06-22-18-59-05.bag) for camera_id in range(1, 76): topic f/realsense{camera_id:03d}/depth/image_rect_raw for _, msg, t in bag.read_messages(topics[topic]): depth_img bridge.imgmsg_to_cv2(msg, desired_encodingpassthrough) # 保存为16位PNG以保留精度 cv2.imwrite(fdepth_{camera_id:03d}.png, depth_img)常见问题及解决方案话题名不匹配确保topic名称与rosbag info显示的一致编码问题desired_encodingpassthrough保留原始数据格式内存不足逐帧处理避免一次性加载所有数据2.3 点云数据直接读取如果bag中已经包含点云数据可以直接提取import rosbag import sensor_msgs.point_cloud2 as pc2 bag rosbag.Bag(2024-06-25-21-47-20.bag) points_list [] for _, msg, _ in bag.read_messages(topics[/realsense001/depth/points/air]): for p in pc2.read_points(msg, field_names(x, y, z)): points_list.append([p[0], p[1], p[2]])3. 深度图转点云的原理与实现3.1 坐标转换理论基础深度图到点云的转换涉及三个关键坐标系像素坐标系(u,v)图像上的二维坐标相机坐标系(Xc,Yc,Zc)以相机光学中心为原点的3D空间世界坐标系(Xw,Yw,Zw)全局统一的3D空间转换公式Z depth[u,v] / 1000 # 毫米转米 Xc (u - Cx) * Z / Fx Yc (v - Cy) * Z / Fy3.2 Python实现深度图转点云def depth_to_pointcloud(depth_img, K): 将深度图转换为相机坐标系下的点云 height, width depth_img.shape fx, fy, cx, cy K[0], K[4], K[2], K[5] # 生成网格坐标 u np.arange(width) v np.arange(height) u, v np.meshgrid(u, v) # 坐标转换 Z depth_img / 1000.0 # 毫米转米 X (u - cx) * Z / fx Y (v - cy) * Z / fy # 过滤无效点 valid Z 0 points np.vstack((X[valid], Y[valid], Z[valid])).T return points3.3 世界坐标系转换from scipy.spatial.transform import Rotation def transform_to_world(points_c, RT): 将相机坐标系点云转换到世界坐标系 tx, ty, tz, rw, rx, ry, rz RT R Rotation.from_quat([rx, ry, rz, rw]).as_matrix() T np.array([tx, ty, tz]) # 齐次坐标转换 points_w (R points_c.T).T T return points_w4. 点云后处理与可视化4.1 点云滤波技术原始点云通常包含噪声和不需要的元素地面去除使用RANSAC算法检测并移除地面平面离群点过滤基于统计或半径的方法去除孤立点import open3d as o3d def filter_pointcloud(pcd): # 地面去除 plane_model, inliers pcd.segment_plane( distance_threshold0.3, ransac_n3, num_iterations1000) non_ground pcd.select_by_index(inliers, invertTrue) # 离群点去除 cl, ind non_ground.remove_statistical_outlier( nb_neighbors20, std_ratio2.0) return cl4.2 多相机数据融合将75个相机的点云转换到世界坐标系后合并all_points [] for cam_id in range(75): depth_img load_depth_image(cam_id) points_c depth_to_pointcloud(depth_img, K[cam_id]) points_w transform_to_world(points_c, RT[cam_id]) all_points.append(points_w) merged_pcd o3d.geometry.PointCloud() merged_pcd.points o3d.utility.Vector3dVector(np.vstack(all_points))4.3 可视化对比使用Open3D进行可视化o3d.visualization.draw_geometries([merged_pcd], window_name融合点云, width1024, height768)5. 点云标注实践5.1 标注工具选择常用点云标注工具对比工具名称优点缺点CloudCompare开源免费功能强大学习曲线陡峭LabelCloud专门为标注设计界面友好功能相对有限SemanticSeg支持AI辅助标注需要配置环境5.2 标注流程优化预分类先使用简单算法(如DBSCAN)进行初步聚类批量操作利用工具的脚本功能自动化重复步骤质量控制定期检查标注一致性from sklearn.cluster import DBSCAN def pre_cluster(points): # 使用DBSCAN进行预聚类 clustering DBSCAN(eps0.5, min_samples10).fit(points) return clustering.labels_在实际项目中我发现先做自动预聚类再人工修正可以节省约40%的标注时间。但要注意自动算法的参数需要根据具体场景调整——停车场中的人体大小、间距与室外场景有很大不同。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2454831.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!