一、开发环境准备

1.1 硬件要求
  • 奥比中光深度相机(如Astra Pro、Gemini等)
  • USB 3.0接口(确保数据传输稳定)
  • 支持OpenGL的显卡(可选,用于点云可视化)
1.2 软件环境
  • SDK安装
    1. 从奥比中光开发者官网下载最新的OrbbecSDK
    2. 运行安装程序并配置环境变量(Windows)或执行./install.sh(Linux)
  • 开发工具链
    • Visual Studio (Windows)
    • GCC 7.5+/Clang 9+(Linux)
    • CMake 3.10+(跨平台项目配置)

二、SDK架构与核心组件

OrbbecSDK采用模块化设计,主要组件包括:

  • DeviceManager:设备发现与管理
  • Device:相机设备抽象
  • StreamProfile:数据流配置(分辨率、帧率、格式等)
  • Frame:图像帧数据容器
  • Pipeline:数据流处理管道
  • FrameListener:帧数据回调接口

三、基本开发流程

3.1 初始化SDK与设备
#include <OrbbecSDK.h>
#include <iostream>
#include <string>int main() {// 初始化SDKob::Context context;// 枚举并打印所有可用设备std::shared_ptr<ob::DeviceList> deviceList = context.queryDeviceList();std::cout << "设备数量: " << deviceList->deviceCount() << std::endl;// 获取第一个设备std::shared_ptr<ob::Device> device;if (deviceList->deviceCount() > 0) {device = deviceList->getDevice(0);std::cout << "已连接设备: " << device->getDeviceInfo()->name() << std::endl;} else {std::cerr << "未发现设备!" << std::endl;return -1;}// 创建数据流处理管道std::shared_ptr<ob::Pipeline> pipeline = std::make_shared<ob::Pipeline>(device);// 配置并启动数据流// ...
}
3.2 配置并启动数据流
// 配置深度流
ob::Config config;
std::shared_ptr<ob::StreamProfileList> profileList = pipeline->getStreamProfileList(OB_SENSOR_DEPTH);// 选择848x480@30fps的深度流配置
std::shared_ptr<ob::VideoStreamProfile> depthProfile = std::dynamic_pointer_cast<ob::VideoStreamProfile>(profileList->getVideoStreamProfile(848, 0, OB_FORMAT_Y16, 30));// 启用深度流
config.enableStream(depthProfile);// 启动管道
pipeline->start(config, [&](std::shared_ptr<ob::FrameSet> frameSet) {// 帧数据回调处理if (frameSet->depthFrame()) {auto depthFrame = frameSet->depthFrame();std::cout << "获取到深度帧: " << "宽度=" << depthFrame->width() << ", 高度=" << depthFrame->height() << ", 时间戳=" << depthFrame->timestamp() << std::endl;// 处理深度数据processDepthFrame(depthFrame);}
});
3.3 深度数据处理
void processDepthFrame(std::shared_ptr<ob::DepthFrame> depthFrame) {// 获取深度数据指针uint16_t* depthData = (uint16_t*)depthFrame->data();int width = depthFrame->width();int height = depthFrame->height();// 计算中心点深度值(单位:毫米)int centerX = width / 2;int centerY = height / 2;uint16_t centerDepth = depthData[centerY * width + centerX];std::cout << "中心点深度: " << centerDepth << "mm" << std::endl;// 可选:转换为点云convertToPointCloud(depthFrame);
}
3.4 点云生成与处理
void convertToPointCloud(std::shared_ptr<ob::DepthFrame> depthFrame) {// 创建点云转换工具std::shared_ptr<ob::PointCloudGenerator> pcGenerator = std::make_shared<ob::PointCloudGenerator>();// 设置点云格式为XYZpcGenerator->setFormat(OB_FORMAT_XYZ);// 生成点云std::shared_ptr<ob::Frame> pointCloud = pcGenerator->generate(depthFrame);// 获取点云数据if (pointCloud) {float* points = (float*)pointCloud->data();int pointCount = pointCloud->dataSize() / (3 * sizeof(float)); // XYZ三个分量// 简单统计:计算平均深度float sumDepth = 0;for (int i = 0; i < pointCount; i++) {float z = points[i * 3 + 2]; // Z坐标if (z > 0) sumDepth += z;}std::cout << "平均深度: " << sumDepth / pointCount << "mm" << std::endl;}
}
3.5 相机参数获取与使用
// 获取内参
auto depthSensor = device->getSensor(OB_SENSOR_DEPTH);
auto intrinsics = depthSensor->getIntrinsics(depthProfile);std::cout << "深度相机内参:" << std::endl<< "fx=" << intrinsics.fx << ", fy=" << intrinsics.fy << std::endl<< "cx=" << intrinsics.cx << ", cy=" << intrinsics.cy << std::endl;// 深度转世界坐标示例
float depthValue = depthData[centerY * width + centerX];
float worldX = (centerX - intrinsics.cx) * depthValue / intrinsics.fx;
float worldY = (centerY - intrinsics.cy) * depthValue / intrinsics.fy;
float worldZ = depthValue;std::cout << "世界坐标: (" << worldX << ", " << worldY << ", " << worldZ << ")mm" << std::endl;
3.6 相机工作模式切换
// 切换到尺寸测量模式(Dimensioning)
ob::WorkingMode workingMode;
workingMode.type = OB_WORKING_MODE_DIMENSIONING;
device->setWorkingMode(workingMode);std::cout << "已切换到尺寸测量模式" << std::endl;

