尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

opencv学习中——YOLO+目标追踪检测视频车辆

opencv学习中——YOLO+目标追踪检测视频车辆 一个多月前发过车辆检测代码opencv学习中——车辆检测代码-CSDN博客纯opencv搞的效果一般每一帧识别的外框会变动甚至嵌套问了大模型说可以通过YOLOByteTrack来解决终于学到这啦~一、基础概念1.1 原理YOLO ByteTrack 是目前工业界最主流、性能与速度平衡最好的目标追踪方案之一。它的核心思想可以概括为YOLO 负责“看”检测ByteTrack 负责“连”关联。1YOLO 检测端提供高质量观测。Bounding Box: (x,y,w,h)Confidence Score: 置信度s∈[0,1]Class ID: 类别标签2ByteTrack 关联端核心算法流程。ByteTrack 的关联策略是一个三阶段匹配过程结合了运动模型卡尔曼滤波很久前看过一个学习视频【从放弃到精通卡尔曼滤波从理论到实践~-哔哩哔哩】 https://b23.tv/HN8w5SJ等之后再回顾一下写一篇笔记和外观特征可选人脸的时候是需要的。匹配流程。就算被遮挡置信度低了也能识别为同一个物体而不是被识别为新物体重新编号。1.2 框和轨迹为啥框要和轨迹匹配咋匹配。1框和轨迹之所以能匹配是因为同一个物体在相邻两帧之间的位置变化很小。追踪器就是利用这种空间上的连续性通过计算重叠面积IoU来判断这个框是不是对应那条轨迹。2当新一帧到来时追踪器会根据卡尔曼滤波预测出每条轨迹在这一帧应该出现在哪里得到一个预测框。匹配的本质就是拿当前帧的检测框去和轨迹的预测框做比较。3ByteTrack 使用的匹配度量是IoU两个框的重叠面积/两个框的并集面积和之前发的人脸检测里面的一样。视频通常是 25~30fps相邻两帧之间只有 33~40ms。在这个时间窗口内行人/车辆不可能瞬移所以同一目标的检测框和预测框必然有大量重叠。IoU 就是对这种空间邻近性最直接、最高效的量化。4多个框 vs 多条轨迹怎么办—— 匈牙利算法。匈牙利算法会找到一个全局 IoU 总和最大的一一对应方案。匈牙利算法的原理就是通过对代价矩阵做等价变换把找全局最优配对的问题转化为在变换后的矩阵中找一组互不冲突的零元素的问题通过等价变换寻找一个能让所有行和列都满意的全局方案。从而避免贪心策略因短视而造成的连锁错配。下图左为匈牙利算法右为贪心算法。5最后的理解在当前帧中检测器输出了 5 个检测框。经过置信度筛选后其中 4 个高分检测框与 3 条已有轨迹的预测框进行 IoU 计算。在构建代价矩阵时这 4 个框中有若干组合的 IoU 低于match_thresh这些低 IoU 组合被直接截断为不可匹配。随后匈牙利算法对剩余的合法组合求解全局最优的一对一指派最终得到 3 对成功匹配以及 1 个未匹配的高分检测框。与此同时最初那个未参与第一轮匹配的剩余检测框若其置信度仍高于追踪器的最低检测阈值也会进入第二轮匹配。第二轮匹配中第一轮未匹配的高分框、符合条件的低分框共同与第一轮中未被匹配的轨迹进行关联。若仍有高分框未匹配成功则追踪器将其判定为新出现的目标并为其初始化一条新轨迹、分配新的 ID若低分框仍未匹配成功则被最终丢弃。如果上面检测框少轨迹多第一轮匹配就算是高分检测框也可能被剩下一个是检测框低于match_thresh一个是匈牙利算法下会将收益更高的框与轨迹配对如果这个高分框只有一条合法轨迹这条轨迹被算法分配给其他框了那这个高分框就会被剩下。1.3 工程实现要点在实际部署 YOLO ByteTrack 时需注意以下5点后续做的时候再回来看看双阈值设置 τhigh​控制精度τlow​控制召回需根据场景调优卡尔曼滤波参数过程噪声Q和观测噪声R影响平滑度运动剧烈的场景需增大Q轨迹缓冲track_buffer默认30帧决定丢失轨迹保留多久过短易断轨过长易误连ReID 按需加载密集场景/相似目标多时开启ReID稀疏场景纯IoU即可达到实时坐标系一致确保YOLO输出的xywh格式与卡尔曼滤波的状态定义对齐1.3 结果简析model.track()返回的是一个Results对象列表通常只取results[0]。它比纯检测的model()返回结果多了一个关键属性id。以下是results[0]的完整结构解析1.4 不同版本对比可以在v8上加ReID/微调检测器/调优卡尔曼参数ROI最高。二、代码import cv2 from ultralytics import YOLO print(OpenCV:, cv2.__version__) print(Ultralytics: OK) # 1. 配置区 VIDEO_PATH rC:\D\video\Cars.mp4 # 视频路径0 表示摄像头 # 漏检了n精度下远处的小车检测不到换了s之后效果好些就是慢m及之后的不考虑了超级卡 MODEL_PATH yolov8s.pt # n/s/m/l/x 精度递增速度递减。预训练权重文件首次运行自动下载 # MODEL_PATH yolo11s.pt # 可以直接切换v11类别识别更准框不会来回切换但是远处车辆没有v8检测好 # 调低之后框不会闪跳了 CONFIDENCE_THRESHOLD 0.3 # 置信度阈值低于此值的检测结果被丢弃 IOU_THRESHOLD 0.5 # NMS IoU 阈值控制重叠框的合并严格程度 # COCO 数据集中车辆相关的类别ID和名称 VEHICLE_CLASSES { 2: car, 3: motorcycle, 5: bus, 7: truck } # 2. 加载模型权重到内存自动识别GPU/CPU model YOLO(MODEL_PATH) # 3. 打开视频 cap cv2.VideoCapture(VIDEO_PATH) if not cap.isOpened(): raise ValueError(f无法打开视频: {VIDEO_PATH}) frame_count 0 while True: ret, frame cap.read() if not ret: break frame_count 1 print(frame.shape) results model.track(frame, persistTrue, confCONFIDENCE_THRESHOLD, iouIOU_THRESHOLD, # 漏检还可能是默认压缩到640*640推理导致可以增大推理分辨率以32为倍数 # 960就有效果了,1280不行本身每帧也是768*1364不算高清 imgsz960 #1280, # botsort对短暂遮挡和漏检的容忍度更高 # 但还是选默认的bytetrack # 因为botsort有点敏感把车子上携带的自行车等也框了出来 # trackerbotsort.yaml ) # 4. 后处理 OpenCV 绘制 for box in results[0].boxes: # 遍历当前帧所有检测框 cls_id int(box.cls[0]) # 获取类别IDtensor→int # 只保留车辆类别 if cls_id not in VEHICLE_CLASSES: continue # 获取追踪IDtrack模式下才有box.id的 track_id int(box.id[0]) if box.id is not None else -1 # 边界框坐标 (x1,y1,x2,y2) x1, y1, x2, y2 map(int, box.xyxy[0]) # 置信度分数box.conf conf float(box.conf[0]) # 标签中加入 Track ID label fID:{track_id} {VEHICLE_CLASSES[cls_id]} {conf:.2f} # 根据类别选择颜色 colors {2:(0,255,0), 3:(255,0,0), 5:(0,0,255), 7:(255,255,0)} color colors.get(cls_id, (128,128,128)) # 未知类别用灰色兜底 # 画框 标签背景 cv2.rectangle(frame, (x1, y1), (x2, y2), color, 2) # 画边界框 (tw, th), _ cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1) # 计算标签文字宽高 cv2.rectangle(frame, (x1, y1-th-8), (x1tw, y1), color, -1) # 画标签背景色块-1填充 cv2.putText(frame, label, (x1, y1-4), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255), 1) # 在背景色块上写白色文字 # 左上角显示帧数和实时FPS cv2.putText(frame, fFrame: {frame_count}, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0,255,255), 2) # 显示 保存 cv2.imshow(Vehicle Detection, frame) if cv2.waitKey(1) 0xFF ord(q): break # 5. 释放资源 cap.release() cv2.destroyAllWindows() print(f✅ 处理完成共 {frame_count} 帧)三、感想后来还试了个Gradio想着能不能手机实时摄像头检测来着好慢好卡好滞后也不太懂能咋优化大模型果然不是万能的先搁置以后图片检测的时候再试下。
返回列表