
简介面向车牌识别应用开发的成都臻识相机 SDK 开发包基于 R3 版本集成最新算法与硬件调用优化适合需要对接臻识相机实现车牌捕获、识别与二次集成的开发者。压缩包共 14 个文件包含 5 个 C/C 头文件、3 个 so 动态库、1 个 chm 帮助文档、1 个 makefile、1 个示例程序及编译中间文件等整体约 865KB以精简的 API 和示例代码为主便于在嵌入式或 Linux 环境下快速构建识别流程。已有 2736 人学习下载。资料提供完整的 SDK 目录结构inc 头文件、doc 文档、demo 示例相互独立开发者可直接参考 userapp 与 cpp 示例了解初始化、抓图、识别等接口调用方式同时 chm 文档对错误码、参数配置和调试工具做了说明有助于排查曝光、白平衡等图像参数问题。对正在做停车场、出入口等车牌识别项目的工程师来说是一份轻量且可直接上手的开发参考资料。 做车牌识别或者智能安防这类项目的朋友应该对成都臻识这个牌子不陌生。最近整理资料翻出来一个他们家的相机开发包opensdk_r3_20210414.rar版本号 R3日期 2021 年 4 月 14 日。这个包在臻识的相机二次开发里算是比较经典的一个版本网上零零散散有人问但很少有人把它讲透。这篇博文就把我实际使用这个 SDK 的过程、踩过的坑、以及一些常规文档里不会写的细节全部摊开来讲。如果你正准备用臻识的相机做道闸车牌识别、停车场出入口、或是门禁访客系统这篇文章能帮你省下不少自己摸索的时间。1. 这个 SDK 是什么为什么值得用1.1 先弄清楚 OpenSDK 的定位臻识的相机自带完整的上位机软件比如他们官方的配套工具直接打开就能看画面、调参数、触发抓拍。但项目一旦要做集成比如把识别结果推到你的后台、联动道闸开闸、对接第三方平台就必须要通过 SDK 来开发。OpenSDK 就是这个桥梁。它把相机底层的视频流取流、车牌识别、IO 信号输出、串口通信这些能力封装成一套接口你拿到手之后不用关心相机内部是怎么处理的只要调用对应的方法就能获取结果。opensdk_r3_20210414.rar里的R3代表第三代 SDK这一代比较大的变化是稳定性和响应速度都有优化。我实测在同型号相机上R3 版本从触发到拿到识别结果的时间控制得更好对于需要快速抬杆放行的场景很重要。1.2 适合哪些场景和人群如果你属于下面这几类人这个 SDK 会比较对你的胃口做停车场管理系统的集成商需要把相机识别结果对接到自己的管理软件里做门禁或者出入口控制项目需要联动闸机、LED 屏显示车牌想基于臻识相机做二次开发比如夜间补光策略调整、特殊车牌识别优化学校、园区、商业综合体做一车一杆的自动化通行改造当然如果你是只想用相机自动识别车牌然后人工在软件里看一眼结果不涉及深度集成那直接买一套成品的停车场管理系统可能更省事没必要碰 SDK。2. 拿到压缩包之后第一件事理解目录结构2.1 压缩包解压后的整体布局R3 版本解压之后目录结构比较规整我用实际内容来展示opensdk_r3_20210414/ ├── doc/ │ ├── OpenSDK开发手册.pdf │ └── 版本升级说明.pdf ├── include/ │ ├── ds_common.h │ ├── ds_platform.h │ └── ds_lpr.h ├── lib/ │ ├── x86/ │ │ └── libds_opensdk.so │ └── arm/ │ └── libds_opensdk.so ├── sample/ │ ├── sample_lpr/ │ ├── sample_platform/ │ └── sample_io/ └── tools/ ├── 设备搜索工具/ └── 固件升级工具/刚拿到手别急着写代码先把 doc 目录下的两份 PDF 过一遍。开发手册里对接口的定义、数据结构的字段说明都写得很清楚尤其是环境布防、撤防的流程后面实际开发会反复用到。2.2 lib 目录里的两个平台选择lib 目录下有x86和arm两个子目录分别对应 PC 端和嵌入式 ARM 平台。如果你是在 Windows 上用 Visual Studio 写代码后面做原型测试用 x86 下的.so文件就行如果是要部署到 RK3288、RK3399 这类 ARM 开发板上就用 arm 目录下的版本这里要注意一个常见的坑很多新手直接照搬 PC 上编译好的程序结果发现 ARM 板上跑不起来卡在动态库加载失败。原因多半是没有把对应架构的.so文件一并部署上去而且被程序依赖的其他系统库在板子上缺失。3. 核心模块拆解接口调用和回调机制3.1 初始化流程里的几个关键步骤SDK 的使用流程大致上是一条线网络搜索-登录设备-布防-接收回调-撤防-登出。我写了一段伪代码来展示整个流程实际开发中这些函数名都以头文件里的为准// 初始化SDK DS_Init(); // 搜索设备或者直接通过IP添加 DS_DeviceInfo device; strcpy(device.ip, 192.168.1.64); device.port 8000; device.username admin; device.password admin123; // 登录设备 DS_Login(device); // 布防订阅事件 DS_SetupAlarmChan(device.loginId, AlarmCallback, NULL); // 业务处理完成 DS_Logout(device.loginId); // 释放SDK资源 DS_Cleanup();登录关键点在于相机默认的用户名密码。臻识相机出厂默认账号通常是admin密码是admin或者admin123不同批次会有差异。设备第一次上电后建议手动改一次密码避免同一网段里有别人也能直接登录你的相机。3.2 回调机制识别结果是这样拿到手的布防之后相机一旦识别到车牌SDK 会主动回调你注册的那个函数。这个机制和主动拉取完全不同你不需要自己轮询。回调函数里能拿到的数据包括车牌号码和车牌颜色识别置信度抓拍图片的路径或者二进制数据触发时间戳车牌的定位坐标矩形框实际项目中拿到识别结果以后一般要立刻做几件事把车牌号码和抓拍时间写入本地数据库如果置信度偏低把图片单独存放方便人工复核触发道闸开闸信号。这些操作在回调函数里执行时要快不要让回调线程阻塞太久否则会影响相机后面几帧的识别推送。4. 从零到跑通一个完整的识别联动开发记录4.1 环境准备和工程配置我这边测试机的环境是 Ubuntu 18.04加一台臻识的智能识别相机型号就不说了R3 支持他们家的主流 IPC。在正式写代码之前需要把开发环境准备好。安装编译依赖sudo apt-get update sudo apt-get install build-essential cmake把我本地的工程目录结构搭建好大概长这样my_lpr_project/ ├── CMakeLists.txt ├── include/ │ └── ds_lpr.h ├── lib/ │ └── libds_opensdk.so └── src/ └── main.c4.2 CMakeLists 的写法参考如果你用 CMake 来管理工程一个能直接跑的 CMakeLists 大概长这样cmake_minimum_required(VERSION 3.10) project(lpr_demo) set(CMAKE_CXX_STANDARD 11) include_directories(${PROJECT_SOURCE_DIR}/include) link_directories(${PROJECT_SOURCE_DIR}/lib) add_executable(lpr_demo src/main.c) target_link_libraries(lpr_demo ds_opensdk pthread dl)这里有个容易翻车的地方就是链接顺序。把pthread和dl放在ds_opensdk后面能避免一些奇怪的未定义引用错误。如果你把库的链接顺序写反了编译时会突然报出一堆undefined reference查了半天原因只是顺序问题。4.3 主程序代码把流程串起来核心代码我简化了一下便于讲解#include stdio.h #include string.h #include unistd.h #include ds_lpr.h // 回调函数定义 void CALLBACK AlarmCallback(DS_AlarmInfo *info, void *userData) { printf(车牌: %s\n, info-license); printf(颜色: %d\n, info-colorType); printf(置信度: %f\n, info-confidence); printf(时间戳: %d\n, (int)info-timestamp); } int main() { DS_Init(); DS_DeviceInfo device; memset(device, 0, sizeof(device)); strcpy(device.ip, 192.168.1.64); device.port 8000; strcpy(device.username, admin); strcpy(device.password, admin123); int loginId DS_Login(device); if (loginId 0) { printf(登录失败错误码: %d\n, loginId); DS_Cleanup(); return -1; } DS_SetupAlarmChan(loginId, AlarmCallback, NULL); printf(布防成功等待识别...\n); sleep(30); // 测试跑30秒 DS_Logout(loginId); DS_Cleanup(); return 0; }编译运行mkdir build cd build cmake .. make ./lpr_demo跑起来之后对着相机前面停一辆车控制台就能看到识别结果打出来。能走到这一步说明 SDK 的主链路已经通了。4.4 把识别结果联动到道闸只打印结果当然不满足真实项目需求。真实场景里识别到车牌后还要联动道闸。可以通过相机自带的 IO 输出接口来控制道闸开闸SDK 里提供了对应的 IO 操作方法。大致思路是收到合法车牌之后调用DS_IOControl拉高 IO 口电平触发道闸控制器延时几秒后再拉低恢复。// 收到车牌后输出高电平触发道闸 DS_IOControl(loginId, 1, 1); // 通道1拉高 usleep(500 * 1000); DS_IOControl(loginId, 1, 0); // 通道1拉低这里需要注意设备端的 IO 接线。不同型号的相机器材接口引脚定义会有差异动手接线之前一定要查阅对应型号的硬件手册。我之前见过一个项目就是因为信号线共地没处理好导致道闸偶尔不动作排查了很久。5. 常见问题与排查技巧实录5.1 相机搜索不到或登录失败这是刚接触时最常遇到的问题。出现这种情况按下面的顺序查先用电脑 Ping 一下相机的 IP确认网络通不通确认电脑和相机在同一个网段。很多相机出厂 IP 是192.168.1.66之类如果你的电脑在10.10.x.x网段那怎么也搜不到检查相机的端口是否默认 8000有的现场把端口改过如果还是不行用臻识的设备搜索工具扫描一次看看能不能发现相机5.2 回调函数收不到数据登录成功了布防也成功了但一直没有回调数据。先确认一件事相机是否真的触发了识别。把相机画面在配套软件里打开看看有没有检测到车牌。如果软件里能看到识别但 SDK 回调没有触发检查一下是否存在多个 SDK 同时连接相机的情况。部分型号的相机只允许一个 SDK 建立布防通道另一个客户端占用之后SDK 这边就拿不到数据了。关掉其他连接程序重新布防试试。5.3 动态库加载失败的坑把程序部署到别的机器上比如从开发机拷贝到服务器容易遇到error while loading shared libraries: libds_opensdk.so: cannot open shared object file这是因为运行时找不到.so文件。解决方法有两种# 方法一临时设置环境变量 export LD_LIBRARY_PATH/your_project/lib:$LD_LIBRARY_PATH ./lpr_demo # 方法二把动态库拷贝到系统库目录 sudo cp libds_opensdk.so /usr/local/lib/ sudo ldconfig建议优先用第一种方法。第二种方法虽然省事但如果你同时有多个版本的 SDK拷贝到系统目录之后容易造成版本冲突到时候很难查。5.4 识别延迟偏大怎么定位R3 的响应速度整体不错但如果现场反馈识别到抬杆的时间太长可以从几个方向排查网络延迟相机到后端的网络是否是跨路由的延迟多大回调解耦回调函数里是不是做了太多耗时操作比如同步写数据库、HTTP 请求外部接口补光策略夜间光线不足会导致识别时间变长把补光灯开启策略改为自动并检查补光灯是否正常亮起我之前调过一个现场识别到结果到抬杆要近 2 秒。查下来发现回调里做了两次 HTTP 请求去访问一个响应很慢的外部接口把这个接口改成了异步调用之后整体响应时间降到了 800 毫秒左右。所以记住一句话回调里任何无关紧要的耗时操作都别做。6. 版本选择与兼容性建议6.1 R3 版本和其他版本的区别臻识的 SDK 版本主要区别在于支持的相机型号、接口定义和部分功能包。R3 版本对新型号支持得更完整同时兼容早期型号。如果你的相机比较新建议直接用 R3 或者更新版本。官网下载 SDK 时要注意看清型号匹配关系。下载错版本后接口调用很容易返回错误码因为函数签名和消息结构不完全一致。6.2 从旧版本升级到 R3 的注意点如果你的老项目已经在别的版本上跑得好好的升级到 R3 时要特别关注头文件的变更数据结构字段是否有增加或删除回调函数原型是否变化初始化参数是否多出了新配置项升级的时候最好先在一个测试环境里编译一遍对照版本升级说明.pdf里的变更日志逐条核对。别直接替换库文件到生产环境很容易在新旧接口不一致上栽跟头。7. 我的一点实战心得体会和臻识相机 OpenSDK 打交道也有几年时间几个小经验供大家参考第一SDK 自带的说明文档一定要认真读一遍尤其是每个接口的返回值和错误码含义。很多调试问题其实只要查一下错误码就能立刻定位方向不需要瞎猜。第二能在本地模拟的数据尽量本地模拟。做车牌识别联动开发时不可能每次都在现场找辆车来测试。可以让相机对准电脑屏幕播放一段包含车牌的测试视频来模拟真实场景这样调试效率会高很多。第三做好日志记录。在回调函数里加日志记录收到底层推送的时间和内容。这一行日志在后期排查现场问题时价值巨大能帮助判断问题是出在相机端还是你的后端程序。第四定期备份 SDK 包和编译产物。这个 SDK 版本比较经典但官方后续版本接口会调整。存放在本地或者内网避免时间久远之后连压缩包都找不到。项目交接时这一点尤其容易被忽视。如果你现在正拿着这个压缩包准备做集成希望这篇文章能帮你理清思路少走一些弯路。这个 SDK 的整体设计逻辑还是比较清晰的上手难度并不算高只要把流程走通一遍后面的扩展就是顺水推舟的事。本文还有配套的精品资源点击获取