十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

librealsense rs-pointcloud 示例深度解析:使用 RealSense SDK 生成并可视化带纹理 3D 点云

librealsense rs-pointcloud 示例深度解析:使用 RealSense SDK 生成并可视化带纹理 3D 点云 librealsense rs-pointcloud 示例深度解析使用 RealSense SDK 生成并可视化带纹理 3D 点云【免费下载链接】librealsenseRealSense SDK项目地址: https://gitcode.com/GitHub_Trending/li/librealsense导读本文基于 Intel RealSense SDKlibrealsense官方示例 rs-pointcloud 展开完整讲解如何用 C 从深度流生成三维点云、把彩色帧映射为点云纹理并通过 OpenGL 实时渲染与交互查看。读完本文你将掌握rs2::pointcloud、rs2::points、rs2::pipeline的核心用法理解深度反投影与纹理坐标映射的底层原理并能独立运行、改造该示例将其中的点云生成流程移植到自己的项目中。示例概览它能做什么rs-pointcloud是 librealsense 仓库中负责点云生成与可视化的图形示例位于 examples/pointcloud/。它的核心能力包括从 RealSense 深度相机实时取流把每一帧深度图转换为 3D 点云把同一时刻的彩色帧作为纹理映射到点云表面生成彩色点云通过 OpenGL 窗口实时渲染并支持鼠标拖拽旋转yaw/pitch、滚轮缩放offset交互查看。其编译入口是 examples/pointcloud/CMakeLists.txt目标rs-pointcloud由 rs-pointcloud.cpp 与共享的 example.hpp 及 ImGui 源码共同构建仅在开启BUILD_GRAPHICAL_EXAMPLES选项时才会编译最终安装到${CMAKE_INSTALL_BINDIR}。因此若你使用 CMake 配置项目需要显式启用图形示例选项并链接依赖如 GLFW/OpenGL。运行后程序会打开一个1280x720的窗口窗口内显示带真实色彩纹理的三维点云按住鼠标左键拖拽可以旋转视角滚动滚轮可以缩放按空格键可将视角复位为初始状态。程序骨架窗口、状态与回调示例开头引入两个关键头文件这与首个教程的写法一脉相承#include librealsense2/rs.hpp // Include RealSense Cross Platform API #include example.hpp // Include short list of convenience functions for renderinglibrealsense2/rs.hpp是 SDK 的跨平台 C API 入口对应 C API 为 include/librealsense2/rs.hexample.hpp是示例共享的轻量辅助库封装了 OpenGL 窗口管理、纹理上传与基础渲染其实现位于 examples/example.hpp。随后代码定义了一个用于管理点云视角旋转的状态结构体并声明两个辅助函数// Struct for managing rotation of pointcloud view struct state { double yaw, pitch, last_x, last_y; bool ml; float offset_x, offset_y; texture tex; }; // Helper functions void register_glfw_callbacks(window app, state app_state); void draw_pointcloud(window app, state app_state, rs2::points points);在实际源码中该结构体名为glfw_state见 examples/example.hpp 中glfw_state的定义字段含义为字段类型作用yaw/pitchdouble点云视图的偏航角与俯仰角控制旋转last_x/last_ydouble记录上一次鼠标位置用于计算拖拽增量mlbool鼠标左键是否按下拖拽旋转的开关offset_x/offset_yfloat滚轮缩放偏移量textextureOpenGL 纹理对象用于上传彩色帧在main中程序创建窗口、初始化状态并注册 GLFW 回调// Create a simple OpenGL window for rendering: window app(1280, 720, RealSense Pointcloud Example); // Construct an object to manage view state state app_state { 0, 0, 0, 0, false, 0, 0, 0 }; // register callbacks to allow manipulation of the pointcloud register_glfw_callbacks(app, app_state);register_glfw_callbacks的实现同样位于 examples/example.hpp鼠标左键按下时置位ml鼠标移动时按位移增量更新yaw/pitch并分别钳制在±120与±80度范围内滚轮事件更新offset_x/offset_y实现缩放空格键key code 32将视角复位。核心数据流pointcloud 与 points示例使用rs2命名空间下的两个关键类using namespace rs2; // Declare pointcloud object, for calculating pointclouds and texture mappings rs2::pointcloud pc; // We want the points object to be persistent so we can display the last cloud when a frame drops rs2::points points;rs2::pointcloud一个处理块processing block / filter负责把深度帧计算为点云并维护纹理映射。其类定义位于 include/librealsense2/hpp/rs_processing.hpp构造时内部调用rs2_create_pointcloud创建底层处理块。它还支持带流类型参数的构造函数pointcloud(rs2_stream stream, int index 0)用于限定处理特定流。rs2::points点云数据帧继承自rs2::frame持有顶点数组与纹理坐标数组。声明为持久对象的目的在于当某一帧数据缺失时窗口仍可继续显示上一次计算出的点云避免画面闪断。其类定义与相关数据结构vertex、texture_coordinate见 include/librealsense2/hpp/rs_frame.hpp。取流Pipeline 启动与帧循环rs2::pipeline是 SDK 的功能入口负责管理设备、传感器与流配置// Declare RealSense pipeline, encapsulating the actual device and sensors pipeline pipe; // Start streaming with default recommended configuration pipe.start();pipe.start()会以 SDK 推荐的默认配置启动相机深度 彩色流。随后主循环反复等待下一组帧while (app) // Application still alive? { // Wait for the next set of frames from the camera auto frames pipe.wait_for_frames(); ... }while (app)依赖window的operator bool()examples/example.hpp每帧刷新双缓冲、轮询 GLFW 事件并在窗口关闭时返回false结束循环。wait_for_frames()则阻塞等待一组时间对齐的帧frameset这是后续深度图与彩色图一一对应的前提。点云生成与纹理映射calculate 与 map_to这是示例的核心逻辑。在真实源码 rs-pointcloud.cpp 中循环体按如下顺序工作auto color frames.get_color_frame(); // For cameras that dont have RGB sensor, well map the pointcloud to infrared instead of color if (!color) color frames.get_infrared_frame(); // Tell pointcloud object to map to this color frame pc.map_to(color); auto depth frames.get_depth_frame(); // Generate the pointcloud and texture mappings points pc.calculate(depth); // Upload the color frame to OpenGL app_state.tex.upload(color);拆解如下取得彩色帧frames.get_color_frame()从帧集中取彩色流对于没有 RGB 传感器的设备例如部分仅提供红外流的型号示例会回退到get_infrared_frame()把红外图作为纹理保证点云始终有颜色可贴。映射纹理pc.map_to(color)告诉pointcloud对象以该彩色帧作为纹理来源。查看 include/librealsense2/hpp/rs_processing.hpp 可知其本质是把彩色流的流类型、像素格式、流索引写入三个底层选项RS2_OPTION_STREAM_FILTER、RS2_OPTION_STREAM_FORMAT_FILTER、RS2_OPTION_STREAM_INDEX_FILTER选项枚举定义于 include/librealsense2/h/rs_option.h随后把该彩色帧送入处理块完成纹理帧登记。计算点云points pc.calculate(depth)将深度帧送入处理块输出rs2::points。该方法的实现include/librealsense2/hpp/rs_processing.hpp会从处理结果中解析出points扩展类型的帧若底层返回 frameset则从中逐个提取点云帧。上传纹理app_state.tex.upload(color)把彩色帧数据上传为 OpenGL 纹理。texture::upload支持RGB8、RGBA8、Y8、Y10BPACK等格式并设置线性过滤与GL_CLAMP包裹模式见 examples/example.hpp 中texture类的实现。渲染管线draw_pointcloud 的 OpenGL 调用计算完点云后调用渲染函数draw_pointcloud(app.width(), app.height(), app_state, points);draw_pointcloud的实现位于 examples/example.hpp其工作分两部分第一部分设置相机与模型变换。依次完成清屏灰色背景153/255、gluPerspective(60, width/height, 0.01f, 10.0f)透视投影、gluLookAt视点定位再根据app_state.pitch/yaw旋转、按offset_y平移缩放视图最后启用深度测试与纹理绑定。第二部分逐点上传顶点与纹理坐标。这是打印点云的关键片段/* this segment actually prints the pointcloud */ auto vertices points.get_vertices(); // get vertices auto tex_coords points.get_texture_coordinates(); // and texture coordinates for (int i 0; i points.size(); i) { if (vertices[i].z) { // upload the point and texture coordinates only for points we have depth data for glVertex3fv(vertices[i]); glTexCoord2fv(tex_coords[i]); } }points.get_vertices()返回const vertex*顶点数组vertex是{float x, y, z;}结构并提供到const float*的隐式转换include/librealsense2/hpp/rs_frame.hpppoints.get_texture_coordinates()返回const texture_coordinate*纹理坐标数组texture_coordinate为{float u, v;}同上文件points.size()返回点云总点数与深度图分辨率宽 × 高一致if (vertices[i].z)这一判空至关重要深度值为 0即该像素没有有效深度数据如遮挡、超量程区域的点不会被上传从而避免在无效位置画出残缺点。顶点与纹理坐标成对提交后GPU 即可把彩色纹理采样到每个点上形成带真实色彩的 3D 点云。底层原理深度反投影与纹理坐标计算rs2::pointcloud之所以能把深度图变成三维点核心在于针孔相机模型的深度反投影。底层实现位于 src/proc/pointcloud.cpptemplateclass MAP_DEPTH void deproject_depth(float * points, const rs2_intrinsics intrin, const uint16_t * depth, MAP_DEPTH map_depth) { for (int y 0; y intrin.height; y) for (int x 0; x intrin.width; x) { const float pixel[] { (float)x, (float)y }; rs2_deproject_pixel_to_point(points, intrin, pixel, map_depth(*depth)); points 3; } }这段代码逐像素调用rs2_deproject_pixel_to_point定义于 include/librealsense2/rsutil.h把像素坐标(x, y)连同深度值反投影为相机坐标系下的三维点(X, Y, Z)。反投影前需要把原始 16 位深度值乘以深度单位换算为米auto depth_scale depth_frame.get_units(); deproject_depth(..., depth_scale { return depth_scale * z; });get_units()返回该深度传感器每 LSB 对应的米数不同设备/量程设置下不同这一换算正是点云尺寸真实性的保证。纹理映射则通过投影 归一化完成同一文件中的工具函数清晰地说明了思路float2 project(const rs2_intrinsics *intrin, const float3 point) { ... rs2_project_point_to_pixel(...); } float2 pixel_to_texcoord(const rs2_intrinsics *intrin, const float2 pixel) { return { pixel.x / intrin-width, pixel.y / intrin-height }; }即把每个三维点用彩色相机内参投影回彩色图像平面得到像素坐标再除以图像宽高归一化为[0,1]的纹理坐标(u, v)从而让每个点知道自己该采样的颜色位置。深度流与彩色流之间的空间变换由set_extrinsics()通过 SDK 的外参图environment::get_instance().get_extrinsics_graph()查询获得保证两路传感器坐标系对齐。另外src/proc/pointcloud.cpp 还引入了occlusion-filter遮挡过滤当深度点投影到彩色图时若落在被遮挡的无效区域会做剔除处理避免透视到物体背后的错误纹理。在支持 CUDARS2_USE_CUDA、SSSE3__SSSE3__或 NEON 的平台上点云计算会分别走 src/proc/cuda/cuda-pointcloud.cpp、src/proc/sse/sse-pointcloud.cpp、src/proc/neon/neon-pointcloud.cpp 的 SIMD/GPU 加速路径这也解释了为何示例在低功耗设备上也能流畅显示高分辨率点云。进阶延伸从示例到你的项目掌握了示例主循环后你可以在此基础上做大量扩展导出点云文件rs2::points提供export_to_ply(fname, texture)方法include/librealsense2/hpp/rs_frame.hpp可直接把当前点云连同纹理导出为 PLY 格式供 MeshLab、CloudCompare 等工具查看无需自己实现序列化。替换渲染后端示例用 OpenGL 固定管线绘制点实际项目中可改为把get_vertices()/get_texture_coordinates()上传到 VBO/VAO或用 PCL/Open3D 等库消费同一份数据。按需取流pipe.start()使用默认推荐配置需要自定义分辨率、帧率或深度量程时可用rs2::config显式配置再配合pipe.start(config)启动。多流/无 RGB 设备适配示例已示范了无彩色帧则回退到红外帧的容错写法接入双目红外等设备时同样适用。性能优化了解底层存在 CUDA/SSE/NEON 加速路径后可参考 src/proc/CMakeLists.txt 中的平台编译选项为高性能设备开启对应指令集。总结rs-pointcloud以最精简的方式展示了 librealsense 点云能力的完整链路pipeline取流 →pointcloud::map_to登记纹理 →pointcloud::calculate反投影生成points→ OpenGL 逐点绘制。配合 src/proc/pointcloud.cpp 的底层实现你可以看到 SDK 如何用相机内参把深度像素反投影为米制坐标、又如何借助外参与彩色内参生成纹理坐标。掌握这一流程后无论是做三维重建、机器人避障还是交互式可视化都能快速迁移这套深度 纹理 → 彩色点云的标准管线。【免费下载链接】librealsenseRealSense SDK项目地址: https://gitcode.com/GitHub_Trending/li/librealsense创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表