核心技术
产品中心
开发者
如何购买
资源中心
Orbbec SDK 文档
欢迎阅读Orbbec SDK(以下简称“SDK”)的使用教程!SDK 不仅提供了简洁的高阶API,又提供全面、灵活的低阶API,能够让您更快速的了解和使用奥比中光3D传感摄像头。
代码示例——C&C++示例说明
获取所有示例都可以在工程的Examples目录中找到
名称 语言 描述
HelloOrbbec C 演示连接到设备获取SDK版本和设备信息
固件升级示例 C 演示选择固件bin或者img文件给设备升级固件版本
传感器控制示例 C 演示对设备、传感器控制命令的操作
深度示例 C 演示使用SDK获取深度数据并绘制显示、获取分辨率并进行设置、显示深度图像
彩色示例 C 演示使用SDK获取彩色数据并绘制显示、获取分辨率并进行设置、显示彩色图像
红外示例 C 演示使用SDK获取红外数据并绘制显示、获取分辨率并进行设置、显示红外图像
深度模式 C 演示如何获取相机深度工作模式,查询支持的深度模式列表,切换模式
热拔插示例 C 演示设备热拔插监控,检测到设备上线自动连接设备打开深度流,检测到设备掉线自动断开设备连接
点云示例 C 演示生成深度点云或RGBD点云并保存成ply格式文件
HelloOrbbec C++ 演示连接到设备获取SDK版本和设备信息
深度示例 C++ 演示使用SDK获取深度数据并绘制显示、获取分辨率并进行设置、显示深度图像
彩色示例 C++ 演示使用SDK获取彩色数据并绘制显示、获取分辨率并进行设置、显示彩色图像
红外示例 C++ 演示使用SDK获取红外数据并绘制显示、获取分辨率并进行设置、显示红外图像
流对齐示例 C++ 演示对传感器数据流对齐的操作
固件升级示例 C++ 演示选择固件bin或者img文件给设备升级固件版本
传感器控制示例 C++ 演示对设备和传感器控制命令的操作
多路流同时开流示例 C++ 演示一个设备同时打开多路流的操作
多设备示例 C++ 演示对多设备进行操作
深度模式 C++ 演示如何获取相机深度工作模式,查询支持的深度模式列表,切换模式
热拔插示例 C++ 演示设备拔插回调的设置,并获取到插拔后处理的流
IMU示例 C++ 获取IMU数据并输出显示
多机同步示例 C++ 演示多机同步功能
点云示例 C++ 演示生成深度点云或RGBD点云并保存成ply格式文件
存储示例 C++ 获取彩色和深度图并存储为png格式
录制示例 C++ 录制当前视频流到文件
回放示例 C++ 载入视频文件进行回放

C

HelloOrbbec

功能描述:用于演示SDK初始化、获取SDK版本、获取设备型号、获取设备序列号、获取固件版本号、SDK释放资源。
本示例基于C Low Level API进行演示
首先获取并打印当前SDK版本
  1. printf("SDK version: %d.%d.%d\n", ob_get_major_version(), ob_get_minor_version(), ob_get_patch_version());
创建一个Context,用于获取设备信息列表和创建设备
  1. ob_error* error = NULL;
  2. ob_context* ctx = ob_create_context( &error );
查询已经接入设备的列表,从而获取列表内设备数量,并通过索引号0创建获取列表内第一个设备
  1. ob_device_list* dev_list = ob_query_device_list( ctx, &error );
  2. int dev_count = ob_device_list_device_count(dev_list, &error);
  3. if(dev_count == 0) {
  4. printf("Device not found!\n");
  5. return -1;
  6. }
  7. ob_device* dev = ob_device_list_get_device(dev_list, 0, &error);
接下来就可以获取和这个设备相关的信息了
  1. //获取设备信息
  2. ob_device_info* dev_info = ob_device_get_device_info(dev, &error);
  3. //获取设备名称
  4. const char* name = ob_device_info_name(dev_info, &error);
  5. //获取设备的pid, vid, uid
  6. int pid = ob_device_info_pid(dev_info, &error);
  7. int vid = ob_device_info_vid(dev_info, &error);
  8. int uid = ob_device_info_uid(dev_info, &error);
  9. //通过获取设备的固件版本号
  10. const char* fw_ver = ob_device_info_firmware_version(dev_info, &error);
  11. //通过获取设备的序列号
  12. const char* sn = ob_device_info_serial_number(dev_info, &error);
  13. //获取支持的传感器列表
  14. ob_sensor_list* sensor_list = ob_device_get_sensor_list(dev, &error);
  15. //获取传感器数量
  16. int count = ob_sensor_list_get_sensor_count(sensor_list, &error);
  17. for(int i = 0; i < count; i++)
  18. {
  19. ob_sensor_type sensor_type = ob_sensor_list_get_sensor_type(sensor_list i, &error);
  20. switch (sensor_type)
  21. {
  22. case OB_SENSOR_COLOR:
  23. break;
  24. case OB_SENSOR_DEPTH:
  25. break;
  26. case OB_SENSOR_IR:
  27. break;
  28. }
  29. }
