奧比中光深度相機開發

一、開發環境準備

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;確…