YOLOv8行人检测项目实战:从环境配置到模型部署全流程
发布时间:2026/9/28 2:11:16来源:尧图网络
简介这份资源是基于YOLOv8的行人检测完整项目包面向计算机、人工智能、通信工程、自动化等专业的在校学生、教师及企业员工尤其适合作为课程设计、毕业设计、大作业或项目初期立项演示的参考方案也适合具备一定基础的小白进阶学习。包内共6个文件以3个pt权重文件、2个py脚本和1个txt说明文档为主压缩包约15.89MB权重文件可直接用于推理与验证脚本涵盖模型训练与视频检测流程说明文档则提供数据集与使用指引。项目代码均经过实际运行测试配套核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果及标签分布图能够直观呈现模型性能与训练过程。目前已有36人学习读者可在此基础上快速复现行人检测流程也可修改代码扩展至其他目标检测任务用于答辩、课设或项目演示均较为稳妥。1. 拿到一个行人检测项目压缩包先别急着解压你从师兄手里接过一个基于YOLOv8的行人检测项目.rar或者从某个资源站下载下来双击解压看到一堆.py、.yaml、.pt文件第一反应大概率是先跑起来看看。然后pip install ultralyticspython train.py报错改路径再报错再改折腾一下午最后卡在数据集格式不对或者显存爆了。这个场景太常见了。行人检测本身是目标检测里最经典也最实用的方向之一——安防监控、客流统计、自动驾驶感知、机器人避障底层都绕不开它。YOLOv8 作为 Ultralytics 维护的检测框架把训练和推理的工程门槛压得很低但“低门槛”不等于“零门槛”。一个打包好的项目里真正决定你能不能复现出结果的往往不是模型结构而是数据集组织、环境版本、训练参数这三件事。这篇文章面向的是拿到类似项目后想真正跑通、并且理解每一步在做什么的从业者。我会按“先看清项目里有什么 → 把环境搭对 → 把数据喂对 → 把训练跑对 → 把坑填上 → 把模型用起来”的顺序讲。新手可以照着命令走熟手可以重点看参数边界和排查逻辑。不保证你一次成功但能让你每次失败都知道该看哪里。2. 拆开压缩包YOLOv8 行人检测项目的标准结构和选型逻辑2.1 一个能跑的行人检测项目目录里应该有什么拿到基于YOLOv8的行人检测项目.rar之后先别管代码用tree或者文件管理器把目录结构看清楚。一个组织得比较规范的项目通常长这样pedestrian_yolov8/ ├── datasets/ │ └── pedestrians/ │ ├── images/ │ │ ├── train/ │ │ ├── val/ │ │ └── test/ │ ├── labels/ │ │ ├── train/ │ │ ├── val/ │ │ └── test/ │ └── data.yaml ├── weights/ │ └── yolov8n.pt ├── runs/ │ └── detect/ │ └── train/ ├── train.py ├── val.py ├── predict.py ├── requirements.txt └── README.md如果你解压出来的目录里没有data.yaml或者images和labels没有按train/val分开放那这个项目大概率是半成品需要你自己补数据集组织这一步。data.yaml是 YOLOv8 训练时读取数据集路径和类别信息的入口文件没有它训练脚本连数据在哪都不知道。weights/目录里放的是预训练权重。YOLOv8 官方提供了yolov8n.pt、yolov8s.pt、yolov8m.pt、yolov8l.pt、yolov8x.pt五个尺度的模型n 最小最快x 最大最准。行人检测如果部署在边缘设备上比如 RK3588 或者算力更紧张的板子一般从yolov8n.pt开始试如果跑在服务器 GPU 上追求精度可以上yolov8m或yolov8l。runs/目录是训练和推理结果的默认输出位置里面会有权重文件、损失曲线、验证指标和预测可视化图。2.2 为什么行人检测优先选 YOLOv8 而不是 Faster R-CNN行人检测这个任务有几个特点目标尺度变化大近处的人占几百像素远处的人可能只有十几像素、遮挡严重、实时性要求高。Faster R-CNN 这类两阶段检测器精度上限高但推理速度很难做到实时尤其是在没有 TensorRT 加速的情况下。YOLOv8 作为单阶段检测器在速度和精度之间取得了比较好的平衡而且 Ultralytics 的工程封装让数据加载、增强、训练、导出形成了一条比较顺的链路。另一个实际原因是生态。YOLOv8 的预训练权重在 COCO 数据集上已经见过大量“person”类样本直接拿来微调行人检测收敛比从零训练快很多。如果你拿到的项目里已经放了yolov8n.pt那说明作者至少考虑到了迁移学习这条路。行人检测数据集如果只有几千张图从预训练权重开始训练是标准做法学习率可以设小一点比如lr00.001甚至0.0005避免把预训练学到的通用特征冲掉。选 YOLOv8 还有一个不太被提及但很实际的理由它的输出格式统一导出 ONNX、TensorRT、OpenVINO 都比较顺。后面如果要部署到 RK3588 或者 Hi3516CV610 这类芯片上YOLOv8 的模型转换链路相对成熟社区里能搜到的踩坑记录也多。这不是说其他模型不能做行人检测而是在“从训练到部署”这条完整路径上YOLOv8 的阻力最小。2.3 环境配置CPU 版本和 GPU 版本的分岔路requirements.txt里通常会写ultralytics、torch、torchvision、opencv-python、numpy这些。但直接pip install -r requirements.txt有个坑它默认装的是 CPU 版本的 PyTorch。如果你机器上有 NVIDIA 显卡比如 GTX 1660 Ti不装 CUDA 版本的 torch训练时device参数设成0也会报错或者自动回退到 CPU速度差几十倍。CPU 版本的安装命令大概是这样pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu pip install ultralytics opencv-python numpyGPU 版本要根据 CUDA 版本选对应的 torch 轮子。比如 CUDA 11.8 环境下pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics opencv-python numpy装完之后用下面这段代码验证 torch 能不能看到显卡import torch print(torch.__version__) print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else CPU only)如果torch.cuda.is_available()返回False但你有显卡大概率是 torch 版本和 CUDA 驱动不匹配。GTX 1660 Ti 支持 CUDA 11.x 和 12.x但驱动版本太老的话只能装 CUDA 11.8 对应的 torch。Ubuntu 20.04 上可以用nvidia-smi看驱动支持的 CUDA 版本上限然后去 PyTorch 官网找对应的安装命令。这一步没有后悔药装错了就卸了重装别在版本冲突上硬扛。3. 把数据喂对行人检测数据集的格式转换与划分3.1 从 Labelme 标注到 YOLO 格式转换脚本和四个边界坑行人检测数据集常见的标注格式有三种VOC XML、COCO JSON、Labelme JSON。YOLOv8 训练需要的是 YOLO 格式的 txt 文件每行是class_id x_center y_center width height坐标都归一化到 0 到 1 之间。如果你拿到的数据集是 Labelme 标注的 JSON需要先转成 YOLO 格式。下面是一个把 Labelme JSON 转成 YOLO txt 的脚本假设所有标注的类别都是person对应class_id0import json import os from pathlib import Path def labelme_to_yolo(json_path, output_dir, class_map): 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 not in class_map: continue class_id class_map[label] points shape[points] xs [p[0] for p in points] ys [p[1] for p in points] x_min, x_max min(xs), max(xs) y_min, y_max min(ys), max(ys) # 边界裁剪防止标注超出图像范围 x_min max(0, min(x_min, img_w)) x_max max(0, min(x_max, img_w)) y_min max(0, min(y_min, img_h)) y_max max(0, min(y_max, img_h)) w x_max - x_min h y_max - y_min if w 1 or h 1: continue x_center (x_min x_max) / 2.0 / img_w y_center (y_min y_max) / 2.0 / img_h w_norm w / img_w h_norm h / img_h lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {w_norm:.6f} {h_norm:.6f}) out_path Path(output_dir) / (Path(json_path).stem .txt) with open(out_path, w) as f: f.write(\n.join(lines)) class_map {person: 0} json_dir datasets/labelme_json out_dir datasets/pedestrians/labels/train os.makedirs(out_dir, exist_okTrue) for jf in Path(json_dir).glob(*.json): labelme_to_yolo(str(jf), out_dir, class_map)这段代码里有几个地方容易翻车。第一Labelme 的points是矩形框的左上角和右下角但顺序不保证所以要用min/max取边界。第二标注可能超出图像边界不裁剪的话归一化坐标会大于 1YOLOv8 训练时虽然会做过滤但最好在转换阶段就处理掉。第三宽高小于 1 像素的框直接跳过这种框训练时是噪声。第四class_map要和data.yaml里的names顺序一致否则类别对不上训练出来的模型会把行人识别成别的类。3.2 data.yaml 的写法路径、类别数和类别名转换完标注之后需要写data.yaml。这个文件告诉 YOLOv8 去哪里找图片和标签以及类别是什么path: /home/user/pedestrian_yolov8/datasets/pedestrians train: images/train val: images/val test: images/test nc: 1 names: 0: personpath是数据集根目录train、val、test是相对于path的图片路径。YOLOv8 会自动把images替换成labels去找对应的 txt 文件所以标签目录必须和图片目录同级且同名。nc是类别数行人检测通常就是 1。names是类别索引到类别名的映射如果后面要做多类别检测比如同时检测行人和车辆这里就要改成nc: 2names里加一行1: car。注意data.yaml里的路径最好用绝对路径相对路径在不同工作目录下执行训练脚本时容易找不到文件。如果项目要迁移到别的机器上记得改path。3.3 训练集、验证集、测试集的划分比例和常见错误行人检测数据集的划分没有绝对标准但常见做法是训练集占 70% 到 80%验证集占 10% 到 15%测试集占 10% 到 15%。如果数据量少于 5000 张验证集可以少一点但测试集必须留出来否则你无法判断模型是真的学到了行人特征还是记住了训练样本。划分的时候有一个血泪经验同一个视频序列里抽出来的帧不能同时出现在训练集和验证集里。比如你从一段监控视频里每隔 10 帧抽一张图这些图之间的差异很小如果随机划分训练集和验证集会有大量近似重复的样本验证指标会虚高实际部署时性能掉得很厉害。正确做法是按视频序列划分或者按时间间隔划分确保验证集里的场景和训练集有足够的差异。另一个常见错误是图片和标签没有一一对应。YOLOv8 训练时如果发现某张图片没有对应的 txt 文件会直接跳过或者报错。可以用下面这段脚本检查from pathlib import Path img_dir Path(datasets/pedestrians/images/train) lbl_dir Path(datasets/pedestrians/labels/train) img_stems {p.stem for p in img_dir.glob(*.jpg)} lbl_stems {p.stem for p in lbl_dir.glob(*.txt)} missing_labels img_stems - lbl_stems missing_images lbl_stems - img_stems print(f图片数: {len(img_stems)}, 标签数: {len(lbl_stems)}) print(f缺标签的图片: {len(missing_labels)}) print(f缺图片的标签: {len(missing_images)})如果缺标签的图片很多要么是标注没做完要么是转换脚本漏了。缺图片的标签一般是删图时没删标签直接清理掉就行。4. 把训练跑对YOLOv8 行人检测的关键参数和损失曲线4.1 训练命令拆解从 yolov8n.pt 开始微调数据准备好之后训练命令本身不复杂yolo detect train \ modelweights/yolov8n.pt \ datadatasets/pedestrians/data.yaml \ epochs100 \ imgsz640 \ batch16 \ device0 \ workers4 \ projectruns/detect \ namepedestrian_train \ lr00.001 \ patience20model指定预训练权重路径。如果weights/目录里没有.pt文件Ultralytics 会自动从网络下载yolov8n.pt但有些环境网络不通所以最好提前把权重放好。data指向data.yaml。epochs是训练轮数行人检测微调一般 50 到 100 轮就够数据量大的话可以到 200。imgsz是输入图像尺寸640 是默认值如果小目标多可以提到 1280但显存占用会翻倍。batch根据显存调GTX 1660 Ti 6GB 显存跑yolov8n加imgsz640batch16基本能稳住跑yolov8m就要降到 8 或 4。device0指定第一块 GPUCPU 训练改成devicecpu。workers是数据加载线程数设成 CPU 核心数的一半左右比较合适。lr0是初始学习率。从预训练权重微调时0.001是一个比较稳的起点。如果训练损失震荡得厉害降到0.0005如果损失下降太慢可以试0.005但再高就容易发散。patience是早停耐心值验证指标连续 20 轮不提升就停止训练避免过拟合。4.2 损失曲线怎么看训练损失和验证损失的背离意味着什么训练跑起来之后runs/detect/pedestrian_train/目录下会生成results.csv和results.png。results.png里通常包含三组曲线训练集的 box_loss、cls_loss、dfl_loss验证集的对应损失以及 mAP50、mAP50-95 这些指标。看损失曲线的核心逻辑是看训练损失和验证损失的关系。如果两条曲线都在下降最后趋于平稳说明训练正常。如果训练损失持续下降但验证损失开始上升这是过拟合的典型信号需要加数据增强、加 dropout、或者减少训练轮数。如果训练损失从一开始就很高且不下降大概率是学习率太大或者数据标签有问题。YOLOv8 的box_loss是边界框回归损失cls_loss是分类损失dfl_loss是分布焦点损失。行人检测如果只有person一个类cls_loss会降得很快因为分类任务太简单。真正需要关注的是box_loss和 mAP 指标。mAP50 达到 0.8 以上行人检测基本可用mAP50-95 能到 0.5 以上说明框的定位精度也不错。如果results.csv里某些轮次的损失是nan一般是学习率太大或者数据里有异常标注。先检查lr0是不是设太高再检查标签文件里有没有坐标超出 0 到 1 范围的行。4.3 显存不够时的降级策略从 batch 到 imgsz 的调整顺序显存不够是训练时最常见的翻车场景。GTX 1660 Ti 6GB 显存跑yolov8m加imgsz640加batch16大概率会 OOM。调整的顺序应该是先降batch再降imgsz最后换更小的模型。batch从 16 降到 8 再到 4显存占用线性下降但训练速度会变慢梯度估计的噪声也会变大。如果batch降到 2 还是 OOM就把imgsz从 640 降到 512 或 416。imgsz对显存的影响是平方级的从 640 降到 416显存占用大概降到原来的 42%。如果还不行就换yolov8n它的参数量和计算量都比yolov8m小很多。还有一个不太被注意的显存占用来源是workers。数据加载线程太多每个线程都会缓存图像显存和内存都会涨。如果 OOM 发生在训练开始前先把workers降到 2 或 0 试试。5. 避坑与排查行人检测训练中最容易翻车的五个地方5.1 现象训练 loss 正常下降但验证 mAP 一直是 0原因data.yaml里的names和标签文件里的class_id对不上。比如标签里写的是0但names里0对应的不是person或者nc设成了 2 但标签里只有0这一类。YOLOv8 在验证时会把预测结果和标签做匹配类别对不上匹配失败mAP 就是 0。解决打开一个标签 txt 文件看第一列的数字。再打开data.yaml确认names里这个数字对应的类别名是你想要的。如果标签里是0names里0: personnc: 1这三者必须一致。5.2 现象训练到一半突然报 CUDA out of memory原因YOLOv8 在训练过程中会做数据增强某些增强操作比如 mosaic、mixup会临时增加显存占用。如果batch设得刚好卡在显存上限训练初期可能没事跑到某个 batch 遇到复杂增强就 OOM 了。解决把batch降到原来的 70% 左右留出余量。或者关掉部分增强在训练命令里加mosaic0.0和mixup0.0但这样可能会影响小目标的检测效果。更好的做法是保持增强降batch。5.3 现象验证集 mAP 很高但实际图片预测时框的位置偏移很大原因验证时的图像预处理和预测时的预处理不一致。YOLOv8 验证时默认会把图像 resize 到imgsz保持长宽比多余部分填充灰色。如果你自己写预测脚本时用了不同的 resize 方式比如直接拉伸框的位置就会偏。解决预测时直接用 Ultralytics 的predict接口或者确保你的预处理和验证时一致。如果必须自己写预处理用letterbox方式 resize记录缩放比例和填充偏移预测完再把框映射回原图坐标。5.4 现象训练日志里cls_loss一直是 0原因行人检测只有一类YOLOv8 在某些版本里对单类别任务的分类损失计算做了优化cls_loss显示为 0 是正常的不影响训练。但如果box_loss也是 0那就是标签文件全是空的或者data.yaml路径写错了YOLOv8 根本没加载到标签。解决先确认box_loss是否大于 0。如果box_loss正常cls_loss为 0 不用管。如果两个都是 0检查labels目录下有没有 txt 文件以及 txt 文件里有没有内容。5.5 现象从预训练权重微调后模型把所有人都检测成“人”但框特别大原因预训练权重是在 COCO 上训练的COCO 里的person类包含各种姿态和尺度。如果行人检测数据集里的行人主要是小目标而训练时imgsz设得太大模型会倾向于预测大框。另外如果lr0设得太大预训练学到的特征被冲掉模型会退化成随机初始化状态。解决把imgsz降到和实际部署时一致的尺寸比如 640 或 512。lr0降到0.0005或0.001。如果数据集里小目标多可以在data.yaml同级目录下加一个hyp.yaml调小box损失权重但更直接的办法是增加小目标样本的比例。6. 从训练到推理把行人检测模型用起来的几个具体技巧训练完成之后runs/detect/pedestrian_train/weights/目录下会有best.pt和last.pt。best.pt是验证指标最好的权重last.pt是最后一轮的权重。实际部署用best.pt但如果你发现best.pt在某些场景下不如last.pt也可以对比测试一下。推理命令很简单yolo detect predict \ modelruns/detect/pedestrian_train/weights/best.pt \ sourcetest_images/ \ conf0.25 \ iou0.45 \ saveTrue \ projectruns/detect \ namepedestrian_predictconf是置信度阈值低于这个值的框会被过滤掉。行人检测里conf0.25是一个比较宽松的起点如果误检多就提到0.4或0.5。iou是 NMS 的 IoU 阈值0.45是默认值如果两个人靠得很近框被合并了就把iou提到0.6或0.7。如果你要把模型集成到自己的 Python 代码里用 Ultralytics 的 API 更灵活from ultralytics import YOLO import cv2 model YOLO(runs/detect/pedestrian_train/weights/best.pt) cap cv2.VideoCapture(test_video.mp4) while cap.isOpened(): ret, frame cap.read() if not ret: break results model(frame, conf0.3, iou0.5, verboseFalse) for box in results[0].boxes: x1, y1, x2, y2 box.xyxy[0].tolist() conf box.conf[0].item() cls int(box.cls[0].item()) if cls 0: # person cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2) cv2.putText(frame, fperson {conf:.2f}, (int(x1), int(y1)-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) cv2.imshow(Pedestrian Detection, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()这段代码里verboseFalse可以关掉每帧的日志输出不然控制台会刷屏。conf0.3和iou0.5是视频推理的常用值比图片推理稍微宽松一点因为视频里目标有运动模糊置信度会偏低。如果后面要部署到 RK3588 或者 Hi3516CV610 这类芯片上需要先把.pt导出成 ONNX再用芯片厂商的工具链转成板端模型。导出命令是yolo export modelruns/detect/pedestrian_train/weights/best.pt formatonnx imgsz640 opset12 simplifyTrueopset12是 ONNX 算子集版本RK3588 的 NPU 工具链对opset12支持比较好。simplifyTrue会做一次图优化去掉冗余算子。导出之后用onnxruntime验证一下 ONNX 模型的输出和 PyTorch 模型是否一致再进板端转换流程。我自己的习惯是每次训练完先不急着导出而是用best.pt在验证集上跑一遍yolo detect val看混淆矩阵和 PR 曲线。如果person类的召回率低于 0.7说明漏检多要么加数据要么降conf。如果精确率低于 0.6说明误检多要么加负样本要么提conf。这两个指标比 mAP 更直观调参的时候盯着它们比盯着 loss 有用。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网