资讯详情

资讯详情

基于Hi3516CV610的智能视觉监控系统开发实战

接到一个做智能视觉监控的需求时我第一反应是别再拿树莓派凑合了——摄像头数据要同时走H.265硬件编码和AI人形检测树莓派的CPU软编码扛不住几路Jetson成本又压不下来。手头这块Hi3516CV610开发板正好是海思新一代轻量级IPC方向上的片子把视频采集、编码、AI推理集成到一颗SoC里很适合做面向园区、仓库、家庭边缘的小型智能视觉监控系统。这篇文章不打算讲太多PPT上的参数我会从为什么选这颗芯片开始把SDK环境搭建、HiMPP媒体流程、RTSP推流和AI检测接入的完整路子走一遍最后整理实际调试中踩过的坑。适合正准备用海思方案做产品的嵌入式工程师、AIoT方向的开发者也适合给安防行业做算法落地的朋友参考。1. 为什么选Hi3516CV610从项目需求反推动器件选型1.1 先搞清楚监控系统的需求边界拿到项目别急着画板子先把需求句式列清楚。一个智能视觉监控系统通常要同时满足“看得见、看得懂、叫得响”三层要求视频要清晰稳定200万像素起步500万像素留余量帧率至少20fps推荐25fps实时晚上要有基本的低照度处理能力。存储要够用本地SD卡或NVR录制码流要支持H.264/H.265减少硬盘占用。智能分析要准人形检测、区域闯入、移动侦测是基本盘最好能跑YOLO这类轻量模型。报警要快检测到异常后要么推报警截图要么点亮GPIO接警灯时延控制在1秒内。成本要可控单板不能太贵整机给渠道留利润毕竟安防是讲究“性价比”的行业。把需求拆完之后选型逻辑就很清晰了。传统方案里有人用“主控USB摄像头PC”做有人用树莓派硬扛还有直接用NVR整机。但放到“单板、低功耗、长时间运行”的智能摄像头场景下这些方案都有自己的毛病。Hi3516CV610这块板子的定位就是这样出来的视频通路和AI推理不让CPU单独背由芯片内部硬件模块分工完成。1.2 CV610在同档位里的竞争力分析先给结论这颗芯片适合做“单路到四路左右的轻量级AI IPC”不太适合做多路大型NVR。我自己拿它和市面上常见的几类方案做过对比差别非常明显维度Hi3516CV610树莓派4BJetson系列视频编码硬件H.264/H.265多路并发不吃CPUCPU软编码1080P25fps时CPU占用高硬件编码需另配模块或依赖GPUAI能力内置NPU可跑YOLOv5s轻量模型无专用NPU只能外接加速棒GPU算力强但功耗和成本跟着涨功耗低整体在3W左右可太阳能供电5~8W还要考虑散热10W以上基本告别电池方案成本单芯片、单板成本有优势板子便宜但附件贵整体不便宜单板价格高适合贵项目适用场景智能摄像头、低功耗IPC、边缘盒子教学演示、快速原型机器人、多路视频结构化服务器当然具体到每个版本的开发板和模组参数都有差别比如DDR大小、sensor接口是MIPI还是LVDS。我手上这块是配SC5008 sensor的500万像素模组跑H.265主码流时CPU占用能控制在很低的水平这就是硬件编码带来的直接好处。选CV610还有一个实际考量它把视频编解码和AI推理算力做在同一个芯片里整个方案就不需要像传统IPC那样外挂一颗协处理芯片。硬件上省一块PCB面积软件上少一个跨芯片通信的模块开发和调试成本都下降不少。1.3 整套系统的软硬件架构视图从我实际搭出来的系统看整体可以分成下面几条链路硬件链路镜头 CMOS sensorSC5008通过MIPI接口进入CV610的VI视频输入模块。VI输出的RAW数据交给VPSS做缩放、降噪、宽动态处理然后兵分两路一路送VENC硬件编码器输出H.265/H.264码流另一路把YUV数据送给NPU做目标检测。网络链路VENC出来的码流封装成RTSP通过有线网口推出去。手机、PC、NVR都能拉流预览。如果项目需要也能通过扩展4G模组走无线。软件链路底层是标准的Linux内核海思叫osdrv中间是媒体平台HiMPP再往上是业务代码。业务代码里我开了几个线程取流线程从VENC拿码AI线程从NPU拿检测结果RTSP服务线程处理客户端请求报警线程输出GPIO。线程之间用环形队列和消息队列交换数据避免互相阻塞。用个通俗的比喻sensor是眼睛VI是视神经入口VPSS是视觉中枢里的预处理区VENC是打包机NPU是大脑RTSP是嗓子眼GPIO是手。整个系统从“看见”到“喊出来”就是这么一条流水线。2. 开发环境搭建与系统烧录从SDK解压到板子跑起来2.1 硬件准备清单与开发工具选型这一节是按我实际调试环境来的抄作业直接照做即可。需要准备的硬件Hi3516CV610开发板一块带SC5008 sensor模组5V/2A以上DC电源别拿手机快充乱怼电流不足会造成启动中途复位USB转TTL串口线3.3V电平CH340或FT232都行用来连uboot和内核串口日志网线一根直连路由器或交换机用于TFTP、SSH、RTSP推流TF卡一张至少8GB建议Class10用于SD卡启动和码流存储Ubuntu开发主机一台我用的20.04 x64虚拟机也可以但串口透传会麻烦一点。开发机上的软件工具就几样串口终端我用 MobaXterm它既能看串口又能SSH一个窗口搞定代码编辑和远程调试用VSCode的Remote-SSH插件主机侧要装NFS服务端和TFTP服务端。这些工具不是随便选的下面一路用到哪算哪你就明白为什么需要它们了。2.2 SDK目录结构与交叉编译链配置海思SDK的包名一般长这样Hi3516CV610_SDK_Vx.x.x.tgz。解压后先别急着编译先看目录结构osdrv/内核、uboot、根文件系统都在这里是整个系统的基础smp/媒体平台MPP库和sample示例代码我们后续要改的推流demo就在这里doc/芯片手册、接口说明、开发指南出问题先翻这里tools/烧录工具、调试工具、交叉编译工具链。交叉编译工具链的安装脚本一般放在SDK里新老版本路径不完全相同老平台常见的是arm-himix100-linux或arm-himix200-linux新平台SDK里也可能内置了更新的工具链。打开SDK里的sdk.unpack脚本跑一遍它会自动解压并安装工具链。我这次安装后确认一下版本arm-himix100-linux-gcc -v能输出版本号就说明交叉编译环境OK。然后写个最简单的hello world试试#include stdio.h int main(void) { printf(hello hi3516cv610\n); return 0; }arm-himix100-linux-gcc -o hello hello.c把编译出的文件拷贝到开发板跑起来看到打印信息后你的开发环境就已经打通了。这一步花不了多少时间但非常有意义——说明从“主机写代码”到“板子上运行”的链路已经通了后边的所有应用开发都会踩在这条链路上。关于“为什么用交叉编译而不直接在板子上编译”原因很直接开发板资源有限跑编译器太占用CPU和内存而且SDK里大量库文件、内核头文件都需要统一路径直接在板子上编译很容易因为路径不统一而出一堆莫名其妙的问题。所以在x86主机上交叉编译出ARM可执行文件再通过网络或TF卡拷到板子运行是嵌入式开发的通用姿势。2.3 根文件系统与SD卡启动烧录实战SDK里的osdrv可以一键编译出内核、uboot和根文件系统。我那次编译大概花了二十分钟主要时间都在编内核。命令是make OSDRV_CROSSarm-himix100-linux -j4-j后面的数字不要一下子拉太高尤其是虚拟机内存不够会直接卡死。编译完成后产物一般在osdrv/pub/目录下包括uImage、u-boot-hi3516cv610.bin、rootfs_xxx.tar等。接下来是给TF卡分区和烧系统。先用读卡器把TF卡插到Ubuntu主机确认设备名是/dev/sdb还是/dev/sdc千万别选错不然会把你硬盘整个抹掉。然后用fdisk重新分区sudo fdisk /dev/sdX我分了两个区第一个分区格式化成FAT32放内核和设备树文件第二个分区格式化成ext4放根文件系统。sudo mkfs.vfat /dev/sdX1 sudo mkfs.ext4 /dev/sdX2把根文件系统解压进第二分区sudo mkdir /mnt/rootfs sudo mount /dev/sdX2 /mnt/rootfs sudo tar xvf rootfs_xxx.tar -C /mnt/rootfs把内核和设备树放进第一分区然后插回开发板。上电后进入uboot命令行设置启动参数。这里的关键参数是bootargs它告诉内核从哪里挂根文件系统、串口用哪个波特率还有给系统分配多少内存。我用的参数大致是这样setenv bootargs mem512M consolettyAMA0,115200 root/dev/mmcblk0p2 rootfstypeext4 rw init/linuxrc setenv bootcmd mmc read 0 0x82000000 0x800 0x4000; bootm 0x82000000 saveenv resetmem512M要和你板子的DDR大小匹配console参数和你串口号对应这套参数在不同板子上有细微差别。最稳妥的办法是查开发板厂家给的启动模板别自己拍脑袋改。启动过程中串口会刷出内核日志。看到“Welcome to HiLinux”或类似的登录提示这套系统就算跑起来了。第一次启动容易踩的坑是SD卡明明插着uboot却提示找不到设备。先别怀疑卡坏了多半是电源电流不够导致卡供电异常换个电源试试其次是FAT分区没放内核文件或文件名对不上uboot的期望。3. 核心应用开发基于HiMPP的采集-编码-推流全流程3.1 HiMPP媒体框架与关键概念HiMPP是海思媒体处理平台所有视频相关业务都要在它上面跑。它的模块很多但做监控系统只需要先理解五个关键模块VB、VI、VPSS、VENC、AI。VBVideo Buffer视频缓冲池是整个视频通路的内存底座。视频采集、编码、AI分析都需要大块内存搬运数据这些内存就是VB池统一管理的。VB池的每个block按图像格式计算大小比如1080P的YUV420一张图就是 1920 × 1080 × 1.5 ≈ 3.11MB一个池一般放4~6块缓冲。VIVideo Input视频输入模块接收sensor送来的RAW数据输出YUV格式的数据给上层。VPSSVideo Pre-Processing Subsystem视频预处理子系统做缩放、降噪、宽动态。它的厉害之处是一个输入可以分发到多个通道输出不同分辨率。VENCVideo Encoder视频编码模块把YUV编码成H.264/H.265码流。AI智能分析模块往NPU送图的通道海思SDK里通常会把它单列出来。这些模块之间的关系我常用“仓库分拣线”来类比VB是仓库货架VI是收货口VPSS是分拣台VENC是打包机AI是质检员。数据从收货口进来在仓库里周转分拣台按需要分成大包小包一部分打包发货编码存储一部分送质检AI检测。3.2 最小推流demo把第一路视频跑起来海思SDK的smp/sample目录里有一个sample_venc工程这就是最基础编码demo。不过它默认跑裸流输出我们改成实时RTSP推流改动量不大。先看核心初始化流程HI_S32 SAMPLE_COMM_VI_CreateVb(VB_CONF_S *pstVbConf) { // 配置VB池每个buffer的大小、数量、物理地址 pstVbConf-u32MaxPoolCnt 1; pstVbConf-astCommPool[0].u32BlkSize 1920 * 1080 * 1.5; pstVbConf-astCommPool[0].u32BlkCnt 6; HI_MPP_SYS_Init(); HI_MPP_VB_SetConfig(pstVbConf); HI_MPP_VB_Init(); } HI_S32 SAMPLE_COMM_VI_Start(VI_DEV ViDev, VI_CHN ViChn) { VI_DEV_ATTR_S stDevAttr; // 根据sensor型号设置输入时序、接口类型、帧率 // SC5008是MIPI接口RAW10输出1080P25fps HI_MPP_VI_SetDevAttr(ViDev, stDevAttr); HI_MPP_VI_EnableChn(ViChn); }把VI、VPSS、VENC一一启动之后主循环取编码流的逻辑长这样VENC_CHN_STAT_S stStat; VENC_STREAM_S stStream; while (1) { HI_MPP_VENC_QueryStatus(VencChn, stStat); if (stStat.u32CurPacks 0) { usleep(10000); continue; } HI_MPP_VENC_GetStream(VencChn, stStream, 1000); // 把stStream里的H.265裸流塞给RTSP打包线程 rtsp_send_h265_packet(stStream.pstPack-pu8Addr, stStream.pstPack-u32Len); HI_MPP_VENC_ReleaseStream(VencChn, stStream); }VENC的编码属性是重点我用的参数是这样的编码协议PT_H265同等画质下比H.264省20%~30%码率存储压力小很多分辨率1920×1080帧率25fps码率控制CBR模式码率设置在2MbpsGOP长度50帧约2秒一个I帧兼顾秒开和存储容错。我在实际调试时发现VB池如果配得太小取流线程稍慢一点编码器就会报“VB full”表现为画面卡顿。一个省内存的技巧是VPSS的通道数量按需裁剪不要图省事把所有通道都开满每多一个通道就多占一份内存。3.3 RTSP/ONVIF对接与存储容量计算编码器拿到的是H.265裸流客户端不能直接播放必须封装成流媒体协议。RTSP是最通用的选择海思SDK自带了基于live555的sample_rtsp把上面取到的H.265包喂给RTP打包器就行。验证推流是否成功我一般用一台Windows笔记本装VLCrtsp://192.168.1.100/live如果VLC能出画面说明RTSP链路通了。进一步可以用ffprobe检查码流参数ffprobe -rtsp_transport tcp -i rtsp://192.168.1.100/live生产级的智能视觉监控系统还需要兼容ONVIF协议这样海康、大华的NVR才能直接发现和取流。ONVIF协议栈可以自己移植也可以买现成的SDK库这部分代码量不小但对做产品的人来说绕不开。个人DIY阶段先用RTSP URL对接足够。存储容量这块我给大家一个计算公式做项目评估时能直接套用单路码率2Mbps 0.25MB/s一天86400秒一天录像总量约为 0.25 × 86400 ≈ 21600MB ≈ 21GB。按7天循环存储需要约150GB空间。如果配500万像素传感器码率压到6Mbps一天就要约65GB。选硬盘时记得留20%以上余量文件系统碎片和坏块会吃掉一部分空间。3.4 智能AI检测接入模型转换与推理落地AI检测是整个系统最大的亮点。CV610内置NPU可以跑YOLOv5轻量模型我们的目标模型是YOLOv5n或YOLOv5s目标类别设为人、车、宠物三类。先看模型转换流程。海思老平台有RuyiStudio和NNIE工具链可以把Caffe模型转换成NPU可执行的wk文件。新版工具链的转换流程一般也是PyTorch导出ONNX再转成海思工具链支持的模型格式。不同SDK版本的工具链名称和转换步骤差异很大我强烈建议你以官方文档为准。我踩过最大的坑是量化精度模型从float转成int8后小目标检测能力明显下降。解决办法是用测试集里贴近真实场景的图片做校准校准集至少200张否则掉点严重。模型转换完之后推理代码就简单多了。流程是从VPSS的智检通道取一帧YUV数据做letterbox缩放归一化后送入NPU推理完做NMS去重输出坐标和类别。参考代码如下HI_S32 AI_Inference(HI_U8 *srcYuv, AI_BOX_S *rstBox, HI_S32 *boxNum) { // 前处理letterbox 归一化 preprocess_yuv(srcYuv, model_input); // 模型推理 hi_npu_inference(model, model_input, raw_output); // 后处理NMS 阈值过滤 postprocess(raw_output, rstBox, boxNum); return HI_SUCCESS; }检测结果要叠加到画面里就要用到OSD功能。把AI框的坐标转换成OSD矩形图推到VENC通道上客户端就能看到“人形检测框置信度”。我第一版做出来时OSD框有0.3秒左右的延迟原因是AI线程和编码线程中间缓冲队列太深。把队列从5帧降到2帧后延迟基本消失了。联动报警也很直接GPIO输出高电平时继电器闭合警灯亮起。我测试时故意把置信度阈值从0.5降到0.3结果误报很多飘动的树叶被当成人。把阈值提回0.55之后就稳定了。阈值这东西不是固定的要根据实际场景天气、光照、目标大小反复调。4. 联调、部署与常见问题排查实录4.1 NFS挂载与开发调试效率提升开发阶段的痛苦之源就是反复烧录文件系统。每次改个代码都要重新烧写一天的时间就耗在等烧写上了。我用NFS解决这个问题把开发板的根文件系统或者业务代码目录放在Ubuntu主机上板子上电后通过网络挂载主机的目录。Ubuntu主机侧装NFS服务并配置导出目录sudo apt install nfs-kernel-server sudo vim /etc/exports # 添加一行 # /home/dev/rootfs *(rw,sync,no_root_squash,no_subtree_check) sudo systemctl restart nfs-kernel-server开发板上执行挂载mount -t nfs -o nolock,tcp,rsize4096,wsize4096 192.168.2.100:/home/dev/rootfs /mnt挂载成功之后主机端改代码、交叉编译生成的可执行文件直接放到NFS目录里板子上就能运行整个迭代周期从“烧录重启”缩短成“秒级生效”。VSCode连接开发板也值得说一下。用Remote-SSH插件在~/.ssh/config里配置开发板IP和账号就能在VSCode里直接编辑板子上的文件同时打开终端执行命令。我习惯把代码仓库先放到Ubuntu主机上在主机侧用VSCode编辑再通过NFS让板子上的应用运行这样串口用来盯日志SSH用来管系统两边不打架。正式部署到现场时不能依赖NFS要把最终版本的可执行文件、动态库和配置文件都拷贝到板子的ext4分区然后写一个开机自启脚本。我放在/etc/init.d/S99monitor里用chmod x添加执行权限系统启动后会自动拉起业务程序。注意要加日志重定向不然程序崩溃了都不知道为什么。4.2 高频问题速查表与实战排查我把这段时间遇到的高频问题整理成了一张速查表都是“现象-原因-解法”的对应关系排查时直接对表查现象可能原因排查与解决串口输出中文乱码终端编码和Linux console编码不匹配把MobaXterm会话编码切到UTF-8或修改内核console参数指定编码板子没启动、串口无输出TX/RX没交叉接线、没有按复位、电源没到调换串口TX/RX接线按复位键万用表测电源电压启动卡在“Starting kernel...”设备树和内核版本不匹配、bootargs错误检查dtb和uImage来源确认console参数和串口号一致画面全绿或有花纹sensor时钟或I2C配置不对、排线没插好dmesg | grep sensor看sensor注册是否成功重新插拔MIPI排线编码输出一卡一卡的VB池太小或码流写入TF卡太慢cat /proc/umap/vb看VB池占用换Class10高速卡AI检测不出目标置信度阈值太高、模型输入尺寸不一致降低阈值到0.5以下测试确认预处理尺寸和模型输入完全一致网络不通网口没配IP、网线质量问题ifconfig查看IP改用直连路由器的短网线测试排查VB池、VENC状态这些底层问题海思有一个非常方便的口子/proc/umap/目录。里面有大量MPP模块的运行状态比如cat /proc/umap/venc能看到编码器有没有丢帧cat /proc/umap/vb能看到内存有没有告警。很多问题不用猜看这个目录下的状态就一目了然了。4.3 稳定运行与性能调优心得系统在开发板上跑通只是第一步稳定运行才是产品级的门槛。我调优时做过的几件事大家可以按顺序过一遍第一编译选项。业务代码编译器用-O2 -Os代码体积和性能取一个平衡。不要在Makefile里偷懒不加优化默认-O0的性能跟实际产品差得不是一点半点。第二线程绑核。AI推理线程和RTSP推流线程是CPU占用的两个大户。CV610是多核CPU用sched_setaffinity把AI线程绑在独立的一个核上其他业务线程分在另外的核上。实测下来绑核能明显减少AI推理的抖动画面和报警都更稳。第三内存优化。MPP各模块占的内存是可以调的。子码流设计成640×36010fps预览和存储完全够用内存开销却低很多。用/proc/umap/vb看实际占用后逐步调小VB池直至余量刚好够用。内存这东西给多了浪费给少了崩溃调成“刚好够小幅余量”是最理想的状态。第四看门狗和日志。生产环境一定要开硬件看门狗程序异常卡死时能自动重启系统。日志统一走syslog每条日志带时间戳和线程名否则出了Bug连“事故时间线”都还原不出来。最后说点个人体会。这套项目我从拿到CV610开发板到跑通第一路AI检测中间花了两三天大部分时间耗在SDK版本和sensor适配这类“文档里没有、只能靠自己试”的问题上。所以如果你也准备踩这条线我劝你先把uboot和调试网络弄扎实再往上层加业务——底层跑不动上层全白搭。另外一个经验是别一上来就想做成NVR那种多路复杂系统先把单路采集-编码-推流-检测跑通后面加路数、加算法都是水到渠成的事。希望这篇文章能让你少走几个弯路有机会一起交流。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →