简介:深视智能SR系列3D相机SDK程序文件,面向工业视觉领域需要对该系列相机进行二次开发的工程师与集成商,解决SDK调用中不同数据采集模式的选型与实现问题。包内程序文件围绕SDK提供了四种典型模式说明:一次回调模式适合设定采集行数不超过15000行并一次性取回全部数据,是官方推荐的开发方式;阻塞模式在采集期间进程会等待直至数据完成;无限循环模式则固定时间返回数据,需及时取出控制器缓存,适用于大批量连续处理;2.5D模式返回单条轮廓,需在EdgeImaging软件中配合实时显示使用。压缩包整体为18.01MB的ZIP文件,内含模式介绍与示例程序,便于开发者对照说明快速测试。目前已有446人学习下载,对于需要快速上手SR系列相机二次开发的读者具有参考价值。
1. SR系列SDK:3D相机不是插上就能出点云
工业现场第一次拿到深视智能SR系列3D相机,不少工程师的第一反应是插上网线、打开IP扫描工具,等着点云画面自己弹出来。实际接上才会发现,这台设备更像一个没有操作界面的传感器:IP要自己配,曝光和激光功率要手调,点云要靠SDK接口一帧一帧取出来。
所谓SR系列3D相机SDK程序文件,就是随相机附带的整套开发套件——头文件、动态库、示例程序和文档,它决定拆箱到产出第一帧点云要花半天还是两周。
按落地顺序,后面依次拆文件结构、搭环境、连接配置、取点云,最后补排错细节,适合评估视觉方案或还没跑通取流的人。
2. SR系列SDK程序文件目录结构与开发环境搭建
2.1 解开SDK压缩包后,先认目录骨架
深视智能SR系列相机的SDK程序文件,交付时是一个压缩包,解开后通常是这样的骨架:
SR_SDK/ ├── include/ # C/C++头文件 │ ├── SRCamera.h # 主接口声明 │ ├── SRTypes.h # 点云/帧数据结构 │ └── SRErrorCode.h # 错误码定义 ├── lib/ │ ├── x64/ # 64位运行库 │ │ ├── SRCamera.lib │ │ └── SRCamera.dll │ └── x86/ # 32位运行库 ├── sample/ │ ├── Cpp/ │ │ ├── EnumCamera/ # 枚举相机示例 │ │ ├── GrabPointCloud/ # 点云取流示例 │ │ └── SetParam/ # 参数配置示例 │ └── CSharp/ # C#版示例 ├── doc/ │ ├── SDK开发手册.pdf │ └── 参数说明表.xlsx └── driver/ └── GigE相机驱动安装包.exe拿到包第一步不是急着编译,而是确认三件事。第一,程序位数和lib目录要一致,x64工程引用x86的lib,链接阶段会报一堆无法解析的外部符号,这不是SDK版本问题。第二,网卡驱动要先装好,SR系列走GigE Vision协议,驱动不对时枚举结果里只见网卡不见相机,这个表象最容易误导排查方向。第三,doc目录里的参数说明表要原样留好,后面调曝光和激光功率全靠它,只翻开发手册的接口列表会漏掉不少参数边界。
2.2 环境变量与工程引用配置
我一般把SDK放在固定路径D:\SDK\SR_SDK,然后把lib\x64加进系统PATH。这一步很多人忽略:编译能过,运行时提示找不到SRCamera.dll,多半就是PATH里没有动态库路径,或者dll没跟着exe一起发布。验证SDK程序文件是否完整,最快的方式是新建一个空工程,只调SRSystemInit和SRSystemShutdown,能编译能运行,说明头文件、lib、dll三条链路都通了。
| 环境变量 | 示例值 | 作用 |
|---|---|---|
| SR_SDK_HOME | D:\SDK\SR_SDK | SDK根目录,工程里按宏引用 |
| PATH | %SR_SDK_HOME%\lib\x64 | 运行时定位SRCamera.dll |
| LD_LIBRARY_PATH | $SR_SDK_HOME/lib/x64 | Linux下动态库搜索路径 |
Linux下还需要确认底层依赖。GigE相机在Linux侧的SDK通常依赖libpcap做报文捕获,缺了pcap库,表现是枚举阶段能看到网卡,但点云数据始终不来。装好依赖后用ldd SRCamera.so检查所有依赖是否解析到具体路径,再进入下一步开发。
2.3 用CMake把示例工程跑起来
SDK自带的sample目录里一般有CMakeLists.txt,用CMake生成工程,比手动在Visual Studio里加include和lib路径更不容易出错,换机器换SDK版本时只需改环境变量。核心配置是这样:
cmake_minimum_required(VERSION 3.10) project(SR_Grab_Demo) set(SR_SDK_HOME "$ENV{SR_SDK_HOME}") include_directories(${SR_SDK_HOME}/include) link_directories(${SR_SDK_HOME}/lib/x64) add_executable(grab_demo src/main.cpp) target_link_libraries(grab_demo SRCamera)这里include_directories解决头文件搜索,link_directories解决lib定位,target_link_libraries把SRCamera库挂到可执行文件上。CMake生成VS工程或Makefile后,编译完把SRCamera.dll复制到exe同目录,或确保PATH包含lib/x64,这一步验证通过后,写业务代码就不会反复被链接错误打断。最常见的报错是LNK1104 cannot open file 'SRCamera.lib',不用重装SDK,检查link_directories路径和lib文件名拼写即可。C#工程则是在项目里引用C#封装dll,且项目属性里显式指定x64平台,AnyCPU在64位机上有时会踩互操作位数不一致的坑。
3. 用SR系列SDK连接相机并调好关键成像参数
3.1 枚举相机:先解决“找不到设备”
SR系列相机的连接流程和主流GigE工业相机一致:先初始化SDK,再枚举设备列表,最后按IP打开。示例代码核心流程如下:
#include "SRCamera.h" SRSystemInit(); // 初始化SDK全局资源,进程内只调一次 SRCameraInfo infoList[16]; int count = 0; SREnumCamera(infoList, &count); // 枚举网段内所有SR相机 for (int i = 0; i < count; i++) { printf("index: %d, IP: %s, MAC: %s\n", i, infoList[i].ip, infoList[i].mac); } SRHandle handle = nullptr; SROpenCamera(infoList[0].ip, &handle); // 按IP打开第一台相机这段代码里,SRSystemInit负责初始化SDK内部资源和网络栈,必须在枚举前调用;SREnumCamera把发现结果写入传入的数组,count返回实际数量;SROpenCamera是阻塞调用,内部完成GigE协议的握手和参数同步。如果count为0,先别怀疑SDK有问题,依次确认:防火墙是否拦截了UDP组播,Windows默认防火墙经常拦掉GigE相机的发现报文;网卡IP和相机是否在同一网段,相机默认IP印在机身标签上;驱动是否安装成功,设备管理器里能看到相机设备才算数。现场最典型的坑是笔记本有线网卡和无线网卡同时启用,组播包走了错误的出口,导致枚举时有时无,临时禁用无线网卡是立竿见影的验证手段。
3.2 成像参数表:曝光、激光功率和触发模式
打开相机之后,参数设置集中在KV风格的接口上。SR系列是结构光方案,以下几个参数共同决定点云质量:
| 参数名 | 设置接口 | 作用 | 典型范围 |
|---|---|---|---|
| ExposureTime | SRSetParam(handle, "ExposureTime", 1000) | 感光时长,影响亮度与信噪比 | 500~3000 us |
| LaserPower | SRSetParam(handle, "LaserPower", 60) | 结构光投影亮度 | 40~90 (%) |
| Gain | SRSetParam(handle, "Gain", 6) | 信号放大倍数 | 0~18 dB |
| TriggerMode | SRSetParam(handle, "TriggerMode", 0) | 0内触发/1硬触发 | 0 / 1 |
| ROIWidth | SRSetParam(handle, "ROIWidth", 1280) | 行方向裁剪,影响帧率 | 0=全幅 |
提示:参数名在不同版本SDK里可能略有差异,以doc目录的参数说明表.xlsx为准。
C++侧统一走SRSetParam,Python版SDK保持同名参数,方便两边切换。调参顺序我是固定的:先把曝光固定到1000us,再逐步加激光功率,点云主体没有大面积过曝就停,最后才动增益。增益是最后手段,它在放大信号的同时把底噪一起放大,表面反光强的工件开高增益,点云边缘会冒出一圈毛刺。ExposureTime和LaserPower的组合还受环境光影响,产线如果靠窗,上午和下午的参数可能需要微调,成熟的方案会加遮光罩或滤光片,让参数一次调通长时间稳定。
3.3 硬触发与外部编码器同步
生产线上SR相机一般不用内触发,而是接光电传感器或编码器。硬触发模式下要确认两件事。一是信号极性,参数表里通常叫TriggerPolarity,默认高电平有效,有些PLC输出是低脉冲,不改极性会一直不触发。二是触发脉宽要大于相机手册标称的最小值,否则偶发丢帧,几百个OK里漏一帧,这种问题最难查,建议用示波器量一次实际脉宽。
切换硬触发之前,先用内触发把曝光和激光功率调通,再改触发方式,排查范围会小很多。编码器同步的场景还要注意触发的均匀性,步进电机加减速段的三轴点云间距不一致,后处理时按编码器位置重采样才能保证测量一致。触发相关的参数通常还有触发延时和去抖,去抖值设太大会吃掉短脉冲,设成0在有电气噪声的现场又会误触发,一般从500us起步逐次加大观察。
4. SR系列SDK点云获取与坐标变换实践
4.1 点云数据结构:一次取回Z、强度和坐标
SR系列SDK把点云封装成SRPointCloudFrame结构,取流接口通常长这样:
SRPointCloudFrame frame; while (bRunning) { SRGetFrame(handle, &frame, 1000); // 1000ms超时 // frame.width, frame.height: 点云宽高 // frame.pointData: SRPoint3f*, 每个点含 x/y/z // frame.intensityData: uint8_t*, 灰度强度 SRReleaseFrame(handle, &frame); // 归还帧缓冲, 必须调用 }拿到frame先检查z的有效性。SR系列在暗色吸光材料、镜面反射和遮挡区域会输出NaN,直接拿去算高度差,整个测量结果都被带偏。我的习惯是处理入口统一做一次无效点剔除,再进入测量算法。另外SRReleaseFrame这一步很多人漏掉,帧缓冲不归还,跑几分钟后取流超时,也是现场常见故障之一。intensityData这条通道往往被忽略,但在表面字符识别场景里,灰度图和点云做像素级对齐后能直接复用传统2D视觉算法,值得单独缓存一帧。
注意:SRReleaseFrame必须与SRGetFrame成对调用,否则帧缓冲耗尽会导致取流超时。
4.2 无效点剔除与Z阈值滤波
for (int i = 0; i < frame.width * frame.height; i++) { SRPoint3f &p = frame.pointData[i]; if (isnan(p.z) || p.z <= 0.0f) { continue; // 跳过无数据点 } if (p.z < zNear || p.z > zFar) { continue; // 按测量范围裁掉离群点 } // 进入后续的高度/轮廓计算 }zNear和zFar取自标定时设定的测量范围上下限,也可以根据实际工件的轮廓波动设一个宽松阈值。滤波参数不要写死在代码里,放到配置文件,现场换治具改配置比重编速度快得多。Python侧写法逻辑一样,只是把pointData换成numpy数组切片,批量操作更快:
xyz = frame.get_points() # (H, W, 3) 的 numpy 数组 valid = ~np.isnan(xyz[..., 2]) & (xyz[..., 2] > 0) valid &= (xyz[..., 2] > z_near) & (xyz[..., 2] < z_far) points = xyz[valid]注意get_points返回的数组默认是行主序,索引顺序是[row, col]。如果后续接PCL或Open3D,把点云拷贝出来时保留原始width和height信息,重建organized point cloud要用它恢复行列结构,直接用滤波后的散点列表会丢失邻接关系,影响法线估计和表面重建质量。
4.3 坐标系标定与点云转深度图
如果只做高度测量,直接用z分量就够;要做XY尺寸测量,得确认坐标原点。SR系列点云默认以相机光轴与测量基准面的交点为原点,要转换到机器人基座或传送带坐标系,走一步齐次变换矩阵左乘:
// 手眼标定得到的4x4变换矩阵, r是旋转分量, t是平移分量 cv::Mat T_cam_to_robot = (cv::Mat_<double>(4,4) << r00, r01, r02, tx, r10, r11, r12, ty, r20, r21, r22, tz, 0, 0, 0, 1);每个点补成齐次坐标后左乘这个矩阵即可。3D相机的标定和2D相机不一样,z方向误差受激光功率、表面反射率和环境光共同影响,标定样本要在实际生产节拍下采集,不要低速静态标完直接上产线。点云转深度图的标准做法是把x、y量化到整数像素索引,把z填入网格:
int col = (int)((p.x - xMin) / step); int row = (int)((p.y - yMin) / step); depthMap.at<float>(row, col) = p.z;深度图分辨率由step决定,step越小分辨率越高,但整图尺寸和计算耗时随之上升,一般按测量精度需求的1/3来取,精度0.1mm的场景取0.033mm就够。SR SDK示例里通常有参考实现,按float格式输出注意主机字节序,按uint16输出注意z的缩放系数,参数说明表里都能查到对应转换关系。别拿原始内存直接当深度图去显示,花屏了先从字节序和缩放系数查起。
5. 提升取流稳定性:缓冲、错误码与现场排错
5.1 帧缓冲不足导致“取流超时”
长时间跑取流,运行几分钟后SRGetFrame开始超时,不是相机死机,多数是主机端缓冲队列占满,应用层消费跟不上。SDK提供缓冲数量参数,典型设置是SRSetParam(handle, "BufferCount", 8),默认值往往只有4。内存够用时提高缓冲数量是最快的止血手段;根治还是要优化消费端处理速度,取流线程只负责拿帧,点云处理后移到独立工作线程。
5.2 常见错误码速查
现场排查先看错误码再动硬件,少走弯路:
| 错误码 | 含义 | 优先处理动作 |
|---|---|---|
| 0x1001 | 枚举无设备 | 查网卡驱动、IP网段、防火墙 |
| 0x1003 | 打开超时 | 确认相机未被其他进程占用 |
| 0x2005 | 帧数据不完整 | 查网线、交换机协商速率 |
| 0x3002 | 参数越界 | 对照参数说明表检查数值范围 |
网线是被忽略的重灾区。GigE相机对链路质量敏感,现场用普通百兆网线跑千兆链路,偶发丢包会以帧不完整的形式暴露。量产方案建议六类屏蔽网线直连,中间不要串家用交换机。
5.3 用帧率统计做最终验收
判断SDK程序文件是否真正跑通,光看一帧画面不够。在取流主线里统计一分钟平均帧率,SR系列在默认分辨率和参数下,内触发帧率稳定在标称值九成以上才算达标。低于这个数,优先检查曝光时间是否过长、ROI是否开得太大,这两个参数对帧率影响最直接。把帧率统计做成启动参数可开关的日志,验收和现场诊断都会省很多时间。最后留一个小技巧:把相机IP固定并写入配置文件,现场换相机不用重新扫描,连接耗时从秒级降到毫秒级,产线运维会感谢这个细节。
本文还有配套的精品资源,点击获取