news 2026/9/16 20:44:31

librealsense 入门实战:用 rs-hello-realsense 示例读取 RealSense 深度数据

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
librealsense 入门实战:用 rs-hello-realsense 示例读取 RealSense 深度数据

librealsense 入门实战:用 rs-hello-realsense 示例读取 RealSense 深度数据

【免费下载链接】librealsenseRealSense SDK项目地址: https://gitcode.com/GitHub_Trending/li/librealsense

导读

rs-hello-realsense是 librealsense(RealSense SDK)中最简单、最适合作为第一个上手的示例程序:它演示了连接 RealSense 设备、启动深度流并读取画面中心像素距离值的最小闭环。读完本文,你将掌握rs2::pipeline的核心用法、深度帧的获取与像素级距离查询 API,并理解这些高层接口在 SDK 源码中的底层实现路径,从而为后续开发点云、对齐、测量等应用打下基础。

本文基于仓库中的 examples/hello-realsense/readme.md 展开,并结合对应的 rs-hello-realsense.cpp、CMakeLists.txt 以及 include/librealsense2/hpp/rs_pipeline.hpp 等源码进行纵深讲解。

示例概述与预期输出

rs-hello-realsense是入门级的 C++ 示例(仓库中的 examples/readme.md 将其标记为最低难度的一星示例),核心目标只有三件事:

  1. 连接一台 RealSense 相机;
  2. 启动深度流;
  3. 持续打印相机视野中心点到前方物体的距离。

预期输出非常直观:在相机已连接且视野中心有物体的情况下,终端会不断刷新一行文本:

The camera is facing an object X meters away

其中X是相机到视野中心物体的距离,单位为。把相机对准不同远近的物体,数值会实时变化,这可以当作验证 SDK 安装与相机工作状态是否正常的"冒烟测试"。

该示例依赖 RealSense 的深度感知能力,关于深度传感技术(结构化光、双目立体视觉、L500 系列)的背景可参考 examples/depth.md;如果你更习惯 C 语言,仓库还提供了功能等价的 C 版本 examples/C/distance/rs-distance.c。

完整代码与构建方式

示例完整源码

readme 中为了讲解循序渐进地分段展示代码,而仓库中的 rs-hello-realsense.cpp 是可直接编译运行的完整版本,包含 readme 未展示的命令行参数解析与异常处理部分:

#include <librealsense2/rs.hpp> // RealSense Cross Platform API #include <iostream> #include <common/cli.h> int main(int argc, char * argv[]) try { auto settings = rs2::cli( "hello-realsense example" ) .process( argc, argv ); // Create a Pipeline - this serves as a top-level API for streaming and processing frames rs2::pipeline p( settings.dump() ); // Configure and start the pipeline p.start(); while (true) { // Block program until frames arrive rs2::frameset frames = p.wait_for_frames(); // Try to get a frame of a depth image rs2::depth_frame depth = frames.get_depth_frame(); // Get the depth frame's dimensions auto width = depth.get_width(); auto height = depth.get_height(); // Query the distance from the camera to the object in the center of the image float dist_to_center = depth.get_distance(width / 2, height / 2); // Print the distance std::cout << "The camera is facing an object " << dist_to_center << " meters away \r"; } return EXIT_SUCCESS; } 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; }

相比 readme 中的教学片段,完整版多了两点值得注意:

  • 命令行参数处理:通过rs2::cli(...).process(argc, argv)解析参数。rs2::cli定义在 common/cli.h,基于 TCLAP 实现,支持--debug(开启 librealsense 调试日志)、--eth/--eth-only/--no-eth(控制是否检测 DDS 网络设备)以及--domain-id <0-232>(DDS 域 ID)等参数,process返回的 JSON 设置会通过rs2::pipeline p( settings.dump() )传给 pipeline 构造器。
  • 异常处理:整个main函数体包在try块中,专门捕获rs2::error(可打印出错的 API 函数名、参数与错误信息)和std::exception,便于在设备缺失或流启动失败时给出清晰的诊断输出。