释放资源,退出程序。
  1. //销毁sensor list
  2. ob_delete_sensor_list(sensor_list, &error);
  3. //销毁device info
  4. ob_delete_device_info(dev_info, &error);
  5. //销毁device
  6. ob_delete_device(dev, &error);
  7. //销毁device list
  8. ob_delete_device_list(dev_list, &error);
  9. //销毁context
  10. ob_delete_context(ctx, &error);

固件升级示例-FirmwareUpgrade

功能描述:本示例演示如何用固件文件给设备升级。
本示例基于C Low Level API进行演示,示例编译语言为C++,Orbbec SDK使用C语言API
在main函数接口通过命令参数获取固件文件
  1. // check_firmware_file_path()函数用于检查文件是否存在,实际代码中最好检查后缀是否为bin或者img, 以及固件文件是否与目标设备相匹配
  2. const char *check_firmware_file_path(int argc, char **argv) {
  3. if(argc < 2) {
  4. printf("Please input firmware path.\n");
  5. return "";
  6. }
  7. const char *filePath = *(argv + 1);
  8. FILE *file = fopen(filePath, "r");
  9. if(!file) {
  10. printf("Open Firmware file failed. filePath: %s\n", filePath);
  11. return "";
  12. }
  13. fclose(file);
  14. return filePath;
  15. }
  16. int main(int argc, char **argv) {
  17. const char *firmware_file_path = check_firmware_file_path(argc, argv);
  18. if(!firmware_file_path || 0 == strlen(firmware_file_path)) {
  19. printf("command: \n$ ./frameware_upgrade[.exe] firmwareFile.bin\n");
  20. return 0;
  21. }
  22. // 接下来的业务代码
  23. return 0;
  24. }
创建ob_context并通过ob_context获取设备,本示例假设运行firmware_upgrade[.exe]之前上位机(Windows、Ubuntu、Android平台)已经插入设备。device_changed_callback用于固件升级后监听device重启后获取被升级设备的业务处理
  1. // 构建ob_context对象
  2. ob_error *error = NULL;
  3. ob_context *ctx = ob_create_context(&error);
  4. check_error(error);
  5. // 设置设备变化监听器,device_changed_callback是管理device声明周期的关键函数,开发者必须关注该回调
  6. ob_set_device_changed_callback(ctx, device_changed_callback, &callback_user_data_, &error);
  7. check_error(error);
  8. // 查询当前已经接入的设备
  9. ob_device_list *dev_list = ob_query_device_list(ctx, &error);
  10. check_error(error);
  11. // 从ob_device_list中获取当前接入设备的数量
  12. int dev_count = ob_device_list_device_count(dev_list, &error);
  13. check_error(error);
  14. if(dev_count == 0) {
  15. // 固件升级示例假设设备已经接入到上位机(Windows、Ubuntu、Android平台)
  16. printf("Device not found!\n");
  17. return -1;
  18. }
  19. // 获取第一个设备,index=0
  20. ob_device *dev = ob_device_list_get_device(dev_list, 0, &error);
  21. check_error(error);
  22. // 打印设备信息
  23. dump_device_info(dev);
获取设备当前的固件版本信息
  1. // 打印设备名称,SN,VID,PID以及固件版本
  2. void dump_device_info(ob_device *device) {
  3. ob_error *error = NULL;
  4. // 获取ob_device_info对象,通过ob_device_info可以获取目标设备的基本信息
  5. ob_device_info *dev_info = ob_device_get_device_info(device, &error);
  6. check_error(error);
  7. // 设备名称
  8. const char *name = ob_device_info_name(dev_info, &error);
  9. check_error(error);
  10. printf("Device name: %s\n", name);
  11. // 设备VID,PID,UID
  12. int pid = ob_device_info_pid(dev_info, &error);
  13. check_error(error);
  14. int vid = ob_device_info_vid(dev_info, &error);
  15. check_error(error);
  16. const char *uid = ob_device_info_uid(dev_info, &error);
  17. check_error(error);
  18. printf("Device pid: %d vid: %d uid: %s\n", pid, vid, uid);
  19. // 设备当前的固件版本号
  20. const char *fw_ver = ob_device_info_firmware_version(dev_info, &error);
  21. check_error(error);
  22. printf("Firmware version: %s\n", fw_ver);
  23. // 设备SN
  24. const char *sn = ob_device_info_serial_number(dev_info, &error);
  25. check_error(error);
  26. printf("Serial number: %s\n", sn);
  27. // 释放资源,否则会造成内存泄漏
  28. ob_delete_device_info(dev_info, &error);
  29. check_error(error);
  30. }
