ARTICLE DETAIL

资讯详情

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

yolo11西红柿检测实战:数据集划分、训练配置与避坑指南

yolo11西红柿检测实战:数据集划分、训练配置与避坑指南 简介面向深度学习初学者与目标检测开发者的西红柿检测项目基于YOLO11算法和Python/PyTorch环境实现覆盖数据标注、格式转换、模型训练与可视化识别全流程。压缩包共一千三百二十二个文件大小约一百四十四兆包含六百五十六张西红柿图像、三百二十六个YOLO格式文本标注、三百二十一个XML标注、三个Python脚本、三个权重文件、三个YAML配置以及训练产生的结果表格与标签缓存等记录。目录结构清晰便于按模块学习或二次开发。目前已有102人学习下载适合入门目标检测完整流程。包内第一个脚本可将图片与XML标注转为YOLO格式并生成训练集、验证集和配置文件第二个脚本用于启动模型训练第三个脚本提供可视化界面加载图片即可完成识别既支持重新训练也可直接调用现成权重快速体验。环境依赖在文本文件中说明按提示自行配置PyTorch即可运行。1. 用 yolo11 训练自己的西红柿检测模型这份资源包里到底有什么做目标检测的人都有过这种经历网上找的公开数据集要么太大、要么跟自己的场景对不上最后只能自己拍照片、自己标注。但当你真的拿一批西红柿图片开始跑 yolo11 时才会发现坑远比想象的多——标签格式、数据集划分、训练参数、可视化界面每一步都能卡住你半天。这份「yolo11 西红柿目标检测」资源包正好把这条路走完了它包含已标注的西红柿数据集、划分脚本、训练脚本和 PyQt 可视化界面从数据集转成 YOLO 格式到最终鼠标点几下完成识别整条链路是通的。它适合两类人一类是刚接触 yolo 系列、想拿一个小数据集把训练流程完整跑一遍的新手另一类是自己手里有标注数据、想快速迁移到 yolo11 做验证的工程师。我拆完这份资源后最直观的感受是数据集不大但流程完整参数细节值得逐行看。2. 从原始图片到 YOLO 格式划分脚本与 data.yaml 的生成逻辑2.1 先看资源包里真实存在的东西解压这个 zip 之后你会看到一批 JPG 图片和几个关键文件。很多人一上来就急着跑训练结果被文件搞懵——这里先把资源包里的东西对照着讲清楚。events.out.tfevents.1733742028.zzg.7648.0TensorBoard 的事件文件。说明这个项目在训练时启用过 TensorBoard 回调训练过程的 loss 曲线、mAP 曲线都记录在里面。labels.cache跑过一次验证或训练后YOLO 会把每张图片的标签路径和哈希缓存起来下次加载时不用重新解析所有标注文件。如果你的图片或标注文件有变动这个缓存会导致「图片和标签对不上」的诡异问题后面避坑章会细说。results.csv训练过程中每个 epoch 的指标记录包括 train/loss、val/loss、mAP50、mAP50-95、precision、recall 等。这个东西比 TensorBoard 更直观Excel 直接打开就能看曲线趋势。若干*.jpg就是西红柿的原始图片文件名有重复的是因为资源包作者把训练集中的样例图一起放进来了不影响训练。这个资源的实际训练集数量不大属于「小数据集跑通流程」的典型规模。你下载后建议先做一件事把所有图片统一重命名成纯数字或纯英文不要带中文、不要带特殊字符。Windows 路径 中文 YOLO 的组合经常出编码问题这是血泪经验。2.2 01 划分数据集.py 做了什么作者给的说明是运行python 01划分数据集.py会把数据集转成 YOLO 格式的 txt同时生成 train.txt、val.txt 和 data.yaml。这个脚本是整条流程的起点也是最容易被跳过、但实际影响最大的一个环节。很多从 VOC 或自己标注工具导出的数据原始标签是 XML 或 JSON必须转成 YOLO 的 txt 格式才能喂给 yolo11。YOLO 格式的标注 txt 每行代表一个目标格式是class_id x_center y_center width height注意这里的x_center y_center width height全部是归一化到 0~1 之间的相对坐标用框的绝对像素值除以图片宽度和高度。这是最容易翻车的地方——如果你直接填了像素坐标loss 会直接爆掉训练出来的模型什么都检测不出来。划分脚本的核心逻辑我按常见实现思路给你还原一下import os import random from pathlib import Path from tqdm import tqdm def convert_to_yolo(txt_path, img_width, img_height): # 假设你的标注是从 LabelImg 导出的 XML 格式 # 这里只展示坐标转换的核心思想 boxes [] for obj in objects: x_center (xmin xmax) / 2 / img_width y_center (ymin ymax) / 2 / img_height box_width (xmax - xmin) / img_width box_height (ymax - ymin) / img_height boxes.append(f0 {x_center:.6f} {y_center:.6f} {box_width:.6f} {box_height:.6f}) return boxes def split_dataset(image_dir, train_ratio0.8, seed42): random.seed(seed) image_paths list(Path(image_dir).glob(*.jpg)) # 支持 jpg/png/jpeg random.shuffle(image_paths) train_count int(len(image_paths) * train_ratio) train_paths image_paths[:train_count] val_paths image_paths[train_count:] for split, paths in [(train, train_paths), (val, val_paths)]: txt_file f{split}.txt with open(txt_file, w) as f: for img_path in paths: f.write(str(img_path.resolve()) \n)逻辑说明脚本先是读取图片宽高把框坐标做归一化转换然后按比例切分训练集和验证集切分时固定了随机种子seed42保证每次划分结果一致——这一点非常关键否则你每次跑训练用的数据分布都不一样对比实验就没意义了。参数说明train_ratio0.8是个合理的默认值对西红柿这种类别单一、目标分布相对均匀的小数据集来说够用。如果你的数据量很少比如只有一两百张建议把比例调到 0.9让训练集更充分如果后续要加数据增强0.8 就合适。seed一定要写死不要省。2.3 data.yaml训练配置的「黑匣子」打开给你看划分脚本还会自动生成 data.yaml内容是path: ./ # 数据集根目录相对路径 train: train.txt # 训练集图片路径列表 val: val.txt # 验证集图片路径列表 nc: 1 # 类别数西红柿只有一类 names: [tomato] # 类别名称列表这里有三个容易踩坑的点。第一个path字段用相对路径时YOLO 会把它当作相对于当前工作目录的路径。你如果在别的目录下运行训练命令就会报dataset not found。我一般习惯path直接写绝对路径一劳永逸。第二个train.txt里存放的是图片的完整路径如果图片移动过位置txt 里的路径就失效了。第三个nc是 1 没问题但如果你后面想加类别比如还检测茄子和辣椒这里就要改成 3同时names要对应加上——很多人忘了改这里训练出来的模型类别索引全乱了推理时框看到的类别名是错的。3. 环境配置与 requirement.txtPyTorch 版本、CUDA 与依赖项对齐3.1 这份资源跑起来需要什么环境作者在摘要里说得很明确代码基于 Python PyTorch 环境requirement.txt在压缩包里环境需要自己配置。这意味着你下载之后还要花 20~30 分钟装环境但这是所有深度学习项目的常态不要指望解压即用。深度学习环境的本质是CUDA → PyTorch → torchvision → ultralyticsYOLO 的官方库。这个依赖链条里任何一个版本不对都会以各种奇怪的方式报错。最常见的崩溃组合是 PyTorch 编译时用的 CUDA 版本和显卡驱动不匹配出现CUDA error: no kernel image is available这种提示。一个常规的 requirement.txt 内容大概是torch2.0.0 torchvision0.15.0 ultralytics8.0.0 pyside6 numpy pillow opencv-python matplotlib tensorboard pandas tqdm这里重点说两个ultralytics是必须的因为 yolo11 的模型定义、训练逻辑全在这个库里版本太低会没有yolo11这个模型入口pyside6是 03pyqt.py 的界面依赖如果只想跑训练不跑界面这个可以不装节省不少时间。3.2 一个规避版本纠结的安装路径如何避免在 PyTorch 安装上反复折腾这里给一条我的经验路径。先确认显卡驱动支持的 CUDA 版本然后装对应版本的 PyTorch。如果你机器上没有 NVIDIA 显卡那只能装 CPU 版训练速度会慢到让你怀疑人生——我拿一个 1000 张的数据集在 CPU 上跑过 yolo11n一个 epoch 差不多要 15 分钟后来果断换 GPU。下面是安装命令的示例# 查看显卡驱动支持的 CUDA 最高版本 nvidia-smi # 以 CUDA 11.8 为例安装 PyTorch按官网命令替换 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 安装 ultralytics 和其余依赖 pip install ultralytics pyside6 numpy opencv-python # 验证安装能正常输出版本即成功 python -c import torch; print(torch.__version__) python -c import ultralytics; print(ultralytics.__version__)参数说明nvidia-smi输出里的 CUDA Version 是驱动支持的最高版本不代表你要装这么高的 PyTorch尽量选低一点的兼容版本更稳比如驱动支持 12.4 就装 cu118 或 cu121 的 PyTorch。--index-url指定了 PyTorch 的官方源比默认 PyPI 源版本更全能直接选到带 CUDA 的版本。装好之后通过两个 print 语句验证能输出版本号说明环境基本通了。3.3 最常见的一个环境坑requirements 装不进去pip install -r requirement.txt装了一半报错是每个项目群都会有人问的问题。报错分两种一种是某个库编译失败比如opencv-python在老版本 Python 上会出这类问题解决方法是先升级 pip 再装另一种是相互冲突比如 2.0.0 的 torch 和 0.15.0 的 torchvision 不配套这个看 torch 官网的版本匹配表手动指定。我自己的习惯是手边常备一个已装好 PyTorch 的环境镜像不管是 Conda 还是 venv遇到新项目只复制环境不改系统环境。因为这类项目每个的依赖版本都略有差异你在 A 项目里pip install torch升级了版本B 项目可能就出现 CUDA 相关玄学报错。环境隔离是深度学习项目的第一条纪律没有之一。4. 运行 02train.py 开始训练epochs、batch、imgsz 与结果解读4.1 从命令行到真正的训练执行环境就绪、数据集划分完毕后02train.py做的事情就是加载 yolo11 预训练权重在自己的西红柿数据集上做微调fine-tune。这是整个资源里最耗时、最消耗耐心的一个步骤但也是最核心的环节——模型能不能检测出西红柿全看这里。运行训练很简单python 02train.py脚本内部的核心逻辑按常见写法展开是这样的from ultralytics import YOLO # 加载 yolo11n 预训练权重首次运行会自动下载 model YOLO(yolo11n.pt) # 开始训练 results model.train( datadata.yaml, # 上一步生成的配置 epochs100, # 总训练轮数 batch16, # 每批图片数量 imgsz640, # 输入图片分辨率 device0, # GPU 索引CPU 则填 cpu workers4, # 数据加载线程数 patience20, # 早停等待轮数 cacheTrue, # 缓存图片到内存 )逻辑说明model YOLO(yolo11n.pt)这行会加载 COCO 预训练权重这是迁移学习的关键——你的西红柿数据量小从头训练几乎不可能收敛但有了 COCO 上学到的通用特征纹理、边缘、颜色只要少量数据就能快速适配到西红柿这个类上。model.train()里传递的是一系列训练超参这些参数直接决定了训练速度、显存占用和最终精度。参数说明epochs100对小数据集来说够用一般训练到 50~70 轮时 loss 就趋于平稳了多出来的轮次主要被早停机制拦截掉。batch16在 8GB 显存以下的显卡上跑 yolo11n 是安全的如果你的显卡是 4GB 显存把 batch 降到 8否则会直接CUDA out of memory。imgsz640是 YOLO 系列的默认输入分辨率西红柿目标在画面里往往占比较大640 够用如果你的图片里西红柿很小远距离拍摄可以改成 960 或 1280但训练时间会翻倍。patience20表示连续 20 轮验证集指标不提升就自动停止这是省时间的利器。cacheTrue表示把图片一次性加载进内存减少磁盘 I/O 等待如果你的显存不紧张就开着训练速度快一截。4.2 results.csv 和 events.out.tfevents 怎么读训练过程中ultralytics 会在runs/detect/train/目录下持续写入结果。用 Excel 打开results.csv你会发现每一列对应一个关键指标train/box_loss是边框回归 losstrain/cls_loss是分类 lossmetrics/precision是精确率metrics/recall是召回率metrics/mAP50(B)是 IoU 阈值 0.5 时的平均精度metrics/mAP50-95(B)是更严格的综合评价指标也是论文里比较常用的一个。怎么看这个表格小数据集上不要追求 mAP50-95 特别高那是数据量极为充足的场景下才可能做到的事。你要看的是两条趋势第一train 和 val 的 loss 是否都在同步下降——如果 train loss 降了但 val loss 不动甚至反升说明模型过拟合了数据量太小 训练轮数太多就会这样第二mAP50 是否稳定在某个值附近——西红柿这种形态规整的目标mAP50 达到 0.9 以上基本就能用在生产场景了。TensorBoard 的事件文件events.out.tfevents.*对应的是训练过程中的可视化日志在项目根目录用命令启动查看tensorboard --logdir ./然后浏览器打开终端里输出的http://localhost:6006就能看到曲线。对新手来说把每个 epoch 的指标存下来的results.csv其实比 TensorBoard 实用因为不用启动服务Excel 直接就能筛选排序。我和同事的日常习惯是训练完先看 results.csv 里最后一个 epoch 的 mAP50 和 precision再拉出损失曲线看有没有尖刺两头一天三遍。4.3 这篇文章里一定会有的一个坑训练集和验证集数据分布不一致前面01划分数据集.py里设置了seed42目的就是保证切分的随机性可控。但如果你的图片是连拍的——同一株西红柿从不同角度连续拍了几十张——随机切分后训练集和验证集里可能会出现「同一颗果实的相似角度照片」验证集指标虚高相当于作弊。这一点在很多小数据集里普遍存在并不是这个资源包的问题但要提醒你留意数据采集时的多样性不同光照、不同角度、不同成熟度图片差异越大验证集的参考价值越高。5. 避坑与排查西红柿小目标检测的五条踩坑记录5.1 训练 loss 为 nan 或直接爆炸现象训练一开始loss 直接变成nan或者前几个 epoch loss 从几万开始往下掉最后模型什么都检测不出来。原因最普遍的三个来源——一是标签 txt 里的坐标没有做归一化绝对值直接进网络导致梯度爆炸二是图片路径是中文或包含空格数据集加载时图片读不到标签却还在数据对不齐三是学习率设置过高在 batch 很小的情况下直接冲出了合理的收敛区间。解决先用labels.cache对应的原始标签文件抽样做一次datasets验证。用 Python 写一个快速脚本读一张图片和对应 txt把标注框画出来比对位置是否合理。归一化坐标时框的 x_center 除以图片宽度、y_center 除以图片高度、宽高也都对应除四点中漏一项模型就会在学习率稍高时立刻爆炸。学习率方面模型默认是 0.01如果小数据集上反复 NaN改成 0.001 再试。5.2 labels.cache 导致的「图片和标签对不上」现象你明明把一张新图片加到数据集目录里也标注好了但训练时这张图片像是被忽略了一样验证结果也没有它的任何指标。原因ultralytics 第一次运行时会生成labels.cache文件里面记录了图片路径和标签文件的哈希对应关系。你在那之后往数据集目录加了新文件下次训练时 ultralytics 还会用旧缓存去匹配导致新增数据没被纳入。解决出现这种「明明加了数据但训练没变化」的情况时先删除根目录下的labels.cache文件再重新训练。删除后会自动重新扫描并重建缓存。从那以后我每次改数据集后第一件事就是删 cache已经形成一个不会忘的习惯。5.3 密集遮挡场景下漏检严重现象单个西红柿在图片里很清晰检测框也很准确但一串西红柿堆叠在一起时模型只能检出最外层的几个被遮挡的漏掉了而且置信度普遍走低。原因这是目标检测在密集小目标场景下的通病本质上是训练数据里缺少密集遮挡的样本。yolo11 的 NMS非极大值抑制会在两个重叠度很高的候选框之间只保留置信度高的一个如果模型没见过这种密集场景它输出的候选框本身就不可靠。解决第一种方法是数据增强——用 Mosaic 增强把多张图片拼接成一张模拟密集分布的场景yolo11 默认开启 Mosaic但如果有数据清洗环节把这一步关了要检查是否恢复。第二种是调 NMS 参数在推理时把iou阈值从默认的 0.45 降到 0.3允许更高度重叠的框保留下来。第三种是从数据端解决——单独把你认为最难检测的密集图片放到训练集里复制几份相当于过采样让模型多学几轮这些困难样本。5.4 CPU 训练慢到无法忍受现象用 CPU 跑训练一个 epoch 用了十分钟以上整整一天下来几个 epoch 都没跑完最终放弃。原因目标检测的矩阵运算量大CPU 上做卷积运算本来就是逆水行舟加上workers数据加载线程数设置太小数据准备时间甚至超过了计算时间。解决不用换机器的情况下有两招可以用。第一把batch调到 4、imgsz降到 320牺牲精度换训练速度先跑通验证流程——注意只是验证流程不是最终模型。第二买或租一块云 GPU现在很多云平台的入门级 GPU 按小时计费也不贵把数据和代码传上去跑比自己机器快了不止二十倍。记住一个原则CPU 只配用来做最后的推理演示不配用来做训练迭代。5.5 PyQt 界面加载图片后检测卡死未响应现象运行03pyqt.py后点击加载图片按钮选了一张大图界面马上变白、卡住不动标题栏显示「未响应」过一会才恢复或者直接崩溃。原因这是典型的界面线程被耗时操作阻塞了。目标检测在 GPU 上推理一次也需要几十毫秒到几百毫秒加上加载高清大图的解码耗时UI 事件循环被阻塞系统就会判定程序未响应。如果图片分辨率特别高比如相机拍的原图 4000×3000检测前的图像预处理更是雪上加霜。解决把图像加载和推理放到一个独立线程里执行UI 主线程只负责接收操作事件。具体来说就是给按钮绑定一个槽函数槽函数内部用QThread或threading.Thread包装推理逻辑推理完成后通过信号机制把结果传回界面线程更新显示。另外在加载图片后先做一次resize把最长边缩到 1280 以内再传入检测网络既保证检测效果又省显存。界面端还有一个优化点加载图片后用QPixmap缩放显示不要把原图直接贴到 label 上省内存也减少刷新卡顿。6. 从单张图片到实时视频流自定义检测脚本与置信度阈值校准以 03pyqt.py 的加载图片检测为起点把它的内部逻辑抽象出来——实际上 ultralytics 的predict方法已经把大部分细节封装好了你要关心的两个核心变量是conf置信度阈值和iouNMS 阈值。针对西红柿这种目标我习惯把 conf 设在 0.25iou 设在 0.45这是 COCO 预训练模型的标准配置但如果你实际应用场景里对漏检零容忍比如分拣产线上不想漏掉任何一个坏果把 conf 降下来到 0.1代价就是一些误检框的出现需要人工在界面里二次确认。把单图检测扩展成摄像头视频流核心代码只有几行from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) # 摄像头实时检测0 表示第一个摄像头 results model.predict(source0, showTrue, conf0.25, imgsz640) # 视频文件检测输出到本地 results model.predict( sourcedemo.mp4, saveTrue, conf0.25, imgsz640, projectoutput, # 输出目录 namevideo_result, # 输出子目录 )逻辑说明model.predict一次调用完成从图片解码、预处理、推理、NMS、后处理到可视化的全部流程。source0是摄像头输入sourcedemo.mp4是视频文件输入showTrue会弹出实时窗口saveTrue会把检测结果保存为视频文件。这里用到的best.pt不是last.pt——训练结束后 ultralytics 会自动保存两个权重文件best.pt是验证集上指标最好的那一轮的权重last.pt是最后一轮的永远用best.pt做推理这是所有做过目标检测实战的人都会反复强调的一点因为训练后期模型可能出现过拟合最后一轮的权重已经不是最优解。验证模型是否真正能用的一个有效技巧是取训练时的那几张样例图片先跑一次推理然后逐一人工检查检测框相比真实标注的偏移量。如果框的中心点偏了超过 5%说明模型对边界的拟合还不够充分如果框的大小普遍偏大或偏小可能是训练时 imgsz 和实际推理时不一致导致的——这个坑我踩得很深训练时用的 640到了推理时为了追求速度把输入调成了 320结果大面积漏检。另外还有一个被人忽略但很实用的校准方式把测试集图片批量跑一遍推理统计每张图的检测数量和平均置信度和 labels 里标注的真实目标数量做个对比。如果检测数量系统性少于标注数量说明阈值过高或模型欠拟合如果检测数量远超标注数量说明有大量误报。根据这个差值来精确调整 conf 值比凭感觉调要科学得多。我在实际跑这类资源时还有一个习惯拿到资源包后不会一上来就把 01、02、03 三个脚本依次跑完而是先用最少的图片比如 10 张跑一遍完整的训练-推理闭环确认代码、数据、环境三者全部正确后再放开全部数据和完整 epoch 数。这个习惯帮我省下来大量的时间——很多时候脚本有序执行到最后才发现环境里的某个依赖版本不对回头改完再重新从第一步跑代价非常大。希望帮到你。本文还有配套的精品资源点击获取
返回列表