CMake 构建配置

该示例的构建由 examples/hello-realsense/CMakeLists.txt 定义:

cmake_minimum_required(VERSION 3.10) project( rs-hello-realsense ) add_executable( ${PROJECT_NAME} rs-hello-realsense.cpp ) set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 11) target_link_libraries( ${PROJECT_NAME} ${DEPENDENCIES} ) set_target_properties( ${PROJECT_NAME} PROPERTIES FOLDER "Examples" ) using_easyloggingpp( ${PROJECT_NAME} SHARED ) install( TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} )

要点说明:

  • 使用C++11标准即可编译,SDK 的 C++ API 对标准要求不高;
  • 链接目标是examples/CMakeLists.txt中统一收集的${DEPENDENCIES}(包括realsense2库及其传递依赖);
  • using_easyloggingpp(...)接入 easyloggingpp 日志框架,这也是rs2::cli--debug参数能够生效的前提;
  • 生成的rs-hello-realsense可执行文件会随 SDK 一并安装到${CMAKE_INSTALL_BINDIR}

按仓库根目录 readme.md 的安装指引完成 SDK 构建(或通过apt安装预编译包)后,即可运行该可执行文件进行验证。

逐步拆解:从包含头文件到打印距离

1. 引入跨平台 API 头文件

#include <librealsense2/rs.hpp> // Include RealSense Cross Platform API

readme 特别强调:除高级功能外,整个 SDK 的全部能力都通过这一个头文件提供rs.hpp会串联起 C++ 封装层(如rs_pipeline.hpprs_frame.hpp)与底层 C API(include/librealsense2/rs.h),因此你的项目只需要引入它,就能访问 pipeline、frame、sensor、processing block 等全部常用对象,无需按模块逐个 include。

2. 创建并启动 pipeline

// Create a Pipeline - this serves as a top-level API for streaming and processing frames rs2::pipeline p; // Configure and start the pipeline p.start();

pipeline 是 SDK 面向应用层提供的最高层抽象,用于简化与设备及视觉处理模块的交互。从 include/librealsense2/hpp/rs_pipeline.hpp 中pipeline类的文档可以看到它的定位:

  • 抽象了相机的配置与流启动过程——调用无参的start()时,pipeline 使用默认配置自动解析并启动设备的深度流,不需要手动枚举设备、查询 profile 或逐流配置;
  • 抽象了视觉模块的触发与线程模型——流循环在后台运行,应用只需通过wait_for_frames()poll_for_frames()取帧;
  • start()只能调用一次,重复启动会抛出异常;它返回的pipeline_profile描述了实际生效的设备与流的 profile。

如果你需要精确控制(例如指定分辨率、帧率或特定设备),可以在start()前通过rs2::config配置;本例为了展示最简用法,直接使用默认配置。

3. 阻塞等待帧集合

// Block program until frames arrive rs2::frameset frames = p.wait_for_frames();

RealSense 相机通常同时提供多路视频流、运动(IMU)流或位姿(Pose)流。wait_for_frames()阻塞当前线程,直到 pipeline 从已配置的各路流中取回一组时间上对齐(coherent)的帧,并以frameset(复合帧集合)的形式返回。这样你拿到的每一帧都属于同一时刻,便于后续做跨流处理。如果你不希望阻塞,可以使用非阻塞的poll_for_frames()轮询。

4. 取出深度帧

// Try to get a frame of a depth image rs2::depth_frame depth = frames.get_depth_frame();

get_depth_frame()frameset提供的辅助方法,负责从帧集合中提取第一个深度数据帧并返回rs2::depth_frame对象。rs2::depth_frame封装了深度图及其元数据,是后续所有距离/深度查询操作的入口。

5. 查询深度帧尺寸

// Get the depth frame's dimensions float width = depth.get_width(); float height = depth.get_height();