给目标设备升级固件 a. 实现C API的固件升级回调接口; b. 调用固件升级接口进行升级;
  1. // 实现C API的固件升级回调接口;
  2. void device_upgrade_callback(ob_upgrade_state state, const char *message, uint8_t percent, void *user_data) {
  3. if(state == STAT_START) {
  4. printf("Upgrade Firmware start\n");
  5. }
  6. else if(state == STAT_FILE_TRANSFER) {
  7. printf("Upgrade Firmware file transfer, percent: %u\n", (uint32_t)percent);
  8. }
  9. else if(state == STAT_IN_PROGRESS) {
  10. printf("Upgrade Firmware in progress, percent: %u\n", (uint32_t)percent);
  11. }
  12. else if(state == STAT_DONE) {
  13. // 固件升级成功
  14. printf("Upgrade Firmware done, percent: %u\n", (uint32_t)percent);
  15. is_upgrade_success_ = true;
  16. }
  17. else if(state == STAT_VERIFY_IMAGE) {
  18. printf("Upgrade Firmware verify image\n");
  19. }
  20. else {
  21. // 固件升级失败
  22. printf("Upgrade Firmware failed. state: %d, errMsg: %s, percent: %u \n", (int)state, message ? message : "", (uint32_t)percent);
  23. }
  24. }
  25. // 对目标设备进行固件升级
  26. bool upgrade_firmware(ob_device *device, const char *firmwarePath) {
  27. const char *index = strstr(firmwarePath, ".img");
  28. bool isImgFile = (bool)index;
  29. index = strstr(firmwarePath, ".bin");
  30. bool isBinFile = (bool)index;
  31. if(!(isImgFile || isBinFile)) {
  32. // 固件升级文件一般为bin或者img,实际业务中最好通过文件名称、文件MD5等信息做防呆
  33. printf("Upgrade Fimware failed. invalid firmware file: %s\n", firmwarePath);
  34. return false;
  35. }
  36. // 调用固件升级接口进行升级;
  37. is_upgrade_success_ = false;
  38. ob_error *error = NULL;
  39. ob_device_upgrade(device, firmwarePath, device_upgrade_callback, false, &callback_user_data_, &error);
  40. check_error(error);
  41. return is_upgrade_success_;
  42. }
固件升级成功后,需要重启设备。重启设备有两种方式,一种是拔插设备(或者操作系统重启),另一种是调用Orbbec SDK的reboot接口。等设备上线后,通过本示例的dump_device_info()函数可以查询当前设备固件版本信息 以下示例演示通过固件reboot接口重启设备
  1. // 重启设备
  2. printf("Reboot device\n");
  3. is_device_removed_ = false;
  4. is_wait_reboot_complete_ = true;
  5. ob_device_reboot(dev, &error);
  6. check_error(error);
  7. // 释放资源,防止内存泄漏
  8. ob_delete_device(dev, &error);
  9. check_error(error);
在ob_device_changed_callback可以监听设备重启时下线、上线的事件,详情可以看热拔插示例
  1. // 监听设备变化
  2. void device_changed_callback(ob_device_list *removed, ob_device_list *added, void *user_data) {
  3. ob_error *error = NULL;
  4. // 通过added处理上线的设备
  5. // 通过removed处理下线的设备
  6. // 释放资源,避免内存泄漏
  7. ob_delete_device_list(removed, &error);
  8. check_error(error);
  9. // 释放资源,避免内存泄漏
  10. ob_delete_device_list(added, &error);
  11. check_error(error);
  12. }

传感器控制示例-SensorControl

功能描述:本示例主要演示了对device控制命令的操作、对Sensor控制命令的操作、对Sensor进行流操作。
本示例基于C Low Level API进行演示
创建一个Context,并查询已经接入设备的列表
  1. ob_error* error = NULL;
  2. ob_context* ctx = ob_create_context( &error );
  3. ob_device_list* dev_list = ob_query_device_list( ctx, &error );
通过索引号打印列表内设备信息
  1. const char *name = ob_device_list_get_device_name(device_list, i, &g_error);
  2. int pid = ob_device_list_get_device_pid(device_list, i, &g_error);
  3. int vid = ob_device_list_get_device_vid(device_list, i, &g_error);
  4. const char *uid = ob_device_list_get_device_uid(device_list, i, &g_error);
  5. const char *sn = ob_device_list_get_device_serial_number(device_list, i, &g_error);
  6. printf("%d. name: %s, pid: %d, vid: %d, uid: %s, sn: %s\n", i, name, pid, vid, uid, sn);
