☰
基于YOLOv5的裂缝检测实战:从训练调参到树莓派部署
2026/10/1 1:36:52 网站建设 项目流程

简介:一套基于YOLOv5的裂缝检测完整工程包,面向深度学习目标检测方向的初学者,也适合作为毕业设计、课程设计或期末大作业的参考实践。项目围绕图像识别技术,完整展示了如何利用YOLOv5端到端地训练和检测裂缝,覆盖从环境搭建、数据配置到图片与实时视频流检测的多个环节。压缩包共51个文件,整体大小约2MB,包含22个YAML模型与训练参数配置、Python脚本、pyc文件及Shell辅助脚本,并附有容器化构建配置、项目说明文档和多张运行效果截图,各文件模块职责清晰。已有49人学习,配套检测脚本可分别完成实时视频流与静态图片的裂缝识别,目录中还提供了可直接加载的模型权重、数据集配置以及训练日志记录,便于对模型进行调试与优化。对想快速掌握YOLOv5工程化落地或完成课程项目的读者而言,这份资源提供了可运行的项目框架、清晰目录结构和完整的配置思路,具有不错的参考与复用价值。

1. 这个标题在讲什么:拿 YOLOv5 做裂缝检测,值不值得上手

“基于YOLOv5的裂缝检测设计.zip”这类压缩包,多半是课程设计或毕业设计里的一套完整工程:YOLOv5 源码、一批裂缝图片和标注、训练脚本。拿到它之后真正要解决的不是“把代码跑起来”,而是让模型在你自己的低对比度、复杂纹理图像上不漏检、不误检。裂缝是细长线状目标,宽度往往只有几个像素,和目标检测最擅长的方形目标完全相反,这也是为什么很多人把基础代码跑通后 mAP 却上不去。下面的内容按环境配置、数据准备、训练调参、避坑、部署的顺序,把这条链路里的关键参数和常见踩坑点讲透,适合应届生照着复现,也适合想用目标检测做结构健康检测预研的工程师先读完再决定投入。

2. 裂缝检测为什么选 YOLOv5:任务特性、源码机制与 conda 环境配置

2.1 裂缝检测的任务特性:小目标、低对比度,决定模型选型不能随便

裂缝在图像里是细长条线状目标,宽度可能只有 5~15 个像素,长度却跨越几十到上百像素。用矩形框去描述它非常别扭:框贴紧裂缝时,长宽比可能到 10:1;框稍微放松一点,框内大部分面积是混凝土背景。目标检测模型在训练时会把框内内容当作正样本,框内背景占比过高,特征就会被背景带偏,模型学到的不是“裂缝区域”而是“裂缝和它周围的灰色纹理”。

再看对比度。真实场景里的裂缝往往和阴影、水渍、钢筋锈迹、墙砖缝混在一起,灰度差异很小。传统视觉方案用 Canny 边缘检测加形态学处理,在受控光源下能出结果,一换环境就崩。用深度目标检测的好处是能从大量样本里自己学习“什么才是裂缝”,不需要手工调阈值,但代价是对数据量和标注质量敏感。

YOLOv5 的目标检测任务把裂缝问题拆成两步:先判断整张图里哪些区域可能有裂缝,再对每个区域回归出矩形框。这和直接做像素级分割不同,输出是一个框加一个置信度,对设计类项目来说更容易评估、更容易部署。后续如果要做裂缝面积计算,可以在检测框基础上加一层分割后处理,而不是一开始就选 Mask R-CNN。

选型上我一般直接劝人放弃 YOLOv5s,从 m 起步。原因很直接:s 的骨干更浅,特征图分辨率更低,对细裂缝的召回能力先天不足。显存允许就直接用 m,后期提精度靠输入分辨率,比换更大的 l 模型更划算。YOLOv5 源码对单类检测非常友好,训练、验证、导出脚本齐全,整个链路在一个仓库里能跑通,适合做设计交付。

2.2 YOLOv5 源码里和裂缝检测强相关的三个机制:CSP、PANet、自适应锚框

