做这种项目之前,我一直觉得“三轮车不戴头盔、违规载人识别抓拍”就是把机动车电警那套搬到非机动车道上,真正上手才发现完全不是一回事。电动三轮车体积小、速度快、位置乱,加上非机动车道光照条件差,单纯在监控画面上画检测框根本没法用。这篇文章不聊理论框架,只聊我实际落地的算法选型、抓拍点位设计、证据链组织和最容易被验收方挑毛病的那些坑。
1. 项目定位与边界:这类“非机动车抓拍”到底在解决什么问题
1.1 你要抓的“违规”究竟指什么:三种典型场景
项目标题里有两件事:一是“不戴头盔”,二是“违规载人”。很多人第一反应是把这两个行为分别做成两个独立检测模型,但实际在业务层必须把它们合并成一个“事件”。
我在项目中把抓拍场景分成三类:
第一类是单人骑行且未佩戴头盔,这种最普遍。难点不在检测头盔,而在确认“头部区域”和“头盔区域”的对应关系。第二类是骑乘人员未戴头盔且载人,载人位置可能是后斗、踏板或侧座,需要先定位人员再判断是否存在多目标。第三类是载人且头盔佩戴完整,这个合规但容易被算法误判成违规,所以判定逻辑要同时看“载人”和“头盔”两个分支。
这种三分法直接影响数据集设计。如果只训练一个“戴头盔/不戴头盔”二分类器,场景二和场景三在画面里经常同时出现头盔和未戴头盔的人,输出结果会乱掉。
所以我在实际算法里用了多人跟踪加属性识别的结构:先检测画面中的“人”和“头盔”两类目标,再做目标关联。一个骑行人头如果没有匹配到任何一个头盔框,就判定为“不戴头盔”;如果同一时刻画面里出现了两个及以上独立人员目标,再结合车型判断是否载人。
1.2 与机动车电警抓拍的本质差异
机动车电警抓拍之所以成熟,是因为车道线清晰、车辆轨迹相对固定、车牌位置统一。三轮车场景完全是另一回事。
先说车身方向。机动车抓拍只需要在车头或车尾一个方向布相机,三轮车可能从左侧、右侧甚至斜侧经过,头盔是否可见取决于相机角度。骑行人如果戴了帽子或者有遮阳棚遮挡,头部目标会被分割。
再说目标尺度。机动车车身占画面比例大,三轮车相对小,如果相机架在杆子高处,骑行人头部可能只占据画面几十个像素。目标检测模型对几十个像素的小目标本就敏感,加上头盔和头发颜色接近,很容易漏检。
还有一个关键差异——雨棚。很多三轮车加装了全封闭雨棚,驾驶员头部被半透明塑料遮挡。这种场景下“不戴头盔”的判定在图像层面很难成立,业务上需要设置“无法判断”的兜底状态,而不是硬判。硬判的结果就是误报率高,最后被人工审核推翻。
1.3 系统组成与数据流向
这类识别抓拍系统的完整链路不是“摄像头+算法”两个词能概括的。按我的经验,至少拆成五层:
采集层是工业相机和补光灯,负责固定点位成像。感知层是边缘计算盒子或AI相机内置算力,跑目标检测和跟踪。事件层完成语义判定,比如“有几个人、头上有没有头盔、是否载人”。证据层生成一组图片和结构化信息,包括时间戳、点位编号、抓拍原因。平台层负责接收、存储、检索和人工复核。
我偏好的数据流向是:相机通过RTSP拉流给边缘盒子,盒子内部以25帧/秒做抽帧推理,检测结果进跟踪器,跟踪稳定后触发抓拍。抓拍得到的图片通过HTTP或MQTT上传到后端服务。这么做的好处是,即使平台断网,边缘端依然可以独立完成识别和抓拍,事后补传。
不要试图把所有画面都传到云端再分析。以某测试点位为例,单路相机一天产生的原始视频流接近400GB,全量上传根本不现实。边缘计算的意义就是把无效画面直接丢弃,只保留证据图片。
2. 感知层选型与部署:摄像头、算力盒子与现场安装
2.1 相机选型:枪机还是球机,补光与抓拍距离
很多刚接触这类项目的人会问:用普通监控摄像头行不行?我这里明确一下:民用安防摄像头适合人形检测,但放到三轮车抓拍这种需要出证据链的场景,清晰度、帧率、曝光控制都跟不上。
建议优先选400万或800万像素的工业级枪型网络相机。枪机画面畸变比球机小,适合固定断面抓拍。变焦范围不用太大,检测区域宽度覆盖5到6米就够用,焦距选8mm到12mm比较稳。球机虽然可以跟踪转动,但转动过程的模糊帧会导致证据卡失效,日常运维成本也高。
补光是必须的。非机动车道夜间环境光很差,没有补光拍出的照片连人脸轮廓都看不清楚。我用的方案是暖光LED常亮灯加频闪灯联动,常亮灯保证视频流里能稳定检测,频闪灯在抓拍瞬间补强画面细节。单点补光灯功率按40W左右配置。
关键参数对照表(基于某测试项目经验值,具体以现场为准):
| 项目 | 建议值 | 说明 |
|---|---|---|
| 相机像素 | 400万–800万 | 头部小目标需要足够像素承载 |
| 抓拍距离 | 8–20米 | 距离太近角度过陡,太远夜间补光不足 |
| 检测区域宽度 | 5–6米 | 覆盖一条非机动车道即可 |
| 安装高度 | 4.5–6米 | 高于3米能避遮挡,超过6米小目标会浅显化 |
| 补光灯类型 | 暖光常亮+频闪 | 频闪能提高抓拍瞬间的清晰度 |
2.2 算力平台选择:本地推理还是边缘盒子
算法跑在哪一层,直接决定了成本上限。有两种主流方案供参考。
第一种是AI相机内置算力,目前市面挺多。优点是一体化程度高,部署简单,布线和设备数量都少。缺点是算力有限,跑轻量模型还行,一旦要同时做检测、跟踪、属性识别,处理帧率会掉到个位数。
第二种是普通相机加边缘计算盒子。盒子的算力一般从8TOPS到100TOPS不等。我用过的测试方案里,20TOPS左右的国产边缘盒子可以同时处理4路400万像素相机的实时流,单路达到25帧/秒检测加跟踪。
如果项目点位多、管理集中,我还会把边缘盒子做成集群,通过一个统一管理平台下发算法版本。算法升级不需要跑到现场烧卡,这在验收后尤其重要,因为你永远不知道现场会加装多少新点位。
对单点试验项目来说,买个AI盒子自己接相机最灵活。启动成本不高,后面换相机、调算法参数都可以自主控制,不被厂商绑定。
2.3 安装高度与角度的三个关键参数
现场安装如果没做好,算法再强也白搭。我吃过亏,总结下来有三个参数必须现场实测。
第一个是相机俯角。推荐在15度到30度之间。俯角太低会把后方远车当作目标,干扰载人判定;俯角太高,骑行人头部会严重变形,头盔检测框不稳定。我习惯先挂临时支架,用实时视频观察不同俯角下的目标尺寸变化再固定。
第二个是水平朝向与车道夹角。相机光轴方向尽量不要与车道完全垂直,建议保持60度到80度的斜向视角。斜向视角可以看到骑行人侧面,头盔特征更明显,同时能拍到车身和人员数量。
第三个是检测断面位置。在监控画面里划定一条虚拟“抓拍线”,当目标越过抓拍线时触发抓拍。这个线不能设在画面边缘,远端目标的框不稳定;也不能太近,太近留给算法的时间不够。
我实测过某个安装点,把抓拍线设在距离相机12米左右的断面,画面中骑行人的头部像素高度约60到80像素,检测置信度能稳定维持在0.85以上;如果放到18米,头部像素高度只有30左右,漏检率明显上升。
3. 模型训练与算法链路:从数据采集到违规事件判定
3.1 训练目标拆解:头、头盔与人员关联
这个项目的模型不是单一目标检测模型,而是检测加属性关联的组合。我从标注阶段就把类别拆成三个:person(含骑行和乘坐人员)、head、helmet。
为什么拆开?因为“是否戴头盔”是一个关系的判断。如果把“戴头盔的人”和“不戴头盔的人”直接做成两个类别,遇到多人场景时类别和个体的对应关系要靠后处理重新梳理,反而麻烦。
我用的是单阶段检测器做定位,再加一个轻量分类分支判断检测到的头部目标是否被头盔覆盖。这个轻量分支的输入是从head框切出来的图像区域,输出“戴/不戴”两个类别。训练时直接把head框和helmet框的IoU大于某个阈值(比如0.5)的样本视为正样本,低于阈值视为负样本。
这里有个容易踩的坑:helmet框是用头部中心点扩展出来的,还是用真实头盔外框?我最后采用了真实头盔外框,因为实测中同一顶头盔在不同角度下比例变化很大,用头部中心点扩展会引入噪声。
在项目初期没有现场数据时,可以先从公开数据集里筛出一部分非机动车样例做预训练,再用现场相机拍摄的视频做迁移学习。现场样本至少要覆盖晴天、阴天、夜间三个时段,否则模型白天效果好、晚上就崩。
3.2 样本采集与标注策略:白天黑夜与雨棚场景
数据采集会直接决定模型上线后的表现,我建议按比例分配样本:白天正常光照占40%,夜间补光场景占40%,清晨黄昏弱光占20%。如果现场存在大量加装雨棚的三轮车,要考虑单独增加一个“遮挡头部”的类别。
标注时需要注意,很多外包标注团队默认只标“人”和“头盔”,这会导致模型对“坐在后斗里的人”失效。我花了很大功夫给标注规范加了一条:只要画面中出现的可辨认的人员,不管在驾驶位还是货斗,都必须标出person框和head框。
对遮挡严重的样本,不要强行标注“不戴头盔”,应标为“无法判断”。这个类别在训练时不会参与违规判定,但能显著降低误报率。实际部署中,把“无法判断”的置信度阈值调低,让这类样本倾向于不抓拍。
我还试过用图像合成的方式扩充夜间样本。具体做法是取白天场景的检测目标,按照夜间背景的光照分布做亮度迁移,再叠加随机噪声边缘。可以节省一部分夜间采集时间,但要注意合成的目标如果过度模糊,会让模型变得过于保守。
3.3 跟踪与事件判定逻辑:避免重复抓拍
边缘端实时检测出目标后,不能每一帧都上报,需要一套多目标跟踪加事件状态机。
我用的跟踪方案是IOU跟踪加外观特征融合。三轮车骑行人的外观变化小,头部检测框稳定,IOU跟踪在短时遮挡下足够用。跟踪器会给每个目标分配一个临时ID,并记录最近N帧的检测结果。
事件判定状态机可以简化为:
- 目标首次进入检测区域,初始化跟踪ID,状态为“观察中”。
- 连续3帧检测到同一ID的目标,且头部判决为“不戴头盔”,状态改为“疑似违规”。
- 目标越过抓拍线,且当前状态为“疑似违规”,触发抓拍事件。
- 同一个跟踪ID在5秒内只触发一次抓拍,避免重复上报。
第4步非常关键。如果漏掉,单辆三轮车通过监控区域会产生几十张图片,后端平台会被刷屏。事件冷却时间可以根据车道宽度调,我一般设4到6秒。
载人判定也是一个独立事件分支。当person目标数量在同一帧图像中大于等于2,且两个person框的中心距离小于预设的车身宽度阈值时,判定为载人。单独做这个判定是因为有时路人从车旁走过,会被误判成“载人”。
3.4 模型加速部署:本地推理框架与边缘端转换
模型训练完成后不能直接扔到边缘盒子跑,得做推理框架转换和量化。目前边缘盒子支持较好的推理框架主要包括TensorRT、OpenVINO和各家芯片自带的Runtime。
我以TensorRT为例说明转换流程。先用训练框架导出ONNX模型,再用TensorRT的ONNX解析器生成engine文件,转换时打开FP16精度。FP16相比FP32的速度提升大约一倍,精度损失在1%以内,对头盔检测来说完全可以接受。
实际转换中经常遇到一个问题:模型里的自定义算子(比如部分检测头的解码层)不被TensorRT直接支持。解决办法是在导出ONNX时把这些算子替换成标准算子,或者在推理代码里把后处理剥离出来,让TensorRT只负责特征提取。
我的一套检测加跟踪推流,在20TOPS边缘盒子上实测,单路1080P分辨率下耗时约25毫秒到35毫秒,折算下来每秒能处理28到40帧。如果分辨率升到400万像素,耗时会增加一倍,这时可以适当降低检测帧率到15帧/秒。
4. 抓拍证据链与后端平台设计
4.1 证据卡设计:特写、全景、号牌与结构化信息
单独一张抓拍图没有说服力。我在平台上保存证据卡时,会将一张大图合成成四宫格:
左上角是全景图,展示三轮车完整轮廓、骑行人员数量和道路环境;右上角是骑行人头部的特写裁剪图;左下角是车辆尾部放大图,用于识别车身编号或悬挂号牌;右下角是车辆后斗区域图,用于确认载人状态。
这个设计参考了电警“三张图”逻辑,但针对三轮车做了调整。三轮车很多没有车牌,所以车辆本身的外观特征(颜色、斗型、雨棚颜色)必须留在证据中。
每次事件会附带一段结构化信息,包括点位编号、相机编号、事件时间、事件类型(未戴头盔/载人/未戴头盔且载人)、置信度、证据卡图片地址。这些字段必须存在同一JSON里,方便后平台直接解析入库。
置信度不是最终判定结果,而是给人工复核看的参考值。我习惯把模型输出的置信度保留两位小数存下来,这样即使算法误判,之后做统计和模型迭代时也能回溯。
4.2 图片存储与命名规则
图片存储看起来简单,但命名规则如果设计不好,后续检索会非常痛苦。
我的命名规则是“点位编号_相机编号_时间戳_跟踪ID_事件类型.jpg”。举一个例子:P01_C02_20250510143025678_00123_helmet.jpg。这样即使图片被到处转发,也能直接从文件名反查点位和事件时间。
存储目录按月份加日期分目录,日目录下再按事件类型分子目录。后端平台检索时,直接按日期范围加事件类型扫目录,减少数据库压力。
文件格式上我统一用JPEG保存证据卡,质量参数设90。原始检测帧单独存为PNG会导致容量爆炸,实测一天单点事件图片量在300到800张之间,JPEG平均一张200KB左右,占用完全可接受。
如果要求保存短视频片段,那存储量会指数增长。我目前只对抽查点保存抓拍前后各1秒的视频片段,普通点位不启用。否则一个点位一天会多出几十GB,后端存储成本会压垮项目预算。
4.3 事件推送与处置闭环
识别抓拍系统产生事件后,还必须有推送和处置环节,否则就是“拍了没人管”。
我设计的流程是这样的:边缘盒子生成事件后,通过MQTT协议即时推送一条消息给平台;平台收到后写入数据库,同时给审核人员的工作台推送待办任务;审核人员快速看一下证据卡,选择“有效”“无效”或“无法确认”;有效的事件进入后续处置流程,无效事件进入误报库,用于后端算法迭代分析。
这个闭环看似简单,却决定了项目的实用价值。我见过不少项目只把抓拍图片发到群里,结果几天后文件夹里堆满图片却没人处理,最后还是被砍掉。
误报库一定要利用好。每个月的误报数据导出来做一次统计分析,看是夜间反光引起的误判,还是远处行人被误认为载人,再针对性采集这些场景的数据去微调模型。持续迭代两个月后,有效率可以从初期的70%左右提升到90%以上。
5. 实测中常踩的坑与优化套路
5.1 头盔远小目标漏检:为什么同一模型在不同距离表现差异很大
现场部署和训练数据集最大的差异是目标尺度。算法在测试视频上看不出来的小目标问题,一旦装到6米高杆子上就会暴露。
我在第一次现场实测时,远处20米外驶来的三轮车完全没检测到。排查后发现,模型训练集中头部框的最小像素尺寸是32像素以上,而现场20米处头部框只有20像素左右。后来我把训练数据的短边进行随机缩放,并把最小目标尺寸降到16像素,重新标注了一批远距离小目标样本,效果立刻好转。
另一个有用技巧是在数据增强里加入随机裁剪和放大。让模型学会在画面中不同尺度下识别同一个目标,而不是只对特定尺度敏感。
如果你不想改动训练数据,也可以在部署时把输入图像切块拼接,将画面分区域放大后再推理。但这样做会让单帧推理耗时翻倍,我用在重点点位,不会全量开启。
5.2 夜间补光与过曝问题
夜间补光能把画面照亮,但也容易过曝。尤其是某些品牌的频闪灯在近处目标上形成强烈的光斑,头部区域反而被“打白”,头盔和头发完全分不清。
我的处理办法是调整曝光参数,设置固定曝光时间和增益上限,而不是让相机自动曝光。自动曝光在夜间遇到车灯或路灯时,画面会忽明忽暗,检测框跟着抖动。
补光角度也要微调。灯光不要正对相机光轴方向,最好稍微偏向外侧,让光线斜着照亮路面。这样既照亮目标,又不会形成正反射。
如果条件允许,在夜间场景里增加一帧IR红外补光图,与可见光图做融合推理。红外图对暗部细节的补充非常明显,我测试后夜间戴盔检测准确率能提升8到10个百分点。
5.3 载人判定误报治理:路人与乘客的区别
“载人”判定是误报最严重的地方。常见场景包括:骑行人和路边行人并行、骑行人身旁有人推车、三轮车旁边经过一辆电动车。这些情况都会在画面里出现两个person框。
先做了距离阈值限制。骑行人对应的person框和路人对应的person框虽有重叠,但中心距离通常大于1米;而真正的载人场景,后斗乘客和驾驶员的中心距离一般不超过1米。这个阈值根据相机安装高度和角度会变,需要现场标定。
再把速度一致性纳入判定。同一跟踪ID下,骑行人移动方向一致,如果旁边出现一个速度方向不同的person框,大概率是路人,不判载人。
用跟踪轨迹的一致性收益很大,我把它作为“载人”事件的必要条件。只有两个person框在连续多帧中保持相对位置稳定,才进入载人判定流程。
5.4 性价比与验收建议
最后聊一下成本控制。边缘盒子加工业相机的单点方案,硬件成本通常控制在几千块这个级别,具体视镜头和补光配置而定。相比动辄几十万的机动车电警系统,三轮车抓拍项目投入低很多,适合重点路口先试点再铺开。
验收时建议把指标分成三块,不要只看算法准确率:
第一是事件有效率,被人工审核认定为有效的抓拍事件占全部抓拍事件的比例。第二是漏检率,用现场摆放假人或安排专人骑行的方式测试算法是否漏拍。第三是系统稳定性,连续运行7天不掉线、不丢事件。
验收前一定留一周试运行时间,把误报和漏报数据攒够。用这些数据调整置信度阈值、事件冷却时间和抓拍线位置,远比算法工程师拍脑袋调参靠谱。
我个人的感受是:这类项目里,算法只占四成,场景理解和现场调试占六成。很多团队拿着高精度模型上去,最后折在现场的安装角度和业务定义上。如果只是想要一个能演示的Demo,那随便一个开源检测模型就能跑通;但要做到天天能出有效证据、能被审核人员认可,还是得把每个环节都当成工程问题来抠。项目扩展方向上,可以考虑把识别结果联动到路口语音提示桩,让现场即时听到“请佩戴头盔”的语音提醒,减少人工处置压力。这个功能我们已经做了,效果还不错。