基于YOLO的行人车辆检测与计数系统实战:从原理到部署

发布时间:2026/10/23 5:29:38
基于YOLO的行人车辆检测与计数系统实战:从原理到部署 某园区做安防系统改造的时候我接过一个挺典型的需求客户要从十几路监控画面里统计出入口的人流和车流。调研那天我去现场待了半天发现三个保安每人盯四块屏手里拿着一张纸画正字。高峰期一到画面里人和车重叠、进进出出别说数准了盯着屏幕半小时眼睛就酸得不行。后来我们交付的这套基于YOLO系列的行人车辆检测与计数系统算是把这块工作接了过去摄像头画面进来模型实时框出行人和车辆再通过计数逻辑统计进出数量最后按小时、按天汇总成流量报表。这篇文章我就把从模型原理到工程落地的完整路径讲一遍为什么选YOLO系列而不是其他检测算法数据怎么准备训练参数怎么调计数逻辑怎么写部署到现场机器上会遇到哪些坑以及几个我踩过的典型问题。整条链路不复杂但每一步都有容易翻车的地方。适合准备做智慧园区、商场客流、交通流量统计的开发者参考也适合刚接触目标检测、想跑通一个完整项目的新手。1. 数得清之前先把需求拆成可落地的指标检测和计数听起来是一回事实际是两个层面的问题。检测的任务是回答画面里有没有目标、目标在哪输出的是一个个框计数要回答的是有多少而且在很多场景下还要进一步回答从哪来、到哪去。如果需求不拆清楚后面整个系统的设计方向都会跑偏。1.1 三种常见的计数需求瞬时人数、断面流量与方向流量我后来把客户的统计人数需求拆成三种签约前就明确问清楚到底要哪一种。第一种是瞬时人数也就是某个区域当前有多少目标。商场某楼层现在有多少人、园区核心区域人数有没有超限这类需求只需要检测加区域判定实现难度相对低。第二种是断面流量一段时间内经过某条线的人或车总数比如小区门口今天进来多少人、路口东西方向过了多少车。这里必须解决同一个目标不能重复数的问题通常要引入跟踪。第三种是方向流量在断面流量基础上还要区分进和出、上行和下行对目标ID的连续性要求更高因为方向判断依赖轨迹的顺序。这三种需求不是层层递进的关系很多客户要的可能只是其中一种。最怕的是把瞬时人数做成方向流量的交付功能做多了反而复杂客户看了数据还会觉得不对。我接过一个真实需求客户说要看商场今天来了多少人这严格说是方向流量而不是瞬时人数如果按瞬时人数去做统计口径从一开始就是错的。1.2 实时性、精度和硬件成本的三角权衡确定需求之后下一步是定指标。我一般会问三个问题现场有几路相机同时接入、画面按多大分辨率处理、现场能放什么级别的机器。这三个答案几乎决定了后面所有技术选型。摄像头通常输出25帧每秒但计数任务不需要每帧都处理。人从进画面到走出去再怎么也要好几秒按5到10帧每秒的采样率就足够漏掉关键事件的可能性很低。把算力省下来做更多路视频往往比单路高帧率更有价值。精度指标也要换算成客户能理解的语言。客户不关心mAP只关心数得对不对。一个误检框在画面里晃动好几秒会不会被重复计数一个目标被漏检几帧跟踪会不会断断了会不会被当成两个人这些问题比mAP数字更直接影响最终统计误差。所以我做方案时通常会算一个计数误差率拿一段标注过的现场视频把系统统计结果和人工数出来的结果对比误差在可接受范围内才算过关。硬件成本这块容易被忽略。训练阶段用好点的显卡没问题但现场部署大多数项目只愿意掏一块中端GPU甚至一个低功耗盒子。所以我从一开始就按这个速度约束选模型而不是先把最大的模型训出来再想怎么压缩。2. YOLO系列凭什么成了这个任务的首选目标检测领域模型很多但提到实时检测大家默认先看YOLO系列。这背后不是跟风而是它确实踩中了行人车辆计数这个任务最核心的诉求快。2.1 从两阶段到单阶段速度是怎么换来的第一次接触目标检测的人很容易被各种模型名字绕晕。简单分个类目前主流检测算法就两大派两阶段和单阶段。两阶段先找候选区域再做分类回归代表思路就是R-CNN那一脉精度普遍高一些但一次推理要走两条链路速度很难满足多路并发。单阶段把检测直接当成回归问题输入图片、输出框和类别一次前向出结果YOLO就是这条路线里最有名的一支。YOLO的核心思想很直觉把输入图片划分成网格每个网格负责预测中心落在自己区域内的目标输出类别、置信度和边界框相对网格的位置。整个过程只做一次前向计算速度快得明显。行人车辆计数这种场景相机多、数据量大、要求尽量实时速度是硬指标所以YOLO系列几乎成了默认选择。2.2 版本演进里的几个关键变化工程上够用就行YOLO系列从早期到现在的版本迭代很快。对做工程的人来说不需要把每篇论文都啃完但有几个关键变化要知道。一是锚框机制从固定候选框逐步演进到无锚框分支说白了就是减少了对预设超参数的依赖训练省心很多。二是主干网络一直在改特征提取能力更强小目标的表现也在变好。三是配套的训练策略越来越完善数据增强、标签分配、学习率调度都内置了几千张数据也能训得挺稳。这里想提醒一句版本号不是越高越好。我实际对比过老版本和新版本在行人车辆数据上的表现新版本同规格下精度确实高一点训练也更快但部署时要注意算子支持和导出兼容性有些新结构在推理引擎里支持不完整速度反而跑不上去。所以我选型的顺序是先确认推理环境支持什么再挑能跑的最高版本。2.3 同门版本怎么选以实际项目为准我通常把YOLO系列按规格分成小、中、大三档。小档适合多路并发和边缘设备中档适合精度敏感但速度也要兼顾的场景大档适合离线分析、对实时性不敏感的任务。型号规格我常用的场景实际感受小档(s)多路实时、低功耗设备640分辨率下单路推理余量大部署问题少中档(m)精度敏感的单路或双路同场景下mAP明显更高误检少一些高档(l/x)离线分析、复杂场景精度上限高但实时性紧张需要更高算力真实项目里我用s和m最多。多数行人车辆场景数据量上来之后s和m的精度差距会缩小而速度差距是实打实的。等s怎么调都差一口气的时候再换m不迟没必要一上来就上大模型。3. 数据这一关标注质量和样本构成决定上限模型再先进数据不给力也白搭。行人车辆这类目标看起来简单数据准备阶段还是有不少讲究而且这些讲究往往不写在官方文档里。3.1 公开数据怎么用自采数据怎么补行人和车辆是检测领域最成熟的类别公开数据集里样本非常多预训练权重也已经见过大量这类目标。所以大部分项目可以走预训练权重加少量现场数据微调的路线不用从零开始。但公开数据有个绕不开的问题视角和现场不一致。公开数据大多是平视街景机位拍的现场很多相机是高处俯视安装目标尺度小、角度完全不同。我碰到过正面机位训练效果很好、换到俯视机位之后漏检率明显上升的情况。解决办法就是自采现场数据每个场景至少抽两三个小时的视频按不同时段抽帧特意挑出有明显遮挡和光照变化的画面标上几百上千张混进训练集一起训练。如果现场还没部署相机用同类场景的视频素材先顶一顶也可以但正式交付前一定要用现场数据再训一轮。这一步几乎决定了模型在现场的可用度。3.2 标注细节这些坑我基本都踩过标注质量直接影响训练效果而标注恰恰是最容易被低估的环节。我有几个反复踩的坑值得单独说说。第一框不要标得太贴目标。很多标注员喜欢把框掐得精准甚至正好贴住目标边缘。但目标在运动框贴太紧会让模型学到错误的边界预测出来的框反而会偏小。稍微留一点背景余量训练更稳。第二遮挡目标不能随便不标。严重遮挡的行人如果完全不标模型学到的是这种画面里没有行人更容易漏检。我的习惯是可见部分足够判断类别的就标被车挡得只剩一条腿的就不标。第三类别不平衡是常态。行人和小轿车样本量通常很大公交车、大货车、电动车则少得多。样本少的类别要么在增强时多复制要么单独调整该类别的检测阈值不能只指望模型自己学会。还有一个教训某客户临时加了一个三轮车类别拿了500多张图让我训结果那类一直不收敛。查到最后发现是标注问题一半的样本类别填错了。数据质量不过关再好的模型也救不回来。3.3 增强策略要对着痛点来YOLO训练默认带了一堆增强策略不需要自己造轮子但要知道每项增强解决什么问题。mosaic增强把多张图拼在一起训练对遮挡和小目标很有效行人车辆这种目标分布比较分散的场景很适合。夜间场景用亮度抖动和直方图均衡来模拟低照度如果现场有雨雾天气加模糊和噪声增强比单纯调亮度更有效。但增强不是越多越好。行人车辆是方向性很强的目标大幅旋转这类增强会制造一堆现实中不存在的样本反而干扰训练。我一般只开对现场真实分布有帮助的增强其他关掉省时间也省算力。4. 训练实战从预训练权重到项目模型的完整路径数据整理完训练阶段反而不是最难的。把流程标准化、参数理解透基本不会出大问题。这一节我直接给出一套可以照着做的路径。4.1 模型规格怎么定我的两条经验法则具体到参数选择我给自己定了两条经验法则每个类别数据量低于几千张的用s型号起步效果不够再升级到m数据量大、GPU余量充足才考虑更大的规格。道理很简单s型号在640分辨率下已经能满足大部分计数场景的检测需求先跑通再升级比一开始就堆大模型稳得多。4.2 数据目录、配置文件与训练命令项目里我会把数据整理成固定结构方便后续增量训练复用dataset/ ├─ images/ │ ├─ train/ │ └─ val/ └─ labels/ ├─ train/ └─ val/类别定义放在一个配置文件里行人车辆相关的常见类别先列出四个为例person、car、bus、truck。实际项目按需要定义也可以加摩托车、自行车、三轮车。path: ./dataset train: images/train val: images/val nc: 4 names: 0: person 1: car 2: bus 3: truck训练命令本身不复杂不同版本的官方仓库写法略有差异但参数思路一致。我给出一个常见示例yolo train datatraffic.yaml modelyolov8s.pt epochs150 imgsz640 batch16 lr00.01这里说明一下为什么用预训练权重而不是从零训练。公开的预训练权重已经见过海量行人和车辆样本迁移到项目数据上只需要很小的代价从零训练需要大得多的数据量在中小规模项目里基本没必要。如果类别数变了最后一个输出层会重新初始化这是正常现象不需要担心。4.3 训练过程怎么盯loss曲线和验证指标训练不是把命令丢下去等结果至少每天看一次曲线。重点盯两条loss曲线的走势。训练loss下降、验证loss也下降说明模型在正常学习验证loss开始持平甚至上升而训练loss还在降基本可以判断过拟合了这时要么加强数据增强要么提前结束训练。如果loss出现NaN优先怀疑学习率过高或者数据里有损坏的图片和空标签。指标主要看两个mAP50和mAP50-95。对计数任务来说mAP50更贴近框大体位置对了没的感受mAP50-95对框的精确程度更敏感。我通常以mAP50作为主要验收指标但也会看一眼mAP50-95防止框虽然被算作命中、位置却飘得厉害的情况。训练早停建议按验证集指标设置连续20个epoch没有提升就停止没必要死等150个epoch跑完。这个设置对中小数据集能省下不少时间。5. 计数模块检测结果如何变成流量数字模型输出的是检测框这些框并不会自动变成多少人多少车。计数模块就是把检测结果翻译成业务数字的关键一层也是我认为最需要动脑子的地方。5.1 区域计数先判断目标在不在多边形里区域计数要回答的是某个区域内现在有多少目标。实现思路很简单拿到每个检测框取一个代表点判断它是否落在预先画好的区域内。代表点我建议用检测框底边中点而不是框的中心。行人双手摆动会让中心点左右偏移可能把原本站在区域内的人判到区域外底边中点是脚踩的位置对站立目标更稳定。车辆也一样底边中点更接近车体着地的语义位置。判断点是否在多边形内用经典的射线法就够了def point_in_polygon(point, polygon): x, y point n len(polygon) inside False px, py polygon[0] for i in range(n 1): cx, cy polygon[i % n] if y min(py, cy) and y max(py, cy) and x max(px, cx): if py ! cy: x_intersect (y - py) * (cx - px) / (cy - py) px if px cx or x x_intersect: inside not inside px, py cx, cy return inside区域计数的输出是瞬时人数帧间会有抖动我会做一次滑动窗口平滑让数字变化更自然也避免报警阈值被单帧抖动触发出误报。5.2 跨线计数跟踪器解决重复计数问题跨线流量统计比区域计数麻烦核心问题在于重复计数。一个行人站在计数线附近来回走动如果没有跟踪机制每次出现在线边都可能被算一次。要解决这个问题得让每个目标有唯一ID并且只对每个ID计一次。做法是给检测结果接一个跟踪链路。跟踪的基本原理是用卡尔曼滤波预测每个目标在下一帧的位置再把新一帧的检测框和预测位置做匹配距离接近就认为是同一个目标。匹配可以用简单的IoU也可以结合外观特征。对行人车辆这类运动比较规律的目标轻量的IoU匹配通常就够用不需要上太重的方案。这里有一条我在实践中摸索出来的重要经验跟踪效果好不好根源在检测稳不稳。模型偶发漏检一帧跟踪就断目标重新出现时会被当成新ID计数直接翻倍。所以做计数系统时我会刻意把检测置信度阈值压低一些宁可多几个误检框也不要让目标消失。多余的误检框可以在跟踪端用持续帧数过滤掉两害相权取其轻。跨线判断的核心代码片段我贴一下思路是记录每个ID上一帧在计数线哪一侧侧向符号发生变化就说明跨线了line_start (100, 400) # 计数线起点 line_end (600, 400) # 计数线终点 track_states {} # track_id - (上一帧side, 是否已计数) def point_side(a, b, p): return (b[0]-a[0])*(p[1]-a[1]) - (b[1]-a[1])*(p[0]-a[0]) for track in tracks: x1, y1, x2, y2 track.box foot ((x1x2)/2, y2) cur_side point_side(line_start, line_end, foot) if track.id in track_states: prev_side, counted track_states[track.id] if prev_side * cur_side 0 and not counted: total_count 1 track_states[track.id] (cur_side, True) else: track_states[track.id] (cur_side, False)如果需要区分进出方向再根据目标是从A侧到B侧还是B侧到A侧分别累加在代码里加两个计数器就行。5.3 计数误差怎么评估才靠谱计数模块做完一定要用现场视频回放验证。我会准备一段人工数过结果的视频对比系统统计的数量算出计数误差率。曾有一套方案在某路口上线初期方向流量误差在15%左右定位下来就是夜间漏检和ID断裂两个原因把检测阈值和跟踪匹配参数调整之后误差降到了5%以内。还有一个容易被忽视的问题计数线的位置。画在视野边缘目标还没完全进入画面就跨线框不稳定会带来很大的计数误差画在画面中间偏下、目标姿态相对完整的位置计数会稳很多。这个细节看似简单但对误差影响很大。6. 部署加速把模型推到现场机器上跑起来训练环境里的模型和现场能稳定跑的模型之间还隔着部署这一步。这一步做不好前面所有工作都白费。6.1 模型导出别踩算子兼容的坑训练和验证都在开发环境里现场部署的第一步是把模型导出成推理格式。导出的坑我在不同框架上都踩过最常见的是三种自定义算子不支持转换、动态输入尺寸导致性能下降、导出前后推理结果不一致。我的建议是训练时就把输入尺寸定死比如640x640不要用动态尺寸。固定尺寸在推理引擎里能走更激进的优化速度更稳定。导出之后一定要拿几张现场图片对比导出前后的输出框确认没有明显差异再往后走。这一步五分钟就能做完却能省掉大量现场排障时间。6.2 让模型跑得更快半精度、量化与小模型替换GPU部署时先把模型转成推理引擎支持的格式同时开启半精度推理。这一步速度提升已经很明显精度几乎没有损失。如果还嫌慢再考虑整数量化速度提升更大但小目标和夜间场景容易出现精度回退必须拿现场数据实测后再决定。优化手段速度提升幅度精度影响我常用的场景固定分辨率半精度明显提升几乎无损通用GPU部署整数量化大幅提升小目标可能掉点低功耗设备换小规格模型大幅提升需要重新训练验证多路视频并发CPU也不是不能跑。现场预算有限时降低输入分辨率、降低采样帧率CPU方案能勉强支撑单路到两路视频。但一旦视频路数多起来CPU解码本身就会占掉大量算力模型能分到的资源非常有限这种场景建议还是用带硬件解码能力的设备。6.3 视频流接入瓶颈经常不在模型本身现场摄像头一般走RTSP协议拉流。做计数系统多了之后我发现最容易出问题的反而是视频流接入和解码这一层。多路视频并发解码非常吃资源处理队列不及时的话延迟会越堆越高模型算得再快也没用。我的处理策略是每路视频独立拉流按固定间隔采样取帧宁可跳帧也不让队列堆积解码端优先用硬解码把CPU资源留给推理和计数逻辑每路视频维护一个最近若干帧的缓冲区用于网络抖动时的异常恢复。这些小细节现场跑起来才知道有多重要。7. 实测踩坑夜间漏检、遮挡误计和视角迁移这一节的内容基本都是从真实项目里踩出来的写出来是希望你能绕开。7.1 夜间与逆光数据增强之外还得有预处理行人车辆检测在白天通常问题不大一到了晚上就开始露馅。夜间漏检率明显上升车灯、路灯会产生光晕误检逆光场景下目标轮廓不清晰框的位置还会飘。我在一个夜晚车流统计项目里最初夜间mAP比白天低了十几个点。后来做了两步修复。第一步是在数据里加入夜间素材并在增强配置里模拟低照度第二步是在推理前加一个轻量的图像预处理做亮度矫正让暗部细节更明显。两步叠加夜间指标拉回大半。还要特别注意夜间误检的形态和白天很不一样比如把路灯光斑当成人、把车灯当作两个目标。这类误检不能只靠检测阈值去除要在跟踪端用持续帧数和运动特征过滤判断目标是不是在画面上稳定移动。7.2 密集遮挡ID跳变是计数的天敌商场出入口的人流高峰期人挨着人检测框互相遮挡。最典型的故障是同一个行人被拆成两个ID计数翻倍或者跟踪ID在两个相邻目标之间跳变统计出来的流量和实际相差很大。这类问题只调跟踪参数是治标不治本。我的经验是回到检测端密集场景下把置信度阈值适当压低让遮挡目标的检测框尽量连续输出跟踪匹配时给IoU阈值留一点余量避免一帧轻微位移就断掉关联。另外有一个思路上的取舍如果客户真正需要的只是区域现在有多少人我建议优先做区域计数而不是断面流量。排队静止场景下跟踪本来就不稳定减少对跟踪的依赖结果反而更准。7.3 机位视角变了模型效果就变了再好的模型也有适用边界。模型是按照训练数据的视角、距离、安装角度学习的现场机位一变效果就可能明显下滑。我遇到过一个典型案例模拟机位测试通过正式机位视野更远目标变小之后漏检率直接上升。解决思路有三个方向。一是用现场数据采样后做增量训练这是最根本的办法。二是适当提高输入分辨率小目标检测会好一些但显存和耗时也要算清楚。三是对远景目标区域做局部放大把远处小目标放大后再送入检测代价是增加一次额外推理适合单路低速场景。项目验收时我会把每条相机的机位参数高度、角度、焦距记录下来和模型版本关联。之后客户调整机位我们就能提前预估效果会怎么变化而不是到了现场才发现问题。最后再分享一个我坚持了很久的习惯模型上线只是开始不是结束。现场环境会变施工围挡、新店招牌、季节植被都会制造新的误检和漏检。我现在每个项目都会留一条反馈数据回灌路径定期从现场抽帧快速人工标注每周做一次增量训练。这套机制跑起来之后系统不是越用越钝而是越用越准。做检测计数项目这么多年我最大的体会就是算法模型只占一半另一半在数据闭环和工程细节里。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询