YOLOv5 的骨干网络叫 CSPDarknet,核心是 CSP(Cross Stage Partial)结构。它会把特征分成两部分,一部分继续走卷积,另一部分直接和前一部分拼接,再用一个过渡层融合。这样可以在减少冗余计算的同时保留深层特征。对裂缝检测的实际意义是:在相同显存预算下,你有余量把模型从 s 换到 m,而不会让训练时间成倍上涨。

PANet 是 YOLOv5 的特征融合结构,比单纯 FPN 多了一条自底向上的路径。裂缝的边界细节在浅层特征里最清晰,语义上下文在深层特征里最可靠。PANet 做的就是让深层语义传回浅层,同时把浅层位置信息再传回高层。两条路径交叉之后,模型对“细裂缝”和“细小噪声”的区分能力,明显比只用 FPN 的模型强。

自适应锚框是 YOLOv5 相对早期 YOLO 版本一个很省事的改进。训练前它会用 k-means 对数据集里的真实标签框重新聚类,输出一组更匹配的锚框。COCO 预训练权重自带的锚框偏向方形目标,裂缝框的长宽比普遍在 1:6 以上,如果不重新聚类,正样本匹配阶段的 IoU 匹配率会很低,很多真实框根本匹配不到锚框,训练就很难收敛。

有人会问,现在有更新的检测器,为什么还要守着 YOLOv5。裂缝检测这类垂直任务通常只有几百到几千张标注图,数据量撑不起 DETR 这类依赖大规模数据收敛的结构。YOLOv5 的 anchor 机制在数据少、目标形状极端的情况下反而更稳,而且源码已经进入维护模式,新功能不再加,社区踩坑资料多,遇到问题搜得到同类案例。做设计交付要的不是最新,是可控和可复现。

2.3 conda 环境配置:YOLOv5 基础笔记里最容易被跳过的版本坑

环境配置是整个设计里最容易翻车的环节。多数教程会让你直接拿 requirements.txt 一键装,但这里有两个坑:Python 版本和 torch 的 CUDA 版本。用 conda 单独建环境是最稳的做法,不要动系统里已有的 Python:

conda create -n yolov5 python=3.8 -y conda activate yolov5 cd yolov5-master pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

逻辑说明:python 3.8 是 YOLOv5 官方脚本里兼容性最稳的版本,3.10 以上也能跑,但个别依赖在 Windows 上容易出编译错误。pip 的 -i 参数只是把源换成清华镜像,网络条件正常的环境用官方源也一样。这里真正要盯的是下一步 torch。

requirements.txt 默认装的是 CPU 版 torch,这是环境配置里最隐蔽的坑。如果你的机器有 NVIDIA 显卡,装完后必须确认 torch 能不能调用 GPU:

pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 python -c "import torch; print(torch.__version__, torch.cuda.is_available())"

参数说明:--index-url 指定从 PyTorch 官方 CUDA 11.8 轮子源拉取安装包;torch.cuda.is_available() 输出 True 才说明 GPU 可用。如果输出 False,先别怀疑显卡,多半是安装时没指定 CUDA 版本,这是最常见的血泪经验。用 CPU 硬训一个 100 epoch 的裂缝模型可能要十几个小时,换成 GPU 后时间能缩短到三分之一以内。版本对照大致是:CUDA 11.7/11.8 对应 torch 1.13~2.x 配 Python 3.8;CUDA 12.x 对应 torch 2.1+ 配 Python 3.10。显卡驱动年份较新时,直接用 cu118 往往最省事。

环境配好后先不要急着训练,跑一次官方示例图验证整个链路:

python detect.py --weights yolov5s.pt --source data/images/bus.jpg

说明:yolov5s.pt 权重文件本地没有时,YOLOv5 会自动下载到 weights 目录,命令能正确输出框坐标并保存到 runs/detect/exp,说明环境、依赖、脚本路径都没问题。网络条件一般时,建议提前把权重文件放进 weights 目录再执行,避免卡在下载环节。这张示例图跑通后,后面再遇到问题就能先排除环境因素,把排查范围收敛到数据和参数上。

