拓冰建站拓冰建站
首页 / 资讯中心 / 正文

YOLOv5 6.1全中文注释版:从源码解析到树莓派部署实战

简介YOLOV5 6.1版本全中文注释源码包面向目标检测初学者、研究生及创新创业大赛参赛团队针对官方代码结构复杂、英文注释难以理解等痛点对模型构建、数据集准备、训练验证、推理部署等核心模块逐行添加中文注解并配套CSDN专栏文章同步讲解帮助读者快速打通从原理到实战的完整链路。压缩包共2000个文件以Python源码、pyc编译文件为主同时包含C/C扩展、yaml配置、pt权重、mat数据文件、文档及辅助脚本覆盖模型定义、图像预处理、指标计算、工具函数等完整工程结构整体约297MB解压后目录层次分明。目前已有2785人学习下载。包内YOLOv5 6.1版本在5.0基础上集成新特性并优化模型大小参数量更少、更适合移动端通过中文注释可深入理解anchor机制、损失函数与推理逻辑快速上手自定义数据集训练为算法改进、论文实验或比赛落地提供有力支撑。1. YOLOv5 6.1 全中文注释版拿到压缩包后先别急着训练先读代码第一次拿到 YOLOv5 6.1 全中文注释压缩包的人大多有个共同反应解压、装依赖、准备数据集、跑 train.py恨不得当晚就看到 loss 曲线往下掉。如果你也打算这么干我劝你停一下。YOLOv5 6.1 是 ultralytics 团队在模型结构上最稳定的一版之一源码里浓缩了 anchor 匹配、损失函数、数据增强、模型部署的整套工程细节这些才是这个项目真正值钱的东西。全中文注释的意义不在于把英文翻译成中文而在于有人替你把这些细节按行讲透让你在改网络结构、调损失权重、做模型剪枝的时候不再靠猜。这篇笔记会从「为什么是 6.1」「解压后先看什么」「怎么用中文注释版跑通自己的数据」「源码注释怎么读」「常见翻车点在哪」一路写到「把训练好的模型部署到树莓派 5 上」。中间涉及的命令、参数、代码片段都是我自己在 Windows 和 Ubuntu 上反复跑过的你可以直接照着复制遇到问题回来对照着排查。适合的人群是两类一类是刚入门目标检测、想从源码层面理解 YOLOv5 的新手另一类是已经跑通过训练、但想改结构却不敢下手的熟手。中文注释版的价值恰恰是给第二类人补上「敢改」的底气。2. 6.1 版本见真章目录结构、网络骨架与选型理由2.1 拿到压缩包第一步确认版本与目录不管压缩包是从网盘、群文件还是同事 U 盘里来的解压后第一件事不是跑代码而是确认版本和目录完整度。一个标准 YOLOv5 6.1 工程的根目录应该有这些内容yolov5-6.1/ ├── data/ # 数据集配置 yaml 与超参数 yaml ├── models/ # 网络结构 yaml 与 common.py / yolo.py ├── utils/ # 数据增强、损失函数、指标计算等工具 ├── runs/ # 训练输出目录训练完自动生成 ├── train.py # 训练入口 ├── detect.py # 推理入口 ├── export.py # 模型导出入口 ├── val.py # 验证入口 └── requirements.txt6.1 版本有一个值得注意的目录变化它在 models 下按模型规格拆分出 yolov5s.yaml、yolov5m.yaml、yolov5l.yaml、yolov5x.yaml同时把锚框自动调整、超参数搜索等代码收敛到了 utils 的对应模块里。和更早的 5.0、6.0 相比6.1 的目录层级更规整入口脚本命名也更稳定很多教程到今天还在使用这套结构所以上手成本低。你在数据目录下还要确认 hyps 文件夹里有没有 hyp.scratch.yaml、hyp.finetune.yaml 等配置文件。全中文注释版一般会在这些 yaml 的每个参数旁边加一行注释告诉你这个参数控制什么、调大调小分别有什么后果。这一步别跳过因为后续你改的 90% 参数都集中在这些文件里。2.2 网络结构从 models/yolov5s.yaml 看整体骨架全中文注释版里注释最密集、也最值得先读的文件是 models/yolov5s.yaml 和 models/common.py。前者是网络的搭积木说明后者是每块积木的实现。yolov5s.yaml 的核心是三个部分backbone、head、anchors。我用缩进注释的方式简化一下它的结构和源码注释对应着看# 这是 yolov5s.yaml 的主体结构注释版 nc: 80 # 类别数训练自己的数据时改成你的类别数 # 锚框尺寸按 coco 数据集预设的 9 组 anchors: - [10, 13, 16, 30, 33, 23] # P3 特征图小目标 - [30, 61, 62, 45, 59, 119] # P4 特征图中目标 - [116, 90, 156, 198, 373, 326] # P5 特征图大目标 backbone: - [-1, 1, Conv, [64, 6, 2, 2]] # 初始卷积步长 2 下采样 - [-1, 1, Conv, [128, 3, 2]] # 下采样 - [-1, 3, C3, [128]] # 3 个 C3 模块残差结构 - [-1, 1, Conv, [256, 3, 2]] # 继续下采样 - [-1, 6, C3, [256]] - [-1, 1, Conv, [512, 3, 2]] - [-1, 9, C3, [512]] - [-1, 1, Conv, [1024, 3, 2]] - [-1, 3, C3, [1024]] - [-1, 1, SPPF, [1024, 5]] # 空间金字塔池化每行配置的第一个数字是「来自哪一层」-1 表示上一层输出直接送进来第二个数字是模块重复次数第三个数字是模块类型中括号里是参数。注释版一般会在每个模块后面标注它的输出通道数和特征图层级。读这个文件时你不需要逐行背重点抓两个信息特征图下采样的节奏以及 C3 模块在每一层的堆叠次数。这决定了模型的计算量和感受野也是你后续做轻量化改造时第一个要动刀的地方。2.3 为什么选 6.1版本对比与选型判断我经常被问既然现在社区里已经有更新的 YOLO 系列为什么还要回头用 6.1答案很实际。6.1 的代码体系相对收敛核心模块不频繁变动中间不起奇奇怪怪的版本兼容问题网上能搜到的大量中文资料、企业项目、比赛方案至今仍然建立在 6.1 的代码结构上。你如果要去改业务代码或者部署到边缘设备找一个稳定且社区资料深厚的版本作为基础比追新版本更省事。6.1 和 7.0 的版本之间最大的差异在于代码组织和模块命名而不是网络结构的颠覆性变化。如果你手上的中文注释版是基于 6.1 做的那么你在 6.1 上学的网络结构和训练流程迁移到后续版本时依然能看懂大部分代码因为主干逻辑是一致的。我的建议是新手直接以 6.1 为主力版本吃透结构之后再去看新版差异不要一上来就在多个版本之间反复横跳那是时间黑洞。3. 用 conda 从零跑通 YOLOv5 6.1环境搭建、数据准备与必调参数3.1 环境搭建conda 环境与依赖安装YOLOv5 6.1 对 PyTorch 的版本要求不算苛刻但踩过坑的人都知道最稳妥的方式是用 conda 单独建一个虚拟环境把项目的依赖隔离起来。这里给一套我反复使用的安装顺序# 1. 创建 Python 3.8 环境 conda create -n yolov5 python3.8 -y conda activate yolov5 # 2. 安装 PyTorch先装 CPU 版跑通再说 pip install torch1.12.1 torchvision0.13.1 --index-url https://download.pytorch.org/whl/cpu # 3. 安装项目依赖 cd yolov5-6.1 pip install -r requirements.txt先装 CPU 版再装 GPU 版是很多老手的习惯因为这样可以先排除环境本身的问题确认代码能跑通后再切换 GPU 加速。requirements.txt 里包含 numpy、opencv、matplotlib、pyyaml、tqdm 等一批基础库全中文注释版一般会在文件里给每个依赖标注用途比如某个包是数据增强用的、某个包是画框用的这一点对新手非常友好。装完依赖后运行一条简单的推理命令验证环境是否正常python detect.py --source data/images/bus.jpg --weights yolov5s.pt6.1 版本会自动下载 yolov5s.pt 权重文件在跑通之前不要训练自己的模型。看到 runs/detect/exp 里出现带检测框的 bus.jpg说明环境基本没有问题了。3.2 准备自己的数据集从标注到 VOC 转 YOLO 格式训练自己的数据集是 YOLOv5 使用频率最高的需求。常见做法是先用 LabelImg 或 X-AnyLabeling 标注图片生成 VOC 格式的 XML 文件再转换成 YOLO 需要的 txt 格式。YOLO 的标注格式是每行一个目标的 class_id x_center y_center width height坐标经过归一化处理。VOC 转 YOLO 的脚本网上有很多核心逻辑是对齐两个坐标系。# voc2yolo.py 核心转换部分 import xml.etree.ElementTree as ET def convert(xml_file, out_txt, class_list): tree ET.parse(xml_file) root tree.getroot() size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) lines [] for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in class_list: continue cls_id class_list.index(cls_name) box obj.find(bndbox) x1 float(box.find(xmin).text) y1 float(box.find(ymin).text) x2 float(box.find(xmax).text) y2 float(box.find(ymax).text) # 计算中心点坐标和宽高然后归一化 x_center (x1 x2) / 2 / img_w y_center (y1 y2) / 2 / img_h w (x2 - x1) / img_w h (y2 - y1) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) with open(out_txt, w) as f: f.write(\n.join(lines))这段代码里有几个容易忽视的细节class_list 的顺序必须和训练时的 data yaml 里 names 顺序完全一致否则类别错位宽高归一化用的是原图尺寸不是网络输入尺寸网络输入尺寸的缩放发生在训练的数据加载阶段。如果你在转换后发现检测框错位优先检查是不是把这两处搞混了。3.3 数据集配置文件以安全帽检测为例训练自己的数据集必须有一个 data yaml里面写明训练集、验证集路径和类别名。以安全帽数据集为例这是很多项目入门时的练习数据配置如下# safety_helmet.yaml train: datasets/safety_helmet/images/train val: datasets/safety_helmet/images/val nc: 2 names: [helmet, head]这里 train 和 val 写的是图片目录的路径。YOLOv5 6.1 在读取数据集时会自动在相同目录下寻找对应同名的 txt 标注文件所以 images/train 旁边应该有 labels/train。很多新手在这个环节翻车就是因为只准备了图片没把 labels 文件夹放到正确的位置结果训练时每张图都匹配不到标注。另外要注意 data yaml 里的路径6.1 版本支持相对路径和绝对路径但我在实际使用中更推荐只写上相对路径尤其在 Linux 服务器上训练时绝对路径在不同机器之间迁移几乎必然失效。全中文注释版一般会在 data yaml 旁加一段说明图片与标注文件的目录对照关系以及路径写错的常见后果。3.4 训练命令与超参数hyp.scratch.yaml 里值得调的 6 个参数训练入口是 train.py下面是一条最精简的训练命令python train.py --data safety_helmet.yaml --weights yolov5s.pt --img 640 --batch-size 8 --epochs 100参数含义分别是数据集配置、预训练权重、输入图片分辨率、批大小、训练轮数。batch-size 要根据显存调整8G 显存跑 yolov5s 用 batch-size 8 比较稳妥如果显存不够就降到 4或者把 --img 从 640 降到 512。新手不要为了追求快速收敛而强行增大 batch梯度爆炸和显存溢出都会让你白白浪费时间。更值得花时间研究的是 data/hyps/hyp.scratch.yaml这个文件控制训练过程中的各种超参数。全中文注释版本最重要的价值也在这里每个参数旁边都写了调大调小的后果。我挑几个影响最明显的参数默认值调大效果调小效果lr00.01收敛快容易发散收敛慢但更稳定lrf0.01最终学习率偏高难以精细收敛后期更稳定weight_decay0.0005正则增强防过拟合过拟合风险上升warmup_epochs3.0学习率上升更平缓前期震荡可能加剧hsv_h / hsv_s0.015 / 0.7色彩扰动更强加快泛化场景适应性下降flipud0.0上下翻转增强适合某些特殊视角保持原图方向不变在调超参数这件事上我的经验是一次只调一个参数每次训练完记录 mAP 和 loss 曲线不要同时动三个以上参数否则出了问题你根本不知道是哪一项造成的。hyp.scratch.yaml 的学习率策略是余弦退火配合 warmup如果你发现 loss 曲线在后期反复震荡优先检查 lrf 是不是设得太大了。提示全中文注释版在 hyp.scratch.yaml 里通常还会标出哪些参数是「数据增强参数」、哪些是「优化器参数」两类参数作用对象不同混着调容易互相干扰。4. 深入源码中文注释版里最值得逐行读的三个地方4.1 Focus 结构与 C3 模块读 common.py 的两种姿势理解 YOLOv5 的源码绕不开 models/common.py 这个文件。全中文注释版对这里的注释密度通常很高因为作者知道这才是整个项目里最容易劝退新手的关卡。第一个要先读懂的是 Focus 模块它在 6.1 版本里负责将输入图像做切片把宽高信息变换到通道维度上从而在保持信息量的同时实现下采样。# common.py 中 Focus 模块的注释版实现 class Focus(nn.Module): def __init__(self, c1, c2, k1, s1): super().__init__() # 先做通道重组再卷积核心是 stride 为 2 之前先把分辨率信息搬到通道上 self.conv Conv(c1 * 4, c2, k, s) def forward(self, x): # x 是 (b, c, w, h)下面四行是标准切片拼接做法 return self.conv(torch.cat([x[..., ::2, ::2], # 左上 x[..., 1::2, ::2], # 左下 x[..., ::2, 1::2], # 右上 x[..., 1::2, 1::2]], 1)) # 右下注释里的关键信息是Focus 把一张图的四个子区域提取出来拼到通道维度分辨率减半但通道数乘四后面的卷积负责做特征提取。在 6.1 版本中Focus 主要用于 yolov5s 及以下的小模型大模型默认开启它来降低计算量。读这里的时候不必死记切片索引记住「空间换通道」的意图就够了。C3 模块是另一个阅读理解重点。它是从 CSPNet 演化过来的结构把输入分成两支一支经过一系列 Bottleneck另一支直接连接最后在末端拼接。中文注释版一般会在 Bottleneck 的残差连接处标注一句这个 add 就是残差思想的体现能有效缓解深层网络的梯度消失。调试时如果你发现深层网络训练不动回到这里检查残差连接是否被自己改断过。4.2 yolo.py 的 Detect 层训练和推理为什么行为不同models/yolo.py 里的 Detect 层是 YOLOv5 输出的最后一道关卡。很多中文注释版会不厌其烦地在每个判断分支里写注释就是因为这层逻辑在训练和推理状态下走的路径完全不同。训练时Detect 层输出的是三个不同尺度特征图上每个网格的预测值推理时它要额外执行 anchor 解码、置信度过滤、NMS 等后处理。如果读者想改输出结构比如把 YOLOv5 改成 2 个检测头的轻量版本那么要改的地方就在这里遍历对象是 self.m 列表里的三个卷积层删掉一层同时要去修改 stride、anchor 索引和输出通道的对应关系。全中文注释版最多注释的地方之一就是告诉你在改检测头数量时哪些位置联动需要跟着改比如 loss 函数里的 nl 参数、yaml 文件里的 anchor 分组以及后处理中的网格生成逻辑。少改一处通常不会直接报错而是会出现预测框整体偏移之类的诡异现象。4.3 读懂损失函数loss.py 里到底在算什么utils/loss.py 是训练过程中的黑匣子很多人训练时只盯着 loss 下降却不知道 loss 由三部分构成。YOLOv5 6.1 的损失主要由三块组成分类损失、置信度损失和框回归损失。置信度损失和分类损失默认使用 BCEWithLogitsLoss框回归损失使用 CIoU。中文注释版一般在每个分支旁标注了当前分支的输入输出形状。理解损失函数对实际调参有什么帮助举例来说如果你发现检测结果中目标被频繁漏检而置信度又不低问题可能出在置信度损失和分类损失的权重配比上可以尝试增大置信度损失的权重。如果发现检测框的位置偏大或偏小优先检查 CIoU 部分和 anchor 的匹配情况而不是盲目调学习率。看懂 loss.py 之后你的调参才从「玄学」变成「有依据的尝试」。5. 趟过的 5 个常见坑环境、数据与训练环节排查5.1 提示 no labels found 但 labels 目录明明存在现象训练启动时报错 no labels found但去查看 labels 文件夹发现 txt 文件都在里面。原因文件后缀不匹配。YOLOv5 默认要求标注文件名与图片文件名完全一致包括扩展名以外的部分且要求标注文件是.txt后缀。如果你从标注工具导出的是.txt.names或包含空格的文件名加载器在匹配阶段就会跳过它们。解决统一图片和标注文件的基础名使用批量重命名脚本清理空格和中文。同时在 data yaml 里再检查一遍 train 路径是否指向了包含所有图片的目录而不是某个子目录。5.2 训练一开始就卡在 Downloading 阶段现象第一次运行 train.py 时长时间停在 Downloading yolov5s.pt 或 Downloading 数据集网络状态不佳时可能直接卡死或超时。原因6.1 版本启动训练或验证时如果本地找不到权重文件会自动从远程拉取。网络受限时这个操作会无限等待。解决提前手动下载好权重文件放到项目根目录。训练命令里加上--weights yolov5s.pt时确保本地文件已存在并用ls -lh yolov5s.pt确认文件完整避免下载到一半的残损文件。如果下载地址不稳定也可以从其他渠道获取同名权重后校验大小一致再使用。5.3 训练中途显存溢出报 CUDA out of memory现象运行十几个 epoch 之后突然报 CUDA out of memory之前的 epoch 都正常。原因显存溢出并不总发生在启动时。训练过程中数据增强在某些 batch 会生成更大的中间张量加上模型 EMA、日志记录等额外的显存开销逐步累积导致峰值超限。解决优先降低 batch-size从 8 降到 4其次降低输入分辨率从 640 降到 512如果还不够在 train.py 中开启梯度累积不必一上来就换更大的显卡。三种方式组合通常可以在不改代码的情况下解决 90% 的显存问题。5.4 训练时类别全部显示为同一个编号现象训练日志里每一行的 class 列始终显示同一个类别数字换数据集也一样。原因这个现象通常是标签顺序和 names 列表顺序不一致导致的。VOC 转 YOLO 时的 class_list 顺序与 data yaml 里 names 的顺序没有对应起来导致模型学到的类别映射和真实标注的意图错位。解决把 voc2yolo 脚本中 class_list 的定义顺序与 data yaml 里的 names 顺序逐一对齐然后重新转换标注。转换完成后随机挑选几张图片对应的 txt 文件打开检查 class_id 是否合理这比训练完再发现类别错乱要省时间得多。5.5 检测框在正确目标附近乱跳但不够贴边现象模型能检测到目标但检测框位置偏移明显尤其在目标边缘处不稳定。原因大概率是标注框质量问题尤其是标注框与目标边缘线不贴合人眼难以察觉但模型能感知。另一个可能原因是输入分辨率太低小目标经过多次下采样后特征损失严重。解决重新检查标注质量重点关注边缘贴合度将 --img 从 640 调整为 768 重新训练观察偏移现象是否缓解。如果标注本身没有问题再检查 anchor 是否需要通过 --autoanchor 重新计算。这一步往往是新手最容易忽略、而老手习惯性优先检查的点。整体排查下来真正需要动模型结构的情况很少绝大多数问题出在数据和参数上。6. 从训练到落地安全帽模型部署到树莓派 5 的推理验证训练好模型并在验证集上拿到不错的 mAP 之后下一步通常是把模型部署到真实设备上。树莓派 5 上部署自己训练的 YOLOv5 模型是近期被频繁讨论的落地方式。树莓派 5 的算力相比前代有明显提升但仍无法像桌面 GPU 那样流畅跑大模型所以部署前要先做模型轻量化。以安全帽检测模型为例完整流程分三步导出模型、部署推理、结果验证。第一步是用 export.py 将 PyTorch 模型导出为更适合边缘设备推理的格式。在树莓派 5 上更推荐使用 ONNX 格式加上 ONNX Runtime 推理导出命令如下python export.py --weights runs/train/exp/weights/best.pt --include onnx --opset 12 --img 640其中--weights指定训练出的最佳权重--opset 12是为了兼容树莓派上的 ONNX Runtime 版本。导出之后会生成 best.onnx 文件。树莓派 5 的 CPU 是 ARM 架构ONNX Runtime 在 ARM 上有良好的支持这是我不想直接用 PyTorch 原生推理的原因。第二步是写一段精简的推理脚本核心逻辑是读取图像、预处理、推理、后处理。预处理阶段要把图片缩放到 640x640 并做归一化后处理阶段要解析 ONNX 输出的张量完成解码和置信度过滤# rpi_helmet_detect.py 树莓派 5 推理脚本核心部分 import cv2 import numpy as np import onnxruntime as ort # 创建 ONNX Runtime 会话 session ort.InferenceSession(best.onnx) input_name session.get_inputs()[0].name img0 cv2.imread(test.jpg) img cv2.resize(img0, (640, 640)) img img[:, :, ::-1].transpose(2, 0, 1) # BGR 转 RGBHWC 转 CHW img np.ascontiguousarray(img.astype(np.float32) / 255.0) img np.expand_dims(img, axis0) # 推理 outputs session.run(None, {input_name: img})[0] # 后处理过滤低置信度框 confidence outputs[..., 4:5].squeeze() mask confidence 0.4 boxes outputs[..., :4].squeeze()[mask] scores confidence[mask] # 注意解码后的框是相对于 640x640 的坐标要缩放回原图尺寸 boxes[:, [0, 2]] boxes[:, [0, 2]] / 640 * img0.shape[1] boxes[:, [1, 3]] boxes[:, [1, 3]] / 640 * img0.shape[0]这段代码中容易出错的地方是坐标缩放YOLOv5 输出的坐标基于网络输入尺寸必须换算回原图尺寸才能正确绘制检测框。另外conf 阈值 0.4 在树莓派设备上是一个经验值阈值过高会导致漏检阈值过低会引入大量误检框落地部署时建议在同一场景下用多张真实图片反复验证后确定阈值。最后一步是验证部署效果。在树莓派 5 上跑完推理后不要只看有没有检测到框还要统计每帧推理耗时和检测准确率。如果推理速度不够理想优先检查是否启用了 ONNX Runtime 的线程数设置可以从 4 线程开始测试逐步增加到 8 线程观察性能提升是否稳定。如果速度提升不明显可能是 CPU 散热限制了频率而不是代码瓶颈。我自己的血泪经验是树莓派上部署不要一开始就追求完美效果先跑通单张图片、确认坐标映射正确再做视频流和速度优化。以后你再拿到新的中文注释版模型这个部署流程可以直接复用。整个过程里最值得投入精力的依然是数据质量和参数验证模型结构本身反而不是瓶颈。希望这篇笔记能帮你把这个方向做成、做透少走我走过的弯路。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门