
简介基于YOLOv8的实时人体检测.zip 是一套面向深度学习和计算机视觉开发者的实战代码包目标是帮助用户快速搭建可在视频流或图像中高效识别人员的检测系统。资源共18个文件以 Python 脚本为主包含 main.py、inference.py 等推理与启动代码以及 requirements.txt、dataset.yaml 等环境与数据配置还有模型权重、示例图片和说明文档整体仅 2.73MB轻量易用。目前已有 44 人学习下载。压缩包内除核心代码外还提供 YOLOv8 自定义数据集转换脚本、通用工具函数与测试输出图便于复现训练和验证流程。对于希望了解 YOLO 系列最新版本应用、开展人体检测实验或进行项目移植的开发者这套资源能提供可直接运行的工程框架降低配置成本。1. YOLOv8实时人体检测不是换模型是换交付方式你有没有接过这种需求工位越界报警、园区闯入检测、工地禁入区域提醒摄像头画面上只需要判“有没有人”。需求方嘴上说的是“做个实时人体检测”实际上要的是一个能跑在低成本盒子上的YOLOv8方案最好从头到尾都能复现。这类项目做到最后交付物通常就是一个“基于YOLOv8的实时人体检测.zip”里面放着训练好的权重、推理脚本、标注好的数据集可能还有一份RK3588部署记录。YOLOv8在这个场景里之所以被选得最多不是因为它在COCO上刷分最高而是因为环境配置简单、训练脚本统一、导出到ONNX和RKNN的链路成熟一个人用GTX 1660 Ti这种入门卡也能把流程完整跑通。这篇笔记写给两类人一类是把人体检测当业务交付的工程师另一类是刚接触YOLO训练、想从零攒一个单类别检测器的学习者。2. YOLOv8环境配置与首次推理先把最小闭环跑通2.1 从conda到GPU可用YOLOv8环境配置的三步拿到这个zip之后不管里面是推理脚本还是训练脚本第一步永远是先把ultralytics环境装干净。常见做法是新建一个独立conda环境避免把系统Python搞乱。Python版本我一般选3.9或3.10太新反而容易踩某些依赖库的兼容问题。conda create -n yolo python3.9 -y conda activate yolo pip install ultralytics python -c import torch; print(torch.cuda.is_available())这段命令的逻辑很直白先隔离环境再装ultralytics主包最后用一句Python确认CUDA是否可用。很多人卡在最后一步torch.cuda.is_available()输出False然后以为是YOLO装错了。其实是因为pip默认安装了CPU版PyTorch你得单独装对应CUDA的torch版本。GTX 1660 Ti配CUDA 11.x的常见组合就能正常用驱动和torch匹配好之后显存6GB跑yolov8n和yolov8s都够用别一上来就试yolov8x。环境配好后建议顺手跑一次官方预测验证整条链路不要直接拿项目里的自定义模型跑因为自定义权重有可能依赖你还没装上的包。验证通了再进项目目录看推理脚本这才是省时间的顺序。2.2 用COCO预训练权重先跑三行只留person类YOLOv8的官方权重是在COCO 80类上训练的其中person正好是第0类。所以哪怕你还没训练自己的数据集也可以用yolov8n.pt先验证摄像头或视频流能不能跑通实时人体检测。命令行最简单的方式是yolo detect predict modelyolov8n.pt sourcetest.mp4 classes0 conf0.35 device0classes0是这条命令最关键的参数它让模型只输出person类的结果过滤掉其余79类conf0.35把置信度阈值从默认0.25提高减少背景误检device0指定第一块GPU。如果你接到的是实时视频流项目常见做法是用Python脚本推流这样后续接电子围栏、告警逻辑才方便from ultralytics import YOLO model YOLO(yolov8n.pt) results model.predict(sourcertsp://192.168.1.64:554/stream, # 换成实际摄像头地址 classes[0], # 只要person conf0.35, # 提高阈值压低误报 imgsz640, # 和训练尺寸保持一致 streamTrue, # 视频流模式逐帧生成结果 device0) for r in results: boxes r.boxes if boxes is not None: print(boxes.xyxy.cpu().numpy(), boxes.conf.cpu().numpy())这段脚本的逻辑是把stream打开后results变成一个生成器每循环一次拿一帧的检测结果boxes.xyxy是左上右下坐标boxes.conf是置信度。需要说明的是imgsz如果设置成大于训练尺寸的值模型会自动缩放但耗时会明显上涨在1660 Ti上我一般就固定在640。2.3 项目包里的隐藏坑类名映射和阈值约定打开别人打包的“实时人体检测.zip”时最容易翻车的地方不是代码跑不起来而是权重文件与推理脚本里的类名约定不一致。有些项目的训练集把类别名叫person_face有些叫worker还有的干脆把安全和帽一起做成了多类别。直接拿通用yolov8n.pt去跑业务现场漏检率会让你怀疑人生。我的处理方式是先建一个独立的labels映射文件不管是训练还是推理都从同一个入口读CLASS_NAMES {0: person}这样的好处是后续换数据集、加类别只改这一处。另一个实际经验是zip包里如果没有提供训练过的weights就别指望用官方权重直接交付。官方模型见过的人形是千奇百怪的但你的现场可能是俯视摄像头、可能是半边身体被遮挡这些场景官方权重大概率扛不住老老实实走下一步训练自己的数据集。3. 训练自己的数据集从COCO子集到你自己的rt-person模型3.1 数据准备目录结构、标注格式和person子集所谓“训练自己的数据集”对实时人体检测来说核心就一件事让模型见过你现场的真实视角。常见的数据组织方式是YOLO格式的目录结构这个zip里的数据集大概率也是这么摆的datasets/rt-person/ ├── images/ │ ├── train/ # 训练图片 │ └── val/ # 验证图片 ├── labels/ │ ├── train/ # 对应标注txt │ └── val/ └── data.yamldata.yaml是YOLOv8训练时必须的配置文件内容很短path: datasets/rt-person train: images/train val: images/val nc: 1 names: [person]这里有个容易忽略的点path字段写的是数据集根目录训练命令里的data参数传这个yaml路径ultralytics会自动拼接出完整路径。标注文件是txt每一行对应一个目标格式是class cx cy w h其中cx cy w h是归一化后的中心点和宽高。如果你用LabelImg或Roboflow导出注意导出格式选YOLO不要选VOC XML否则还得自己写转换脚本。3.2 GTX 1660 Ti上的训练参数batch、imgsz、workers怎么给很多人第一次训练时喜欢把epochs拉到300但6GB显存的小卡根本扛不住大模型大batch。我的习惯是先用yolov8s.pt做预训练权重因为s模型在1660 Ti上还能保持可用的训练速度精度比n高出一截。训练命令如下yolo detect train modelyolov8s.pt datart-person.yaml \ epochs100 imgsz640 batch8 device0 \ workers2 cacheTrue patience20几个关键的参数取舍参数常用值说明imgsz640和部署时保持一致改大会拖慢速度和显存batch8~161660 Ti 6GB下yolov8s建议8yolov8n可以开到16workers0~4Windows下必须设0或2设大了会报DataLoader错误cacheTrue把图片缓存到内存减少硬盘IO等待训练快很多patience20验证集mAP连续20轮不涨就早停省时间补充一个判断标准训练完看runs/detect/exp/weights/下的best.pt和last.pt用best.pt做后续部署。很多新人拿last.pt去导出结果发现效果比best差一截这不是玄学last是最后一轮的参数best是验证集上最好的。3.3 用yolov8画损失函数曲线图读results.csv而不是截图ultralytics训练过程会自动生成results.png但那张图更像一个速览想要判断过拟合、欠拟合还是学习率问题最好自己从results.csv里画。这个文件在训练输出目录下每一行是一个epoch列名带train/box_loss、val/box_loss等字段。import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/detect/train/results.csv) fig, axes plt.subplots(1, 3, figsize(15, 4)) # 训练损失和验证损失放一起对比 axes[0].plot(df[epoch], df[train/box_loss], labeltrain_box_loss) axes[0].plot(df[epoch], df[val/box_loss], labelval_box_loss) axes[0].set_title(Box Loss) axes[0].legend() axes[1].plot(df[epoch], df[metrics/precision(B)], labelprecision) axes[1].plot(df[epoch], df[metrics/recall(B)], labelrecall) axes[1].set_title(Precision / Recall) axes[1].legend() axes[2].plot(df[epoch], df[metrics/mAP50(B)], labelmAP50) axes[2].set_title(mAP50) axes[2].legend() plt.tight_layout() plt.savefig(my_loss_curves.png, dpi150)这段代码的逻辑很简单把CSV里三个关键维度分别画出来。注意不要单独看train/box_loss降得多快要看它和val/box_loss的差距是否越拉越大。两条线分开很大说明模型在背训练集不是真学到了泛化特征。mAP50能过0.9再谈部署如果只有0.7多半是数据量不够或者标注有一半是错的。4. 把yolov8部署到RK3588从pt到onnx再到rknn的量化链路4.1 导出ONNXopset、imgsz和固定shapeRK3588上跑YOLOv8不能直接拿best.pt上去常见链路是先转ONNX再转RKNN。很多人第一步就翻车pytorch模型直接转RKNN会报各种算子不支持所以先导出ONNX是必不可少的缓冲。导出命令yolo export modelruns/detect/rt-person/weights/best.pt \ formatonnx opset12 imgsz640 dynamicFalse simplifyTrue对应的Python API写法from ultralytics import YOLO model YOLO(runs/detect/rt-person/weights/best.pt) model.export(formatonnx, opset12, imgsz640, dynamicFalse, simplifyTrue)导出后可以先在电脑上用onnxruntime验证一遍import onnxruntime as ort import numpy as np sess ort.InferenceSession(best.onnx) input_name sess.get_inputs()[0].name # 输入shape是[1,3,640,640]注意先做letterbox再归一化 dummy np.zeros((1, 3, 640, 640), dtypenp.float32) outputs sess.run(None, {input_name: dummy}) print([o.shape for o in outputs])这段代码的核心是确认导出后的tensor shape是否符合预期。YOLOv8的ONNX输出通常是三个检测头concat后的结果shape为[1, 84, 8400]80类版本或[1, 5, 8400]单类版本。opset12是转化成RKNN时兼容性最好的经验值opset太高在RKNN工具链里容易报算子不支持dynamicFalse要求固定输入尺寸RK3588上固定640比动态shape稳定得多。4.2 RKNN转换与INT8量化校准集不能随便给拿到ONNX后在RK3588上部署yolov8的下一步就是用RKNN-Toolkit转成rknn格式。以rknn-toolkit2的API为例转换脚本的常见写法是from rknn.api import RKNN rknn RKNN() rknn.config(target_platformrk3588, mean_values[[0, 0, 0]], std_values[[255, 255, 255]], quantized_dtypew8a8) rknn.load_onnx(modelbest.onnx) rknn.build(do_quantizationTrue, datasetcalib.txt) rknn.export_rknn(best.rknn) rknn.release()这里mean_values和std_values是最容易搞错的地方。YOLOv8训练时用的是像素除以255的归一化方式所以均值设为0、标准差设为255。如果你在这里填了ImageNet那套mean[0.485,0.456,0.406]推理结果会偏差到完全没法用。datasetcalib.txt里的内容是几百张图片的路径每行一张/path/to/calib/img_001.jpg /path/to/calib/img_002.jpg校准集不要从训练集里拿最好用现场实拍或验证集图片让量化过程看到真实部署场景的像素分布。INT8量化后mAP掉1~2个点是正常现象但如果掉超过3个点回去检查校准集数量和预处理是否对齐。4.3 板端推理队列加跳帧别让后处理拖死摄像头RK3588的NPU推理速度不慢但很多项目最终延迟高是因为导入和前后处理拖了后腿。板端常见做法是Python调RKNN的runtime APIfrom rknnlite.api import RKNNLite rknn RKNNLite() rknn.load_rknn(best.rknn) rknn.init_runtime(core_maskRKNNLite.NPU_CORE_0_1_2) # 每一帧推理前先做letterbox # frame_resized, ratio, pad letterbox(frame, (640, 640)) # 推理输出是一个list需要自行解析坐标并映射回原图板端推理的pipeline设计我的习惯是摄像头采集线程和推理线程分开中间用队列缓冲检测频率控制在10~15 FPS足够业务用不要每帧都推理否则CPU占用直接把NPU的收益吃掉。后处理里的NMS也要自己实现YOLO的ONNX/RKNN输出是原始预测框不做过NMS的话同一人会被框三四次。5. 实时人体检测避坑指南五个高频翻车现场5.1 用yolov8n.pt做电子围栏误检和漏检并存现象现场画面里没人系统却频繁报警或者人走过时框没跟上。原因是官方权重是通用模型对俯视、侧视、遮挡等场景没有专门优化。解决方法是先用classes[0]强制过滤类别再调整置信度阈值到0.4~0.5。如果还不行说明这个项目必须走自定义训练不是调参能救的。5.2 训练时GPU利用率低1660Ti跑了很久还在epoch 1现象nvidia-smi看GPU使用率一直在30%以下训练进度条像卡住一样。原因是数据读取瓶颈CPU来不及喂图。解决方法是加上cacheTrue或者把workers从0改成2。Windows系统下workers设大了反而会报DataLoader worker错误所以我的经验是Windows用0或2Linux才考虑4。5.3 转换RKNN后推理结果全空或坐标乱跳现象同一张图在电脑上onnxruntime推理正常转到RK3588后一张图都检测不出来或者画框的位置完全不对。原因几乎都是预处理不一致。RKNN转换和板端推理时mean_values/std_values填错或者没做letterbox直接resize到640。解决方法是统一预处理链路板端推理前先letterbox到640×640记录缩放比和padding推理后再把坐标映射回原图。这是我在RK3588部署yolov8时踩过最多的一类坑值得写进检查清单。5.4 同一人输出三四个框现象图像上一个人在头顶、胸口、腿部各有一个框置信度都挺高。原因是NMS没做或阈值太低。YOLO的检测头本身会产生大量冗余框ONNX导出时是不带NMS的需要自己在后处理里加。常见做法是NMS的IoU阈值取0.45~0.5太低会漏太高会重。5.5 热力图一片红无法定位模型在看什么现象想用热力图查漏检原因结果整张图都是红色。原因是直接对DetectionHead输出做GradCAM没有意义目标梯度传不到特征层。解决方法是选择Backbone最后一个特征输出作为target layer。这部分我给一个参考用法from pytorch_grad_cam import GradCAM from ultralytics import YOLO model YOLO(best.pt).model # 拿到底层nn.Module # 打印结构后定位目标层通常是SPPF模块的输出 target_layers [model.model[-3]] cam GradCAM(modelmodel, target_layerstarget_layers)这段代码能跑通的前提是你先打印一次模型结构确认SPPF层的索引。不同YOLOv8版本层索引可能偏移一位手输索引翻车太常见了。6. 用热力图与网络结构图给模型做体检模型训练完、部署前我习惯花半小时做一次“体检”体检工具就是热力图和网络结构图。热力图的意义在于回答“模型为什么这么判断”一张图片里人站在阴影下热力图如果只点亮人脚的部分说明模型学到的特征偏向局部纹理如果背景里的柱子也被点亮那你基本可以断定部署后会有一批柱子误检。这个洞察直接决定你要不要回头补数据而不是盲调阈值。网络结构图的价值在于确认你改了YAML之后模型到底变成了什么样。YOLOv8的yaml结构分Backbone、Neck、Head三段常见改动是给C2f层加注意力模块、或者在小目标层增加检测头。做这些改动前用print(model)看一眼参数量和每层输出shape能避免改完训练到一半才发现结构错位的尴尬。调试时把yaml里不用的层注释掉参数量变化立刻可见。我自己的习惯是给每个交付的模型保留三样东西训练用的data.yaml、转换后的best.rknn、一份热力图截图。后续现场出问题先看图再调阈值基本不用翻旧账。这条路走到现在也还是会在某些奇怪的光线下被模型秀一脸但至少能快速定位是特征问题还是部署问题。希望帮到你。本文还有配套的精品资源点击获取