3. 训练自己的裂缝数据集:从标注规范到拿到 best.pt 的完整路径

3.1 数据准备:裂缝怎么标、数据集目录怎么组织

裂缝检测的第一步是数据,不是代码。常见做法是先用公开裂缝数据集把流程跑通,再补充 200~500 张自己场景的实拍图做微调。公开数据集的图像尺寸、光照、相机角度都比较统一,直接拿来训练,换场景后很容易翻车,补拍是必须的。

标注工具用 LabelImg 即可,导出格式选 YOLO,每张图片对应一个同名 .txt。标注操作看着简单,但几个规则直接决定模型收敛质量:

一条长裂缝一定要切成多段标注,每段短边贴住裂缝边缘,长边顺着裂缝走向,不要用一个大框把整条裂缝包进去。框内背景占比太高,模型学到的是“背景+裂缝”的混合特征,误检率会明显上升。标注时我习惯让相邻两个框的水平间隔不小于 10 个像素,宁可断开,也不要大面积重叠,否则后面 NMS 阶段会引发合并问题。

数据集目录按 YOLOv5 约定的格式组织:

mkdir -p datasets/crack/images/train datasets/crack/images/val mkdir -p datasets/crack/labels/train datasets/crack/labels/val

命令说明:images 放图片,labels 放同名 txt,train 和 val 严格分开。网上有文章说只建一个 images 目录让 train.py 自动划分,实际跑的时候你会发现划分逻辑不受控,val 集合里是什么图取决于内部随机种子,不方便复现。手工划分最稳。

划分脚本可以直接用下面这段,把原始图片和标签按 8:2 比例复制到训练目录和验证目录:

import os import random import shutil random.seed(42) image_dir = "raw_images" # 原始图片目录 label_dir = "raw_labels" # 原始标签目录 train_ratio = 0.85 # 训练集比例 imgs = [f for f in os.listdir(image_dir) if f.lower().endswith((".jpg", ".png", ".jpeg"))] random.shuffle(imgs) split = int(len(imgs) * train_ratio) for i, img in enumerate(imgs): label = img.rsplit(".", 1)[0] + ".txt" # 跳过没有对应标签的图片,否则会被当成背景负样本 if not os.path.exists(os.path.join(label_dir, label)): continue subset = "train" if i < split else "val" shutil.copy(os.path.join(image_dir, img), f"datasets/crack/images/{subset}/{img}") shutil.copy(os.path.join(label_dir, label), f"datasets/crack/labels/{subset}/{label}") print(f"训练集: {min(split, len(imgs))} 张, 验证集: {max(len(imgs) - split, 0)} 张")

逻辑说明:random.seed(42) 固定随机种子,保证同一批数据两次划分结果一致;复制而不是移动,是为了保留一份原始数据,训练中发现标注错误还能回头修,算是后悔药。只处理有同名 txt 的图片,是因为无标签图会被当成背景参与训练,背景过多会压扁正样本比例。输出数字和图片总数对不上时,大概率是原始 labels 目录里缺了部分同名 txt,需要补标。

划分完成后马上做一次数据一致性检查:

find datasets/crack/images/val -type f | wc -l find datasets/crack/labels/val -type f | wc -l

两个命令结果必须相等,train 目录同样。不等的情况多半是原始图片有 .jpg 和 .JPG 两种扩展名,而前面的划分脚本只匹配了 .jpg,大小写混用问题在 Windows 尤其常见。

提示:val 目录里图片数和标签数相等,不代表每张图都有同名 txt,还要跑一遍标签存在性检查。文件名大小写不一致时,YOLO 会跳过对应图片。

3.2 修改 data.yaml 和模型配置:把类别数先改对

YOLOv5 用 yaml 文件组织数据路径和类别信息,新建 datasets/crack/data.yaml:

train: datasets/crack/images/train val: datasets/crack/images/val nc: 1 names: ["crack"]

参数说明:train/val 相对路径是相对你执行 train.py 的目录,怕换终端后路径失效,写绝对路径更稳。nc 是类别数,这里是单类;names 是类别名列表,顺序和标注文件里的 class_id 一一对应。很多设计包原样保留了 COCO 的 80 类名,只改了 nc,导致训练时一直报索引越界,排查半天才发现是 names 里还留着其他类。