创建一个设备
  1. if(devCount <= 1) {
  2. // 如果插入单个设备,默认选择第一个
  3. device = ob_device_list_get_device(dev_list, 0, &g_error);
  4. }
  5. else {
  6. // 如果有多个设备,用户输入选择
  7. device = select_device(dev_list); // select_device 代码请参考实例源码
  8. }
获取并打印当前创建的设备信息
  1. ob_device_info *deviceInfo = ob_device_get_device_info(device, &g_error);
  2. const char *name = ob_device_info_name(deviceInfo, &g_error);
  3. int pid = ob_device_info_pid(deviceInfo, &g_error);
  4. int vid = ob_device_info_vid(deviceInfo, &g_error);
  5. const char *uid = ob_device_info_uid(deviceInfo, &g_error);
  6. printf("Current Device: name: %s, pid: %d, vid: %d, uid: %s\n", name, pid, vid, uid);
获取支持的控制命令属性
  1. // 获取支持控制命令属性个数
  2. uint32_t propertySize = ob_device_get_supported_property_count(device, &g_error);
  3. // 通过索引号i获取控制命令属性项
  4. ob_property_item property_item = ob_device_get_supported_property(device, i, &g_error);
读/写控制命令
  1. // 读取
  2. bool_ret = ob_device_get_bool_property(device, property_item.id, &g_error);// bool型参数
  3. int_ret = ob_device_get_int_property(device, property_item.id, &g_error);/ int 型参数
  4. float_ret = ob_device_get_float_property(device, property_item.id, &g_error);// float型参数
  5. // 读取命令的值范围、默认值、步进值等信息
  6. ob_int_property_range int_range;
  7. ob_float_property_range float_range;
  8. ob_bool_property_range bool_range;
  9. sprintf(str, "Bool value(min:0, max:1, step:1)"); // bool 型
  10. int_range = ob_device_get_int_property_range(device, property_item.id, &g_error); // int 型
  11. float_range = ob_device_get_float_property_range(device, property_item.id, &g_error); // float型
  12. // 写入
  13. ob_device_set_bool_property(device, property_item.id, bool_value, &g_error); // bool型参数
  14. ob_device_set_int_property(device, property_item.id, int_value, &g_error); // int 型参数
  15. ob_device_set_float_property(device, property_item.id, float_value, &g_error); // float型参数
最后程序退出时需要释放相应的已创建资源。
  1. //销毁context
  2. ob_delete_context(ctx, &g_error);
  3. //销毁device list
  4. ob_delete_device_list(dev_list, &g_error);
  5. //销毁device
  6. ob_delete_device(device, &g_error);

深度示例-DepthViewer

功能描述:演示使用SDK获取深度数据并绘制显示、获取分辨率并进行设置、显示深度图像
本示例基于C High Level API进行演示
首先需要创建Pipeline,用于连接设备后打开彩色和深度流
  1. pipe = ob_create_pipeline( &error );
创建Config,用于配置彩色和深度流的分辨率、帧率、格式
  1. ob_config* config = ob_create_config( &error );
配置流
  1. //配置Depth流
  2. ob_stream_profile * depth_profile = NULL;
  3. ob_stream_profile_list *profiles = ob_pipeline_get_stream_profile_list(pipe, OB_SENSOR_DEPTH, &error);
  4. //根据指定的格式查找对应的Profile,优先查找Y16格式
  5. depth_profile = ob_stream_profile_list_get_video_stream_profile(profiles, 640, 0, OB_FORMAT_Y16, 30, &error);
  6. //没找到Y16格式后不匹配格式查找对应的Profile进行开流
  7. if(error){
  8. depth_profile = ob_stream_profile_list_get_video_stream_profile(profiles, 640, 0, OB_FORMAT_UNKNOWN, 30, &error);
  9. error = nullptr;
  10. }
  11. ob_config_enable_stream(config, depth_profile, &error); // 使能配置
通过Config,启动Pipeline
  1. ob_pipeline_start_with_config(pipe, config, &error);
释放资源,退出程序。
  1. //销毁frameSet,回收内存
  2. ob_delete_frame(frameset, &error);
  3. //销毁profile
  4. ob_delete_stream_profile(depth_profile, &error);
  5. //销毁profile list
  6. ob_delete_stream_profile_list(profiles, &error);
  7. //销毁device
  8. ob_delete_device(device, &error);
  9. //销毁pipeline
  10. ob_delete_pipeline(pipe, &error);

彩色示例-ColorViewer

功能描述:演示使用SDK获取彩色数据并绘制显示、获取分辨率并进行设置、显示彩色图像
本示例基于C High Level API进行演示
首先需要创建Pipeline,用于连接设备后打开彩色和深度流
  1. pipe = ob_create_pipeline( &error );
