ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

YOLOv5+DeepSORT实现车辆行人追踪与计数:原理、配置与调优

YOLOv5+DeepSORT实现车辆行人追踪与计数:原理、配置与调优 简介面向人工智能、深度学习方向的毕业设计基于YOLOv5与DeepSort实现车辆和行人实时追踪与计数。源码经过本地编译验证运行稳定适合高校学生完成课程设计、毕业论文或相关课题入门学习。包内共120个文件主要包括Python源码py/pyc、模型配置文件yaml、标注与说明文档xml/txt/md以及训练权重pt、示例视频mp4等压缩包约129.68MB目录结构清晰便于按模块检索。目前已有232人学习下载。内容覆盖目标检测、特征提取、多目标跟踪与计数全流程附带预训练权重和测试视频可直接运行验证效果也可作为毕业设计演示、项目答辩或二次开发的基础。项目难度适中助教审定适合需要结合实际代码理解YOLOv5与DeepSort原理的学习者。1. 这个毕业设计压缩包里的追踪计数项目拆开是什么拿到一个命名带“毕业设计.zip”的工程大多数人会先双击解压期待里面有一个能直接运行的exe。实际上这类基于YOLOv5DeepSORT的项目打开后看到的是一堆.py文件、.yaml配置和一个README真正要跑起来得自己把模型权重、Python环境和视频输入全部配齐。这条技术路线之所以在毕设里被反复使用不是因为代码量少而是因为它把两个成熟库拼在一起YOLOv5负责“看到人车”DeepSORT负责“记住谁是谁”最后由一段计数逻辑把轨迹去重后统计出来。这套方案的适用面很宽校门口的车辆进出统计、商场客流、实验室的交通视频分析都能用而且对硬件要求不高一张GTX 1660就能跑到实时。适合的人群是已经把Python基础课学完、想在毕业设计里用上目标检测但不想从零写网络的学生或者刚工作的工程师想快速搭一个行人追踪demo。需要先说清楚的是YOLOv5和DeepSORT并不是同一个仓库里的东西前者是检测器后者是跟踪器两者通过框坐标和外观特征对接这才是整个项目真正的技术门槛。2. YOLOv5DeepSORT为什么能组合成稳定追踪器2.1 yolov5网络结构检测器输出什么决定了跟踪器能不能接住yolov5网络结构从整体上看是典型的单阶段检测器由Backbone、Neck和Head三段组成。Backbone是CSPDarknet负责从原始图像里提取多尺度特征CSP结构把特征图拆成两条路径再合并好处是在减少计算量的同时保住梯度流动性Neck用的是PANet把高层语义特征和底层空间特征做双向融合这样小目标比如远处的行人也能被召回Head部分输出三个尺度的预测结果分别对应大、中、小目标每个预测结果包含边界框坐标、类别置信度和目标属于各分类的概率分布。选择yolov5而不是Faster R-CNN或者SSD来配合DeepSORT原因很直接追踪任务要求检测器足够快DeepSORT本身并不能提高帧率检测慢一帧整个管道就慢一帧。yolov5s在640x640输入下一张GTX 1660上的推理时间大约在10ms量级而Faster R-CNN的ResNet50版本通常在200ms以上实时性差距巨大。下表是毕设里最常比较的四个模型尺寸参数来源是业内公开的基准测试数据不同版本之间有小幅浮动但量级是可信的。模型参数量单帧推理耗时T4640输入适用场景YOLOv5s约7M约3ms笔记本CPU可勉强跑实时性最好YOLOv5m约21M约6ms中等显卡精度与速度平衡YOLOv5l约46M约10ms精度优先需要独立显卡YOLOv5x约86M约17ms离线分析不适合视频流实时追踪毕设里选yolov5s或yolov5m最合理。s在夜间、雨雾条件下漏检会明显变多m的改善值得多花那几毫秒。如果手里只有CPU没有N卡s加640输入还能勉强每秒跑几帧再大就完全不现实。2.2 DeepSORT的级联匹配运动特征和外观特征谁说了算DeepSORT全称是Deep Simple Online and Realtime Tracking它是SORT的改进版。SORT只用了卡尔曼滤波预测目标位置再用IoU做匈牙利匹配一旦目标被遮挡几帧重新出现时就会丢失原ID这在行人互相遮挡时几乎必然发生。DeepSORT在保留卡尔曼滤波的同时加入了一个外观特征提取器通常是ReID网络把每个检测框内的目标编码成一个128维或512维向量入库保存匹配时用余弦距离衡量外观相似度。两种距离的计算方式完全不同。马氏距离衡量的是“卡尔曼滤波预测的位置”和“当前检测框位置”的偏差把预测误差的协方差矩阵考虑进去主要用于剔除明显不可能匹配的检测框。余弦距离衡量的是“这个人的衣服颜色、轮廓特征”和“之前某个ID记住的样子”的差异。最终的总代价是两种距离的加权和权重由一个超参数控制常见代码里默认为0或1即要么只看运动、要么只看外观。级联匹配的意思是把连续丢失帧数少的轨迹优先匹配不让那些消失很久的轨迹抢占资源最后再用IoU匹配兜底处理新出现的框。这段逻辑的核心价值在代码里体现得很清楚。以下是在工程里常见的做法我一般把ReID特征提取放到一个单独类里管理避免每次匹配都重载模型# DeepSORT外观特征提取器的常见封装模型可用torchreid里的osnet或resnet50 import torch import torchreid # 加载预训练ReID模型输出特征维度默认512 model torchreid.models.build_model( nameosnet_x1_0, num_classes1000, pretrainedTrue ) model.eval().cuda() def extract_feature(crop_image): # 输入是检测框裁剪出来的行人小图尺寸resize到(256, 128) tensor torch.from_numpy(crop_image).permute(2, 0, 1).unsqueeze(0).float() / 255.0 tensor tensor.cuda() with torch.no_grad(): feature model(tensor) # 输出形状(1, 512) return feature这里有两个关键参数需要注意。num_classes1000只是初始化分类头用推理时取的是分类头之前的全局特征向量类别数并不会影响特征质量。输入尺寸必须固定ReID网络对尺度敏感如果检测框宽度和高度比严重失衡比如一辆卡车被硬压成(256, 128)特征会严重失真这也是为什么很多人只对行人和小轿车做追踪没问题一加入公交车和大货车ID就开始乱跳。2.3 从检测框到稳定track_id的组装循环把yolov5和DeepSORT接到一起并不存在一个官方标准接口常见做法是每个视频帧先过yolov5得到检测框再把框坐标从xyxy格式转成DeepSORT需要的xywh连同置信度和原始帧一起交给deepsort.update。update内部会先做卡尔曼预测再看哪些框能和已有轨迹匹配最终返回带track_id的框列表以及被丢弃的孤点框。# 检测与跟踪拼装的核心循环基于yolov5官方推理代码的常见改造 import torch from deep_sort_pytorch.deep_sort import DeepSort model torch.hub.load(ultralytics/yolov5, yolov5s, pretrainedTrue) tracker DeepSort(osnet_x1_0.pth, max_dist0.2, max_age70, n_init3) for frame in video_frames: results model(frame, size640) # 提取检测框、置信度、类别只保留行人和车辆 boxes results.xyxy[0][:, :4].cpu().numpy() # 格式 [x1, y1, x2, y2] confs results.xyxy[0][:, 4].cpu().numpy() clss results.xyxy[0][:, 5].cpu().numpy() # 转成DeepSORT需要的中心点坐标加宽高 xywh np.zeros_like(boxes) xywh[:, 0] (boxes[:, 0] boxes[:, 2]) / 2 # cx xywh[:, 1] (boxes[:, 1] boxes[:, 3]) / 2 # cy xywh[:, 2] boxes[:, 2] - boxes[:, 0] # w xywh[:, 3] boxes[:, 3] - boxes[:, 1] # h tracked tracker.update(xywh, confs, frame) # 返回的每个元素是 [x1, y1, x2, y2, track_id]max_dist这个参数是这段组装逻辑里最值得调的。它控制外观特征允许的最大余弦距离设为0.2意味着两个目标只允许有20%的表观差异被看成同一个人数值越小人越容易被当成新目标导致同一个行人穿过画面被记成3个不同ID计数虚高数值越大又会出现跨人合并两个并排行走的人被认成一个人计数偏低。毕设视频如果是固定机位、光线稳定我会把max_dist放到0.3到0.5之间行人多的场景取小值车辆多的场景取大值因为车辆外观比行人更容易区分。3. 最小复现把YOLOv5DeepSORT工程跑在视频上3.1 yolov5环境配置的最小命令避开版本地狱yolov5环境配置是新手第一个滑铁卢问题几乎都出在PyTorch版本和CUDA版本不匹配上。常见做法是直接创建独立conda环境先装PyTorch再装yolov5依赖顺序不能反因为yolov5的requirements.txt里有很多包依赖torch版本。以下是我实际可用的最小命令集Python版本建议3.8到3.10之间torch版本用1.12到2.1都可以但不要直接装最新版部分yolov5老分支代码在torch 2.2以上会报torch.cuda.Event相关警告。# 创建干净环境Python 3.9兼容性最稳 conda create -n track python3.9 -y conda activate track # 先装PyTorch根据自己的CUDA版本选对应命令 # CUDA 11.8 执行下面这条 pip install torch1.13.1cu117 torchvision0.14.1cu117 -f https://download.pytorch.org/whl/torch_stable.html # 克隆yolov5官方仓库并安装依赖 git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt最后一条命令会装opencv-python、pandas、matplotlib、seaborn等一堆依赖如果网络不好单独pip install也会花很长时间。这里有个容易忽略的点requirements.txt里有pycocotools在Windows上编译很痛苦建议提前装好Visual Studio Build Tools或者直接用pip install pycocotools-windows替代效果一样。DeepSORT不是yolov5仓库的一部分我一般单独克隆一个deep_sort_pytorch分支里面除了ReID模型权重还依赖scipy和sklearn记得顺手装齐。跑通之前别急着上自定义权重先下载官方的yolov5s.pt跑一下自带图片确认环境没问题再进入下一步。验证命令和视频推理完全一样只是把source参数从视频文件换成图片路径。3.2 只检测行人和车detect.py的最小命令与参数对照环境装好后最直接的最小复现命令是直接调用yolov5自带的detect.py虽然最终的计数功能要在自己写的脚本里实现但用detect.py可以先确认模型和视频解码全链路正常。# 用官方权重跑一段交通视频只输出person和car两类 python detect.py \ --source traffic.mp4 \ --weights yolov5s.pt \ --conf-thres 0.25 \ --iou-thres 0.45 \ --classes 0 2 \ --project runs/detect \ --name demo \ --exist-ok上面的命令里--classes 0 2是关键这里的0是COCO数据集里person类别对应的索引2是car。如果想同时统计bus和truck就把索引5和7也加进去--classes 0 2 5 7。--conf-thres控制检测置信度阈值0.25是yolov5默认值毕设场景里如果镜头离马路比较远、目标小我会调低到0.15代价是误检变多反过来如果画面里出现大量重叠的假框就往上调到0.4。--iou-thres是NMS阈值0.45意味着两个重叠超过45%的框会被合并成一个行人密集时建议降到0.35有效减少两个人叠成一个框的现象。实际跑通之后你会在runs/detect/demo里看到带画框的视频。这个阶段能证明环境无误但detect.py本身不提供任何跟踪能力画面里的每一帧的框是独立的同一个行人每帧都会产生新框要拿到连续ID必须换成自己写脚本对接DeepSORT。3.3 刚跑通时最常见的三种现象不是环境坏了第一次把视频跑通后打开输出文件会出现三种非常典型的现象很多人误以为是代码有问题其实都在预期内。画面里某些帧的行人突然消失了然后下一帧又出现这不是显卡问题是检测阈值设置过高加上目标在远处只有几十个像素yolov5s对这种小目标本来召回率就一般。另一种现象是画面里出现大量半透明重复框两个框几乎贴着那多半是--conf-thres调太低把路牌、电线杆的影子当成了人我在校门口场景里把阈值设成0.15时树影和共享单车几乎全被识别成行人。第三种现象最值得注意也是后面会重点解决的就算接上了DeepSORT也会看到框下面有ID在跳比如一个人从画面左边走到右边ID从2变成7再变成15。这不是DeepSORT不工作是运动模型和外观模型的参数没配对后面第四、五章会专门处理。现在只需要确认代码链条是通的视频能读、模型能推理、框能画上去复现就算完成了。4. 车辆行人计数从数框到数ID的实现4.1 视觉计数原理的两种落点帧内统计和跨帧去重视觉计数的原理拆开来看其实就两种做法。第一种是帧内统计每帧检测出多少个人就输出多少个人然后把所有帧的数值加起来取平均或乘以帧率估算流量。这种做法实现起来最简单但偏差极大因为一个人占5帧就会被统计5次画面里两个人来回走动帧内统计值会被放大好几倍这就是很多人反馈的“重复计数”问题的源头。第二种是跨帧去重核心是跟踪ID。只有当一个目标被DeepSORT赋予了稳定的track_id计数才能准确某个ID首次出现时加一之后这个ID不管出连续出现多少帧都只算一次ID消失超过一定帧数后从内存里移除。这才是“车辆行人追踪和计数”这个标题里“计数”应该有的含义。工程上最常见的落地方法是虚拟线计数和区域计数前者在画面里画一条线检测目标中心点穿越这条线时计数适合统计单向车流和进出人流后者在画面里指定一个多边形区域落在区域里的ID数就是当前人数适合统计广场、候车厅的瞬时人数。4.2 在DeepSORT的track_id上做虚拟线计数下面这段代码是我在实际项目里常用的车辆计数脚本核心在yolov5官方推理循环基础上对接DeepSORT的track_id做车辆穿越虚拟线的计数。它和4.1里说的两种原理都对得上数据来自检测框去重靠track_id。import cv2 import torch from deep_sort_pytorch.deep_sort import DeepSort # 初始化检测器和跟踪器 model torch.hub.load(ultralytics/yolov5, yolov5s, pretrainedTrue) model.classes [0, 2, 5, 7] # person, car, bus, truck tracker DeepSort(osnet_x1_0.pth, max_dist0.3, max_age50, n_init3) cap cv2.VideoCapture(traffic.mp4) line_x 640 # 在x640处画一条垂直线 count 0 passed_ids set() # 用set记录已经穿过线的ID while cap.isOpened(): ok, frame cap.read() if not ok: break results model(frame, size640) boxes results.xyxy[0][:, :4].cpu().numpy() confs results.xyxy[0][:, 4].cpu().numpy() # 转xyxy为xywh xywhs torch.cat([ (boxes[:, :2] boxes[:, 2:]) / 2, # cx, cy boxes[:, 2:] - boxes[:, :2] # w, h ], dim1) outputs tracker.update(xywhs, confs, frame) for x1, y1, x2, y2, track_id in outputs: cx int((x1 x2) / 2) # 取检测框底部中心点减少人头顶偏差 if track_id not in passed_ids and cx line_x: count 1 passed_ids.add(track_id) # 该ID已经计数后续帧不再重复 cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2) cv2.putText(frame, fID:{track_id}, (int(x1), int(y1)-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) cv2.line(frame, (line_x, 0), (line_x, frame.shape[0]), (0, 0, 255), 2) cv2.putText(frame, fCount: {count}, (30, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2) cv2.imshow(counting, frame) if cv2.waitKey(1) ord(q): break这段代码的正确性完全系于passed_ids这个集合。track_id是DeepSORT在内部维护的稳定标识同一个车辆在连续帧里会尽量复用同一个IDid第一次穿过line_x时计数加一之后即使这辆车继续出现在画面里因为ID已经在集合里不会再触发累加这就消除了“重复计数”。如果漏掉这个去重逻辑直接在检测循环里遇到中心点超过line_x就count加一那么一辆车在40帧里穿越线会被计20次以上误差会让人完全无法接受。关于取哪个点作为参考点代码里用的是检测框顶两点x坐标的平均即框的几何中心。对于行人中心点没问题对于货车如果只检测到车尾中心点滞后明显我后来改成取x2和y2两点框底边中点在穿越横向底线时更稳定。车辆追踪里这个差异经常决定一次穿越会不会漏计因为车头先掠过线和车尾再掠过线中间隔着好几帧。4.3 计数准不准要用“人工数一遍”来验证写完了计数逻辑不要直接拿结果写进报告先做一次准确率验证。常见的做法是拿一段10到15秒、大概100到300辆车的夜间或白天路口视频先自己在播放器里人工数一遍记下真实车辆数再跑一遍自己的脚本记录输出值。然后算误差率(脚本计数 - 人工计数) / 人工计数。误差率在3%以内可以认为系统基本可靠。方便起见我会在脚本里加两个额外输出每一帧实际出现的ID数量和总检测框数量存成CSV。这组数据可以用来定位误差来源如果总检测框数远大于真实车辆数是置信度阈值太低导致误检如果ID数量虚高是max_dist太小导致同一辆车被反复赋予新ID如果实际帧数不连续是卡尔曼预测在遮挡时把轨迹丢了。这类定位方法比反复肉眼观察视频高效得多也是毕设答辩时能讲出深度的细节。5. 训练自己的车辆行人数据集摆脱预训练权重局限5.1 yolov5训练自己的数据集labelme标注转YOLO格式脚本官方yolov5s.pt是基于COCO训练的COCO里有80个类行人和轿车性能尚可但如果你的毕设场景是校园里的电动三轮车、景区电瓶车或是戴着安全帽的施工人员COCO权重基本不认识它们。这时就需要用自己的数据重新训练。yolov5训练自己的数据集有两个前提一是数据按它规定的目录结构摆放二是标签必须是YOLO格式。用labelme标注完得到的是JSON多边形坐标直接放到yolov5里会报标签错误需要转一次。# labelme格式转YOLO格式遍历JSON目录生成每张图对应的txt标签 import json import os from glob import glob classes {person: 0, car: 2, truck: 7} # 按需修改 for json_path in glob(labels/*.json): with open(json_path, encodingutf-8) as f: data json.load(f) img_w data[imageWidth] img_h data[imageHeight] lines [] for shape in data[shapes]: label shape[label] if label not in classes: continue # YOLO格式要求class cx cy w h全部归一化到[0,1] xs [p[0] for p in shape[points]] ys [p[1] for p in shape[points]] x_min, x_max min(xs), max(xs) y_min, y_max min(ys), max(ys) box_w (x_max - x_min) / img_w box_h (y_max - y_min) / img_h cx (x_min x_max) / 2 / img_w cy (y_min y_max) / 2 / img_h lines.append(f{classes[label]} {cx:.6f} {cy:.6f} {box_w:.6f} {box_h:.6f}) txt_path os.path.splitext(json_path)[0] .txt with open(txt_path, w) as f: f.write(\n.join(lines))这段脚本最需要注意的是归一化。YOLO的标签不是像素值而是相对图片宽高的比例如果直接把像素坐标写进txt训练时损失函数不会报错但mAP会剧烈震荡。我见过不止一次标注数据转完格式后发现物体框全部贴边或消失最后定位到是除法分母用错了宽度除成了图片高度。另外多边形的外接矩形可能包含大量背景这对训练环岛、斑马线上的目标影响不大但如果是细长的红绿灯直接算外接矩形会把背景当成目标的一部分需要按长边裁剪。如果你的数据和COCO类别完全一致只是想提高当前场景的检测率不需要从零标几千张我一般会先在预训练权重上冻结Backbone只训练Head数据量500张左右就能有明显改善。5.2 train.py最小命令与yolov5超参数的真实含义数据准备好后在yolov5目录下新建data/custom.yaml内容指定训练集、验证集路径和类别名然后执行训练命令。这里有一组毕设场景下常用的小数据集训练命令python train.py \ --data data/custom.yaml \ --weights yolov5s.pt \ --epochs 100 \ --batch-size 16 \ --imgsz 640 \ --device 0 \ --workers 4 \ --cache \ --hyp hyp.scratch-low.yaml--cache参数会把图像预加载到内存里训练小数据集时能节省大量磁盘IO时间代价是占用约2倍数据集大小的内存。--hyp hyp.scratch-low.yaml比默认的hyp.scratch.yaml增强幅度小因为我们对小数据集做太强的mosaic、mixup增强反而会让模型学不到稳定特征。yolov5超参数是这个仓库里最值得手动调的模块以下几个参数直接影响训练效果含义容易被误解参数所在文件键名推荐初值实际作用初始学习率lr00.01过大会loss爆炸过小收敛慢最终学习率比例lrf0.01训练结束时lr lr0 * lrf动量momentum0.937影响梯度更新稳定性权重衰减weight_decay0.0005防止过拟合数据少时调大预热轮数warmup_epochs3.0让bn层先稳定不要设0Mosaic概率mosaic1.0数据少时降到0.5更稳学习率这块有个毕设新手最容易踩的坑看到loss曲线不平滑就盲改lr0实际上一开始loss在4到6个epoch内波动大是bn层预热的正常现象0.01这个初值能直接沿用到50个epoch。我在校门口行人训练里把weight_decay调成0.001loss下降略慢但验证集mAP反而高了大约2个点对小数据集是正向的。如果想省调参时间直接跑一次默认超参数把训练日志里每10个epoch的mAP_0.5记下来再单独改某一项做对照比同时改三个参数更容易定位是谁起作用。5.3 算力不够时冻结主干训练30分钟看到效果没有24G大显存显卡也可以先把模型主干冻结掉只训练Head部分。主干Backbone已经通过预训练学到了纹理、边缘、颜色这些通用特征没必要在小数据集上重新学而且冻结后反向传播只更新Head的参数显存占用可以降一半左右。常见做法是给模型每层设置requires_gradFalse具体命令如下# 冻结yolov5s的backbone层只训练neck和head python train.py \ --data data/custom.yaml \ --weights yolov5s.pt \ --epochs 50 \ --batch-size 8 \ --freeze 10 \ --cache--freeze 10的意思是冻结前10层在yolov5s里大约对应整个Backbone。冻结后的训练速度快很多我的一次测试里400张图片、50个epoch在GTX 1660上只用了25分钟mAP_0.5从0.47升到0.72。冻结训练结束如果想进一步提升可以去掉--freeze用很小的学习率--lr0 0.001继续训练20个epoch把Backbone解冻效果往往能追平从头全量训练。如果你的毕设时间实在紧张还有一个更取巧但答辩上说得过去的路径用yolov5的推理结果作为伪标签配合LabelImg或X-AnyLabeling这类自动标注工具先自动标注一批视频帧再人肉修正其中的错框。校门口这种固定场景自动标注能省掉约70%的标注时间但只建议用于最终测试视频训练集里如果混入大量自动标注错误框模型会被带偏。6. YOLOv5DeepSORT在真实场景下的性能调优6.1 视频卡成PPT多线程抽帧比调模型更有效毕设演示时最尴尬的瞬间是接上摄像头或解码高清视频后画面掉到每秒5帧。先别急着换更大的GPUYOLOv5DeepSORT的推理链里至少有三段串行视频解码、模型推理、跟踪匹配。代码里最常见的问题是把cv2.VideoCapture.read()和模型推理放在同一个线程里当视频是2K分辨率或来自网络摄像头时解码本身就吃掉大量时间。常见的解法是启动一个专门线程只负责读帧把帧塞进队列推理线程从队列里取。import threading import queue frame_queue queue.Queue(maxsize16) # 队列越大延时越高不是越大越好 def read_frames(cap): while cap.isOpened(): ok, frame cap.read() if not ok: break if frame_queue.qsize() 16: # 积压过多就丢弃保实时性 frame_queue.put(frame) cap cv2.VideoCapture(0) t threading.Thread(targetread_frames, args(cap,), daemonTrue) t.start() while True: frame frame_queue.get() results model(frame, size640) # 后续DeepSORT和绘图逻辑不变队列长度16是一个经验值它相当于最多缓存0.5秒的帧既能吸收解码的抖动又不会让画面延时大到大车已经开过虚拟线还没被处理。如果做的是实时性要求很高的出入口闸机计数队列长度要收到4或5宁可短暂跳帧也不能让计数延时超过200毫秒。6.2 DeepSORT参数调优表ID跳变和漏跟往这里找参数位置推荐范围症状与调法max_dist构造DeepSort时0.2到0.5ID跳变严重就调大不同目标混在一起就调小max_age构造DeepSort时30到100目标短暂遮挡后丢ID调大到100目标长时间消失后误认调小n_init构造DeepSort时3到5小于3容易把误检当成新轨迹噪声多时调大max_iou_distanceDeepSort内部0.7到0.9遮挡严重时调大但会引入更多错误关联当目标被遮挡后重新出现ID从5变成23把所有责任推给max_dist并不公平max_age在这里同样关键。max_age限制了轨迹在没有匹配的情况下能存活多少帧这个值太小一辆车在红绿灯后停了太久跟踪器判定它已离开并清掉ID绿灯亮起重新出发时它就是一个新ID计数就会把同一辆车记两次。我一般会把max_age设到70以上尤其在堵车场景里车停个二三十秒是常事。6.3 区分“硬链接计数”和视觉计数别搜错方向搜“计数”相关技术时会翻到一堆“硬链接计数”的资料那是文件系统里inode的链接数统计属于操作系统概念和车辆行人追踪里的视觉计数完全是两条技术线。视觉计数的核心刚才已经说透了检测器给出框跟踪器给出ID计数逻辑拿ID去重。那些LED计数电路和纸张计数显示装置则是嵌入式硬件方案原理上是传感器脉冲计数不是图像理解。如果在搜索资料时看到这些词及时切换搜索词比如直接搜“yolov5 deepsort count vehicles”否则容易被带偏到完全无关的方向。最后的落点回到实际效果验证打开你的流量统计脚本用一段固定背景的校园道路视频先跑一遍拿到计数结果再把max_age从70调到30对比计数差值两次结果的差值就是你要在毕设报告里说明的ID稳定性和计数误差来源。这套调参对比方法本身就是答辩时的加分内容。本文还有配套的精品资源点击获取
返回列表