模型配置文件 models/yolov5m.yaml 只需要改一处:

nc: 1

其他 depth_multiple、width_multiple 参数保持默认。这些参数控制模型深度和宽度倍数,改动会让网络结构偏离预训练权重,迁移学习的效果变差。模型加载 yolov5m.pt 时,输出层类别数从 COCO 的 80 变成 1,原输出层权重会被丢弃并重新初始化。

3.3 训练命令与超参数:先跑通整条链路,再谈提精度

第一次训练的目标不是 mAP 多高,而是全程不报错、能生成权重、能用检测脚本画出框。先不要调参,按下面这个命令跑:

python train.py \ --data datasets/crack/data.yaml \ --cfg models/yolov5m.yaml \ --weights yolov5m.pt \ --epochs 100 \ --batch-size 16 \ --img-size 640 \ --device 0

参数说明:--weights 填 yolov5m.pt 是用 COCO 预训练权重做迁移学习,骨干特征已经具备通用物体感知;如果改成空字符串从零训练,几百张裂缝图很难收敛。--epochs 100 是预算值,YOLOv5 默认早停会在指标不再提升时提前结束,不会真的跑满。--batch-size 16 大约需要 20GB 显存,8GB 显存改成 8,再小就要用第 5 章说的梯度累积。--img-size 640 是输入分辨率,裂缝细的话后续优先提到 1280,而不是换更大的 l 模型。

训练日志里重点看 P(精确率)、R(召回率)、mAP@0.5、mAP@0.5:0.95 四个输出。第一次跑通时 mAP 低很正常,关键是 epoch 后没有出现 NaN、权重能保存。训练结束后会生成 runs/train/exp/weights/best.pt,用 detect.py 看几张 val 图:

python detect.py \ --weights runs/train/exp/weights/best.pt \ --source datasets/crack/images/val \ --conf-thres 0.3

如果这一步能画出框,你的“基于YOLOv5的裂缝检测设计”就已经完成了最核心的链路,接下来才是让指标变好看的过程。

4. YOLOv5 裂缝检测的必调参数与后处理:把 mAP 从 0.6 拉到 0.85 的路线

4.1 图像尺寸、batch、epoch、锚框:四个超参数怎么联动

先说结论:裂缝检测提升 mAP,优先动输入分辨率,其次动锚框,最后才动网络宽度和深度。原因是裂缝目标的尺度很极端,提高分辨率等于直接把目标放大给模型看,效果立竿见影。

图像尺寸的选择直接受显存约束。把 img-size 从 640 提到 1280,特征图面积变成原来的 4 倍,显存占用大约翻两倍以上,训练时间也变长。常见配置对照如下:

img-size显存占用趋势训练耗时趋势小裂缝召回适用场景
640基准基准一般快速验证流程
1280约 2~3 倍约 1.5~2 倍明显提升裂缝较细、显卡 24GB
1536更高更长趋于饱和只对极细裂缝有增量

这里的数字是量级趋势,不是精确测量值,不同显卡、不同 batch 下会有差异。数据以路面裂缝为主、宽度在 10 像素以上时,640 就够;如果是桥梁混凝土细微裂缝,宽度只有 3~5 像素,别犹豫直接上 1280。

batch 决定 BN 层的统计稳定性。裂缝数据集通常只有几百到上千张,batch 太小时每个 batch 的样本方差大,BN 均值来回跳,loss 会震荡。常见做法是 batch 尽量大,最小不要低于 8。显存不够时优先降 img-size 而不是降 batch,640 配 batch 16 的效果通常优于 512 配 batch 32。

epoch 和早停绑定看。YOLOv5 的数据集小,一般 60~80 轮就收敛。训练日志里 Best fitness 连续 30 轮不更新,就可以 Ctrl+C 手动停,权重保留的是 best.pt 而不是最后一轮的 last.pt。跑满 100 轮不收敛,问题通常不在 epoch 上,回数据里找原因。