创建Config,用于配置彩色和深度流的分辨率、帧率、格式
  1. ob_config* config = ob_create_config( &error );
配置流
  1. //配置Color流
  2. ob_stream_profile * color_profile = NULL;
  3. ob_stream_profile_list *profiles = ob_pipeline_get_stream_profile_list(pipe, OB_SENSOR_Color, &error);
  4. //根据指定的格式查找对应的Profile,优先选择RGB888格式
  5. color_profile = ob_stream_profile_list_get_video_stream_profile(profiles, 640, 0, OB_FORMAT_RGB, 30, &error);
  6. //没找到RGB888格式后不匹配格式查找对应的Profile进行开流
  7. if(error){
  8. color_profile = ob_stream_profile_list_get_video_stream_profile(profiles, 640, 0, OB_FORMAT_UNKNOWN, 30, &error);
  9. error = nullptr;
  10. }
  11. ob_config_enable_stream(config, depth_profile, &error); // 使能配置
通过Config,启动Pipeline
  1. ob_pipeline_start_with_config(pipe, config, &error);
释放资源,退出程序。
  1. //销毁frameSet,回收内存
  2. ob_delete_frame(frameset, &error);
  3. //销毁profile
  4. ob_delete_stream_profile(color_profile, &error);
  5. //销毁profile list
  6. ob_delete_stream_profile_list(profiles, &error);
  7. //销毁device
  8. ob_delete_device(device, &error);
  9. //销毁pipeline
  10. ob_delete_pipeline(pipe, &error);

红外示例-InfraredViewer

功能描述:演示使用SDK获取红外数据并绘制显示、获取分辨率并进行设置、显示红外图像
本示例基于C High Level API进行演示
首先需要创建Pipeline,用于连接设备后打开彩色和深度流
  1. pipe = ob_create_pipeline( &error );
创建Config,用于配置彩色和深度流的分辨率、帧率、格式
  1. ob_config* config = ob_create_config( &error );
配置流
  1. //配置IR流
  2. ob_stream_profile * ir_profile = NULL;
  3. ob_stream_profile_list *profiles = ob_pipeline_get_stream_profile_list(pipe, OB_SENSOR_IR, &error);
  4. //根据指定的格式查找对应的Profile,优先查找Y16格式
  5. ir_profile = ob_stream_profile_list_get_video_stream_profile(profiles, 640, 0, OB_FORMAT_Y16, 30, &error);
  6. //没找到Y16格式后不匹配格式查找对应的Profile进行开流
  7. if(error) {
  8. ir_profile = ob_stream_profile_list_get_video_stream_profile(profiles, 640, 0, OB_FORMAT_UNKNOWN, 30, &error);
  9. error = nullptr;
  10. }
  11. ob_config_enable_stream(config, depth_profile, &error); // 使能配置
配置IR输出源
  1. //判断是否支持切换左右IR通道
  2. if(ob_device_is_property_supported(device, OB_PROP_IR_CHANNEL_DATA_SOURCE_INT, OB_PERMISSION_READ_WRITE, &error)) {
  3. // Gemini 2 和 Gemini 2 L 产品支持SENSOR_IR选择sensor输出,0是左IR,1是右IR。
  4. int32_t dataSource = 0;
  5. ob_device_set_int_property(device, OB_PROP_IR_CHANNEL_DATA_SOURCE_INT, dataSource, &error);
  6. }
通过Config,启动Pipeline
  1. ob_pipeline_start_with_config(pipe, config, &error);
释放资源,退出程序。
  1. //销毁frameSet,回收内存
  2. ob_delete_frame(frameset, &error);
  3. //销毁profile
  4. ob_delete_stream_profile(ir_profile, &error);
  5. //销毁profile list
  6. ob_delete_stream_profile_list(profiles, &error);
  7. //销毁device
  8. ob_delete_device(device, &error);
  9. //销毁pipeline
  10. ob_delete_pipeline(pipe, &error);

切换相机深度工作模式-DepthWorkMode

功能描述:Gemini 2 、Gemini 2 L 、Astra 2、 Gemini 2 XL 设备支持深度工作模式切换。主要演示切换相机深度模式,先查询深度模式列表,然后选择对应的相机深度模式,调用接口切换 首先获取设备
  1. //创建一个Context,与Pipeline不同,Context是底层API的入口,在开关流等常用操作上
  2. //使用低级会稍微复杂一些,但是底层API可以提供更多灵活的操作,如获取多个设备,读写
  3. //设备及相机的属性等
  4. ob_error * error = NULL;
  5. ob_context *ctx = ob_create_context(&error);
  6. check_error(error);
  7. //查询已经接入设备的列表
  8. ob_device_list *dev_list = ob_query_device_list(ctx, &error);
  9. check_error(error);
  10. //获取接入设备的数量
  11. int dev_count = ob_device_list_device_count(dev_list, &error);
  12. check_error(error);
  13. if(dev_count == 0) {
  14. printf("Device not found!\n");
  15. return -1;
  16. }
  17. //创建设备,0表示第一个设备的索引
  18. ob_device *dev = ob_device_list_get_device(dev_list, 0, &error);
  19. check_error(error);
