请参照我们的在线文档:http://doc.percipio.xyz/cam/last/apiguides/api_description.html
因为所有SDK都是基于C++代码,所以以C++为例:
一、官网下载SDK
下载链接:https://www.percipio.xyz/downloadcenter/
目前图漾SDK支持:Android、ROS、C#、Python、Windows、Halcon、Linux(ubuntu以及嵌入式开发)
图像类别:
深度图
输出的深度图是一个16bit位深的单通道矩阵,在SDK提供的sample程序中,输出的深度图均被映射到了RGB色彩空间,所以显示出来的结果为RGB三通道8bit位深的位图,深度数据无外参,无畸变,只能提供用于转换点云数据的内参。
IR图
IR图像为CMOS输出的红外图像,部分型号的相机在输出了深度图的同时输出IR图像之后,IR图像是会被相机系统处理过的图像,如果需要看原始的IR图像,需要关闭深度图输出,这个时候,激光器也会自动关闭,如果需要打开激光器,需在主动调用SDK API关闭激光器的自动控制功能,并且设置激光机强度,才能看到正常的红外点阵图像,IR图像分为左IR图和右IR图,二者均包含内参和畸变参数,但是因为左IR和深度图是同一个空间坐标系,所以左IR无外参。
RGB图像
percipio不同型号的相机提供输出不同数据类型的RGB图像,一类为正常的YUV422/JPG图像,经OPENCV处理之后,最终显示为RGB位图,另外一类RGB图像是基于RAW Sensor输出的原始bayer图像,SDK提供了软件ISP处理功能,最终显示为RGB位图,RGB图提供了内参,外参数,畸变参数。
二、SDK 应用参考
通过运行 SDK 开发包中的 lib/win/hostapp/x64 中可执行文件,或者运行 sample/build/bin/Release 目录下的可执行文件,可简单应用相机。
备注,Percipio 提供了在 SDK 基础上二次开发的看图软件 Percipio Viewer,支持用户快速浏览深度图、彩色图、红外图和点云图,以及在线调整相机的曝光参数、激光亮度等。 Percipio Viewer 安装包下载链接:https://www.percipio.xyz/downloadcenter。 使用说明请参见 Percipio Viewer 用户指南。
三、示例程序说明(C++SDK 自带sample,其他语言也会自带sample)
SDK中include目录下包含四个头文件:
TYApi.h:设备操作相关API接口,包含设备操作及设备相关参数读写控制等
-
TYCoordinateMapper.h:坐标系转换相关API接口:
1.基于相机像素坐标系和空间点云坐标系相互转换接口; 2.基于RGB外参的深度图和RGB图像坐标系相互转换接口; 3.基于RGB外参的点云坐标系转换接口;
-
TYImageProc.h:主要包含滤波和矫正处理的API接口:
1.TYUndistortImage:根据畸变参数矫正图像 2.TYDepthSpeckleFilter:过滤相机输出的原始深度图中的噪点 3.TYDepthEnhenceFilter:利用多帧以及双边滤波优化深度图数据 4.TyIsp.h:bayer输出的RGB图像软ISP处理相关的API接口,相关用法可以参考SDK中的sample代码SimpleView_FetchFrame
示例:
-
ListDevices
该示例程序用于枚举连接到上位机上的所有深度相机。
-
DumpAllFeatures
该示例程序用于枚举深度相机支持的各个组件和属性,以及各个属性支持的读写等信息。
-
ForceDeviceIP
该示例程序用于强制设置网络深度相机的 IP 地址。
-
LoopDetect
该示例程序用于处理因环境不稳定等因素造成的数据连接异常。
-
SimpleView_FetchFrame
该示例程序用于深度相机工作在自由采集模式下连续采集图像并输出图像数据。
-
SimpleView_Callback
该示例程序用于深度相机工作在自由采集模式下连续采集图像,在独立的数据处理线程(防止堵塞图像数据获取)中进行 OpenCV
渲染,并输出图像数据。 -
SimpleView_FetchHisto
该示例程序用于获取图像亮度数据直方图。
-
SimpleView_MultiDevice
该示例程序用于多台深度相机同时连续采集图像并输出图像数据。
-
SimpleView_Point3D
该示例程序用于获取 3D 点云数据。
-
SimpleView_Registration
该示例程序用于获取深度相机的内参、外参、深度图和彩色图,并将深度图和彩色图对齐。
-
SimpleView_TriggerDelay
该示例程序用于设置硬件触发延时时间,深度相机在接收到硬件触发信号并等待特定延时之后采集图像。
-
SimpleView_TriggerMode0
该示例程序用于设置深度相机工作在模式 0,相机连续采集图像并以最高帧率输出图像数据。
-
SimpleView_TriggerMode1
该示例程序用于设置深度相机工作在模式 1,相机收到软触发指令或硬触发信号后采集图像并输出图像数据。只有网络相机才有Resend,重传可以参考此样例
-
SimpleView_TriggerMode_M2S1
该示例程序用于设置主设备(相机)工作在模式 2,多台从设备(相机)工作在模式 1,以实现多台深度相机级联触发,同时采集图像。
主设备收到上位机发送的软件触发信号后,通过硬件 TRIGGER OUT
接口输出触发信号,同时触发自身采集并输出深度图;从设备收到主设备的硬件触发信号后,采集并输出深度图。 -
SimpleView_TriggerMode_M3S1
该示例程序用于设置主设备(相机)工作在模式 3,多台从设备(相机)工作在模式 1,以实现多台深度相机按照设置的帧率级联触发,同时采集图像。
主设备按照设置的帧率,通过硬件 TRIGGER OUT
接口输出触发信号,同时触发自身采集并输出深度图;从设备收到主设备的硬件触发信号后,采集并输出深度图。 -
SimpleView_TriggerMode18
该示例程序用于设置深度相机工作在模式 18,相机每接收到一次软触发指令或硬触发信号后,便按照设置的帧率,以 1+duty
的方式采集一轮图像并输出图像数据(1:出 1 次泛光;duty:出 duty 次激光)。 -
SimpleView_TriggerMode19
该示例程序用于设置深度相机工作在模式 19,相机接收到一次软触发或者硬触发信号后,便按照设置的帧率,以 1+duty
的方式连续采集图像并输出图像数据(1:出 1 次泛光;duty:出 duty 次激光)。 -
SimpleView_TriggerMode20
该示例程序用于设置深度相机工作在模式
20,根据设置的触发开始时间(start_time_us)、每两帧的时间间隔数组(offset_us_list[
])和触发次数(offset_us_count),相机定时采集(1 +offset_us_count)帧图像并输出图像数据。启用此⼯作模式要求相机先启动 PTP 对时,且 offset_us_count ≤ 50。 -
SimpleView_TriggerMode21
该示例程序用于设置深度相机工作在模式
21,根据设置的触发开始时间(start_time_us)、触发次数(trigger_count)和触发时间间隔(peroid_us),相机每间隔
peroid_us 采集⼀帧图像,共采集 trigger_count 帧图像并输出图像数据。此工作模式要求相机先启动 PTP 对时。
过滤和填洞、相机相关的属性设置
https://gitee.com/jiyuchen/percipio_-sample.git
网络相机重连示例:
链接:https://pan.baidu.com/s/1S6kKWrROdRpzT1yTqCSSGQ
提取码:efbd
链接:https://pan.baidu.com/s/1fA0162i6CEs2JpjsrMzGEw
提取码:dd7f
–来自百度网盘超级会员V2的分享
RGB_DEPTH异步取图示例 :
链接:https://pan.baidu.com/s/1oUVaJtInaeN6foyvmhMYNg
提取码:sy1c
四、开发流程(其他语言可参考)
下面以 SDK 示例程序 Simpleview_FetchFrame 为例详细说明图像获取流程。
初始化API
TYInitLib 初始化设备对象等数据结构。
打开设备
获取设备列表
初次获取设备信息时可以通过 selectDevice() 查询已连接的设备数量,并获得所有已连接的设备列表。 |
---|
打开接口
TYOpenInterface 打开接口。 |
---|
打开设备
TYOpenDevice 打开设备。
TYOpenDeviceWithIP 打开网络设备。
配置组件
查询设备的组件状态
TYGetComponentIDs 获取设备支持的组件信息。
TYGetEnabledComponents 获取已经打开的组件信息。
配置组件
TYEnableComponents 使能组件。
TYDisableComponents 关闭组件。
设备打开后,默认只有虚拟组件 TY_COMPONENT_DEVICE 是使能状态。多个组件可以通过 位或 方式同时使能。
int32_t componentIDs = TY_COMPONENT_DEPTH_CAM | TY_COMPONENT_RGB_CAM; TYEnableComponents(hDevice, componentIDs);
配置属性
查询指定属性的信息:
TYGetFeatureInfo() 通过填充结构体 TY_FEATURE_INFO 来获取指定组件的指定属性的信息。如果指定组件不包含所指定的属性,则 TY_FEATURE_INFO 中 isValid 值为 false;如果该组件包含所指定的参数,则 TY_FEATURE_INFO 中 isValid 值为 true。也可以通过 TYGetIntRange 等具体参数类型的 API 接口查询指定功能参数的信息。
- 常用读写属性函数如下:
- TYGetIntRange
- TYGetInt
- TYSetInt
- TYGetFloatRange
- TYGetFloat
- TYSetFloat
- TYGetEnumEntryCount
- TYGetEnumEntryInfo
- TYGetEnum
- TYSetEnum
- TYGetBool
- TYSetBool
- TYGetStringLength
- TYGetString
- TYSetString
- TYGetStruct
- TYSetStruct
示例:
调用 TYSetEnum() 设置深度图像传感器输出数据的格式和分辨率:
LOGD(“=== Configure feature, set resolution to 640x480.”); ASSERT_OK(TYSetEnum(hDevice, TY_COMPONENT_DEPTH_CAM, TY_ENUM_IMAGE_MODE, TY_IMAGE_MODE_DEPTH16_640x480));
设置RGBD异步:
ASSERT_OK(TYSetEnum(hDevice, TY_COMPONENT_DEVICE, TY_ENUM_STREAM_ASYNC, TY_STREAM_ASYNC_DEPTH_RGB));
设置相机同步上本地电脑时间:
LOGD("Set type of time sync mechanism");
ASSERT_OK(TYSetEnum(hDevice, TY_COMPONENT_DEVICE, TY_ENUM_TIME_SYNC_TYPE, TY_TIME_SYNC_TYPE_HOST));
LOGD("Wait for time sync ready");
while (1) {
bool sync_ready;
ASSERT_OK(TYGetBool(hDevice, TY_COMPONENT_DEVICE, TY_BOOL_TIME_SYNC_READY, &sync_ready));
if (sync_ready) {
break;
}
MSLEEP(10);
}
设置重传(只针对网络相机)
//for network only
LOGD("=== resend: %d", resend);
if (resend) {
bool hasResend;
ASSERT_OK(TYHasFeature(hDevice, TY_COMPONENT_DEVICE, TY_BOOL_GVSP_RESEND, &hasResend));
if (hasResend) {
LOGD("=== Open resend");
ASSERT_OK(TYSetBool(hDevice, TY_COMPONENT_DEVICE, TY_BOOL_GVSP_RESEND, true));
} else {
LOGD("=== Not support feature TY_BOOL_GVSP_RESEND");
}
}
坐标转换
相关坐标和图像转换都在:include文件夹下 TYCoordinateMapper.h
CPU加速关闭
用这个函数,sdk 库初始化之前使用,参数false关闭cpu加速,对齐CPU占用率会降低
帧缓冲管理:
调用 API 查询当前配置下每个帧缓冲的大小。
uint32_t frameSize; ASSERT_OK( TYGetFrameBufferSize(hDevice, &frameSize) ); LOGD(" - Get size of framebuffer, %d", frameSize);
分配深度数据存储空间。
按照实际查询函数返回的帧缓冲的大小分配两组 frameBuffer 空间,并传递给底层驱动缓冲队列,作为数据获取的通道。
驱动内部维护一个缓冲队列(frameBuffer Queue),每帧数据传出时会将填充好的 frameBuffer 作 Dequeue 操作,并完全传出给用户使用。用户完成该帧图像数据处理后,需做 Enqueue 动作以返还该 frameBuffer 给驱动层缓冲队列。用户需要保证新的一帧数据到来时驱动的缓冲队列不为空,否则该帧数据将被丢弃。
LOGD(" - Allocate & enqueue buffers"); char* frameBuffer[2]; frameBuffer[0] = new char[frameSize]; frameBuffer[1] = new char[frameSize]; LOGD(" - Enqueue buffer (%p, %d)“, frameBuffer[0], frameSize); ASSERT_OK( TYEnqueueBuffer(hDevice, frameBuffer[0], frameSize) ); LOGD(” - Enqueue buffer (%p, %d)", frameBuffer[1], frameSize); ASSERT_OK( TYEnqueueBuffer(hDevice, frameBuffer[1], frameSize) );
回调函数注册
TYRegisterEventCallback
使用回调函数的方式获取图像数据时,需要注册该函数,当图像数据到达后,该回调函数会主动被执行。在使用主动获取图像模式时,需要调用该函数注册回调函数为 NULL。
LOGD(“Register event callback”); ASSERT_OK(TYRegisterEventCallback(hDevice, eventCallback, NULL))
配置工作模式
根据实际需要配置深度相机工作模式,详情请参考 工作模式配置。
启动深度采集
TYStartCapture
如果深度相机工作在模式 1 下,可以使用软件触发接口函数 TYSendSoftTrigger(),通过 USB 接口或者以太网接口发送指令,控制相机图像采集的时机。
获取帧数据
TYFetchFrame
主动获取深度数据模式下,应用可调用该接口获取深度数据。注意回调函数模式下不需要调用。获取数据后,用户程序进行运算处理时,应采用独立线程,避免堵塞图像获取线程的运转。
停止采集
TYStopCapture 停止图像数据采集,相机停止深度数据计算和输出。
关闭设备
TYCloseDevice 关闭设备,TYCloseInterface 释放占用的接口。
释放API
TYDeinitLib 释放 API 后,需要释放分配的内存资源,避免内存泄露。
五、SDK Sample代码流程详解
参照链接在线文档:camke编译不同版本的SDK这里不再赘述,链接
5.1 详解SGBM算法
在线文档链接:https://doc.percipio.xyz/cam/last/apiguides/api_description.html#sgbm
受相机算力影响,IMAGE_NUM 和 MATCH_WIN_HEIGHT 之间存在一个约束: ( IMAGE_NUM + 1 ) / 2 *
MATCH_WIN_HEIGHT < 48
与测距范围、精度、帧率相关
TY_FLOAT_SCALE_UNIT = 0x010a | TY_FEATURE_FLOAT
设置深度图中像素值的单位。
深度数据可表示的最大值 = 65536 * TY_FLOAT_SCALE_UNIT。
设定值会影响到最终的深度计算结果。若设定值过小,可能会导致深度计算出现误差。若设定值过大,可能会降低深度计算的精度。
TY_INT_SGBM_DISPARITY_NUM = 0x0611 | TY_FEATURE_INT
设置视差搜索范围。匹配窗口在搜索过程中的视差搜索范围,整型属性。
设定值越大,相机Z方向的测量范围越大,算力会增加。建议设置成 16 的整数倍。
TY_INT_SGBM_DISPARITY_OFFSET = 0x0612 | TY_FEATURE_INT
设置开始搜索的视差值。整型属性。
设定值越小,Z方向最大测量值(Zmax)越大,即测量范围越远,但设定值下限受景深影响。
TY_INT_SGBM_IMAGE_NUM = 0x0610 | TY_FEATURE_INT
设置用于深度计算的 IR 图像数量。整型属性。
设定值越大,输出深度图像质量越好,帧率越小。设定值上限受相机算力影响。
TY_INT_SGBM_MATCH_WIN_HEIGHT = 0x0613 | TY_FEATURE_INT
设置视差匹配窗口的高。整型属性。设定值必须为奇数。
TY_INT_SGBM_MATCH_WIN_WIDTH = 0x061A | TY_FEATURE_INT
设置视差匹配窗口的宽。整型属性。设定值必须为奇数。
视差匹配窗口(MATCH_WIN_HEIGHT * MATCH_WIN_WIDTH)越大,深度图更加平滑,但是精度会降低。视差匹配窗口越小,深度图显示更多细节,但是出现错误匹配的几率越大。
与图像中边缘像素平滑处理相关
TY_INT_SGBM_SEMI_PARAM_P1 = 0x0614 | TY_FEATURE_INT
相邻像素 (+/-1) 约束惩罚参数 P1。
设定值越大,深度图越平滑。
防止出现不连续或不合理的深度值,有效抑制噪声和不连续性。
TY_INT_SGBM_SEMI_PARAM_P2 = 0x0615 | TY_FEATURE_INT
周围像素约束惩罚参数 P2。
设定值越大,深度图越平滑。P2 > P1。
该参数可以有效地处理纹理丰富区域,减少误匹配的数量。
TY_INT_SGBM_SEMI_PARAM_P1_SCALE = 0x061F | TY_FEATURE_INT
相邻像素 (+/-1) 约束惩罚参数 P1_scale,值越小越平滑。
TY_BOOL_SGBM_HFILTER_HALF_WIN = 0x0619 | TY_FEATURE_BOOL
半搜索滤波开关。
用于进一步优化深度图,去除噪声和不连续性,对物体边缘点云更友好。
与误匹配相关
TY_INT_SGBM_UNIQUE_FACTOR = 0x0616 | TY_FEATURE_INT
唯一性检查参数 1,即最优与次优匹配点的百分比。
设定值越大,匹配代价越唯一,值越大错误匹配点过滤掉的越多。
TY_INT_SGBM_UNIQUE_ABSDIFF = 0x0617 | TY_FEATURE_INT
唯一性检查参数 2,即最优与次优匹配点的差值。
设定值越大,匹配代价越唯一,值越大错误匹配点过滤掉的越多。
TY_BOOL_SGBM_LRC = 0x061C | TY_FEATURE_BOOL
左右一致性检查开关。
TY_INT_SGBM_LRC_DIFF = 0x061D | TY_FEATURE_INT
左右一致性检查参数。
在进行立体匹配时,对于同一物体表面上的像素,左图匹配右图的视差为 LR,右图匹配左图的视差为 RL。当 ABS(LR-RL) > max LRC diff 时,则认为该点是可信匹配点。
左右一致性检查参数设定值越小,匹配越可靠。
中值滤波
TY_BOOL_SGBM_MEDFILTER = 0x061B | TY_FEATURE_BOOL
中值滤波开关。
用于消除孤立的噪声点,同时尽可能地保留图像的边缘信息。
TY_INT_SGBM_MEDFILTER_THRESH = 0x061E | TY_FEATURE_INT
中值滤波阈值。
设定值越大,过滤的噪点越多,但也可能会导致深度图的细节信息丢失。
5.2 TOF属性
1.1、图像质量设置
TY_ENUM_DEPTH_QUALITY = 0x0900 | TY_FEATURE_ENUM,
设置 ToF 深度相机输出的深度图质量。枚举型属性,定义如下:
typedef enum TY_DEPTH_QUALITY_LIST
{
TY_DEPTH_QUALITY_BASIC = 1,
TY_DEPTH_QUALITY_MEDIUM = 2,
TY_DEPTH_QUALITY_HIGH = 4,
}TY_DEPTH_QUALITY_LIST;
深度图质量设置为 BASIC 时,深度值抖动幅度大,输出帧率高。
深度图质量设置为 MEDIUM 时,深度值抖动幅度中等,输出帧率中等。
深度图质量设置为 HIGH 时,深度值抖动幅度小,输出帧率低。
1.2、飞点滤波设置
TY_INT_FILTER_THRESHOLD = 0x0901 | TY_FEATURE_INT,
ToF 深度相机飞点滤波阈值。整型属性,范围 [0,100]。默认值为 0,即不加滤波。滤波阈值设置越小,过滤的飞点越多。
滤波阈值设置过小,可能会把大量有效深度信息过滤掉。
//示例:将 ToF 深度相机飞点滤波阈值设置为 43。
ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_DEPTH_CAM, TY_INT_FILTER_THRESHOLD, 43));
1.3、调制频道设置
TY_INT_TOF_CHANNEL = 0x0902 | TY_FEATURE_INT,
ToF 深度相机调制频道。整型属性。不同调制频道的调制频率不同,互不干扰。如需在同一场景运行多台 ToF 深度相机,首先需确保同系列相机的调制频道不同。
示例:将 ToF 深度相机调制频道设置为 2。
ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_DEPTH_CAM, TY_INT_TOF_CHANNEL, 2));
1.4、激光调制光强设置
TY_INT_TOF_MODULATION_THRESHOLD = 0x0903 | TY_FEATURE_INT,
ToF 深度相机接收激光调制光强的阈值,整型属性。小于此阈值的像素点不参与计算深度,即像素点的深度值赋值为 0。
示例:将 ToF 深度相机接收激光调制光强的阈值设置为 300。
ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_DEPTH_CAM, TY_INT_TOF_MODULATION_THRESHOLD, 300));
1.5、抖动过滤设置
TY_INT_TOF_JITTER_THRESHOLD = 0x0307 | TY_FEATURE_INT,
ToF 深度相机抖动过滤阈值。整型属性。阈值设置值越大,深度图边缘抖动的深度数据过滤得越少。
示例:将 ToF 深度相机抖动过滤阈值设置为 5。
ASSERT_OK(TYSetInt(hDevice, TY_COMPONENT_DEPTH_CAM, TY_INT_TOF_JITTER_THRESHOLD, 5));
六、相机内外参数
SDK中定义了一个结构:TY_CAMERA_CALIB_INFO,该结构内包含了相机出厂前标定好的标定尺寸,内参,外参,畸变参数,SDK API利用相关参数进行相关处理的时候都是使用这个结构的,可以通过使用API:TYGetStruct读取的该结构,需要注意的是,该标定参数和当前相机实际输出分辨率下的参数并不一致,SDK提供的相关API都会在内部根据实际图像分辨率自动调整参数来进行相关处理。
1、内参:用于空间坐标系与相机像素坐标系转换,该参数为3x3矩阵:
Fx 0 Cx
0 Fy Cy
0 0 1
Fx:归一化横向焦距
Fy:归一化纵向焦距
Cx:像素坐标系横向中心位置
Cy:像素坐标系纵向中心位置
2、外参:用于不同空间坐标系之间的转换,该矩阵为4x4矩阵:
R11 R12 R13 T1
R21 R22 R23 T2
R31 R32 R33 T3
0 0 0 1
该参数用于初始坐标系中的坐标点向新的坐标系转换
R11 R12 R13 T1分别为x在新的坐标系中x y z三轴的旋转系数及偏移量
R21 R22 R23 T2分别为y在新的坐标系中x y z三轴的旋转系数及偏移量
R31 R32 R33 T3分别为z在新的坐标系中x y z三轴的旋转系数及偏移量
3、畸变参数:用于修正图像畸变
一般双目相机只需要矫正RGB畸变,TOF相机需要对深度图矫正畸变(详见对齐或者点云实例)
畸变参数包含多个畸变因素的参数,参见SDK头文件定义:
typedef struct TY_CAMERA_DISTORTION
{
float data[12];///<Definition is compatible with opencv3.0+ :k1,k2,p1,p2,k3,k4,k5,k6,s1,s2,s3,s4
}TY_CAMERA_DISTORTION;
1.k1 k2 k3 k4 k5 k6是基于理想模型的径向畸变系数
2.p1 p2 为切向畸变系数
3.s1 s2 s3 s4 为薄棱镜畸变系数
SDK中提供了利用该参数进行图像畸变矫正的API接口:
TY_CAPI TYUndistortImage (const TY_CAMERA_CALIB_INFO *srcCalibInfo
, const TY_IMAGE_DATA *srcImage
, const TY_CAMERA_INTRINSIC *cameraNewIntrinsic
, TY_IMAGE_DATA *dstImage
);
SDK中定义了一个结构:TY_CAMERA_CALIB_INFO,该结构内包含了相机出厂前标定好的标定尺寸,内参,外参,畸变参数,SDK API利用相关参数进行相关处理的时候都是使用这个结构的,可以通过使用API:TYGetStruct读取的该结构,需要注意的是,该标定参数和当前相机实际输出分辨率下的参数并不一致,SDK提供的相关API都会在内部根据实际图像分辨率自动调整参数来进行相关处理。
六、对齐和坐标转换
1、对齐
参考示例:SimpleView_Registration
该示例程序用于获取深度相机的内参、外参、深度图和彩色图,并将深度图和彩色图对齐。
对齐方式:RGBToDepth 和DepthToRGB,
一般用到深度学习 ,建议深度对应到彩色(DepthToRGB),这个会产生一个和RGB对齐的DEPTH,后面会用到新的DEPTH去取数据和转点云
// 定义一个函数 doRgbRegister(),实现对齐功能,下面是我们doRgbRegister代码:
static void doRegister(const TY_CAMERA_CALIB_INFO& depth_calib
, const TY_CAMERA_CALIB_INFO& color_calib
, const cv::Mat& depth
, const float f_scale_unit
, const cv::Mat& color
, bool needUndistort
, cv::Mat& undistort_color
, cv::Mat& out
, bool map_depth_to_color
)
{
// do undistortion
if (needUndistort) {
TY_IMAGE_DATA src;
src.width = color.cols;
src.height = color.rows;
src.size = color.size().area() * 3;
src.pixelFormat = TY_PIXEL_FORMAT_RGB;
src.buffer = color.data;
undistort_color = cv::Mat(color.size(), CV_8UC3);
TY_IMAGE_DATA dst;
dst.width = color.cols;
dst.height = color.rows;
dst.size = undistort_color.size().area() * 3;
dst.buffer = undistort_color.data;
dst.pixelFormat = TY_PIXEL_FORMAT_RGB;
ASSERT_OK(TYUndistortImage(&color_calib, &src, NULL, &dst));
}
else {
undistort_color = color;
}
// do register
if (map_depth_to_color) {
out = cv::Mat::zeros(undistort_color.size(), CV_16U);
ASSERT_OK(
TYMapDepthImageToColorCoordinate(
&depth_calib,
depth.cols, depth.rows, depth.ptr<uint16_t>(),
&color_calib,
out.cols, out.rows, out.ptr<uint16_t>(), f_scale_unit
)
);
cv::Mat temp;
//you may want to use median filter to fill holes in projected depth image
//or do something else here
cv::medianBlur(out, temp, 5);
out = temp;
}
else {
out = cv::Mat::zeros(depth.size(), CV_8UC3);
ASSERT_OK(
TYMapRGBImageToDepthCoordinate(
&depth_calib,
depth.cols, depth.rows, depth.ptr<uint16_t>(),
&color_calib,
undistort_color.cols, undistort_color.rows, undistort_color.ptr<uint8_t>(),
out.ptr<uint8_t>(), f_scale_unit
)
);
}
}
二、对齐后坐标准换
可以在TYCoordinateMapper.h文件可以找到相关像素和坐标的转换:
对齐之后RGBPix=DepthPix,经过这个函数TYMapDepthToPoint3d -》深度转点云坐标
三、其他坐标变换
参考链接:https://doc.percipio.xyz/cam/last/apiguides/api_description.html#id30
七、点云
1、参考示例(CMakeLists.txt中OPENGL_VIEW置成ON,或者编译手动选择ON)
SimpleView_Point3D
该示例程序用于获取 3D 点云数据
2、PCL生成彩色点云(仅供参考)
pcl::PointCloud<pcl::PointXYZRGB> cloud; // 生成的点云 cloud
pcl::PointXYZRGB point;
for (int m = 0; m < depth.rows; m++)
{
for (int n=0; n < depth.cols; n++)
{
point.x = p3d[(m*(depth.cols)+n)].x;
point.y = p3d[(m*(depth.cols)+n)].y;
point.z = p3d[(m*(depth.cols)+n)].z;
point.r = color_data_mat.at<cv::Vec3b>(m, n)[0];
point.g = color_data_mat.at<cv::Vec3b>(m, n)[1];
point.b =color_data_mat.at<cv::Vec3b>(m, n)[2];
cloud.points.push_back(point); // 构造xyzrgb类型点云
}
}
cloud.width = (uint32_t)cloud.points.size();
cloud.height = 1;
3、PCL显示点云(仅供参考)
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer1(new pcl::visualization::PCLVisualizer("3D Viewer"));
pcl::PointCloud<pcl::PointXYZRGB>::Ptr basic_cloud_ptr(new pcl::PointCloud<pcl::PointXYZRGB>);
basic_cloud_ptr = cloud.makeShared(); // 转换为指针格式 basic_cloud_ptr
basic_cloud_ptr->is_dense = false; // 自己创建的点云,默认为dense,需要修改属性,否则removenanfrompointcloud函数无效
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_ptr(new pcl::PointCloud<pcl::PointXYZRGB>);
std::vector<int> mapping;
pcl::removeNaNFromPointCloud(*basic_cloud_ptr, *cloud_ptr, mapping); // 移除无效点
viewer1->removeAllPointClouds(); // 移除当前所有点云
viewer1->addPointCloud<pcl::PointXYZRGB> (cloud_ptr, "initial");
viewer1->updatePointCloud(cloud_ptr, "initial");
viewer1->spinOnce(100);
4、保存点云参数和导入查看
我们提供相关点云,可以给予自己需要保存自己相应格式。可以用我们的percipio-view保存点云用CloudCompare查看点云细节。
八、常见问题:
1. 深度图通过外参转换到RGB的像素坐标系之后,如果需要使用内参转换到空间点云坐标系,调用相关API的时候使用的的参数应该改为RGB参数,而不是深度相机的参数。
2. SDK sample代码SimpleView_Registration中默认的设置演示的是RGB图像反向对齐到深度相机坐标系,但是因为深度图上会有失效点,所以这些位置无法对应到RGB坐标系上面去,因此演示的对齐之后的RGB图像会是不完整的,如果要保证RGB图像的完整性,可以将代码中的宏MAP_DEPTH_TO_COLOR置为1,将深度图转换到RGB坐标系中去,这样就能得要一个转换了坐标系的深度图和矫正畸变之后完整的RGB图像。
3. Sample代码中,以SimpleView_FetchFrame为例,默认是将RGB/IR/Depth输出全部打开的,在这种情况下,设备输出的数据量会非常大,USB/网络带宽会将预览的帧率拉到很低,验证深度图的输出帧率的时候,可以将IR/RGB输出全部关闭。
4. Sample代码中显示深度图的代码会将深度图映射到RGB色彩空间,该函数对CPU的消耗比较大,特别是在debug模式下,将会对帧率影响非常大。
5. Sample代码中预览的时候调用的函数get_fps可以统计系统实时运行程序时候的帧率,相关代码可以查看文件common.hpp,将变量kMaxCounter的值改小一些可以提高帧率显示的频率。
6. Sample代码中的SimpleView_Point3D在使用cmake生成项目的时候默认是不会编译的,需要将CMakeLists.txt文件中的OPENGL_VIEW置成ON,然后使用Cmake才能生成对应的项目,另外该示例代码依赖于opengl模块,请确认系统中已经配置好了opengl。
7. 对于Sample代码中的SimpleView_Point3D,需要注意的是在代码中将深度图转化成点云之后,增加了y和z坐标的取反操作,这在代码及数据处理中并不是必要的,在这里仅仅是为了在3D视窗中显示的时候提前做一次镜像,让显示视窗看起来“更正常一点”。
8. 相机输出的深度图,最好调用一次喊出TYDepthSpeckleFilter,进行一次滤波,特别是网口相机,基于精度更好的算法,深度数据中的边沿会有一些脏点,需要经过这个函数进行滤波,让深度数据更干净一些。
9. 滤波函数TYDepthEnhenceFilter只做了3D滤波和双边滤波,
函数参数中虽然有导向滤波的指针参数,但是需要设置成NULL,代码里面目前并没有实现此滤波功能。文章来源:https://www.toymoban.com/news/detail-727337.html
10. 关于相机连接上的一些问题:
a) USB相机使用的USB线应该严格按照USB工业标准线长进行限制:USB2.0不能超过5米,USB3.0不能超过2米,否则会因为线长过长
的信号衰减以及电磁干扰等原因导致SDK无法打开相机或者无法通过SDK获取图像数据。
b) 网口相机需要保证相机和上位机在同一个网段,相机本身默认支持DHCP自动获取IP地址,在通过路由器网络系统的时候,保证PC也是通过路由器自动获取IP,这样二者就可以保持在同一个网段了,但是如果相机和PC是通过交换机直连的话,在windows系统下,上位机和相机都可以通过自动获取IP得到一个私网IP地址,这样二者就可以联通,但是在linux下,默认系统是无法自动获取IP的,这时需要手动设置Linux系统的IP地址,然后通过SDK的sample程序中的ForceDevicesIP强制设置相机的IP,并且和上位机IP为同一个IP网段。
11、如何更改分辨率:
SimpleView_FetchFrame例程中
查看Get_default_image_mode函数的实现方式。
如果直接设置,请确认相机的图片类型和支持的分辨率(看图软件和sample例程属性可查询)文章来源地址https://www.toymoban.com/news/detail-727337.html
//彩色图:
//看图软件查看其相机支持的图片类型和分辨率
ASSERT_OK(TYSetEnum(hDevice, TY_COMPONENT_RGB_CAM_LEFT, TY_ENUM_IMAGE_MODE, TY_PIXEL_FORMAT_YUYV | TY_RESOLUTION_MODE_640x480));
//深度图:
//看图软件查看其相机支持的分辨率
ASSERT_OK(TYSetEnum(hDevice, TY_COMPONENT_DEPTH_CAM, TY_ENUM_IMAGE_MODE, TY_PIXEL_FORMAT_DEPTH16| TY_RESOLUTION_MODE_640x480));
到了这里,关于图漾相机-SDK开发流程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!