get_width()/get_height()返回深度图像的像素宽高。readme 特别提示:默认深度帧的尺寸可能因传感器型号而异(例如 D415 与 D435 的分辨率配置就不同),因此不要硬编码像素坐标,而是动态读取尺寸后计算中心点。

6. 查询中心像素的距离

// Query the distance from the camera to the object in the center of the image float dist_to_center = depth.get_distance(width / 2, height / 2);

get_distance(int x, int y)rs2::depth_frame的核心方法,返回指定像素处物体到相机平面的距离,单位为米。它定义在 include/librealsense2/hpp/rs_frame.hpp 中,底层调用 C APIrs2_depth_frame_get_distance。用(width / 2, height / 2)即取图像正中心的像素。

7. 打印结果

// Print the distance std::cout << "The camera is facing an object " << dist_to_center << " meters away \r";

\r(回车符)让输出在同一行不断刷新,形成实时测距效果。

源码级原理:get_distance 的底层实现与边界校验

教学示例到此为止,但如果你想深入理解get_distance究竟做了什么,可以顺着 C++ 封装向下追两层:

第一层:C++ 封装(include/librealsense2/hpp/rs_frame.hpp)中,get_distance的文档明确写道:"Provide the depth in meters at the given pixel",其实现直接委托给 C API:

float get_distance(int x, int y) const { rs2_error * e = nullptr; auto r = rs2_depth_frame_get_distance(get(), x, y, &e); error::handle(e); return r; }

第二层:C API 实现(src/rs.cpp)中,rs2_depth_frame_get_distance做了两件事——接口类型校验与像素坐标范围校验,然后调用内部实现:

float rs2_depth_frame_get_distance(const rs2_frame* frame_ref, int x, int y, rs2_error** error) BEGIN_API_CALL { VALIDATE_NOT_NULL(frame_ref); auto df = VALIDATE_INTERFACE(((frame_interface*)frame_ref), librealsense::depth_frame); VALIDATE_RANGE(x, 0, df->get_width() - 1); VALIDATE_RANGE(y, 0, df->get_height() - 1); return df->get_distance(x, y); }

这段实现透露了几个关键事实:

  • 坐标系约定:像素坐标以图像左上角为原点(C API 文档注释为 "Left-Upper corner origin"),这与很多图像处理库的约定一致;
  • 越界保护VALIDATE_RANGE会把超出[0, width-1]/[0, height-1]的像素坐标当作错误处理并抛出异常,因此示例中动态读取width/height再取中心点的写法既正确又安全;
  • 深度单位:返回值为米(metric units),配合get_units()(返回原始深度值到米的换算系数)可以验证这一结论。

值得一提的是,同一份 C API 还被各语言封装复用:例如 Android 的 JNI 层 src/android/jni/frame.cpp 中DepthFrame.nGetDistance也直接调用rs2_depth_frame_get_distance,说明这条距离查询链路是 SDK 全平台共享的核心能力。

与 C 语言版本对照:更贴近底层的手动流程

如果你在 readme 之外还想看看"不用高层 pipeline"的写法,仓库提供了同主题的 C 版示例 examples/C/distance/rs-distance.c。它把 pipeline 内部帮你做的事一步步手动展开,非常适合理解高层 API 的封装意义:

  • rs2_create_context创建 context,rs2_query_devices枚举设备;
  • rs2_create_config+rs2_config_enable_stream(config, RS2_STREAM_DEPTH, STREAM_INDEX, WIDTH, HEIGHT, RS2_FORMAT_Z16, FPS, &e)显式指定深度流参数(其中RS2_FORMAT_Z16表示 16 位深度格式,WIDTH为 640、HEIGHT为 0 表示自动解析);
  • rs2_pipeline_start_with_config按配置启动;
  • 循环中rs2_pipeline_wait_for_frames取帧,用rs2_is_frame_extendable_to(frame, RS2_EXTENSION_DEPTH_FRAME, &e)判断帧是否为深度帧后,再调用rs2_depth_frame_get_distance(frame, width / 2, height / 2, &e)获取中心距离。