检查设备是否支持相机深度工作模式,Gemini 2、Gemini 2 L、 Gemini 2 XL、Astra 2 支持深度模式切换。
  1. // 检查是否支持相机深度工作模式
  2. if(!ob_device_is_property_supported(dev, OB_STRUCT_CURRENT_DEPTH_ALG_MODE, OB_PERMISSION_READ_WRITE, &error)) {
  3. printf("FAILED!!, Device not support depth work mode");
  4. check_error(error);
  5. return -1;
  6. }
  7. check_error(error);
查询设备的当前深度工作模式
  1. // 查询当前的深度工作模式
  2. ob_depth_work_mode cur_work_mode = ob_device_get_current_depth_work_mode(dev, &error);
  3. check_error(error);
  4. printf("Current depth work mode: %s\n", cur_work_mode.name);
查询设备支持的相机深度模式列表
  1. // 获取列表长度
  2. uint32_t mode_count = ob_depth_work_mode_list_count(mode_list, &error);
  3. printf("Support depth work mode list count: %u\n", mode_count);
  4. int cur_mode_index = -1;
  5. for(uint32_t i = 0; i < mode_count; i++) {
  6. ob_depth_work_mode mode = ob_depth_work_mode_list_get_item(mode_list, i, &error);
  7. check_error(error);
  8. printf("depth work mode[%u], name: %s", i, mode.name);
  9. }
切换相机深度模式
  1. // 切换到新的相机深度模式
  2. ob_device_switch_depth_work_mode_by_name(dev, mode.name, &error);
  3. check_error(error);
到此切换相机深度模式结束,可以用pipeline进行打开相机取流 注意:
  1. 如果需要切换相机深度模式,那么打开数据流必须在切换深度工作模式之后;每个相机深度模式下支持的有效分辨率不同
  2. 如果已经用pipeline打开数据流,那么切换相机深度工作模式前必须把原来申请的pipeline释放; 切换相机深度工作模式后重新创建pipeline,否则会造成野指针或者内存泄露;
最后释放资源
  1. // 销毁mode_list
  2. ob_delete_depth_work_mode_list(mode_list, &error);
  3. check_error(error);
  4. //销毁device
  5. ob_delete_device(dev, &error);
  6. check_error(error);
  7. //销毁device list
  8. ob_delete_device_list(dev_list, &error);
  9. check_error(error);
  10. //销毁context
  11. ob_delete_context(ctx, &error);
  12. check_error(error);

热拔插示例-HotPlugin

功能描述: 设备热拔插监控,检测到设备上线自动连接设备打开深度流,检测到设备掉线自动断开设备连接。
本示例基于C Low Level API进行注册设备上下线回调,基于High Level API进行开流取帧演示
创建设备连接处理函数,函数内创建pipeline并调用create_and_start_with_config开启彩色流和深度流。
  1. //设备连接处理
  2. void device_connect_callback( ob_device_list* connectList ) {
  3. uint32_t count = ob_device_list_device_count(connectList, &error);
  4. check_error(error);
  5. printf("Device connect: %d\n", count);
  6. if(count > 0) {
  7. if(pipeline == NULL) {
  8. pipeline = ob_create_pipeline(&error);
  9. check_error(error);
  10. create_and_start_with_config();
  11. }
  12. }
  13. }
创建设备断开处理函数,函数内将pipeline停止,并将退出pipeline标记isExit设为true
  1. //设备断开处理
  2. void device_disconnect_callback( ob_device_list* disconnectList ) {
  3. uint32_t count = ob_device_list_device_count(disconnectList, &error);
  4. check_error(error);
  5. printf("Device disconnect: %d\n", count);
  6. if(count > 0) {
  7. isExit = true;
  8. }
  9. }
设备连接、断开处理函数将会在设备上下线回调函数内被调用
  1. //设备状态改变回调
  2. void on_device_changed_callback( ob_device_list* removed, ob_device_list* added, void* pCallback ) {
  3. device_disconnect_callback( removed );
  4. device_connect_callback( added );
  5. }
主函数main内,首先需要创建一个Context并注册设备上下线回调
  1. //创建上下文
  2. ob_context* ctx = ob_create_context( &error );
  3. //注册设备回调
  4. ob_set_device_changed_callback( ctx, on_device_changed_callback, NULL, &error );
