恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
yolov8行人检测毕设实战:从环境搭建到ONNX部署
首页
资讯中心
/
yolov8行人检测毕设实战:从环境搭建到ONNX部署
yolov8行人检测毕设实战:从环境搭建到ONNX部署
发布时间:2026/9/26 1:56:37
简介基于YOLOv8的行人检测系统是一套面向计算机专业本科毕业设计的高分完整项目曾获导师指导与评审认可代码完整、可直接运行特别适合正在筹备毕业设计的学生以及需要课程设计、期末大作业或项目实战练习的学习者。资源内包含项目全部源码、多种规格的训练后权重模型、用于效果验证的示例图片、模型配置文件以及训练脚本和文档说明能够覆盖从数据准备、模型训练到推理检测的常规流程即使是基础薄弱的使用者也能根据说明快速复现。整个压缩包共十五个文件整体大小约一百五十五点七四兆字节其中图片文件用于展示检测效果权重文件对应不同精度与速度的模型版本配置文件和脚本则支持自定义训练与融合策略目录划分清晰方便按需取用。目前已有一百一十六人学习下载整体体量适中、应用价值明确既可用于学术研究参考也能作为工程化改造的起点。1. 一套配齐源码模型数据的yolov8行人检测毕设先搞清楚它装了什么“基于yolov8的行人检测系统源码训练好的模型全部数据”这类毕业设计项目在现在的CSDN和GitHub上几乎成了标配打包形式。我拿到手的第一反应不是先翻文档而是先验证一件事这套代码在我的机器上能不能把一张行人照片直接推出结果。如果模型路径和源码对不上后面所有训练都是在补无底洞。这套项目的完整形态一般包含三块训练脚本和推理脚本组成的源码、一个或多个训练好的.pt权重文件、以及标注好的行人检测数据集。对毕设来说它们分别对应三个验收点——系统能不能跑、检测准不准、数据是不是你自己能讲清楚的。这篇文章按一条可复现的落地方案拆开讲从环境搭建到数据组织、训练调参、避坑、导出部署全覆盖适合要交毕设的学生也适合第一次碰yolov8行人检测的开发者照着自己电脑一步步复现。2. 拆解yolov8行人检测项目的目录源码、权重和数据集各管哪一段2.1 拿到压缩包先看这四类文件训练脚本、推理入口、配置、权重解开压缩包后常见目录形态是这样的pedestrian_detect/ ├── train.py # 训练入口 ├── detect.py # 推理入口 ├── utils/ │ ├── datasets.py │ └── plots.py ├── runs/ │ └── detect/ │ └── train/ │ └── weights/ │ ├── best.pt │ └── last.pt └── datasets/ └── pedestrian/ ├── data.yaml ├── images/ └── labels/train.py负责读数据集和训练参数detect.py负责加载权重推理。runs/detect/train/weights下面那两个.pt是核心交付物best.pt是验证集上mAP最高的那一轮权重last.pt是训练结束时的最后一轮权重。对毕设答辩来说演示优先用best.pt但如果你发现best.pt在个别测试图上出现过拟合换成last.pt反而可能更稳。datasets/pedestrian目录就是“全部数据”所指的内容YOLO系列项目的数据到这里全是图片配txt标签的平铺结构具体组织方式下一节细说。2.2 训练好的模型怎么被调用ultralytics推理接口的最小用法不管源码里封装了多少层yolov8的推理核心就一段代码from ultralytics import YOLO # 加载训练好的权重路径换成你自己的 best.pt model YOLO(runs/detect/train/weights/best.pt) # 对单张图推理conf 是置信度阈值iou 是 NMS 阈值 results model(street.jpg, conf0.25, iou0.45, imgsz640, saveTrue)model(street.jpg, ...)返回的是一个Results列表每张图对应一个元素。取框和置信度时用boxes属性for r in results: for box in r.boxes: # xyxy 是归一化前的像素坐标conf 是置信度cls 是类别 id x1, y1, x2, y2 box.xyxy[0].tolist() conf box.conf[0].item() cls int(box.cls[0].item()) print(fperson: {conf:.2f} box: {x1:.0f},{y1:.0f},{x2:.0f},{y2:.0f})saveTrue会把画好框的结果图存到runs/detect/predict目录下这是最快的“跑通”验证方式。参数里conf0.25表示低于25%置信度的框全部丢掉iou0.45是NMS合并重叠框的阈值imgsz640会把输入图缩放成640x640再推理。这三个参数对行人检测的效果影响很大后面第3章单独讲。2.3 数据集的目录组织与标注格式YOLO的txt标签到底写了什么行人检测数据集的目录必须严格匹配data.yaml里的路径否则训练直接报错。常见结构datasets/pedestrian/ ├── data.yaml ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/images和labels文件名一一对应图片是000001.jpg标签就是000001.txt。txt里每行代表一个目标框格式是0 0.521484 0.437500 0.183594 0.410156五个数分别是类别id、归一化后的中心点x、中心点y、框宽、框高。这个关键点很反直觉yolov8的标签不是左上角和右下角而是中心点加宽高。我见过有人直接拿VOC的xml坐标换算成xyxy塞进txt结果训练出来的模型框全部偏到图片右下角。data.yaml是数据集的身份证path: datasets/pedestrian train: images/train val: images/val nc: 1 names: [person]nc: 1表示只有一个类别names里写person。如果你用的是基于opencv的传统行人检测做对照实验这套YOLO格式的布局依然成立——只是传统方法吃的是图片不吃txt标签。3. ubuntu20.04上搭建yolov8环境CPU版本也能把行人检测跑通3.1 环境准备从conda建环境到装ultralytics的完整命令在ubuntu20.04上搭一套CPU版本的yolov8环境是很多学生卡住的第一道坎。先装Miniconda然后按下面的顺序执行# 创建独立环境避免把系统 python 弄乱 conda create -n yolo python3.10 -y conda activate yolo # 安装 ultralytics 库yolov8 的训练和推理都封装在里面 pip install ultralytics # CPU 版本的 torch不装 CUDA 版也能跑推理和训练 pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu这里有两个关键点。第一必须用conda activate yolo把环境切过去不然pip装到系统python里后面import ultralytics会报ModuleNotFoundError。第二CPU版本torch和CUDA版本不能混装如果之前装过带cuda的torch建议先pip uninstall torch torchvision再执行上面最后一行。装完后验证一下python -c from ultralytics import YOLO; print(YOLO.__name__)能打印出YOLO就说明环境通了。很多人卡在“pip install ultralytics”这一步下载慢常见的做法是加-i https://pypi.tuna.tsinghua.edu.cn/simple换国内源但对毕设项目来说等官方源一次装完反而少踩版本坑。3.2 用训练好的模型跑一张行人照片把推理保存到本地环境就绪后新建一个detect_pedestrian.py写最简推理脚本from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) results model(test.jpg, conf0.25, iou0.45, imgsz640, saveTrue) for r in results: # speed 字典包含预处理、推理、后处理耗时CPU 上可以看到瓶颈在哪 print(r.speed) print(f检测到 {len(r.boxes)} 个行人)运行python detect_pedestrian.py跑完看runs/detect/predict/test.jpg如果框画在行人身上说明模型和代码路径都对了。在这个CPU环境里r.speed打印出的inference时间通常是几百毫秒到一两秒取决于你的机器。这个脚本是整个系统的地基之后接摄像头也好、接GUI也好都是在这段代码外面包一层循环。3.3 三个必调参数conf、iou、imgsz对行人检测的影响参数名作用推荐值调参方向conf置信度阈值低于该值的框被丢弃0.25行人太密容易漏检就调低到0.1误检多就调高到0.5iouNMS合并重叠框的阈值0.45行人互相遮挡严重时调低到0.3减少重复框imgsz输入缩放尺寸640小目标多就调成960但CPU推理时间会翻倍imgsz是这里面最容易忽略的参数。行人检测场景里远处的小行人只有二三十个像素用640推理可能直接漏掉这时候调到960能明显提升召回。代价是计算量几乎翻倍CPU环境下跑一帧从1秒变成2秒以上。我的建议是先拿640跑通全流程最后调优阶段再试960。iou在行人密集的街景里很关键两个行人叠着走阈值太高会把两个人都框成一个。注意CPU环境训练yolov8不是不行但效率很低。如果你的项目数据量超过两三千张建议找一台带NVIDIA显卡的机器跑训练CPU只负责推理。gtx1660ti这类6G显存显卡跑yolov8n是够用的后面训练章节会讲怎么设batch。4. 用全部数据重新训练yolov8行人检测模型从labelme标注到train.py参数4.1 labelme标注数据转成YOLO格式JSON转txt脚本很多行人检测数据集是用labelme标注的生成的是JSON文件。yolov8不认JSON要先转成txt。这里给一个可以直接用的转换脚本import json import os def labelme_to_yolo(json_path, out_txt_path, target_labelperson): with open(json_path, r, 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 ! target_label: continue # labelme 的 points 是多边形顶点这里取外接矩形 xs [p[0] for p in shape[points]] ys [p[1] for p in shape[points]] xmin, xmax min(xs), max(xs) ymin, ymax min(ys), max(ys) # 转成 YOLO 需要的中心点 宽高并归一化 cx (xmin xmax) / 2 / img_w cy (ymin ymax) / 2 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f0 {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) with open(out_txt_path, w) as f: f.write(\n.join(lines)) # 批量转换遍历 labels 目录下的所有 json for fname in os.listdir(labels): if fname.endswith(.json): labelme_to_yolo( os.path.join(labels, fname), os.path.join(labels, fname.replace(.json, .txt)) )脚本的逻辑是把labelme的多边形顶点取最小外接矩形再转成归一化的中心点坐标。这里有三个坑。第一类别id必须从0开始目标类别是person就写0如果数据集里还有carcar就写1顺序必须和data.yaml里的names一一对应。第二imageWidth和imageHeight必须和原图实际尺寸一致有些人标注完改了图没重新标注归一化全错。第三txt文件名必须和图片名完全一致包括后缀替换方式不然训练时找不到标签。4.2 训练参数怎么设epochs、imgsz、batch、patience转换完数据训练代码是纯ultralytics风格from ultralytics import YOLO # 用 yolov8n 的预训练权重做初始化比随机权重收敛快很多 model YOLO(yolov8n.pt) results model.train( datadatasets/pedestrian/data.yaml, epochs100, imgsz640, batch16, patience20, device0, # 0 表示第一张显卡CPU 训练改成 cpu namepedestrian, # 训练结果保存到 runs/detect/pedestrian )gtx1660ti这类6G显存显卡batch16和imgsz640刚好能跑起来再往上加batch就报CUDA out of memory。如果没有显卡devicecpu也能训练只是epochs100可能要跑到天荒地老建议把epochs降到30先验证流程通不通。参数名作用经验值epochs训练轮数100小数据集50就够patience连续多少轮验证集mAP不涨就早停20防止过拟合batch每批图片数6G显存用16CPU用8imgsz训练时的输入尺寸640patience20是一道保险训练到第80轮如果val mAP已经不再提升它会自动停省时间。训练结束后runs/detect/pedestrian/weights目录下会出现新的best.pt和last.pt这就是你重新训练的模型。4.3 画损失函数曲线图把结果可视化训练过程中随时监控训练时想确认模型有没有在收敛可以画损失曲线。ultralytics在训练过程中会把每个epoch的指标写进results.csv读出来画图import pandas as pd import matplotlib.pyplot as plt # results.csv 是训练过程中自动生成的 df pd.read_csv(runs/detect/pedestrian/results.csv) plt.figure(figsize(10, 6)) plt.plot(df[epoch], df[train/box_loss], labeltrain box_loss) plt.plot(df[epoch], df[val/box_loss], labelval box_loss) plt.xlabel(epoch) plt.ylabel(loss) plt.legend() plt.grid(True) plt.savefig(loss_curve.png, dpi150)判断模型好坏看两条曲线的走势train和val的box_loss都下降且最终贴近说明拟合正常train不断下降但val先降后升说明过拟合了需要加数据增强或调高patience提前停。这张loss曲线图放毕设论文里很好用比贴一堆训练日志直观得多。5. 行人检测训练易翻车的5个坑数据标签、显存与评估的踩坑记录5.1 现象训练完模型把什么都框成行人连路牌和树都不放过原因data.yaml里的names顺序和标签txt里的类别id对不上。常见做法是从某个数据集里白嫖了labels但names写成了[person, car]而txt里的id0其实代表car。解决打开一个txt文件看id再对照data.yaml逐个核对不要想当然认为id0一定是person。5.2 现象val精度高得离谱测试集上一塌糊涂原因数据划分时train和val里有重复图片或者补丁数据没做过去重模型相当于“开卷考试”。解决用图片的md5做一次全量去重保证train和val的图片文件名没有任何交集更严格的做法是用工具按场景划分把同一段视频抽出来的帧全部放进同一个集合。5.3 现象gtx1660ti一跑训练就报CUDA out of memory原因batch和imgsz把显存挤爆了6G显存撑不住16张640x640的图。解决先batch8、imgsz640跑通再把batch提到12还不行就把modelyolov8n.pt换成yolov8nn是nano最轻量不要一上来就用yolov8s或yolov8m。yolov8n在行人检测上的精度损失很小但对显存友好得多。5.4 现象近处行人都能框住远处的行人全漏检原因数据集里近景行人太多模型没见过多少小目标。解决训练时开mosaic增强ultralytics默认最后一个epoch关mosaic不用改数据侧把小目标样本单独复制几份或者把imgsz调到960训练。这里有个玄学点同样的数据imgsz640训练出来的模型对远处小行人基本无解但用960训一版漏检率能低不少。5.5 现象CPU推理一帧要两秒接了视频流直接卡成幻灯片原因常见写法是每帧都重新加载模型或者每帧都做letterbox缩放、BGR2RGB转换把时间耗在无关操作上。解决模型只加载一次放进循环外面预处理统一用cv2.resize加等比例填充不要每帧都申请新数组。如果还嫌慢把conf从0.25提到0.4能跳过大量低置信度框的后处理。对毕设的演示场景来说实时性不如检测效果重要卡一点没关系但代码里要能讲清楚瓶颈在哪。6. 导出ONNX模型并验证精度把yolov8行人检测接到部署侧毕设做到“模型能跑”只是及格加分项是把模型导出成ONNX证明它能脱离ultralytics独立部署。导出代码很短from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) # 导出 ONNXimgsz 必须和训练时一致这里用 640 model.export(formatonnx, imgsz640)生成best.onnx后用onnxruntime验证import onnxruntime as ort import cv2 import numpy as np sess ort.InferenceSession(best.onnx) input_name sess.get_inputs()[0].name img cv2.imread(test.jpg) img cv2.resize(img, (640, 640)) # YOLO 的 ONNX 输入是 RGB、0~1 归一化、NCHW 布局 img img[:, :, ::-1].transpose(2, 0, 1)[None] / 255.0 out sess.run(None, {input_name: img.astype(np.float32)})[0] print(out.shape) # (1, 84, 8400)84 4个框坐标 80个类别概率 背景ONNX的输出维度里8400是候选框数量4是xyxy坐标1是person类的置信度。验证方法很简单拿十张图分别跑pytorch版和onnx版对比输出的框和置信度误差在0.01以内就算成功。这一步在答辩时很有说服力因为你可以直接说“这个模型能接到rk3588这类边缘设备上”。以前我图省事训练完直接说部署结果在目标设备上框的位置偏了十来个像素后来养成了导出后先对标一次的习惯。模型能跑不算完能复现才算这算是我在这个项目上最值的一条经验希望帮到你。本文还有配套的精品资源点击获取