You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

YOLO+Sort车辆轨迹绘制代码出现列表索引越界错误求助

问题解决:车辆轨迹绘制的索引越界与全程轨迹保留

问题背景

使用YOLOv8+Sort算法追踪视频中的车辆,通过trajectories字典存储每个车辆ID对应的中心坐标(列表格式,每两个元素为一组(x,y)坐标),目标是全程保留车辆行驶轨迹。原代码尝试提取每个ID列表的最后四个坐标点绘制轨迹连线,但处理第二个车辆ID时触发IndexError: list index out of range,报错行:third_coordinate = trajectories[id][p + 2]。调整全局变量p、q的自增位置仍报错,移除自增则只能绘制前四个点,无法更新最新轨迹。

错误原因

  1. 全局变量冲突:p、q是所有车辆ID共用的全局计数器,第一个ID处理后p、q会递增,后续ID的轨迹列表长度可能仅为4(如第二个ID的列表为[541,140,542,141]),此时p已变为2,p+2=4超出列表索引范围(列表最大索引为3)。
  2. 轨迹保留逻辑错误:原代码直接在每一帧的视频画面上绘制轨迹,但下一帧的画面是全新的视频帧,之前绘制的轨迹会被覆盖,无法实现“全程保留”。
  3. 取点逻辑偏差:需求是绘制全程轨迹,无需用全局计数器逐个取点,应基于每个ID的轨迹列表,依次连接所有连续坐标点。

修复方案

  1. 删除全局的p、q变量,每个车辆ID的轨迹独立处理。
  2. 创建独立的轨迹画布,所有轨迹绘制在该画布上,避免被新帧覆盖。
  3. 遍历每个ID的轨迹列表,依次连接所有连续的坐标点,实现全程轨迹保留。

完整修复代码

import cv2
import numpy as np
import math
from ultralytics import YOLO
from sort import Sort
import cvzone
from typing import Union, Any

cap = cv2.VideoCapture("../Videos/3 way traffic.mp4")  # 加载视频
model = YOLO("../Yolo-Weights/yolov8l.pt")
classNames = ["person", "bicycle", "car", "motorbike", "aeroplane", "bus", "train", "truck"]
mask = cv2.imread("mask.png")
tracker = Sort(max_age=20, min_hits=3, iou_threshold=0.3)  # 初始化Sort追踪器
trajectories = {}

# 获取视频尺寸,创建空白轨迹画布(用于保留全程轨迹)
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
trajectory_img = np.zeros((frame_height, frame_width, 3), dtype=np.uint8)

while True:
    success, img = cap.read()
    if not success:
        break
    imgRegion = cv2.bitwise_and(img, mask)
    results = model(imgRegion, stream=True)
    detections = np.empty((0, 5))
    
    # 检测目标并筛选车辆类
    for r in results:
        boxes = r.boxes
        for box in boxes:
            x1, y1, x2, y2 = box.xyxy[0]
            x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
            w, h = x2 - x1, y2 - y1
            conf: float = math.ceil((box.conf[0] * 100)) / 100
            cls = int(box.cls[0])
            currentClass: Union[str, Any] = classNames[cls]
            
            # 筛选车辆类且置信度达标
            if (currentClass in ["car", "truck", "bus", "motorbike"]) and conf > 0.3:
                currentArray = np.array([x1, y1, x2, y2, conf])
                detections = np.vstack((detections, currentArray))
                cvzone.putTextRect(img, f' {currentClass}', (x1 + 10, y1 + 20), 
                                  colorT=(255, 255, 255), colorR=(60, 20, 220), 
                                  font=cv2.FONT_HERSHEY_TRIPLEX, scale=0.75, thickness=1, offset=2)
    
    # 更新追踪结果
    resultsTracker = tracker.update(detections)
    for result in resultsTracker:
        x1, y1, x2, y2, id = result
        x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
        w, h = x2 - x1, y2 - y1
        
        # 绘制目标框和中心圆点
        cvzone.cornerRect(img, (x1, y1, w, h), l=17, t=2, rt=1, colorR=(255, 228, 181), colorC=(60, 20, 220))
        cx, cy = x1 + w // 2, y1 + h // 2
        cv2.circle(img, (cx, cy), 5, (255, 0, 255), cv2.FILLED)
        
        # 更新轨迹字典
        if id in trajectories:
            trajectories[id].extend([cx, cy])
        else:
            trajectories[id] = [cx, cy]
        
        # 绘制全程轨迹:遍历当前ID的所有连续坐标点
        traj = trajectories[id]
        if len(traj) >= 4:  # 至少有两个坐标点才能连线
            for i in range(0, len(traj)-2, 2):
                prev_x, prev_y = traj[i], traj[i+1]
                curr_x, curr_y = traj[i+2], traj[i+3]
                # 在轨迹画布上绘制连线(不会被新帧覆盖)
                cv2.line(trajectory_img, (prev_x, prev_y), (curr_x, curr_y), (0, 255, 0), 2)
    
    # 将轨迹画布与当前视频帧叠加显示
    img_with_trajectory = cv2.addWeighted(img, 0.8, trajectory_img, 0.2, 0)
    cv2.imshow("Image", img_with_trajectory)
    # 按q退出,原waitKey(0)会逐帧暂停,改成waitKey(1)正常播放,可按需调整
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

关键优化点

  • 新增trajectory_img空白画布,所有轨迹绘制在该画布上,确保全程轨迹不会被新帧覆盖。
  • 移除全局计数器,针对每个ID的轨迹列表,遍历所有连续坐标对绘制连线,实现完整轨迹展示。
  • 调整cv2.waitKey(0)为cv2.waitKey(1),让视频正常播放(若需逐帧查看可改回0)。

内容的提问来源于stack exchange,提问作者Shaair

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 18:24:50