安全帽检测这个需求,乍看之下没什么技术含量:不就是摄像头对着工地出入口,发现没戴安全帽的人就抓拍告警吗?真把方案从 PPT 推到现场落地,我发现所有坑都藏在“在哪里算”这三个字里。我最后把检测主流程放在 RK3588 上做,而不是丢到云端,也不是用一台老工控机硬扛,是一轮非常具体的架构权衡。这篇内容是我的选型和落地记录,写给准备做边缘 AI 视频分析的开发者参考,也写给被“算力焦虑”困扰、不知道 6 TOPS 到底够不够用的同学。
1. 从“为什么不上云”说起:安全帽检测场景的真实约束
1.1 工地视频流的三个特点
安全帽检测面对的不是一张图,而是一路路 7x24 小时的视频流。工地监控的摄像头点位分布很散,而且大部分是普通枪机或球机,输出 H.264/H.265 的 RTSP 流。这类场景和互联网图片审核最大的区别是:数据不是“传过来处理”,而是“设备在那里一直产生数据”。
我第一次梳理需求时列了三个真实约束。第一是实时性,管理者希望在人员进入危险区域后的几秒内就收到告警,而不是等云端批量分析完再回传,真出了安全事故,延迟几十秒就可能失去处置意义。第二是网络稳定性,工地现场的网络经常因为施工断电、运营商线路挖断、弱电井进水而中断,如果检测逻辑完全依赖云端,断网就等于没有监控。第三是带宽成本,16 路 1080p 视频流如果全部推到云端,一天的流量费用就够吓人,更别提存储费用。
这些约束叠加起来,结论非常明确:检测逻辑必须在靠近摄像头的地方完成。云端不是不能用,而是只能做“事后复核”和“数据汇总”,不能承担“实时发现”这个主任务。这也是边缘 AI 在这个场景里成立的根本原因。
1.2 云端方案看起来很美,但账要算细
我不是否定云。相反,团队一开始的方案就是云端识别:现场用 NVR 或推流网关把 H.264 流转推到云服务器,GPU 实例跑检测模型,识别到未戴安全帽就通过 App 推送告警。演示的时候一切正常,但放到一个春节假期连下三天雨的工地上,问题就暴露了。
首先是推流不稳定。现场一个核心交换机的光模块被雷打坏后,整片区域的视频全部离线,告警功能直接消失。其次是成本,云 GPU 实例按小时计费,一天 24 小时挂着跑,一个月账单下来完全不是做项目前谈预算时那个数字。第三是延迟,虽然检测本身只要几十毫秒,但视频推流、排队、服务端拉流解码、再返回结果,端到端延迟经常到 5 秒以上,管理者在手机上看告警图片会觉得“人都走过去了才报警”。
这不是说云端架构错了,而是说安全帽检测这种“高并发、长在线、低时延”的业务,更适合在边缘端做第一层筛选,把疑似违规的图片和短视频片段回传云端,做二次分析留存。想清楚这个分工之后,选型的关键就变成了:找一块能同时扛住视频解码和神经网络推理的芯片。
1.3 选型前必须列出的硬指标
很多人在选边缘设备时只看“TOPS 算力”,这是最容易跑偏的。我后来是把需求拆成硬指标再对比的:
- 视频解码路数:至少支持 8 路 1080p H.264/H.265 硬件解码,不能占用 CPU 做软解。
- NPU/GPU 算力:能跑 YOLOv5s 或同级别模型,int8 量化后单路帧率不低于 10 FPS。
- CPU 性能:要能同时跑 RTSP 拉流、图像缩放、后处理 NMS 和告警逻辑。
- 内存与存储:4GB 内存起步,最好支持 M.2 SSD,用于缓存告警图片和短视频。
- 功耗与散热:能装在标准弱电箱或防水箱里,不依赖大风扇和空调机房。
- 工具链成熟度:模型转换工具要能支持自家的训练框架和模型格式。
拿着这份清单再去选型,思路就清晰了很多。纯 CPU 工控机虽然便宜,但多路视频解码很容易把 8 核 CPU 打满;一些轻量级 ARM 开发板功耗很低,但 NPU 算力普遍在 1 TOPS 左右,跑安全帽模型很吃力;老式 GPU 方案性能强,但功耗和体积又扛不住工地现场的环境。就在这个对比过程中,RK3588 这颗 SoC 进入了候选列表。
2. RK3588 打动我的几个点:芯片选型不是看算力数字
2.1 6 TOPS NPU 到底意味着什么
RK3588 最吸引人的标签是“6 TOPS NPU”。但这个词太容易被误读了。TOPS 是理论峰值算力,实际能跑出多少,取决于模型结构、量化方式、输入分辨率以及工具链的优化程度。我在项目里用的是 YOLOv5s,输入 640x640,转成 RKNN int8 量化模型之后,单次推理大约 20 到 30 毫秒,折算下来每秒能跑 30 到 50 次检测。
这个数字对单路视频来说绝对够用。安全帽检测不需要对每一帧都推理,25 FPS 的视频流每隔三帧抽一帧检测,实际检测频率大约 8 FPS,对行人走动、探头进入检测区域这类动作已经完全够用。6 TOPS 的实际价值是“余量”:即使同时接入 4 到 8 路视频,每路都按抽帧策略做检测,NPU 依然能扛住。
另一个容易忽略的点是 NPU 和 CPU 的协同。很多场景下单看推理时间很漂亮,但 CPU 一旦要同时做解码、缩放、NMS、画框、截图,整个系统的实时性就崩了。RK3588 的 NPU 采用异步推理模式,CPU 提交任务后可以去做别的,等 NPU 中断回来再取结果,这让流水线设计变得很从容。
2.2 真正拉开差距的是视频编解码能力
比 NPU 更打动我的是 RK3588 的视频编解码能力。它自带硬件编解码模块,支持 H.264/H.265 解码,官方标称可以做到多路 1080p 同时解码。这意味着拉取多路 RTSP 流时,解码工作完全由硬件完成,CPU 占用率几乎可以忽略不计。
这个能力在边缘 AI 项目里比多少 TOPS 都重要。因为视频分析的第一步永远是解码,如果解码靠 CPU 软解,一个 1080p/25FPS 的 H.264 流就能吃掉一个中端 ARM 核的大部分性能。我实测过用一个通用 ARM 开发板跑单路 1080p 软解,CPU 占用直接到 50% 以上,再叠加 NPU 推理和后处理,整机就变得极其吃力。而 RK3588 的硬解几乎没有这种感觉,多路视频流的解码压力被独立承担,留给 CPU 的空间很大。
所以我的选型经验是:边缘视频分析设备,先把“解码能力”排到第一位,再看算力。一个解码能力不足的芯片,就算 NPU 再强,也无法落地多路视频场景。
2.3 和同类方案的取舍
在初筛对比时,我和团队也看了不少方案。一类是纯 CPU 工控机,优点是兼容性好、内存大,缺点是解码和 AI 推理都靠 CPU,8 路视频基本跑不动;另一类是主流的 ARM 开发板,大部分不带强力的硬件视频编解码器,也不带 NPU,需要用 OpenCV 把视频帧一帧帧喂给 CPU 跑,推理速度很难看;还有一类是 GPU 边缘计算设备,性能和生态确实好,但价格、功耗、体积都不太适合工地的安装环境。
RK3588 不是各方面最强的,但它在“解码能力、AI 算力、CPU 性能、功耗、价格”这五个维度上最均衡。尤其是价格下来之后,单片 RK3588 可以作为一路独立的“边缘分析盒子”,坏了直接换备件,成本可控。这也是我最终拍板用它的主要原因:不是因为它每一项都第一,而是它在真实约束下是综合最优解。
3. 安全帽检测模型从训练到 RKNN 的落地全流程
3.1 模型选型:不是精度越高越好
选模型时我一开始也想直接用更大的模型,毕竟听着更有安全感。后来发现边缘端最稀缺的资源不是算力,而是“每一毫秒都要省着用”。在 RK3588 的 NPU 上,模型参数量直接决定推理时间。YOLOv5s 这种轻量模型在 6 TOPS 的 NPU 上就有不错的表现;YOLOv7 或 YOLOv8m 这类大模型虽然精度更高,但推理时间可能翻倍,多路视频场景下帧率会受限。
我最后选的基线是 YOLOv5s,输入 640x640,类别定义成 person、helmet、head 三类。其中 helmet 表示已佩戴的安全帽,head 表示检测到的人头区域,person 是整个人体框。最终判断逻辑不只看 helment 的置信度,而是看 head 是否和 helmet 匹配:当检测到 head 但周围没有匹配的 helmet 时,判定为未佩戴。这套逻辑比直接检测“未戴帽的人”更稳,因为安全帽的形态变化比人的形态变化小,正着戴、歪着戴、反光、阴影情况下都能被检出来。
模型选型还有一个容易被忽略的点:通道数和量化友好度。有些模型结构在 GPU 上效果不错,但转到 NPU 时个别算子不支持,或者 int8 量化后精度掉得厉害。YOLOv5s 在这方面的兼容性很好,主干网络基本都能被 RKNN 工具链完整映射,这是我选择它而不是某个自定义魔改模型的另一个原因。
3.2 数据准备:安全帽检测的真正难点
安全帽检测的训练数据,比大多数目标检测任务更考验“脏活累活”。公开的安全帽数据集并不少,但直接拿来用的效果往往不理想,原因在于工地现场的照片高度雷同:不是固定角度对着入口拍,就是黄昏逆光、雨天反光、夜间红外补光。模型在公开数据集上看着 AP 很高,到现场一测就露馅。
我在落地项目里,是用“公开数据+现场自采+针对性增强”三管齐下。现场自采很重要,我在项目点位和管理方沟通后,用测试相机采集不同光线、不同方向、不同戴帽姿态的画面,截取成图片,总共标了几千张。增强方面重点做亮度扰动、噪声扰动、随机角度旋转、马赛克增强。
最难处理的是小目标问题。工地出入口区域很大,人离摄像头远的时候,头和帽子只有几十个像素。我在标注时专门要求把所有小目标框都标出来,并在增强时把图片随机裁剪、缩放,强制模型学习小尺度特征。验证集上也专门增加了一个“远距离样本”的切片,防止模型只对近景有效。
3.3 ONNX 转 RKNN 与 int8 量化
训练完成后,我的流程是先把 PyTorch 模型导出成 ONNX,再用 RKNN 工具链转成 RKNN 格式部署到板子上。这个过程中最需要花心思的是 int8 量化。用 float16 模型跑在 RK3588 上,虽然精度损失小,但 NPU 推理速度并不理想;用 int8 量化,速度能明显提上来,但校准集选不好,精度可能直接掉几个点。
我的做法是准备 200 张左右能覆盖“正常、逆光、夜视、距离远近、有无帽子”的现场图片作为校准集,在转换工具里按 per-channel 方式量化。第一次试跑时,helmet 类的精度从 float 模型的 91% 掉到了 74%,排查发现是校准集里安全帽出现频率太低,校准阶段对 helmet 的激活分布估计不准。后来把校准集改成 50% 以上是带安全帽的图片,掉点控制在 2 个百分点以内,这个幅度对现场判断完全能接受。
还需要注意一个细节:转 RKNN 之前,ONNX 模型里的后处理模块要尽量裁掉。我的习惯是只保留卷积和池化这类结构,NMS 和坐标解码全部放到 CPU 上做。这样 RKNN 模型更干净,NPU 只需要负责张量运算,后处理的灵活性也更高。
3.4 推理代码怎么组织
板子上的推理代码,我按流水线的方式组织成了几个模块:拉流模块、解码模块、预处理模块、NPU 推理模块、后处理模块、告警模块。
拉流模块用 FFmpeg 的 RTSP 接口收流,超时时间要设得比默认值更保守,否则断流后重连会卡住整个线程。解码模块直接用 RK3588 的硬件解码 API,把 H.264/H.265 流解码成 NV12 帧,这一步不经过 CPU 软解,CPU 占用非常低。预处理模块做 letterbox 缩放,把任意分辨率的帧先缩放并填充到 640x640,再把像素从 NV12 转成 RGB 并完成归一化,放到 NPU 需要的输入内存里。
推理接口我封装成同步加异步两套。同步模式用于调试,异步模式用于正式运行。异步模式下,CPU 把当前帧的输入数据拷贝到 NPU 内存后立刻返回,继续处理上一帧的后处理结果,NPU 在后台跑当前帧的推理。这样整个流水线的吞吐量比“一帧一帧同步等”高很多。核心代码大致是这个结构:
# 伪代码,展示流水线主循环 while True: batch = decoder.read_frames() for frame in batch: if frame.frame_id % detect_stride == 0: tensor = preprocess(frame) npu_async_submit(tensor, callback=postprocess) result = npu_async_get_result() if result is not None: alarm_rule.process(result, frame.timestamp)这个结构维护起来很直接,每个模块都能单独定位问题,而且后续换成其他芯片平台时,只需要替换解码和推理两个模块。
4. 多路视频架构里的几个关键权衡
4.1 解码方案:硬件解码和 CPU 解码的差别
多路视频场景里,第一个要做的决定就是解码方案。RK3588 的硬件解码能力很强,但它要求流必须交给硬件解码模块。这里有个取舍:硬件解码的帧格式是 NV12,送进 NPU 之前还要做颜色空间转换和缩放;CPU 解码虽然能直接得到 RGB 帧,但多路视频时 CPU 会被拖垮。
我实测对比过,单路 1080p 用 CPU 解码后直接送 NPU,CPU 占用能到 30% 以上;改用硬件解码后 CPU 占用降到 5% 以下,多出来的 CPU 余量可以留给后处理逻辑和告警服务。代价是代码复杂度高了一些,要引入硬件解码的取帧和缓冲管理。对于四路以上的项目,这个代价值得付。
需要注意硬解的 buffer 管理。硬件解码输出的帧地址是从专用内存池分配的,如果处理速度跟不上解码速度,buffer 会被占满,新帧就会丢弃。我的策略是拉流后立刻做一次轻量级抽帧判断,检测帧先落到环形缓冲队列,预处理线程从队列里取帧,而不是解码线程直接阻塞等 NPU。
4.2 帧率与检测节奏:不要每帧都检测
很多人的第一反应是“摄像头 25 FPS,模型也应该跑 25 FPS”。实际做下来完全没必要。安全帽检测面对的是人的动作,人进入监控区域到离开,时间窗口至少有好几秒,只要检测频率不低于 5 FPS,就能保证不漏报。我把每路视频的检测节奏设在 5 到 8 FPS,也就是每 3 到 5 帧做一次检测。
这样做的好处非常明显:NPU 负载被大幅降低,单颗 RK3588 可以接入更多路视频。比如 4 路视频,每路按 6 FPS 检测,总共需要 24 FPS 的检测能力,YOLOv5s 在 int8 下完全能跑满。如果需要 8 路视频,可以把每路的检测频率压到 3 FPS,再配合运动检测做触发式检测,性能依然够用。
这里要特别小心“检测频率低导致漏报”的问题。我的做法是配合一个轻量运动检测模块,当画面里检测区域内有明显运动时,临时把抽帧频率提高一倍,静止画面则降低检测频率。这样既不浪费算力,也不会错过突发情况。
4.3 告警与回传:边缘端先兜底
架构决策里另一个重要分支是告警链路。我的设计是边缘端独立完成“检测→判定→截图→保存→上传”的完整闭环,云端只是为了汇总和二次人工复核。本地判定命中后,边缘盒子立刻保存当前帧的 JPEG 图和前后 5 秒的短视频片段,然后通过 HTTP 或 MQTT 上报到平台。
这个“边缘端先兜底”的设计,在断网情况下价值极其明显。有一次项目现场运营商光缆被施工挖断,平台端断联了大约两个小时,但这段时间内边缘盒子没有停止工作,所有告警截图和短视频都缓存在本地 SSD,网络恢复后自动补传。管理者事后还是能看到完整的违规记录,而不是一片空白。
回传策略上我最开始把所有告警帧都传,结果网络稍差就一直缓冲。后来改成了“告警图片即时传,视频片段压缩后传”,并且视频片段采用低码率 H.264 编码,单段 10 秒大约 500KB,网络占用大幅下降。平台端收图后可以根据时间戳和点位 ID 归并分析,误报率低。
5. 实测结果和踩坑实录
5.1 一组基准测试数据
在项目正式上线前,我在测试环境里做了一轮基准测试。环境是 RK3588 开发板加主动散热风扇,外接一块 M.2 SSD,系统里跑了一个轻量级的容器编排服务。接入了 4 路 1080p H.265 摄像头,每路固定检测频率 6 FPS,模型是 YOLOv5s int8。
测试结果大概是这样:
| 指标 | 数值 |
|---|---|
| 视频接入路数 | 4 路 1080p / 25 FPS |
| 视频解码方式 | RK3588 硬件解码 |
| 单次模型推理耗时 | 约 22 ms |
| 单路实际检测频率 | 约 6 FPS |
| NPU 占用率 | 约 55% |
| CPU 总占用率 | 约 25% |
| 内存占用 | 约 1.4 GB |
| 整机功耗 | 约 15 W(含风扇) |
| 端到端告警延迟 | 小于 1.5 秒 |
这个结果比想象中好一些。NPU 没打满,CPU 也没被打满,后续如果接入更多点位,还有比较充裕的扩展空间。这也验证了一个判断:前期担心的“推理不够快”其实不是问题,最大的瓶颈反而是网络流的不稳定。
5.2 量化掉点怎么抢救
量化掉点是 RKNN 落地最容易遇到的坑。我前前后后踩了两次,第一次是校准集选得不够,第二次是模型某一层对量化特别敏感。
第一次掉点出现在 helmet 类,原因前面说过,校准集里安全帽太少。解决办法比较粗暴,重新整理校准集,强制让带帽子和不带帽子的场景各占一半,同时通过脚本测试不同校准集得到的模型精度,挑精度最好的那版。
第二次是 head 类在近距离大尺寸样本下掉点明显,定位到是模型中某个分离卷积层对量化敏感。我处理是用混合量化,把这一层单独保留为 float16,其余层保持 int8。RKNN 工具链支持按层指定量化精度,这样做之后 head 类的精度基本和 float 模型持平,推理耗时只增加了约 10%。
给后来者一个建议:不要一上来就追求全 int8。先跑 float16,确认检测逻辑没问题,再逐步把大层切到 int8,每一次切换都用盲测视频看效果,而不是只看验证集指标。
5.3 掉线和内存泄漏怎么处理
工地现场的网络设备常年被粉尘、潮湿、雷击、临时施工折磨。RTSP 流动不动就断,这是做项目教会我的第一课。最开始的拉流代码用的是简单阻塞读取,断流后要等到 TCP 超时才能发现,线程会卡死。后来我改成独立一个“保活线程”,每 10 秒检查一次拉流线程的心跳,超过 30 秒没有新帧就强制重建拉流上下文。
内存泄漏问题是运行一周后从监控面板发现的。观察free命令的输出,内存占用从启动时的 400MB 慢慢涨到 2.8GB。定位后发现是硬解 buffer 的释放时机写错了——有些帧被绑定到 Python 对象,GC 不及时,导致底层 buffer 一直没归还给驱动。最终解决办法是显式在密集循环里调用释放接口,并且把取帧循环改成 C 扩展模块,避免 Python 对象堆积。
这里给大家一个通用排查思路:边缘设备长时间运行,不要等客户报问题,要自己在板子上跑一个轻量监控脚本,记录 CPU、内存、NPU 占用、磁盘剩余空间、网络连通状态,一旦内存增长趋势超过阈值就自动预警。很多偶发问题只有靠日志才能定位。
6. 什么情况下别选 RK3588:选型边界与常见问题速查
6.1 不适合的场景
RK3588 再香,也不是所有边缘 AI 项目都适用。如果你只是做一个便携式的低功耗设备,由电池供电,整个系统预算功耗在 5W 以内,RK3588 就不太合适,它带着视频解码和 AI 单元,闲置功耗也比很多低端 MCU 平台高。如果检测模型复杂度特别高,比如要做 transformer 类的大模型实时推理,RK3588 的 6 TOPS 也扛不住,这类场景还是得上更强的 GPU 或专用 AI 芯片。
还有一种情况是视频路数特别多,比如一个工地要接 32 路摄像头全部做安全帽检测。单片 RK3588 即使把检测频率压到很低,也还是撑不住这么多路。合理做法是每 4 到 8 路部署一个 RK3588 盒子,再往上做集群管理。因为边缘盒子的成本低,故障隔离也更容易,比一台大服务器集中处理更适合分散的工地环境。
最后一个不太适合的场景是:如果现有系统已经有一台空闲的高性能 GPU 服务器,并且工地现场网络条件很好,那直接把视频流推回机房做检测也没问题。边缘化不是目的,省钱和稳定才是目的,不能为了用 RK3588 而用 RK3588。
6.2 常见问题速查表
最后把我在项目里遇到的高频问题整理成了速查表,方便大家直接参考:
| 问题 | 可能原因 | 排查/解决办法 |
|---|---|---|
| NPU 推理时间异常高 | 模型没有量化成 int8,输入分辨率过大 | 确认 RKNN 模型量化配置,检查输入尺寸 |
| 某类目标检测精度骤降 | 量化校准集分布偏差 | 重新整理校准集,混合量化敏感层 |
| RTSP 断流后不再出图 | 拉流线程阻塞,没有心跳检测 | 增加保活线程,超时强制重建拉流 |
| 长时间运行内存持续上涨 | 硬解 buffer 未释放或 Python 对象堆积 | 显式释放 buffer,循环内避免对象引用累积 |
| 告警图片上传太慢 | 网络带宽不足,视频片段码率过高 | 降低回传码率,图片即时传,视频压缩后传 |
| 高温环境 NPU 降频 | 被动散热不足 | 增加主动风扇或更大散热片,监测芯片温度 |
| 模型更新后效果变差 | 新旧模型判断规则不一致 | 版本化模型文件,使用独立配置区分告警阈值 |
踩过几次坑之后,我的体会是:边缘 AI 项目的复杂度不在“AI”上,而在“工程”上。模型选型和训练反而是一开始就能确定的事情,真正花时间的是视频流接入、内存释放、断线重连、告警可靠性这些琐碎但致命的环节。RK3588 作为一个把解码、算力和通用计算都揉在一起的平台,把这些工程问题收敛到了一块板上。如果回到项目原点,我依然会选它,只不过会更早地把“多路视频解码”“断网兜底”和“量化校准”这三件事排进开发计划的最前面。