主循环主要任务是,当pipeline在设备上线后已创建启动,从pipeline获取数据帧集合,并将数据帧集合内的Color和Depth相关信息打印输出。
  1. //等待一帧数据,超时时间为100ms
  2. ob_frame* frameset = ob_pipeline_wait_for_frameset( pipeline, 100, &error );
  3. if ( frameset ) {
  4. //获取深度数据帧
  5. ob_frame* depth_frame = ob_frameset_depth_frame( frameset, &error );
  6. if ( depth_frame ) {
  7. printf( "=====Depth Frame Info======Index: %lld TimeStamp: %lld\n", ob_frame_index( depth_frame, &error ), ob_frame_time_stamp( depth_frame, &error ) );
  8. //释放深度数据帧
  9. ob_delete_frame( depth_frame, &error );
  10. }
  11. //获取Color数据帧
  12. ob_frame* color_frame = ob_frameset_color_frame( frameset, &error );
  13. if ( color_frame ) {
  14. printf( "=====Color Frame Info======Index: %lld TimeStamp: %lld\n", ob_frame_index( color_frame, &error ), ob_frame_time_stamp( color_frame, &error ) );
  15. //释放Color数据帧
  16. ob_delete_frame( color_frame, &error );
  17. }
  18. //释放frameSet
  19. ob_delete_frame( frameset, &error );
  20. }
退出主循环后,需要将相关资源释放
  1. if ( pipeline ) {
  2. //停止pipeline
  3. ob_pipeline_stop( pipeline, &error );
  4. // 销毁pipeline
  5. ob_delete_pipeline( pipeline, &error );
  6. }
  7. // 销毁dev_list
  8. if ( dev_list ) {
  9. ob_delete_device_list( dev_list, &error );
  10. }
  11. // 销毁ctx
  12. if ( ctx ) {
  13. ob_delete_context( ctx, &error );
  14. }

点云示例-PointCloud

功能描述:连接设备开流,生成深度点云或RGBD点云并保存成ply格式文件。
本示例基于C++ High Level API进行演示
创建点云保存成ply格式文件函数,ply文件格式详细描述可在网络上查看
  1. //保存点云数据到ply
  2. void save_points_to_ply( ob_frame* frame, const char* fileName ) {
  3. int pointsSize = ob_frame_data_size( frame, &error ) / sizeof( ob_point );
  4. check_error( error );
  5. FILE* fp = fopen( fileName, "wb+" );
  6. fprintf( fp, "ply\n" );
  7. fprintf( fp, "format ascii 1.0\n" );
  8. fprintf( fp, "element vertex %d\n", pointsSize );
  9. fprintf( fp, "property float x\n" );
  10. fprintf( fp, "property float y\n" );
  11. fprintf( fp, "property float z\n" );
  12. fprintf( fp, "end_header\n" );
  13. ob_point* point = ( ob_point* )ob_frame_data( frame, &error );
  14. check_error( error );
  15. for ( int i = 0; i < pointsSize; i++ ) {
  16. fprintf( fp, "%.3f %.3f %.3f\n", point->x, point->y, point->z );
  17. point++;
  18. }
  19. fflush( fp );
  20. fclose( fp );
  21. }
  22. //保存彩色点云数据到ply
  23. void save_rgb_points_to_ply( ob_frame* frame, const char* fileName ) {
  24. int pointsSize = ob_frame_data_size( frame, &error ) / sizeof( ob_color_point );
  25. check_error( error );
  26. FILE* fp = fopen( fileName, "wb+" );
  27. fprintf( fp, "ply\n" );
  28. fprintf( fp, "format ascii 1.0\n" );
  29. fprintf( fp, "element vertex %d\n", pointsSize );
  30. fprintf( fp, "property float x\n" );
  31. fprintf( fp, "property float y\n" );
  32. fprintf( fp, "property float z\n" );
  33. fprintf( fp, "property uchar red\n" );
  34. fprintf( fp, "property uchar green\n" );
  35. fprintf( fp, "property uchar blue\n" );
  36. fprintf( fp, "end_header\n" );
  37. ob_color_point* point = ( ob_color_point* )ob_frame_data( frame, &error );
  38. check_error( error );
  39. for ( int i = 0; i < pointsSize; i++ ) {
  40. fprintf( fp, "%.3f %.3f %.3f %d %d %d\n", point->x, point->y, point->z, ( int )point->r, ( int )point->g, ( int )point->b );
  41. point++;
  42. }
  43. fflush( fp );
  44. fclose( fp );
  45. }