对比可见:C++ 示例中一行p.start()背后,实际上封装了 C 版里 context 创建、设备查询、config 配置、pipeline 启动的全套流程;而frames.get_depth_frame()也等价于 C 版的"遍历复合帧、逐个判断扩展类型、提取深度帧"逻辑。理解这一对照关系,有助于你在需要精细控制(如多设备选型、自定义流参数)时切换到更底层的 API。

常见问题与排查方向

  • 设备未连接/驱动未就绪:程序在p.start()阶段会抛出异常,完整版示例会打印"RealSense error calling ..."及具体失败的 API 与参数。请确认相机已插入、udev 规则已按 scripts/setup_udev_rules.sh 安装(Linux),并参考 doc/troubleshooting.md 排查。
  • 视野中心无有效深度:当中心像素处物体过近(低于传感器最小感知距离)或材质无反射时,get_distance可能返回 0 或不稳定数值,可尝试对准 0.5~3 米内的物体验证。
  • 输出不刷新\r在部分终端(如某些 IDE 内嵌终端)可能显示异常,改用\nstd::flush即可观察输出。
  • 想自定义分辨率/帧率:改用rs2::configenable_stream显式指定流参数,写法可参考上文 C 版示例中的参数枚举(WIDTHHEIGHTFPSRS2_FORMAT_Z16)。

总结:从"Hello World"到下一步

rs-hello-realsense用约 30 行核心代码完成了"连接设备 → 启动深度流 → 取帧 → 查像素距离 → 打印"的完整闭环,是理解 librealsense C++ API 设计哲学的最佳起点。它揭示的pipeline → frameset → depth_frame → get_distance这条调用链,正是后续几乎所有深度应用(点云、空间对齐、测量 等)的公共骨架。建议你在运行通过后,动手把get_distance的查询坐标从中心点改成任意像素、或把距离输出改为逐行打印整幅深度图,以加深对深度帧数据结构与坐标体系的理解。

【免费下载链接】librealsenseRealSense SDK项目地址: https://gitcode.com/GitHub_Trending/li/librealsense

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 20:44:27

OpenCode 的 /models 报 401?TaoToken 的 Base URL 别加 /v1

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/16 20:44:06

蜂鸟芯片:国产离线语音识别的硬核实践指南

1. 项目概述&#xff1a;为什么“蜂鸟”不是一只普通的小鸟&#xff1f;云知声&#xff08;Unisound&#xff09;的蜂鸟系列芯片&#xff0c;名字听着轻巧&#xff0c;但实际是嵌入式AI语音识别领域里少有的、真正把“离线”二字刻进骨子里的硬核方案。我第一次在客户现场看到它…

作者头像 李华
网站建设 2026/9/16 20:43:51

AI工具矩阵如何提升本科开题报告效率

1. 本科开题报告的核心痛点解析本科阶段的开题报告是学术研究的第一个正式里程碑&#xff0c;却让无数学生辗转反侧。根据我指导过200本科生的经验&#xff0c;90%的迷茫集中在三个维度&#xff1a;选题价值论证薄弱&#xff08;42%&#xff09;、文献综述质量低下&#xff08;…

作者头像 李华
网站建设 2026/9/16 20:43:48

跑 AHE 时 401?TaoToken 的 Base URL 这样填

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/16 20:41:54

AI智能体升级实践:从规则匹配到Function Call,准确率提升86%

“这周必须把规则匹配换成大模型方案&#xff0c;准确率再上不去&#xff0c;项目就黄了。”这是我上一个项目里&#xff0c;业务负责人拍桌子说的话。当时我们做的AI智能体是面向电商客服场景的商品推荐助手&#xff0c;底层用的是一套积累了两年多的规则匹配引擎&#xff1a;…

作者头像 李华