ARTICLE DETAIL

资讯详情

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

YOLOv5+DeepSORT高速车流人流量统计:跟踪稳定才是计数关键

YOLOv5+DeepSORT高速车流人流量统计:跟踪稳定才是计数关键 简介基于YOLOv5与DeepSORT算法实现的高速移动场景下车流人流量统计实战项目适合计算机相关专业毕业设计、课程设计或项目练习。项目由大四学生完成并经导师评审认可代码完整、可直接运行对初学者较为友好。压缩包共117个文件约80.21MB包含55个Python源码、20个YAML配置、1个预训练权重文件pt、4个MP4演示视频及DOCX使用手册等覆盖模型训练、目标检测、追踪计数与部署配置等环节。另有Dockerfile、Shell脚本及GIF效果图便于环境搭建与结果预览。目前已有65人学习使用尤其适合需要快速搭建完整检测计数方案、理清多目标追踪流程的开发者可直接基于源码二次开发或作为答辩展示材料。1. yolov5deepsort 做高速移动车流人流量统计为什么说难点在“跟踪”而不是“检测”高速监控画面里一辆车从入画到出画可能只有几秒钟人眼盯着屏幕数完一个小时的录像误差且不说眼睛先受不了。用 yolov5deepsort 实现高速移动车流人流量统计本质上不是“把车框出来”这么简单yolov5 负责每帧目标检测deepsort 负责把同一辆车在连续帧里的身份串成一条稳定轨迹只有轨迹稳定了“通过检测线的车辆数”才有意义。这个毕业设计最典型的分水岭也在这里——检测模型一跑就出框但一接跟踪就开始丢 ID、重复计数、遮挡断轨。本文按“原理 → 环境 → 核心代码 → 踩坑 → 加分项”的顺序把这个项目完整落地适合有 Python 和 PyTorch 基础、想拿一个能演示能答辩的完整系统当毕设入口的同学。2. 项目原理拆解先看清检测与跟踪的分工再理解计数逻辑2.1 yolov5 单帧检测到底输出了什么yolov5 是单阶段目标检测器输入一帧图像输出的是 N 个检测框每个框带 6 个值x1、y1、x2、y2、confidence、class_id。注意这个输出是“无状态”的——它只告诉你这一帧里哪里有车、哪里有人不告诉你这个框和上一帧的哪个框是同一个人或同一辆车。很多刚接触这个项目的同学会在这里产生一个误解视频第一帧检测出 10 辆车第二帧检测出 12 辆是不是我画面里的车流就是 12 减 10完全不是。第二帧的 12 个框里可能有 9 个是上一帧那 10 辆车里的另外 3 个是新进入画面的还有 1 辆上一帧的车被遮挡漏检了。没有身份关联你连“哪辆是新的”都判断不了。yolov5 内部还有一个关键后处理步骤叫 NMS非极大值抑制。模型原始输出会有大量重叠框NMS 按置信度排序把与最高分框重叠度超过阈值的框抑制掉保留最具代表性的那个。这个阈值就是 iou-thres后面调参会用到。我建议你在动手写主循环前先做一个最小验证拿一段高速路口的短视频跑通 yolov5 检测把每帧检测到的框数、每个框的置信度打印出来保存成日志。这个日志是你后面排查跟踪问题时的“基准答案”。很多看起来像是跟踪的问题根因其实在检测阶段就埋下了。2.2 deepsort 如何把跨帧目标串成同一条轨迹deepsort 的输入是每帧的检测框序列输出是带有全局唯一 track_id 的目标框。它内部由三块组成卡尔曼滤波负责运动预测。每一帧跟踪器会基于上一帧的位置和速度预测当前帧目标应该出现在哪里。预测结果和真实检测框之间计算一个“门控距离”超出合理运动范围的匹配直接被排除。高速场景下车辆帧间位移大卡尔曼滤波的预测协方差如果不匹配实际车速就会出现“本来该往右走预测框却停在原地”的情况导致匹配失败。匈牙利算法负责最优匹配。得到所有预测轨迹和当前帧检测框的代价矩阵后用匈牙利算法求全局最优匹配尽量让每个检测框都找到最合理的轨迹。这一步是 deepsort 的“调度核心”它保证匹配不是贪心的一对一而是全局代价最小化。外观特征负责身份校验。仅靠运动预测两辆车交错时很容易互相抢身份。deepsort 在初始化每条轨迹时会用一个 ReID 小网络提取目标的外观特征向量存进特征库然后与当前检测框的外观特征计算余弦距离。运动相似但外观不一致的匹配会被拉低权重这就是 deepsort 比原始 sort 算法抗 ID Switch 强很多的原因。这三个模块的配合决定了跟踪质量也对应三个核心超参数max_dist 控制外观距离上限max_age 控制轨迹丢失后还能保留多少帧n_init 控制新轨迹需要连续命中多少帧才转正。后面第 4 章会展开调参逻辑。2.3 车流人流计数的落地形式虚拟检测线加一点状态管理跟踪只是手段统计才是目的。最常见的计数实现是画一条虚拟检测线也可以是一个区域然后判断目标中心点是否跨过这条线。这里有一个关键设计决策什么时候算“通过”我一般用前后帧位置结合检测线判断。比如检测线是一条水平线上一帧目标中心在线上方这一帧在下方就算一次穿越。这样比单纯判断“当前帧中心在下方”更稳能避免目标在线上来回抖动造成的重复计数。计数的状态管理也很重要。每条轨迹有一个 track_id你需要在内存里维护一个 dict记录哪些 track_id 已经计数过了。否则车辆在检测线附近因为遮挡丢失 ID、重新生成新 ID 后会被再计一次。这个 dict 就是“已统计名单”每帧更新项目结束时清空。2.4 一个需要提前确认的边界统计类别和方向问题车流人流量统计不是“把一切框都数一遍”。COCO 类别里car、truck、bus、motorbike、bicycle 都属于车辆person 属于行人。你的项目如果要求区分“车流量”和“人流量”就需要在检测结果里按 class_id 做分流并且决定是否把自行车归到车辆还是行人侧。方向统计则依赖检测线的方向性。高速出入口一般需要分“入城”和“出城”两个方向车流量的统计要按穿越方向分别计数。实现上需要记录目标上一帧中心点相对检测线的位置再判断本次穿越是正向还是反向。我建议你在最开始就确定统计几个方向、分几类目标、检测线画在什么位置。不要等代码跑通再改因为检测线的坐标和方向逻辑会蔓延到主循环、状态管理、结果保存多个地方后期改动容易引入隐蔽 bug。3. conda 环境搭建与源码目录梳理用最快的路径跑通第一帧3.1 为什么要用 conda 单独建环境Python 版本怎么选yolov5 的依赖经历过多次迭代PyTorch 版本、torchvision 版本、numpy 版本之间互相有兼容性要求。如果你直接在系统 Python 里装大概率会因为某个包版本冲突浪费一整天。用 conda 单独建一个环境是最稳妥的做法隔离干净删了重建也方便。Python 版本我建议选 3.8。yolov5 官方在较长一段时间内对 3.8 支持最稳定3.10 之后某些依赖需要重新编译对毕设项目没必要冒险。创建命令如下conda create -n yolo_deepsort python3.8 -y conda activate yolo_deepsort创建这一步完成后先确认环境激活是否成功再装 PyTorch。不要急着把 CUDA 相关包一次全装完因为你的显卡驱动版本和 CUDA 版本未必匹配。稳妥的做法是先用 CPU 版本跑通项目再换 CUDA 版提速。3.2 依赖安装与权重文件准备安装 PyTorch 时我一般先用如下命令装 CPU 版验证代码流程pip install torch1.12.1 torchvision0.13.1 --index-url https://download.pytorch.org/whl/cpuCPU 版跑通后再到 PyTorch 官网按显卡驱动选对应的 CUDA 版本安装。这一步非常重要不要直接pip install torch装最新版最新版对老显卡支持差而且某些 torchvision 接口和 yolov5 源码不兼容。随后安装其他依赖pip install opencv-python numpy pillow pyyaml scipy tqdm seaborn matplotlib这个项目还需要两个权重文件yolov5s.pt检测权重和 ckpt.t7deepsort 的 ReID 权重。yolov5s.pt 从 yolov5 仓库的 release 页面下载ckpt.t7 从 deep sort pytorch 相关仓库的 release 或网盘下载。两个文件体积都不大但下载后要检查文件能否被 torch.load 正常加载这一步常被忽略。3.3 跑通项目模板的命令与验证方法项目源码目录通常长这样yolov5 检测模块和 deep_sort 跟踪模块并列主脚本在根目录project_root/ ├── yolov5/ # 检测模块 │ ├── models/ │ ├── utils/ │ └── weights/yolov5s.pt ├── deep_sort/ # 跟踪模块 │ ├── deep_sort/ │ └── deep/checkpoint/ckpt.t7 ├── track.py # 主运行脚本 ├── configs/ └── runs/ # 输出结果目录拿到代码后不要直接跑大视频先用一个小视频做冒烟测试。命令类似python track.py --source assets/test_clip.mp4 --yolo-weights yolov5/weights/yolov5s.pt --conf-thres 0.25 --iou-thres 0.45跑通的标准是视频窗口正常弹出检测框跟着画面里的车动每辆车左上角有稳定的 ID 数字。如果视频窗口一闪而过、没有显示计数先检查视频源路径和输出路径再检查控制台有没有报错信息。这一步最常见的失败点是cv2.VideoCapture打不开视频文件原因往往是 OpenCV 没装全或视频编码器缺失。先换 mp4 试试最后才考虑重装 opencv-python。4. 核心代码实现检测循环、跟踪循环与跨线计数三块拼图4.1 加载 yolov5 模型conf-thres 和 iou-thres 该怎么设主循环开始前先加载检测模型并解析类别名。项目使用 COCO 类别所以要确认你的代码里读的是 COCO 标签还是自定义标签。import torch from pathlib import Path from yolov5.models.experimental import attempt_load from yolov5.utils.torch_utils import select_device # 加载权重这一步会把模型结构定义和权重一起加载进来 device select_device(0 if torch.cuda.is_available() else cpu) model attempt_load(yolov5/weights/yolov5s.pt, map_locationdevice) model.eval() # 类别名列表COCO 数据集共 80 类 names model.module.names if hasattr(model, module) else model.names print(可用的检测类别:, names)逻辑说明attempt_load是 yolov5 提供的一个兼容加载函数能处理不同来源的权重文件。map_locationdevice特别关键它决定权重加载到 GPU 还是 CPU。本机没有 CUDA 时不写这个参数会直接报错。names的作用是后续把 class_id 转成可读的类别名。你能看到names[2]是 carnames[0]是 person。注意有些自定义训练模型里这个列表会被替换逻辑要跟着变。参数说明这里出现的两个阈值conf-thres和iou-thres不是模型本身的参数而是在推理后处理阶段生效的后处理参数。conf_thres0.25表示置信度低于 0.25 的框直接丢弃适合远处目标多的高速场景iou_thres0.45是 NMS 的重叠阈值两颗车距近、互相遮挡时这个值不宜设太高否则会把两辆车框成一个。4.2 初始化 deepsort读懂 max_age、max_dist、n_init 三个超参数跟踪器的初始化参数直接决定整条计数链路的质量每个参数都要理解后才好调。from deep_sort.deep_sort import DeepSort # 初始化 deepsort 跟踪器 tracker DeepSort( model_pathdeep_sort/deep/checkpoint/ckpt.t7, max_dist0.3, # 外观特征余弦距离阈值默认0.2高速场景放宽到0.3 max_iou_distance0.7, # 级联匹配中 IoU 阈值默认0.7 max_age90, # 轨迹最大保留帧数默认70高速遮挡多时调大 n_init3, # 连续命中3帧才确认轨迹 nn_budget100, # ReID 特征缓存数量 use_cudatorch.cuda.is_available() )参数说明逐条拆max_dist0.3ReID 特征向量和轨迹特征库之间的最大余弦距离。阈值越大匹配越宽松越不容易丢 ID但也越容易出现错误匹配。默认 0.2 在市区场景够用高速场景车速快、帧间外观变化大我经常放宽到 0.3。max_iou_distance0.7用于级联匹配的最小 IoU 阈值0.7 表示预测框和检测框重合度高于 0.7 才考虑匹配。这个值和 yolov5 的 iou-thres 是两回事后者管 NMS前者管跟踪匹配别混。max_age90一条轨迹连续多少帧没有被任何检测框匹配上就从跟踪器中删除。高速场景下车辆可能被路牌、天桥遮挡 10 到 20 帧默认 70 够用但遇到长隧道就直接断。调大到 90 以上能减少轨迹断裂代价是目标离开画面后还会残留几秒延迟计数时需要注意。n_init3新轨迹要连续命中 3 帧才会被确认低于这个帧数的都算“未确认轨迹”。n_init 设太大会漏掉快速穿越画面的目标设太小会出现大量一次性 ID。4.3 车流人流量统计的跨线计数实现与去重主循环是这个项目的心脏。检测、跟踪、计数、可视化全在视频帧的循环里完成。这里直接给出一个经过整理的实现骨架import cv2 import numpy as np import torch from yolov5.utils.general import non_max_suppression, scale_coords # 虚拟横线假设帧高720 LINE_Y 450 # 存储已经计数的 track_id防止重复计数 counted_ids set() # 分类统计 vehicle_count 0 person_count 0 cap cv2.VideoCapture(assets/highway.mp4) while cap.isOpened(): ret, frame cap.read() if not ret: break # -------- 检测部分 -------- img_rgb cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) img_tensor torch.from_numpy(img_rgb).permute(2, 0, 1).unsqueeze(0).float() / 255.0 img_tensor img_tensor.to(device) with torch.no_grad(): pred model(img_tensor)[0] det non_max_suppression(pred, conf_thres0.25, iou_thres0.45)[0] boxes_xywh, confs, clss [], [], [] if det is not None and len(det): # 坐标已经相对于预处理尺寸缩放回原始帧 det[:, :4] scale_coords(img_tensor.shape[2:], det[:, :4], frame.shape).round() for *xyxy, conf, cls_id in det: x1, y1, x2, y2 map(int, xyxy) # 只保留车辆和行人 if int(cls_id) in [0, 2, 5, 7]: # person, car, bus, truck boxes_xywh.append([x1, y1, x2 - x1, y2 - y1]) confs.append(float(conf)) clss.append(int(cls_id)) # -------- 跟踪部分 -------- if len(boxes_xywh) 0: tracks tracker.update(np.array(boxes_xywh), confs, frame) else: tracks tracker.update(np.empty((0, 4)), np.empty(0), frame) # -------- 跨线计数 -------- for trk in tracks: x1, y1, x2, y2, track_id trk center_y (y1 y2) / 2.0 # 中心跨过检测线即计数每个 track_id 只计一次 if center_y LINE_Y and track_id not in counted_ids: counted_ids.add(track_id) # 通过中心点反查类别这里用跟踪框和检测框中心点最近匹配 # 简化处理从当前帧检测结果中找到中心点最近的类 if nearest_cls is not None: if nearest_cls 0: person_count 1 else: vehicle_count 1 # -------- 可视化 -------- cv2.line(frame, (50, LINE_Y), (frame.shape[1] - 50, LINE_Y), (0, 255, 0), 2) for trk in tracks: x1, y1, x2, y2, track_id trk cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.putText(frame, fID:{track_id}, (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2) cv2.putText(frame, fvehicles: {vehicle_count} persons: {person_count}, (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 0), 2) cv2.imshow(traffic count, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()这段代码的逻辑链是对每一帧先让 yolov5 产出检测框再让 deepsort 把这些框和上一帧的轨迹做匹配得到带 track_id 的稳定跟踪框最后用中心点穿越检测线的方法进行计数。其中scale_coords这行很关键yolov5 内部会把输入图片缩放到 640x640输出的坐标也是基于 640 尺寸的不缩放回原始帧尺寸画框和计数坐标全都会偏移。counted_ids用 set 存储已计数的 track_id这是去重的核心。如果目标被遮挡导致 ID 丢失deepsort 分配了一个从未见过的新 IDset 里没有记录就会再计一次这就是重复计数的直接原因之一。想缓解只能把跟踪调稳让 ID 尽量不跳变。tracks数组来自deep_sort库的 update 方法每一行是[x1, y1, x2, y2, track_id]。注意它不带类别所以计数阶段需要从检测结果里把类别“补回来”。做法是对每个跟踪框在当前帧所有检测框里找中心点欧氏距离最近的那个框取其类别。这算是工程上最朴素且有效的类别关联方法实际项目中我见过有人直接把cls_id塞进 tracking 接口一并输出这样代码更干净但耦合度高。4.4 把计数结果写到文件而不是只显示在窗口里演示时视频窗口实时显示计数就够了但毕设答辩需要结果数据来支撑。我建议在代码末尾把统计结果导出为文本文件或 CSVwith open(runs/count_result.csv, w) as f: f.write(vehicle_count,person_count\n) f.write(f{vehicle_count},{person_count}\n) print(统计完成车辆数:, vehicle_count, 行人数:, person_count)另外还可以保存一版“带叠加框的标注视频”。实现上只需要在每次cv2.imshow之前把帧写入cv2.VideoWriter这里不再重复贴代码。要提醒的是VideoWriter 的编码器选择要用 mp4v帧率和原视频一致否则输出视频会花屏或长度不对。最后调试时在控制台打印每一帧的检测数量、跟踪数量、计数累计数量会大幅加速定位问题。尤其是计数数字在某一帧突然跳了很大的数基本可以直接定位是去重逻辑失效而不是模型出了问题。5. 高速场景避坑排查计数翻车的五个典型问题和修法5.1 同一辆车被计数两次ID 跳变的真凶现象监控视频里一辆白色轿车驶过检测线画面中的 ID 从 37 突然跳成 51最终计数统计里显示两辆车。回放时发现实际上只有一辆车。原因车辆在高速场景帧间位移大卡尔曼滤波预测的位置和实际位置偏差太大或外观特征因为反光、图像模糊等原因变化剧烈deepsort 没能把当前检测框和原轨迹匹配上于是分配了新 ID。解决先看是不是检测漏帧造成的。连续丢帧超过 max_age轨迹就会从删除队列里消失之后新目标重新建轨迹。将max_age从 70 调到 120再观察 ID 跳变是否减少。另一个方向是放宽max_dist0.2 太紧就改 0.3让外观匹配更容易命中。注意代价是误匹配变多所以调参后要仔细观察不同车辆交错时是否互相换 ID。5.2 目标一帧漏检就丢跟踪轨迹被切断现象一辆车被路牌挡住了一瞬间跟踪框直接消失车从路牌另一边出来时变成了新 ID人流量统计里一个行人被数了两次。原因检测器在遮挡瞬间没有输出对应的框deepsort 找不到匹配的检测框只能让轨迹进入“未命中”状态。如果这种情况持续超过 max_age轨迹就被移除了。解决max_age 是首选调大到 150 以上让轨迹容忍更长时间的遮挡。另一个角度是降低 conf-thres从 0.25 降到 0.15让遮挡瞬间被漏检的车辆还有可能被检测出来。不过要小心低阈值带来了大量误检框跟踪器会把噪声也当成目标ID 数量反而膨胀。所以更推荐结合场景高速遮挡多max_age 优先调大再用一个低置信度阈值做补充。5.3 远处的车和行人完全检测不到conf-thres 设太高现象视频里远处驶来的车辆肉眼能看到但画面里没有检测框直到距离很近时才有框。计数结果比实际流量少一截。原因远处目标在图像中的像素面积小模型对它的响应置信度本来就低。conf-thres 默认 0.25 时这些低置信度框会被全部过滤等于从源头上切断了跟踪的可能性。解决把conf-thres下调到 0.1 或 0.15 试一下你会发现远处目标开始出框但噪声也会变多。另一个有效措施是提高输入分辨率检测时把帧缩放到 640 不够就用 960 甚至 1280小目标占的像素面积变大模型更容易输出高置信度结果。代价是每帧推理时间变长GPU 占用升高。高速场景如果视频本身是 1080p我建议缩放到 960 即可1280 对速度影响明显但精度提升有限性价比不高。5.4 车流密集时两个目标黏成一个框现象两辆并排的轿车在画面里被画成了同一个红色框计数直接少算一辆或者两辆车交错时 ID 互相交换。原因NMS 的 IoU 阈值设得太高导致重叠程度较大的相邻车辆被抑制掉其中一个框。跟踪器匹配时又因为错误的检测框位置把两个目标合并成了一条轨迹。解决iou_thres从 0.45 调到 0.3让 NMS 对重叠框更敏感两车距离近时也能各自保留出独立的框。注意 NMS 阈值太低的副作用是同一辆车可能被输出多个框这时 deepsort 匹配会困惑。我的经验是高速并排车流场景 0.35 左右比较稳做实验时把几个值都试一遍看哪个值下跟踪 ID 不跳变、不合并。5.5 deepsort 权重加载失败与依赖版本乱账现象运行track.py时报FileNotFoundError找不到ckpt.t7或者报KeyError、RuntimeError提示模型结构不匹配。原因权重文件没有实际下载成功文件只有几十 KB 但实际应为几百 MB另一个原因是 deepsort 源码版本和权重文件训练时用的 torchreid 版本不一致导致torch.load反序列化时字典键对不上。解决下载权重后先看文件大小ckpt.t7通常 300MB 以上大小不对就重新下载。加载时不要直接torch.load(path)先加一行打印权重文件的内部键名确认它来自哪个版本的 ReID 模型再和源码里的加载逻辑比对。如果是版本问题去 deep_sort_pytorch 仓库找和权重文件对应的源码版本不要混搭最新版和旧权重。环境方面scikit-learn和scipy版本也要盯住某些老代码依赖sklearn.preprocessing里的旧函数新版本换位置会直接ImportError。6. 给这个项目加分超参数调优、自定义数据集训练与 ONNX 部署6.1 用计数误差和 ID Switch 验证你的系统不是“看起来能用”毕设答辩最怕被问“你统计的准确率是多少”如果你只说“感觉挺准”就会被追问到翻车。我会把验证拆成两个指标计数准确率和 ID Switch 次数。手动准备一段 30 秒左右的测试视频先人工数出真实车辆数再跑项目得到统计数算误差。ID Switch 次数需要你观察视频回放里同一辆车的跟踪 ID 变化了几次变化次数越多说明跟踪质量越差重复计数风险越高。参数调优时每次都跑同一段测试视频对比几个版本的数字。这是最朴素的消融实验但比任何花哨的指标都更有说服力。最后把对比表放进论文里整个系统的可信度立刻不同。6.2 想提高检测精度就训练你自己的数据集市面上预训练 yolov5s 权重在通用场景下表现不错但你的毕设场景如果是特定路口、特定角度通用模型未必有最优效果。训练自己的数据集是值得做的进阶标注工具用 labelimg导出 YOLO 格式的 txt 标注文件每个文件夹放图片和同名 txt然后改data/custom.yaml里的类别数量和路径调用train.py --data custom.yaml --weights yolov5s.pt --img 640 --epochs 100。训练完成后把best.pt换到第 4 章的attempt_load里即可。这里要注意训练集的标注质量直接决定跟踪阶段的体验。如果标注框比实际车辆大不少检测框位置不稳定deepsort 匹配会频繁出错。6.3 把模型导出 ONNX部署到边缘设备答辩加分项之一是证明你的方案不只是跑在实验室 GPU 上还能部署到边缘设备。yolov5 官方提供export.py脚本一条命令导出 ONNX 权重deepsort 的 ReID 网络比较轻量直接部署也没问题python yolov5/export.py --weights yolov5/weights/yolov5s.pt --include onnx --opset 12导出后拿到一个 onnx 文件市面上大部分推理框架ONNX Runtime、TensorRT都能直接加载。边缘设备部署的常见做法是用 TensorRT 引擎加速推理把 onnx 转成 trt 模型后运行帧率能比 PyTorch 原生推理快数倍。不过 TensorRT 的优化过程极度依赖 GPU 型号换一张显卡就要重新转一次模型这个坑提前知道就不慌。这段路走完你的毕设就有了完整闭环检测准确率可解释、跟踪稳定有验证、计数误差可量化、部署方案可演示。我自己做这类项目时习惯把每次调参后的视频和原始视频放一起对比播放用肉眼看 ID 跳变是最快的问题定位办法。真希望有人早点告诉我这些超参数不是越多越好把 max_age 和 conf-thres 这两个值调明白项目基本就成功了大半调不明白的时候先停手检查检测框质量而不是在跟踪参数里空转。希望这篇能帮你把这个方案稳稳落地。本文还有配套的精品资源点击获取
返回列表