锚框是裂缝检测最值得花时间的参数。YOLOv5 训练前会自动运行 k-means 聚类,日志会打印类似 AutoAnchor、BPR 的信息。如果 BPR 低于 0.9,说明默认锚框严重不匹配,要把聚类出的新锚框写进模型 yaml 的 anchors 段再重新训练。锚框的数值不是固定的,但排列思路固定:小尺度特征图配小锚框,大尺度特征图配大锚框,每组里必须要有长宽比接近 1:6~1:10 的细长条,用来匹配裂缝。

除了 train.py 的命令行参数,YOLOv5 的超参数文件 data/hyps/hyp.scratch-low.yaml 也直接影响裂缝训练。裂缝是结构表面缺陷,大幅的颜色扰动没有意义,建议把 hsv_h 从 0.015 降到 0.005,translate 从 0.1 降到 0.05。有些教程推荐 fliplr=0.5 开随机翻转,对裂缝检测反而有问题:裂缝走向不是对称特征,翻转会改变方向分布,建议关掉或降到 0.1。

4.2 后处理:conf-thres 与 iou-thres 是裂缝框质量的开关

很多设计交付只讲训练不讲后处理,detect.py 一跑,输出图上一堆碎框,看起来像“标得比裂缝还密”。这里的开关就是两个参数:conf-thres 和 iou-thres。

conf-thres 是置信度阈值,低于阈值的候选框直接丢弃。默认 0.25 偏向召回,适合通用检测;裂缝框数量多、局部响应强,同一段裂缝经常出现多个候选框,阈值提到 0.35~0.40 后碎框明显收敛。但如果裂缝本身很淡,阈值一提就把真裂缝过滤了,所以这个值要结合下一节的误检统计来定。

iou-thres 是 NMS 使用的 IoU 阈值,NMS 会把 IoU 高于阈值的候选框合并成一个。方形目标默认 0.45 合理,裂缝长条框之间重叠面积天然偏大,两段相接的断裂缝很容易被并成一个框。把 iou-thres 降到 0.3,可以让断裂缝保留为两个独立框,代价是同一段裂缝可能拆出多个框,需要配合可视化结果微调。

实际调参命令:

python detect.py \ --weights runs/train/exp/weights/best.pt \ --source datasets/crack/images/val \ --conf-thres 0.35 \ --iou-thres 0.3 \ --img-size 1280 \ --save-txt

参数说明:--save-txt 会把每个框的类别、置信度、坐标保存成 txt,方便后续做漏检统计;--img-size 必须和训练时一致,训练用 1280 而推理用 640 会让框坐标整体偏移,这个问题在部署章节还会遇到。调参时不要只看一两张图,拉 30~50 张 val 图跑一遍,记录误检数和漏检数再定。

4.3 验证阶段看什么:混淆矩阵、PR 曲线和漏检图

训练完的 runs/train/exp 目录下会有 confusion_matrix.png 和 PR_curve.png,这两张图比 mAP 数字更能定位问题。

混淆矩阵里关注背景列和裂缝行的交叉项。背景被大量预测成裂缝,说明正样本不够,需要在训练集里补背景负样本,或者提高 conf-thres;裂缝被预测成背景,说明裂缝样本多样性不足,光照和角度覆盖不够。很多笔记只说“mAP 不高就加数据”,实际先看混淆矩阵能省去一整周瞎折腾。

PR 曲线的形状同样直观。曲线尾部断崖式下跌,说明存在一小批难样本,模型在它们身上召不回。对裂缝检测来说,难样本通常是低照度下的细微裂缝,此时把 hyp 文件里的 hsv_s 调高,让模型多看些饱和度变化后的裂缝,比单纯加大训练集管用。

漏检图分析是容易被人忽略的一步。detect.py 的 --save-txt 会输出所有检测结果,漏检就是“有真实标签但没有检测框”的图,可以用脚本挑出来:

