librealsense 标标签点云实战:基于 RealSense 的 rs-labeled-pointcloud 示例深度解析
librealsense 标标签点云实战基于 RealSense 的 rs-labeled-pointcloud 示例深度解析【免费下载链接】librealsenseRealSense SDK项目地址: https://gitcode.com/GitHub_Trending/li/librealsense导读本文以 librealsense 仓库中的 labeledpointcloud 示例 为主线完整讲解如何使用 RealSense SDK 生成并可视化带语义标签的 3D 点云Labeled Point Cloud。你将从零了解RS2_STREAM_LABELED_POINT_CLOUD流的启用方式、labeled_points帧的数据结构与标签枚举含义、标签到颜色的映射表以及基于 OpenGL 的绘制与交互实现并最终掌握在自有应用中复刻该能力的完整代码路径。示例概览与预期效果rs-labeled-pointcloud是 librealsense 官方图形化示例之一位于 examples/labeledpointcloud/。它的核心目标是用一行配置启用标签点云流实时获取相机输出的每个三维点及其分类标签然后渲染为按语义着色的彩色点云。运行后应用会打开一个 OpenGL 窗口显示带标签的点云。与普通点云示例不同这里的每个点不再是按深度或颜色着色而是按语义类别着色——地面、近地面、头顶障碍物、悬崖、危险区等类别各自拥有独立的颜色。用户可以通过鼠标拖拽旋转视角、滚轮缩放交互式观察环境语义分布。注本示例属于图形化示例Graphical Examples构建时受BUILD_GRAPHICAL_EXAMPLES选项控制详见 CMakeLists.txt。构建与运行方式本示例的构建入口在 examples/labeledpointcloud/CMakeLists.txt关键内容如下if(BUILD_GRAPHICAL_EXAMPLES) add_executable(rs-labeled-pointcloud rs-labeled-pointcloud.cpp ../example.hpp labeled-pointcloud-drawing.hpp ../../common/labeled-point-cloud-utilities.cpp ${IMGUI_SOURCES}) set_property(TARGET rs-labeled-pointcloud PROPERTY CXX_STANDARD 11) target_link_libraries(rs-labeled-pointcloud ${DEPENDENCIES}) include_directories(../) set_target_properties (rs-labeled-pointcloud PROPERTIES FOLDER Examples) install(TARGETS rs-labeled-pointcloud RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) endif()从中可以得到几个重要信息依赖条件必须开启BUILD_GRAPHICAL_EXAMPLES同时会拉入 IMGUI 相关源码IMGUI_SOURCES才会编译该示例C 标准目标使用 C11组成文件主程序 rs-labeled-pointcloud.cpp、OpenGL 窗口辅助头文件 example.hpp、绘制实现 labeled-pointcloud-drawing.hpp以及标签配色工具 labeled-point-cloud-utilities.cpp安装构建成功后可通过install目标将rs-labeled-pointcloud安装到CMAKE_INSTALL_BINDIR。在配置 CMake 时开启图形化示例即可编译cmake .. -DBUILD_GRAPHICAL_EXAMPLESON make rs-labeled-pointcloud运行前请确保已正确安装相机驱动并授予 USB 访问权限udev 规则见 config/99-realsense-libusb.rules然后直接执行./rs-labeled-pointcloud代码结构总览头文件引入与 capture 示例 的第一步相同首先引入 RealSense 跨平台 C API#include librealsense2/rs.hpp // Include RealSense Cross Platform API #include example.hpp // Include short list of convenience functions for rendering #include labeled-pointcloud-drawing.hpp #include algorithm // std::min, std::max #include setrs.hpp 是 SDK 的统一入口聚合了所有rs2命名空间下的类型example.hpp 是示例共用的轻量辅助库封装了 OpenGL 窗口创建、纹理对象texture与视角状态glfw_state等渲染基础设施labeled-pointcloud-drawing.hpp是本示例专属的绘制实现algorithm提供std::min/std::max等标准算法。窗口、视角状态与鼠标交互程序先创建 1280×720 的渲染窗口并初始化一个管理视角的状态对象// Create a simple OpenGL window for rendering: window app(1280, 720, RealSense Pointcloud Example); // Construct an object to manage view state glfw_state app_state; app_state.offset_y 90; // register callbacks to allow manipulation of the pointcloud register_glfw_callbacks(app, app_state);glfw_state中保存了偏航角yaw、俯仰角pitch、鼠标上次位置、拖拽标志以及offset_y缩放偏移等信息register_glfw_callbacks通过 glfw 注册鼠标回调从而支持用鼠标旋转拖拽与缩放滚轮点云视角。渲染主循环的条件是while (app)即窗口存活期间持续取帧渲染。声明rs2命名空间与启用标签点云流示例使用rs2命名空间下的类pipeline类封装了实际设备与传感器的流式传输逻辑// Declare RealSense pipeline, encapsulating the actual device and sensors rs2::pipeline pipe; // Defining a streaming configuration with the labeled point cloud streaming rs2::config cfg; cfg.enable_stream(RS2_STREAM_LABELED_POINT_CLOUD); // Start streaming with this configuration pipe.start(cfg);这一小段是本示例与普通点云示例的核心差异通过cfg.enable_stream(RS2_STREAM_LABELED_POINT_CLOUD)直接启用标签点云流之后pipe.start(cfg)会自动选择合适的设备与传感器开始输出。RS2_STREAM_LABELED_POINT_CLOUD在 rs_sensor.h 中定义是一个独立的流类型labeled point cloud stream。从帧中提取标签点云数据获取标签点云帧主循环中先等待下一组帧再从中提取标签点云帧while (app) // Application still alive? { // Wait for the next set of frames from the camera auto data pipe.wait_for_frames(); auto labels_frame data.get_labeled_point_cloud_frame(); // Draw the labeled pointcloud draw_labeled_pointcloud( app.width(), app.height(), app_state, labels_frame.get_vertices(), labels_frame.get_labels(), labels_frame.size() ); }get_labeled_point_cloud_frame()是frameset的便捷方法在 rs_frame.hpp 中实现为从帧集合中取第一个RS2_STREAM_LABELED_POINT_CLOUD流对应的帧并转换为labeled_points类型labeled_points get_labeled_point_cloud_frame() const { auto f first_or_default(RS2_STREAM_LABELED_POINT_CLOUD); return f.aslabeled_points(); }labeled_points 帧的数据结构labeled_points是对底层 C API 的 C 封装定义于 rs_frame.hpp它同时暴露两组长度一致的数据方法返回类型含义get_vertices()const vertex*点云顶点数组每个vertex为{x, y, z}三维坐标get_labels()const uint8_t*与顶点一一对应的标签数组取值为rs2_point_cloud_label枚举size()size_t顶点/标签数量get_width()/get_height()unsigned int标签点云宽/高像素get_bits_per_pixel()unsigned int每像素位数从实现看这些方法分别桥接到rs2_get_frame_labeled_vertices、rs2_get_frame_labels、rs2_get_frame_labeled_points_count等 C 接口构造时会通过RS2_EXTENSION_LABELED_POINTS扩展校验帧类型。也就是说顶点与标签是并行数组第i个顶点的语义类别就是labels[i]。需要特别说明的是原文档 readme.md 中有一段把顶点与标签分别复制到std::vector的过渡代码vertices_vec、labels_vec这是早期版本的实现思路当前仓库的实际主程序rs-labeled-pointcloud.cpp已将提取与绘制合并为一次调用直接向draw_labeled_pointcloud传入原始指针与数量。两种方式在原理上等价——标签数组长度始终等于顶点数量可按索引一一对应。标签语义与颜色映射标签枚举全集每个点的标签取值定义在 rs_types.h 的rs2_point_cloud_label枚举中完整含义如下枚举值语义RS2_POINT_CLOUD_LABEL_UNKNOWN无法对该点做出有效分类RS2_POINT_CLOUD_LABEL_UNDEFINEDNAN 像素无效深度RS2_POINT_CLOUD_LABEL_INVALID该点被丢弃如超出垂直视场角或距离过近RS2_POINT_CLOUD_LABEL_GROUND属于地面平面RS2_POINT_CLOUD_LABEL_NEAR_GROUND不在平面上但也不算真正的障碍物RS2_POINT_CLOUD_LABEL_OVERHEAD高于机器人高度、低于天花板高度的物体RS2_POINT_CLOUD_LABEL_ABOVE_CEILING_HEIGHT高于天花板高度的物体RS2_POINT_CLOUD_LABEL_GAP属于间隙区域Gap RegionRS2_POINT_CLOUD_LABEL_MASKED属于被掩蔽区域Masked RegionRS2_POINT_CLOUD_LABEL_CLIFF可能是悬崖/边缘RS2_POINT_CLOUD_LABEL_OBSTACLE潜在障碍物RS2_POINT_CLOUD_LABEL_OBSTACLE_DANGER危险区内的实际障碍物RS2_POINT_CLOUD_LABEL_OBSTACLE_WARNING警告区内的实际障碍物RS2_POINT_CLOUD_LABEL_COUNT枚举计数哨兵值从这些语义可以看出标签点云主要面向机器人避障与地面检测场景区分地面/近地面、检测上方悬垂物、识别悬崖与危险/警告区障碍物。标签到颜色映射表示例通过工具类rs2::labeled_point_cloud_utilities获取统一的标签配色方案接口定义于 labeled-point-cloud-utilities.h实现于 labeled-point-cloud-utilities.cppstd::maprs2_point_cloud_label, float3 labeled_point_cloud_utilities::get_label_to_color3f()该函数返回完整的rs2_point_cloud_label - float3(RGB)映射具体配色如下标签颜色RGB 值UNKNOWN/UNDEFINED/INVALID/GAP橙色(1.0, 0.65, 0.2)GROUND白色(1.0, 1.0, 1.0)NEAR_GROUND绿色(0.0, 1.0, 0.0)OVERHEAD青色(0.0, 1.0, 1.0)ABOVE_CEILING_HEIGHT蓝色(0.0, 0.0, 1.0)MASKED灰色(0.5, 0.5, 0.5)CLIFF深紫色(0.2, 0.1, 0.2)OBSTACLE粉色(1.0, 0.75, 0.8)OBSTACLE_DANGER红色(1.0, 0.0, 0.0)OBSTACLE_WARNING黄色(1.0, 1.0, 0.0)颜色语义设计直观危险OBSTACLE_DANGER用醒目的红色警告区用黄色正常地面用白色无效/未知点用橙色便于使用者快速评估机器人周边环境的风险分布。你可以在自己的应用中直接复用get_label_to_color3f()得到一致的配色。OpenGL 绘制核心按标签着色渲染绘制函数签名与入口校验点云的实际渲染位于 labeled-pointcloud-drawing.hpp 的draw_labeled_pointcloudvoid draw_labeled_pointcloud(float width, float height, glfw_state app_state, const rs2::vertex* vertices, const uint8_t* labels, size_t vertices_count) { if( vertices_count 0 || ! vertices || ! labels ) return; ... }函数首先对空指针与零顶点做防御性校验。随后是一系列标准的固定管线 OpenGL 操作清屏背景色为灰色153/255、设置透视投影gluPerspective(60, width/height, 0.01f, 10.0f)、通过gluLookAt定位相机并应用由app_state记录的平移/俯仰/偏航变换实现视角交互点大小由glPointSize(width / 640)根据窗口宽度自适应并开启深度测试。核心渲染循环真正绘制标签点云的关键循环如下auto label_to_color3f rs2::labeled_point_cloud_utilities::get_label_to_color3f(); /* this segment actually renders the labeled pointcloud */ for (int i 0; i vertices_count; i) { // Set the vertex color from the label value auto label labels[i]; auto color label_to_color3f[static_castrs2_point_cloud_label(label)]; glColor3f(color.x, color.y, color.z); // Draw the vertex rs2::vertex vtx { -vertices[i].y, vertices[i].z, -vertices[i].x }; glVertex3fv(std::move(vtx)); }这段代码体现了标签点云渲染与普通点云的本质区别颜色来自标签而非纹理每帧先查一次get_label_to_color3f()映射表然后对每个顶点取其标签值uint8_t强转为rs2_point_cloud_label枚举查表得到float3颜色并调用glColor3f设置当前点颜色再以glVertex3fv提交顶点。因此整幅点云的着色完全由语义类别驱动同一类别的点在视觉上统一着色。坐标系的硬编码转换代码注释明确说明——标签点云LPC位于**机器人坐标系Robot coordinate system**而非光学坐标系optical coordinate system严格来说应通过外参extrinsic完成转换本示例为了简洁直接硬编码了转换式{-vertices[i].y, vertices[i].z, -vertices[i].x}。绘制收尾循环结束后依次执行glEnd()、弹栈恢复GL_MODELVIEW与GL_PROJECTION矩阵、glPopAttrib()恢复属性完成一帧的渲染。整个绘制过程全部使用 OpenGL 1.x 固定管线 API因此引入了GL_SILENCE_DEPRECATION宏以抑制弃用告警并#define GLFW_INCLUDE_GLU引入 GLU 辅助函数。底层原理标签点云从哪里来要真正理解这个示例值得看一下标签点云流的产生端。从源码结构看该功能由 D500 系列设备的深度映射模块实现相关证据位于 src/ds/d500/d500-depth-mapping.cpp文件开头将标签点云流映射为PAL8四字符码并注释说明标签点云流使用 PAL8 而非 GREY格式d500-depth-mapping.cpp模块内部创建了_point_cloud_stream(new stream(RS2_STREAM_LABELED_POINT_CLOUD))这个流对象d500-depth-mapping.cpp在流配置与帧处理逻辑中多次对p-get_stream_type() RS2_STREAM_LABELED_POINT_CLOUD做分支判断以生成对应的顶点与标签数据d500-depth-mapping.cpp。也就是说cfg.enable_stream(RS2_STREAM_LABELED_POINT_CLOUD)会让 pipeline 选择具备该能力的 D500 系列设备由深度映射算法在设备/算法层完成地面检测、障碍物分类等语义分析随深度数据一起输出每个点的标签SDK 侧再通过labeled_points帧类型把顶点 标签两路数据暴露给应用。因此本示例的 API 使用方式与数据布局可以看作 D500 语义感知能力的标准消费方式。异常处理与健壮性主程序的主体被包裹在 try-catch 中catch (const rs2::error e) { std::cerr RealSense error calling e.get_failed_function() ( e.get_failed_args() ):\n e.what() std::endl; return EXIT_FAILURE; } catch (const std::exception e) { std::cerr e.what() std::endl; return EXIT_FAILURE; }对rs2::errorSDK 运行时错误含失败函数名与参数信息和一般std::exception分别处理并将错误信息输出到标准错误流后以非零码退出。这是所有官方示例通用的错误处理范式可参考 examples/example.hpp 与其他示例保持一致的实践。小结在自有应用中复刻标签点云能力综合全文在自己的程序中接入标签点云只需四步启用流cfg.enable_stream(RS2_STREAM_LABELED_POINT_CLOUD)后pipe.start(cfg)取帧pipe.wait_for_frames().get_labeled_point_cloud_frame()得到labeled_points帧取数据通过get_vertices()、get_labels()、size()拿到并行数组渲染按labels[i]查get_label_to_color3f()得到颜色对每个顶点调用 OpenGL 绘制注意机器人坐标系到光学坐标系的转换。如需进一步研究可以继续阅读完整主程序rs-labeled-pointcloud.cpp绘制实现与坐标系转换labeled-pointcloud-drawing.hpp标签配色工具labeled-point-cloud-utilities.cpp帧类型 API 定义rs_frame.hpp标签枚举定义rs_types.h底层流实现d500-depth-mapping.cpp【免费下载链接】librealsenseRealSense SDK项目地址: https://gitcode.com/GitHub_Trending/li/librealsense创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →