ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

YOLOv5草莓目标检测实战:数据预处理、模型训练与调优指南

YOLOv5草莓目标检测实战:数据预处理、模型训练与调优指南 简介这是一份基于YOLOv5的草莓目标检测项目源自猛犸杯比赛赛题面向目标检测初学者、计算机相关专业学生及竞赛参与者。项目包括可直接运行的Python源码与训练脚本、主办方提供的草莓图像数据集几百张及对应XML标注文件重点演示在数据量受限时如何通过数据清洗、数据增强与标注转换等预处理环节提升模型准确率。压缩包共507个文件以402张JPG原图和100个XML标注文件为主另有IPYNB主程序、3个数据库文件及说明文档整体约979.54MB。已有200人下载学习并提供远程教学支持便于解决运行中的实际问题。适合作为课程设计、毕业设计或算法练习的参考也可在此基础上二次开发应用于自定义目标检测任务。1. 从比赛赛题看YOLOv5草莓目标检测的落地路径草莓目标检测这类赛题通常给几百张已经标注的图片要求在测试集上识别出成熟和未成熟果实并按IoU阈值计算AP。很多人看到“几百张”第一反应是数据不够实际上这个量级配合预训练权重和在线增强比赛里完全能跑出mAP 0.8以上的结果。YOLOv5的优势是训练脚本、验证脚本和导出脚本一体Python源码可控换数据只需要改yaml和标注格式。我们按比赛准备的顺序把环境、标注、训练、评估和微调几个环节的命令与参数逐个说清遇到报错也知道去哪一行改。2. YOLOv5环境搭建与草莓数据集格式预处理YOLOv5的源码环境依赖是固定的第一步先把Python版本和依赖库锁住。如果直接用系统Python 3.13去跑requirements.txt大概率在opencv-python或pandas的wheel编译上卡住。我一般用Miniconda建独立环境Python指定3.8装完依赖后训练、验证、导出都在同一个环境里不会出现“本机能跑、换机器崩”的情况。2.1 用Miniconda创建YOLOv5专用Python环境conda create -n yolov5 python3.8 -y conda activate yolov5 cd yolov5 pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simplerequirements.txt锁定的是YOLOv5官方仓库在release/v6.0之后维护的依赖版本torch和opencv-python是重头。指定清华镜像可以缩短安装时间如果是内网环境提前把wheel包下载好再离线安装也一样。安装完成后检查GPU是否可用python -c import torch; print(torch.cuda.is_available(), torch.cuda.device_count())输出True 1表示CUDA版torch已生效。如果输出False说明装成了CPU版需要去PyTorch官网按CUDA版本重新安装再补装requirements里其他依赖。这一步装错后面训练时间会差几十倍几百张图的数据集可能从一小时变成十小时。2.2 草莓图像数据集目录组织与YOLO标注格式转换YOLOv5要求数据集按images和labels两个顶层目录组织train和val子目录两边对应。比赛给的数据常见是VOC的XML标注少数是COCO的JSON。下面是一段VOC转YOLO格式的核心代码。# voc_to_yolo.py import os import xml.etree.ElementTree as ET def convert(width, height, box): dw 1.0 / width dh 1.0 / height x (box[0] box[1]) / 2.0 y (box[2] box[3]) / 2.0 w box[1] - box[0] h box[3] - box[2] return x * dw, y * dh, w * dw, h * dh class_map {immature: 0, mature: 1} for xml_file in os.listdir(annotations): tree ET.parse(os.path.join(annotations, xml_file)) root tree.getroot() width int(root.find(size/width).text) height int(root.find(size/height).text) out_name os.path.join(labels, xml_file.replace(.xml, .txt)) with open(out_name, w) as f: for obj in root.iter(object): name obj.find(name).text if name not in class_map: continue box obj.find(bndbox) x0 float(box.find(xmin).text) y0 float(box.find(ymin).text) x1 float(box.find(xmax).text) y1 float(box.find(ymax).text) x0 min(max(x0, 0), width) x1 min(max(x1, 0), width) y0 min(max(y0, 0), height) y1 min(max(y1, 0), height) if x1 x0 or y1 y0: continue cx, cy, w, h convert(width, height, [x0, y0, x1, y1]) f.write(f{class_map[name]} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}\n)convert函数把左上右下坐标转成中心点加宽高的归一化形式。坐标越界处理放在转换前因为比赛数据里偶尔会出现轻微越界的框直接过滤会导致目标丢失clip后再判断是否反向框能最大化保留有效标签。转换后抽查几个txt确认每行5列数字且坐标都在0到1之间再进入下一步。2.3 自定义data.yaml与train/val划分在项目根目录创建datasets/strawberry目录结构如下datasets/strawberry/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yaml划分训练集和验证集用一段简短的Python脚本# split_data.py import os, random, shutil random.seed(42) src_images images/all src_labels labels/all for split in [train, val]: os.makedirs(fdatasets/strawberry/images/{split}, exist_okTrue) os.makedirs(fdatasets/strawberry/labels/{split}, exist_okTrue) files [f for f in os.listdir(src_images) if f.endswith(.jpg)] random.shuffle(files) split_index int(len(files) * 0.8) for f in files[:split_index]: shutil.copy(f{src_images}/{f}, datasets/strawberry/images/train/ f) shutil.copy(f{src_labels}/{f.replace(.jpg, .txt)}, datasets/strawberry/labels/train/) for f in files[split_index:]: shutil.copy(f{src_images}/{f}, datasets/strawberry/images/val/ f) shutil.copy(f{src_labels}/{f.replace(.jpg, .txt)}, datasets/strawberry/labels/val/)这里用随机采样而不是按目录顺序切分因为比赛数据往往按拍摄批次存放直接取前80%会导致训练集和验证集光照分布不均匀。固定random.seed保证重复运行结果一致。如果数据里有明显重复的近景图先把重复图去重再做划分。data.yaml按以下内容编写路径使用相对项目根目录的写法。# datasets/strawberry/data.yaml path: datasets/strawberry train: images/train val: images/val nc: 2 names: [immature, mature]需要警惕的地方是nc必须和labels里的类别id最大值加1一致YOLOv5不会自动校验这一点。常见报错是“indices should be between 0 and nc-1”出现时直接检查标注txt里是否有超过nc-1的id。3. 用YOLOv5s训练草莓检测模型参数设置与训练命令数据准备好之后进入训练环节。比赛场景不用追求大模型几百张草莓图用YOLOv5s在单卡上能稳定收敛参数量小、推理速度快评测阶段的硬件限制基本可以忽略。3.1 为什么选YOLOv5s而不是YOLOv5m或YOLOv5x先看一组官方结构默认参数模型权重深度倍数通道倍数显存占用约速度参考yolov5s.pt0.330.503.7GB最快yolov5m.pt0.670.755.6GB较快yolov5l.pt1.01.09.2GB中等yolov5x.pt1.331.2514GB慢几百张的小数据YOLOv5l以上的模型在训练集上容易把注意力集中到背景纹理验证集反而掉点YOLOv5s叠加迁移学习的表现通常不比大模型差训练时间只有五分之一。我一般先跑一版s确认baseline再按上一版的结果决定要不要换m。3.2 下载预训练权重并启动训练本次使用yolov5s预训练权重来初始化参数。train.py检测到本机没有yolov5s.pt时会自动下载网络受限的环境可以手动把权重文件放到weights目录。# 在yolov5项目根目录执行 python train.py \ --weights yolov5s.pt \ --data datasets/strawberry/data.yaml \ --epochs 200 \ --batch-size 16 \ --img 640 \ --device 0 \ --cache \ --patience 40 \ --project runs/train \ --name strawberry_exp参数说明--img 640训练时会将图像resize到640x640。草莓果实体型小如果原图分辨率较高可以降到608或512减少小目标被压缩的损失。--batch-size 16在8GB显存下属于安全值显存不够则改成8并把cache去掉。--patience 40是早停策略验证集指标连续40个epoch不提升就停适合比赛期间反复试参数。--cache把图像缓存到内存几百张图只占几百MB能明显加快数据加载。YOLOv5默认开启mosaic和旋转这类在线增强因此不用在训练命令里额外写增强参数。若数据中草莓重叠非常密集常见做法是到数据增强配置里把copy_paste从0调高到0.5让本图中的目标复制粘贴到另一位置增强遮挡样本。训练时终端会周期性打印loss和精度信息只要看到mAP_0.5在逐步上升就可以放着跑。3.3 训练过程中的日志监控与权重选择训练结束后runs/train/strawberry_exp目录下会生成best.pt、last.pt和results.csv。比赛提交时优先用best.pt因为它是验证集指标最高的权重last.pt是最后一个epoch的权重如果前面出现过更高点last未必更好。很多参赛者不看results.csv就直接提交这是最容易丢分的习惯。验证集指标在表格里的对应关系metrics/precision 精确率metrics/recall 召回率metrics/mAP_0.5 主评测目标metrics/mAP_0.5:0.95 更严格的综合指标# 用训练日志画mAP曲线 python -c import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/train/strawberry_exp/results.csv) plt.plot(df[epoch], df[metrics/mAP_0.5]) plt.xlabel(epoch) plt.ylabel(mAP0.5) plt.savefig(map_curve.png) 这段脚本只展示results.csv的读取方式比赛里查看训练曲线能判断是欠拟合还是过拟合。如果mAP_0.5曲线还在缓慢上升说明训练没有完全收敛可以加大epoch数继续训练曲线已经平坦反而说明早停设置合理。4. 用验证集评估草莓检测模型的性能与错误分析训练完成后不要急着跑测试集。先用验证集做一轮detect确认置信度阈值、NMS参数和类别分布符合比赛要求再决定要不要调整策略。4.1 单张草莓图的测试命令与参数python detect.py \ --weights runs/train/strawberry_exp/best.pt \ --source datasets/strawberry/images/val/ \ --imgsz 640 \ --conf-thres 0.25 \ --iou-thres 0.45 \ --save-txt \ --project runs/detect \ --name val_out--source支持单个图片、图片目录或视频文件val目录下所有jpg会被逐张推断--conf-thres 0.25过滤掉置信度低于0.25的框草莓目标尺寸较小不推荐把这个值调到0.4以上容易漏检--iou-thres 0.45是NMS去重的IoU阈值果实重叠严重的测试图可以提高到0.5减少重复框。如果推理时内存不足或速度变慢优先检查--imgsz是否和训练一致。训练用的608这里设640边长变化超过10%会直接影响mAP两者保持一致最稳妥。4.2 使用val.py计算精确率、召回率和mAP验证脚本会输出与比赛评分一致的指标python val.py \ --weights runs/train/strawberry_exp/best.pt \ --data datasets/strawberry/data.yaml \ --img 640 \ --task val \ --iou 0.5 \ --conf-thres 0.001这里有两处关键设置--iou 0.5指定主评测mAP的IoU阈值和比赛要求保持一致。--conf-thres 0.001统计mAP时把置信度阈值压低让AP曲线完整计算。实际推理时可以用更高的conf-thres过滤噪声。输出表中Speed和mAP_0.5一目了然。如果mAP_0.5低于0.6先看precision和recall哪一项拖后腿。recall低说明漏检多优先增强小目标precision低说明误检多需要回查标注是否有漏标或类别边界模糊。4.3 从混淆矩阵和目视图诊断误检val.py会在runs/val/exp目录生成confusion_matrix.png。草莓比赛里最常见的混淆项是背景被误认为mature原因通常是未成熟青果和叶片颜色相近标注时归类不一致。处理方式不是调阈值而是回看标注把验证集里混淆的样本单独挑出来并统计各类别框数量分布。# analyz_labels.py import os from collections import Counter counts Counter() for txt in os.listdir(datasets/strawberry/labels/train): with open(os.path.join(datasets/strawberry/labels/train, txt)) as f: for line in f: cls_id int(line.split()[0]) counts[cls_id] 1 print(counts)类别严重不平衡时比如mature只占20%训练会偏向多数类。解决手段是在训练配置里设置类别权重或者做简单的过采样把少数类图片复制一份到训练目录让比例接近1:1。过采样不改变标注格式只是同一份数据多放几份在几百张数据量下代价很低。5. 针对比赛小数据集的增强、TTA与微调技巧几百张草莓图做比赛核心不是堆模型大小而是怎么让有限的样本产生足够的分布覆盖。最后这部分是几个常见且见效快的技巧。5.1 在hyp配置里针对小目标改数据增强参数YOLOv5的超参数文件位于data/hyps/hyp.scratch-low.yaml。草莓果实偏小推荐重点调整翻转和HSV变换# data/hyps/hyp.scratch-low.yaml 针对草莓的推荐值 hsv_h: 0.015 hsv_s: 0.7 hsv_v: 0.4 degrees: 0.0 flipud: 0.5 fliplr: 0.5 mosaic: 1.0 mixup: 0.15 copy_paste: 0.5草莓的颜色是成熟度标注的关键特征hsv_h调太大会把红色改成蓝色破坏类别可区分性保持0.015左右hsv_s和hsv_v提升到0.7和0.4可以模拟田间不同光照。degrees保持0草莓没有明显方向性旋转只会让背景噪声增多。flipud和fliplr各开0.5在俯拍草莓垄的图像上适用。mixup和copy_paste在小数据集上能降低过拟合但mixup不要超过0.2否则训练出的框中心位置和大小分布会与真实数据偏差过大。验证修改是否生效的方法是重新训练时看前几个epoch的输出图像。YOLOv5会把增强后的示例图保存到runs/train/exp*/train_batch*.jpg检查增强后的草莓是否仍保持真实的颜色比例即可。5.2 评测时开启TTA提升分数比赛评分以测试集为主时TTA是低成本提分手段。detect.py内置了augment参数python detect.py \ --weights runs/train/strawberry_exp/best.pt \ --source test_images \ --img 640 \ --augment \ --conf-thres 0.25加--augment后每张图会做原图、横向翻转、纵向翻转、双翻转后分别推理结果合并时置信度取平均。TTA在草莓这种小目标尺寸上通常能带来小幅mAP提升代价是推理时间翻倍如果比赛有时间限制只在最终评测阶段开启即可。5.3 用低置信度检测结果定位漏检目标如果TTA之后mAP仍不稳定把conf-thres降到0.15保存txt与标注文件做差值能快速找到哪些目标在低置信度下才被检出python detect.py \ --weights runs/train/strawberry_exp/best.pt \ --source val \ --conf-thres 0.15 \ --save-txt再用脚本比对低阈值检测txt和标注txt找出稳定丢失的果实框位。这些丢失目标通常是小果或遮挡果此时单独增加该区域的copy_paste增强比盲目调置信度更有效。提交前记住一个原则用固定seed重新跑最终的训练保证结果可复现比赛答辩时也能对每个参数的选择依据给出解释。本文还有配套的精品资源点击获取
返回列表