import os import cv2 gt_dir = "datasets/crack/labels/val" det_dir = "runs/detect/exp/labels" img_dir = "datasets/crack/images/val" for file in os.listdir(gt_dir): det_path = os.path.join(det_dir, file) if not os.path.exists(det_path): # 真实标签存在且检测结果为空,判定为漏检 img_path = os.path.join(img_dir, file.replace(".txt", ".jpg")) if os.path.exists(img_path): img = cv2.imread(img_path) cv2.imwrite(f"miss_{file.replace('.txt', '.jpg')}", img)

逻辑说明:遍历 val 的每个真实标签,如果同名检测结果不存在,说明模型在这张图上没输出任何框。批量导出后单独看一遍,你会发现自己数据的“盲区”比预想中集中,可能是逆光、可能是模板缝和真裂缝长得像。这一步做完,下一轮训练该增强什么、该改哪个阈值,心里就有底了。

5. 裂缝检测常见问题与排查:训练翻车、数据错乱、路径踩坑的记录

5.1 训练 loss 正常下降,val mAP 却一直为 0

现象:train loss 从 0.08 一路降到 0.03,训练集 mAP 接近 0.9,验证集 mAP 固定为 0,detect.py 在 val 图上完全画不出框。

原因:最常见的是数据切分错位。划分脚本只按图片后缀匹配,导致 val 里部分图片没有对应标签,YOLOv5 把它们当作背景图参与验证;或者是标签和图片同名但大小写不一致,Windows 上尤其常见。

解决:先对比 val 目录里图片数和标签数,再用脚本找出缺标签的图片:

import os image_dir = "datasets/crack/images/val" label_dir = "datasets/crack/labels/val" imgs = [f for f in os.listdir(image_dir) if f.endswith(".jpg")] for img in imgs: label = img.replace(".jpg", ".txt") if not os.path.exists(os.path.join(label_dir, label)): print(f"缺失标签: {img}")

逻辑说明:脚本检查每张图片的同名 txt 是否存在,缺一个就能立即定位。特意保留这个简单版而不是合并进划分脚本,是为了从别处拷来数据集时可以独立验证。吃了几次这个亏之后,我养成了训练前必跑一遍的习惯。数据量小时,发现问题直接补标签比重新训练省时间。

5.2 NMS 把裂缝框合并成一整条,或者同一段裂缝被拆成两个框

现象:检测结果里两段断裂的裂缝被一个大框包住;另一种情况是同一段连续裂缝被拆成两个框,中间有重叠。

原因:两个现象方向相反,但都指向 IoU 阈值。iou-thres 太高,NMS 把重叠区域大的不同目标合并;太低,同一目标的多候选框无法有效抑制。裂缝是长条框,IoU 分布和方形目标差异很大,网上默认参数没有参考价值。

解决:detect.py 里把 --iou-thres 从默认 0.45 降到 0.3,跑同一批 val 图对比。拆框变严重就回调到 0.35,合并问题依旧就继续降到 0.25。每次调整把预测图保存下来,不要只看命令行输出的 mAP 数字。注意这个问题是后处理层面的,重新训练解决不了,调 NMS 参数就够。

5.3 裂缝正样本太少,模型把所有目标都预测成背景

现象:训练完成后 P 和 R 都很低,可视化结果是整张图干干净净,没有一个框,但 val loss 看起来并不奇怪。

原因:这是典型的正负样本不均衡。裂缝是细线,一张 640x640 图里真实框面积可能只占 1%~3%。数据只有两三百张时,网络发现“什么都不输出”就能让 loss 停在低位。另一个常见原因是标签 class_id 和 names 不对应,比如 class_id 写成了 1,但 names 里只有 index 0。

解决:先检查标签内容,确认 class_id 全部是 0。然后做三件事:把长裂缝切成子框增加正样本数量;在 hyp 文件里适度增强 scale 和 translation;用预训练权重做迁移学习,不要从零训练。做了这些还不收敛,就把训练集每张图的标签可视化出来,看有没有标注框被意外丢出图像边界。

5.4 Windows 下数据集路径带中文或空格,训练中途崩溃

现象:训练开始正常,一两个 epoch 后突然报 cv2.error 或 FileNotFoundError,重跑可能换一个 epoch 崩。