创建Pipeline及流配置
  1. //创建pipeline 用于连接设备后打开Color和Depth流
  2. pipeline = ob_create_pipeline( &error );
  3. //创建config,用于配置 Color 和 Depth 流的 分辨率、帧率、格式
  4. ob_config* config = ob_create_config( &error );
  5. //配置Depth流
  6. ob_stream_profile * depth_profile = NULL;
  7. ob_stream_profile_list *profiles = ob_pipeline_get_stream_profile_list(pipeline, OB_SENSOR_DEPTH, &error);
  8. //根据指定的格式查找对应的Profile,优先查找Y16格式
  9. depth_profile = ob_stream_profile_list_get_video_stream_profile(profiles, 640, 0, OB_FORMAT_Y16, 30, &error);
  10. //没找到Y16格式后不匹配格式查找对应的Profile进行开流
  11. if(error){
  12. depth_profile = ob_stream_profile_list_get_video_stream_profile(profiles, 640, 0, OB_FORMAT_UNKNOWN, 30, &error);
  13. error = NULL;
  14. }
  15. //配置Color流
  16. ob_stream_profile *color_profile = NULL;
  17. profiles = ob_pipeline_get_stream_profile_list(pipeline, OB_SENSOR_COLOR, &error);
  18. if(error){
  19. printf("Current device is not support color sensor!\n");
  20. //如果不存在Color Sensor 点云转换分辨率配置为深度分辨率
  21. ob_config_set_d2c_target_resolution(config,ob_video_stream_profile_width(depth_profile, &error),ob_video_stream_profile_height(depth_profile, &error),&error);
  22. ob_config_set_depth_scale_require(config,false,&error);
  23. error = NULL;
  24. }
  25. //根据指定的格式查找对应的Profile,优先选择RGB888格式
  26. if(profiles){
  27. color_profile = ob_stream_profile_list_get_video_stream_profile(profiles, 640, 0, OB_FORMAT_RGB, 30, &error);
  28. }
  29. //没找到RGB888格式后不匹配格式查找对应的Profile进行开流
  30. if(profiles && error){
  31. color_profile = ob_stream_profile_list_get_video_stream_profile(profiles, 640, 0, OB_FORMAT_UNKNOWN, 30, &error);
  32. error = NULL;
  33. }
  34. ob_config_enable_stream( config, color_profile, &error ); // 使能配置
从Pipeline上获取当前打开的设备,用以打开设备D2C功能
  1. //获取device句柄
  2. ob_device *device = ob_pipeline_get_device(pipeline, &error);
  3. // 开启D2C对齐, 生成RGBD点云时需要开启
  4. ob_config_set_align_mode(config,ALIGN_D2C_HW_MODE,&error);
开流,并在开流后创建点云filter。点云filter用于将depth和color帧数据转换成点云数据。点云filter在开流后创建目的是让SDK内部自动根据当前开流配置设置好相机参数。当然也可以自行设置。
  1. //创建点云Filter对象(点云Filter创建时会在Pipeline内部获取设备参数, 所以尽量在Filter创建前配置好设备)
  2. ob_filter *point_cloud = ob_create_pointcloud_filter(&error);
  3. //从pipeline获取当前开流的相机参数,并传入到点云filter
  4. ob_camera_param camera_param = ob_pipeline_get_camera_param(pipeline, &error);
  5. ob_pointcloud_filter_set_camera_param(point_cloud, camera_param, &error);
启动主循环,循环内根据用户按键调用点云filter生成深度点云或RGBD点云数据,并保存成ply文件。
  1. //等待一帧数据,超时时间为100ms
  2. ob_frame* frameset = ob_pipeline_wait_for_frames( pipeline, 100, &error );
  3. if ( frameset != NULL )
  4. {
  5. //按R键保存ply数据
  6. if ( ( key == 'R' || key == 'r' ) && frameset != NULL ) {
  7. ob_pointcloud_filter_set_point_format( point_cloud, OB_FORMAT_RGB_POINT, &error );
  8. ob_frame *pointsFrame = ob_filter_process(point_cloud, frameset, &error);
  9. save_rgb_points_to_ply( pointsFrame, "rgb_points.ply" );
  10. ob_delete_frame( pointsFrame, &error );
  11. }
  12. else if ( ( key == 'D' || key == 'd' ) && frameset != NULL ) {
  13. //生成点云并保存
  14. ob_pointcloud_filter_set_point_format( point_cloud, OB_FORMAT_POINT, &error );
  15. ob_frame *pointsFrame = ob_filter_process(point_cloud, frameset, &error);
  16. save_points_to_ply( pointsFrame, "points.ply" );
  17. ob_delete_frame( pointsFrame, &error );
  18. }
  19. ob_delete_frame( frameset, &error ); // 销毁frameSet 回收内存
  20. }
主循环退出后,停流并销毁回收资源
  1. // 停止pipeline
  2. ob_pipeline_stop( pipeline, &error );
  3. // 销毁pipeline
  4. ob_delete_pipeline( pipeline, &error );
  5. ob_delete_context( ctx, &error );