四、完整示例代码

下面是一个完整的奥比中光深度相机C++开发示例,包含设备初始化、数据流获取、深度处理和点云生成:

#include <OrbbecSDK.h>
#include <iostream>
#include <string>
#include <vector>
#include <atomic>// 全局标志,控制程序运行
std::atomic<bool> running(true);// 处理深度帧
void processDepthFrame(std::shared_ptr<ob::DepthFrame> depthFrame, std::shared_ptr<ob::PointCloudGenerator> pcGenerator) {if (!depthFrame) return;// 获取深度数据uint16_t* depthData = (uint16_t*)depthFrame->data();int width = depthFrame->width();int height = depthFrame->height();// 计算中心点深度int centerX = width / 2;int centerY = height / 2;uint16_t centerDepth = depthData[centerY * width + centerX];std::cout << "深度帧: 宽度=" << width << ", 高度=" << height << ", 中心点深度=" << centerDepth << "mm" << std::endl;// 生成点云if (pcGenerator) {auto pointCloud = pcGenerator->generate(depthFrame);if (pointCloud) {float* points = (float*)pointCloud->data();int pointCount = pointCloud->dataSize() / (3 * sizeof(float));// 简单统计:计算平均深度float sumDepth = 0;int validPoints = 0;for (int i = 0; i < pointCount; i++) {float z = points[i * 3 + 2];if (z > 0) {sumDepth += z;validPoints++;}}if (validPoints > 0) {std::cout << "点云: 点数=" << validPoints << ", 平均深度=" << sumDepth / validPoints << "mm" << std::endl;}}}
}int main() {try {// 初始化SDKob::Context context;// 枚举设备std::shared_ptr<ob::DeviceList> deviceList = context.queryDeviceList();if (deviceList->deviceCount() == 0) {std::cerr << "未发现设备!" << std::endl;return -1;}// 获取第一个设备std::shared_ptr<ob::Device> device = deviceList->getDevice(0);std::cout << "已连接设备: " << device->getDeviceInfo()->name() << std::endl;// 创建数据流处理管道std::shared_ptr<ob::Pipeline> pipeline = std::make_shared<ob::Pipeline>(device);// 获取深度流配置列表std::shared_ptr<ob::StreamProfileList> depthProfileList = pipeline->getStreamProfileList(OB_SENSOR_DEPTH);// 选择合适的深度流配置(848x480@30fps, Y16格式)std::shared_ptr<ob::VideoStreamProfile> depthProfile = std::dynamic_pointer_cast<ob::VideoStreamProfile>(depthProfileList->getVideoStreamProfile(848, 0, OB_FORMAT_Y16, 30));if (!depthProfile) {// 如果没有指定配置,获取默认配置depthProfile = std::dynamic_pointer_cast<ob::VideoStreamProfile>(depthProfileList->getDefaultVideoStreamProfile());}// 创建配置对象并启用深度流ob::Config config;config.enableStream(depthProfile);// 创建点云生成器std::shared_ptr<ob::PointCloudGenerator> pcGenerator = std::make_shared<ob::PointCloudGenerator>();pcGenerator->setFormat(OB_FORMAT_XYZ);  // 设置点云格式为XYZ// 打印相机内参auto depthSensor = device->getSensor(OB_SENSOR_DEPTH);auto intrinsics = depthSensor->getIntrinsics(depthProfile);std::cout << "深度相机内参:" << std::endl<< "fx=" << intrinsics.fx << ", fy=" << intrinsics.fy << std::endl<< "cx=" << intrinsics.cx << ", cy=" << intrinsics.cy << std::endl;// 启动数据流pipeline->start(config, [&](std::shared_ptr<ob::FrameSet> frameSet) {if (frameSet && frameSet->depthFrame()) {processDepthFrame(frameSet->depthFrame(), pcGenerator);}});std::cout << "按Enter键退出..." << std::endl;std::cin.get();running = false;// 停止数据流pipeline->stop();std::cout << "程序已退出" << std::endl;return 0;}catch (const ob::Error& e) {std::cerr << "SDK错误: " << e.getName() << " (" << e.getFunction() << ")" << std::endl<< "错误码: " << e.getErrorCode() << std::endl<< "错误描述: " << e.getDescription() << std::endl;return -1;}catch (const std::exception& e) {std::cerr << "异常: " << e.what() << std::endl;return -1;}
}    

五、CMake配置示例

为了方便项目构建,建议使用CMake配置:

cmake_minimum_required(VERSION 3.10)
project(OrbbecDepthCameraDemo)# 设置C++标准
set(CMAKE_CXX_STANDARD 11)# 查找OrbbecSDK
find_package(OrbbecSDK REQUIRED)# 添加可执行文件
add_executable(orbbec_demo orbbec_depth_camera_demo.cpp)# 链接OrbbecSDK库
target_link_libraries(orbbec_demo ${OrbbecSDK_LIBRARIES}
)# 包含头文件目录
target_include_directories(orbbec_demo PUBLIC${OrbbecSDK_INCLUDE_DIRS}
)# 设置可执行文件输出路径
set_target_properties(orbbec_demo PROPERTIESRUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)

六、常见功能扩展

6.1 RGB-D数据同步获取
// 启用RGB流
std::shared_ptr<ob::StreamProfileList> colorProfileList = pipeline->getStreamProfileList(OB_SENSOR_COLOR);
std::shared_ptr<ob::VideoStreamProfile> colorProfile = std::dynamic_pointer_cast<ob::VideoStreamProfile>(colorProfileList->getVideoStreamProfile(1280, 0, OB_FORMAT_RGB, 30));
config.enableStream(colorProfile);// 在帧回调中处理RGB和深度数据
pipeline->start(config, [&](std::shared_ptr<ob::FrameSet> frameSet) {if (frameSet->depthFrame() && frameSet->colorFrame()) {auto depthFrame = frameSet->depthFrame();auto colorFrame = frameSet->colorFrame();// 处理同步的RGB-D数据processRGBDFrame(depthFrame, colorFrame);}
});
6.2 深度图与彩色图对齐
// 创建对齐器
std::shared_ptr<ob::Align> align = std::make_shared<ob::Align>(OB_ALIGN_DEPTH_TO_COLOR);// 在帧回调中应用对齐
pipeline->start(config, [&](std::shared_ptr<ob::FrameSet> frameSet) {if (frameSet) {// 应用对齐auto alignedFrameSet = align->process(frameSet);if (alignedFrameSet->depthFrame() && alignedFrameSet->colorFrame()) {auto depthFrame = alignedFrameSet->depthFrame();auto colorFrame = alignedFrameSet->colorFrame();// 处理对齐后的RGB-D数据processAlignedRGBDFrame(depthFrame, colorFrame);}}
});
6.3 保存深度图和点云数据
// 保存深度图为PNG
void saveDepthImage(std::shared_ptr<ob::DepthFrame> depthFrame, const std::string& filename) {cv::Mat depthMat(depthFrame->height(), depthFrame->width(), CV_16UC1, depthFrame->data());cv::imwrite(filename, depthMat);
}// 保存点云为PLY格式
void savePointCloud(std::shared_ptr<ob::Frame> pointCloud, const std::string& filename) {float* points = (float*)pointCloud->data();int pointCount = pointCloud->dataSize() / (3 * sizeof(float));std::ofstream file(filename);if (file.is_open()) {// PLY文件头file << "ply\n";file << "format ascii 1.0\n";file << "element vertex " << pointCount << "\n";file << "property float x\n";file << "property float y\n";file << "property float z\n";file << "end_header\n";// 写入点数据for (int i = 0; i < pointCount; i++) {float x = points[i * 3];float y = points[i * 3 + 1];float z = points[i * 3 + 2];file << x << " " << y << " " << z << "\n";}file.close();}
}

七、注意事项

  1. 线程安全:OrbbecSDK的多数对象非线程安全,避免在多线程中同时操作同一实例
  2. 内存管理:Frame对象使用智能指针管理,避免手动释放
  3. 错误处理:建议使用try-catch捕获SDK抛出的异常
  4. 性能优化
    • 减少帧回调中的复杂计算
    • 使用硬件加速(如OpenCL)处理点云
    • 避免频繁创建和销毁SDK对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/92204.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/92204.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/92204.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

标题 “Python 网络爬虫 —— selenium库驱动浏览器

一、Selenium 库核心认知 Selenium 库是 Web 应用程序测试与自动化操作的利器 &#xff0c;能驱动浏览器&#xff08;如 Edge、Firefox 等&#xff09;执行点击、输入、打开、验证等操作 。与 Requests 库差异显著&#xff1a;Requests 库仅能获取网页原始代码&#xff0c;而 …

从实践出发--探究C/C++空类的大小,真的是1吗?

文章目录测试代码VS2022正常运行编译失败GCC总结Author: NemaleSu Data: 2025/07/21 测试环境&#xff1a; Win11&#xff1a;VS2022Ubuntu22.04&#xff1a;gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0 相信众多cpper听过太多书籍、视频、文档、博客等资料&#xff0c;说C/C…

数据结构自学Day11-- 排序算法

一、排序算法的概念排序&#xff08;Sorting&#xff09;是指&#xff1a;将一组“无序”的数据&#xff0c;按照某种“顺序规则”排列成“有序”的过程。1、按排序顺序分类&#xff1a;升序&#xff1a;从小到大排列&#xff0c;如 1, 3, 5, 7, 9降序&#xff1a;从大到小排列…

电子元器件—三极管(一篇文章搞懂电路中的三极管)(笔记)(面试考试必备知识点)

三极管的定义及工作原理1. 定义三极管&#xff08;Transistor&#xff09;是一种具有三层半导体材料&#xff08;P-N-P 或 N-P-N&#xff09;构成的半导体器件&#xff0c;用于信号放大、开关控制和信号调制等应用。三极管有三个引脚&#xff1a;发射极&#xff08;Emitter&…

数据结构之克鲁斯卡尔算法

前言&#xff1a;和Prim算法一样&#xff0c;Kruskal 算法也是用来生成最小生成树的&#xff0c;这篇文章来学习一下Kruskal算法的实现 一、实现流程 初始化的时候&#xff0c;将所有的边用一个数组存储&#xff0c;并且按权值从小到大进行排序&#xff0c;每次选一个权值最小的…

MongoDB 查询时区问题

MongoDB默认时区是UTC&#xff0c;比北京时区晚八小时&#xff0c;北京时间UTC8h。 // 北京时间的 2024-10-01 08:00:00 // (>) 大于 - $gt // (<) 小于 - $lt // (>) 大于等于 - $gte // (< ) 小于等于 - $lte// Z代表UTC时区1、{"gmtCreate":{"$…

Windows VS2019 编译 Apache Thrift 0.15.0

随着微服务架构的普及,高效的跨语言远程过程调用(RPC) 成为了构建分布式系统的重要基础。Apache Thrift 是 Facebook 开源的一个轻量级、高性能的 RPC 框架,它允许开发者通过一个通用的接口定义语言(IDL)来定义服务接口和数据结构,并自动生成多种语言的客户端和服务端代…

搭建种草商城框架指南

一、引言在当今电商市场&#xff0c;种草商城以其独特的社交化购物模式受到越来越多用户的喜爱。搭建一个功能完善、体验良好的种草商城框架&#xff0c;需要综合考虑前端界面、后端服务、数据库设计等多个方面。本文将为你详细介绍搭建种草商城框架的关键要点和技术选型。二、…

docker--挂载

设置容器的挂载 需要注意 挂载行为会覆盖容器目标目录的原有内容(未验证)。 查看容器的挂载情况 在容器外部查看: docker inspect <容器名或容器ID> | grep -A n "Mounts" -A n 的含义 -A 是 --after-context 的缩写,表示显示匹配行及其后 n 行。 "Mo…

以Streamable HTTP方式访问mcp server的过程

一、mcp server 部署 使用fastmcp框架 部署 mcp server&#xff0c; 以下是源代码 # 引入 fastmcp 依赖包 from fastmcp import FastMCP# 新建fastmcp实例&#xff0c; 名字叫做 weather mcp FastMCP("weather")mcp.tool(name"weather", tags{"weath…

二次元 IP 虚拟数字人宣传:漫画角色动态直播与衍生周边预售联动

当漫画角色从静态画稿中走出&#xff0c;以动态直播的形式与粉丝实时互动&#xff0c;再顺势开启衍生周边预售 —— 虚拟数字人技术正重塑二次元 IP 的宣传逻辑。这种 “动态直播 周边预售” 的联动模式&#xff0c;不仅打破了次元壁&#xff0c;更让 IP 热度高效转化为商业价…

如何在服务器上获取Linux目录大小

目前我在管理一台hostease的服务器时遇到服务器磁盘空间不足的情况。随着在系统中添加更多文件&#xff0c;这些系统文件目录也变得越来越大。过大的目录也消耗了系统资源&#xff0c;导致系统运行缓慢。后来我通过下列的方法对服务器上的磁盘空间使用进行了逐一检查。在这篇综…

来伊份养馋记社区零售 4.0 上海首店落沪:重构 “家门口” 的生活服务生态

7 月 19 日&#xff0c;来伊份与养馋记战略合作的首个 “社区零售 4.0” 门店在上海松江泗泾镇泗宝路正式开业。这不仅是双方自今年 1 月达成战略合作后的实质性落地&#xff0c;更是 3 月 “社区生活新生态” 构想的首次规模化实践&#xff0c;标志着零食行业巨头与社区零售新…

从C++开始的编程生活(3)——引用类型、内联inline和nullptr

前言 本系列文章承接C语言的学习&#xff0c;需要有C语言的基础才能学会哦~ 第3篇主要讲的是有关于C的引用类型、内联inline和nullptr。 C才起步&#xff0c;都很简单呢&#xff01; 目录 前言 引用类型 基本语法 特性 应用 const引用 基本语法 引用与指针的关系 内联…

makefile-- 其他函数

fuctionsjoin​$(join <list1>,<list2>)连接函数把list2 中单词对应的添加到list1 的后面若list1 的单词个数> list2 &#xff0c;多出的list1 保持不变若list2 的单词个数> list21&#xff0c;多出的list2 添加到list1 后面foreach​$(foreach <var>…

【unity实战】使用unity的Navigation+LineRenderer实现一个3D人物寻路提前指示预测移动轨迹的效果,并可以适配不同的地形

文章目录 前言 实战 1、实现要点 1.1 NavMesh.CalculatePath方法计算两个点之间的导航路径 1.2 寻找投射的地面点 2、代码实现如下 3、烘培地面导航网格 4、添加导航玩家代理,并挂载前面的脚本 5、创建Line Renderer,并放在角色下面作为子物体 6、运行游戏查看效果 专栏推荐 …

宝塔申请证书错误,提示 module ‘OpenSSL.crypto‘ has no attribute ‘sign‘

遇到"module OpenSSL.crypto has no attribute sign"错误时&#xff0c;通常是由于pyOpenSSL版本兼容性问题导致的‌。以下是解决方案&#xff1a;通过SSH连接到服务器&#xff0c;执行以下命令安装指定版本的pyOpenSSL&#xff1a;btpip install pyOpenSSL24.2.1-U然…

【ffmpeg源码学习】详解pkg-config的作用

文章目录 前言 一、什么是pkg-config? 二、为什么需要 pkg-config? 三、pkg-config 的工作原理 3.1 .pc 文件 3.2 查询流程 3.3 查找路径 四、pkg-config 在 FFmpeg 中的作用 五、pkg-config 的常用命令 六、在项目中的实际用法 6.1 makefile示例: 6.2 cmake示例: 6.3 gcc命…

PHPStorm携手ThinkPHP8:开启高效开发之旅

目录一、前期准备1.1 开发环境搭建1.2 配置 Xdebug二、PHPStorm 集成 ThinkPHP82.1 导入 ThinkPHP8 项目2.2 配置 PHP 解释器2.3 配置服务器三、ThinkPHP8 项目开发基础3.1 项目结构剖析3.2 控制器与方法创建3.3 视图渲染与数据传递四、数据库操作与模型定义4.1 数据库配置4.2 …

HTTP性能优化实战技术详解(2025)

HTTP性能优化实战技术详解本文基于提供的文章大纲&#xff0c;对HTTP性能优化进行扩展说明。文章结构清晰&#xff0c;从理解瓶颈到具体优化策略&#xff0c;再到监控与高级技巧&#xff0c;逐步展开。每个部分包括背景介绍、核心原理、实施步骤、示例或工具推荐&#xff0c;确…