原因:YOLOv5 读取图片依赖 OpenCV 的 imread,它对非 ASCII 路径支持很弱;中文路径还会在数据加载的多进程里触发编码错误。项目目录放在“桌面/毕业设计/裂缝检测”下是必踩的坑。

解决:把项目整个路径改成纯英文,目录名不要带空格。如果已经训练到一半,先停掉,把数据集和 yolov5 目录一起移动到 D:/crack_detection 下,再改 data.yaml 里的路径,epoch 数改成剩余数继续训练。移动过程中不要删 runs 目录,权重还在,只是重新跑时会从头记录日志。

5.5 显存不足时盲目缩小 batch 或模型,训练反而更慢

现象:显卡只有 8GB,按教程把 batch 从 16 改成 2,训练时间反而拉长,loss 还震荡。

原因:batch=2 时 GPU 计算单元利用率低,BN 统计量不稳定,模型朝一个方向还没走稳就换方向;把模型从 m 换成 s 虽然省显存,但小模型在裂缝这种小目标上精度下降,需要更多 epoch 补偿,总时间并没有省下来。

解决:先降 img-size 到 512,再降 batch 到 8。如果还是不够,用 YOLOv5 的梯度累积参数:train.py 后加 --nbs 64。nbs 是名义 batch size,代码会把 batch=8 的多次迭代梯度累积后更新一次权重,模拟 batch=64 的效果。训练时间会比正常 batch 长一点,但比 batch=2 的震荡收敛快得多,显存占用基本不变。

6. 树莓派 5 上部署自训练的 YOLOv5 裂缝模型:导出、推理与掉帧的取舍

6.1 从 PyTorch 到 NCNN:树莓派上最常走的部署路径

树莓派上直接跑 PyTorch 不现实,内存和算力都撑不住。常见做法是先把 PyTorch 权重转成 ONNX,再用 NCNN 的 onnx2ncnn 工具转成树莓派可用的 param/bin 格式。YOLOv5 自带导出脚本,第一步命令是:

python export.py --weights runs/train/exp/weights/best.pt --include onnx --img-size 640

参数说明:--img-size 要和训练分辨率一致,不一致会改变输出特征图的尺度,部署后框会偏移。导出后用 onnx-simplifier 优化一遍,再走 NCNN 的工具链转格式。树莓派 5 的 CPU 有 4 个性能核,NCNN 推理延迟会明显优于直接跑 PyTorch,具体帧率和模型宽度、输入分辨率强相关。这里给不出一个万能数字,你在自己的板子上跑一遍 benchmark 最靠谱。

6.2 部署时的输入分辨率取舍:416 还是 320,必须重新验证

很多设计包只教导出不教重新验证,把训练时的 640 输入原样拿到树莓派上跑,帧率直接掉到个位数。换到边缘端,输入分辨率一般要降到 416 或 320,但代价是细裂缝进入模型后只剩几十个像素,检测精度会掉。用降分辨率模型跑那批标准 val 图,对比 mAP 和单帧耗时,才算完成部署验证。

输入分辨率帧率趋势精度趋势适用场景
640基准基准后台批处理,不要求实时
416提升明显轻微下降实时巡检但裂缝较粗
320最快下降较多只做预筛选,需要二次确认

实际项目里我一般先用 416 跑,因为裂缝本来就是小目标,320 下容易整条漏掉,省下来的帧率没有意义。

6.3 部署后别只盯 FPS:漏检率和困难集才是验收标准

部署完成后,录一段 10 秒连续画面跑一遍,逐帧统计漏检数。只看 FPS 很容易把问题盖住,一段画面里漏了三条裂缝,帧率再高也不能交付。我通常会把部署后漏检最集中的样本单独存成“困难集”,之后每次调参都拿它回归。习惯是:先在桌面端把 mAP 调到满意,再到树莓派上换分辨率、做量化,最后用困难集验收,而不是一开始就在边缘端反复试参数。这个顺序能帮你把调参和部署两个变量拆开,哪一步出问题都能单独定位。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询