YOLOv8 + ByteTrack 车辆跟踪计数实战:跨线统计完整流程
这篇教程根据我复现车辆跟踪计数流程时整理,重点演示视频准备、YOLOv8 检测、ByteTrack 跟踪、跨线计数和结果视频导出。
本文整理自我的学习和项目复现过程,尽量按实操顺序保留 notebook 的关键步骤,同时把数据集获取方式调整为适合中文教程发布的写法。
本文会重点跑通以下流程:
- 准备车辆计数视频
- 安装 YOLOv8 和 ByteTrack
- 封装跟踪器参数与匹配逻辑
- 筛选车辆类别并运行检测
- 按跨线方向统计车辆数量
如果你正在系统学习目标检测、实例分割、OCR、多目标跟踪或视觉大模型,建议收藏本文;配套 notebook、示例图片和运行环境说明后续会继续整理。如果环境配置卡住,可以在评论区说明具体报错。
📚 文章目录
- YOLOv8 + ByteTrack 车辆跟踪计数实战:跨线统计完整流程
- ⚙️ 检查环境
- 🎬 准备车辆视频
- 🧩 安装 YOLOv8
- 🧩 安装 ByteTrack
- 🔧 封装跟踪参数
- 🧩 安装 Supervision
- 🚗 加载检测模型
- 🏷️ 筛选车辆类别
- 🖼️ 单帧检测预览
- 📏 设置计数线
- 📹 生成计数视频
- 📌 小结
- 📚 同系列教程汇总
⚙️ 检查环境
确认 GPU 和工作目录。
!nvidia-smiimportos HOME=os.getcwd()print(HOME)🎬 准备车辆视频
下载车辆计数示例视频,也可以替换为自己的视频。
%cd{HOME}!wget--load-cookies/tmp/cookies.txt"https://docs.google.com/uc?export=download&confirm=$(wget --quiet --save-cookies /tmp/cookies.txt --keep-session-cookies --no-check-certificate 'https://docs.google.com/uc?export=download&id=1pz68D1Gsx80MoPg-_q-IbEdESEmyVLm-' -O- | sed -rn 's/.*confirm=([0-9A-Za-z_]+).*/\1\n/p')&id=1pz68D1Gsx80MoPg-_q-IbEdESEmyVLm-"-O vehicle-counting.mp4&&rm-rf/tmp/cookies.txtSOURCE_VIDEO_PATH=f"{HOME}/vehicle-counting.mp4"🧩 安装 YOLOv8
安装 Ultralytics 并关闭匿名同步。
# Pip install method (recommended)!pip install"ultralytics<=8.3.40"fromIPythonimportdisplay display.clear_output()# 关闭 Ultralytics 匿名同步!yolo settings sync=Falseimportultralytics ultralytics.checks()🧩 安装 ByteTrack
安装 ByteTrack 及相关依赖。
%cd{HOME}!git clone https://github.com/ifzhang/ByteTrack.git%cd{HOME}/ByteTrack# 兼容旧版依赖!sed-i's/onnx==1.8.1/onnx==1.9.0/g'requirements.txt !pip3 install-q-r requirements.txt !python3 setup.py-q develop !pip install-q cython_bbox !pip install-q onemetric# 兼容旧版依赖!pip install-q loguru lap thopfromIPythonimportdisplay display.clear_output()importsys sys.path.append(f"{HOME}/ByteTrack")importyoloxprint("yolox.__version__:",yolox.__version__)🔧 封装跟踪参数
定义 ByteTrack 参数和检测框匹配逻辑。
fromyolox.tracker.byte_trackerimportBYTETracker,STrackfromonemetric.cv.utils.iouimportbox_iou_batchfromdataclassesimportdataclass@dataclass(frozen=True)classBYTETrackerArgs:track_thresh:float=0.25track_buffer:int=30match_thresh:float=0.8aspect_ratio_thresh:float=3.0min_box_area:float=1.0mot20:bool=False🧩 安装 Supervision
安装视频读取、标注和跨线计数工具。
!pip install supervision==0.1.0fromIPythonimportdisplay display.clear_output()importsupervisionprint("supervision.__version__:",supervision.__version__)fromsupervision.draw.colorimportColorPalettefromsupervision.geometry.dataclassesimportPointfromsupervision.video.dataclassesimportVideoInfofromsupervision.video.sourceimportget_video_frames_generatorfromsupervision.video.sinkimportVideoSinkfromsupervision.notebook.utilsimportshow_frame_in_notebookfromsupervision.tools.detectionsimportDetections,BoxAnnotatorfromsupervision.tools.line_counterimportLineCounter,LineCounterAnnotatorfromtypingimportListimportnumpyasnp# converts Detections into format that can be consumed by match_detections_with_tracks functiondefdetections2boxes(detections:Detections)->np.ndarray:returnnp.hstack((detections.xyxy,detections.confidence[:,np.newaxis]))# converts List[STrack] into format that can be consumed by match_detections_with_tracks functiondeftracks2boxes(tracks:List[STrack])->np.ndarray:returnnp.array([track.tlbrfortrackintracks],dtype=float)# matches our bounding boxes with predictionsdefmatch_detections_with_tracks(detections:Detections,tracks:List[STrack])->Detections:ifnotnp.any(detections.xyxy)orlen(tracks)==0:returnnp.empty((0,))tracks_boxes=tracks2boxes(tracks=tracks)iou=box_iou_batch(tracks_boxes,detections.xyxy)track2detection=np.argmax(iou,axis=1)tracker_ids=[None]*len(detections)fortracker_index,detection_indexinenumerate(track2detection):ifiou[tracker_index,detection_index]!=0:tracker_ids[detection_index]=tracks[tracker_index].track_idreturntracker_ids🚗 加载检测模型
加载 YOLOv8 车辆检测模型。
# 参数设置MODEL="yolov8x.pt"fromultralyticsimportYOLO model=YOLO(MODEL)model.fuse()🏷️ 筛选车辆类别
只保留 car、motorcycle、bus、truck 等类别。
# 类别 ID 到类别名的映射CLASS_NAMES_DICT=model.model.names# 关注车辆类别:car、motorcycle、bus、truckCLASS_ID=[2,3,5,7]🖼️ 单帧检测预览
在单帧上检查检测框和类别标签。
# 创建视频帧生成器generator=get_video_frames_generator(SOURCE_VIDEO_PATH)# create instance of BoxAnnotatorbox_annotator=BoxAnnotator(color=ColorPalette(),thickness=4,text_thickness=4,text_scale=2)# acquire first video frameiterator=iter(generator)frame=next(iterator)# model prediction on single frame and conversion to supervision Detectionsresults=model(frame)detections=Detections(xyxy=results[0].boxes.xyxy.cpu().numpy(),confidence=results[0].boxes.conf.cpu().numpy(),class_id=results[0].boxes.cls.cpu().numpy().astype(int))# format custom labelslabels=[f"{CLASS_NAMES_DICT[class_id]}{confidence:0.2f}"for_,confidence,class_id,tracker_idindetections]# annotate and display frameframe=box_annotator.annotate(frame=frame,detections=detections,labels=labels)%matplotlib inline show_frame_in_notebook(frame,(16,16))📏 设置计数线
定义跨线统计位置和输出视频路径。
# 参数设置LINE_START=Point(50,1500)LINE_END=Point(3840-50,1500)TARGET_VIDEO_PATH=f"{HOME}/vehicle-counting-result.mp4"VideoInfo.from_video_path(SOURCE_VIDEO_PATH)📹 生成计数视频
逐帧检测、跟踪并统计车辆通过数量。
fromtqdm.notebookimporttqdm# create BYTETracker instancebyte_tracker=BYTETracker(BYTETrackerArgs())# create VideoInfo instancevideo_info=VideoInfo.from_video_path(SOURCE_VIDEO_PATH)# 创建视频帧生成器generator=get_video_frames_generator(SOURCE_VIDEO_PATH)# create LineCounter instanceline_counter=LineCounter(start=LINE_START,end=LINE_END)# create instance of BoxAnnotator and LineCounterAnnotatorbox_annotator=BoxAnnotator(color=ColorPalette(),thickness=4,text_thickness=4,text_scale=2)line_annotator=LineCounterAnnotator(thickness=4,text_thickness=4,text_scale=2)# open target video filewithVideoSink(TARGET_VIDEO_PATH,video_info)assink:# loop over video framesforframeintqdm(generator,total=video_info.total_frames):# model prediction on single frame and conversion to supervision Detectionsresults=model(frame)detections=Detections(xyxy=results[0].boxes.xyxy.cpu().numpy(),confidence=results[0].boxes.conf.cpu().numpy(),class_id=results[0].boxes.cls.cpu().numpy().astype(int))# filtering out detections with unwanted classesmask=np.array([class_idinCLASS_IDforclass_idindetections.class_id],dtype=bool)detections.filter(mask=mask,inplace=True)# tracking detectionstracks=byte_tracker.update(output_results=detections2boxes(detections=detections),img_info=frame.shape,img_size=frame.shape)tracker_id=match_detections_with_tracks(detections=detections,tracks=tracks)detections.tracker_id=np.array(tracker_id)# filtering out detections without trackersmask=np.array([tracker_idisnotNonefortracker_idindetections.tracker_id],dtype=bool)detections.filter(mask=mask,inplace=True)# format custom labelslabels=[f"#{tracker_id}{CLASS_NAMES_DICT[class_id]}{confidence:0.2f}"for_,confidence,class_id,tracker_idindetections]# updating line counterline_counter.update(detections=detections)# annotate and display frameframe=box_annotator.annotate(frame=frame,detections=detections,labels=labels)line_annotator.annotate(frame=frame,line_counter=line_counter)sink.write_frame(frame)📌 小结
这篇教程完整整理了YOLOv8 车辆跟踪计数的核心复现流程。实际操作时,建议先确认 GPU、依赖版本、数据集路径和模型权重路径,再逐段运行 notebook。
后续我会继续按源项目顺序整理同系列中的目标检测、实例分割、OCR、多目标跟踪和视觉大模型教程。
📚 同系列教程汇总
Google Gemini 3.5 Flash 零样本目标检测教程:从提示词到可视化结果
GLM-OCR 文档识别实战教程:从验证码、公式到车牌 OCR
RF-DETR + ByteTrack 多目标跟踪实战教程:从命令行到 Python 视频轨迹可视化
SAM 3 图像分割实战教程:文本、框和点提示的多种分割方式
YOLOv8 + ByteTrack 车辆跟踪计数实战:跨线统计完整流程