简介这份资源面向从事目标检测的开发者与农业视觉应用研究者提供白萝卜检测的YOLO系列算法训练数据集可直接用于模型训练与验证测试。压缩包共2000个文件约32.8MB包含1000张图像对应的标注文件其中999个txt为YOLO格式标签1000个xml为VOC格式标签另附1个data.yaml数据集配置文件已按训练与验证需求划分完毕兼容yolov5、yolov8、yolov9、yolov7、yolov10及yolo11等主流版本。YOLO标签采用类别索引与归一化中心点、宽高比例值便于直接读取训练VOC格式则方便在Pascal VOC流程或转换工具中使用。目前已有59人学习下载适合希望快速搭建白萝卜检测基线、验证数据增强与模型对比效果的读者省去自行采集与标注的成本。1. 白萝卜检测数据集1000张带标签图像到底能训出什么去年帮一个做农机视觉的朋友调模型他拿了一包“白萝卜检测数据集”过来说是在田间地头拍的1000张图像带标签想直接塞进 YOLO 里跑。结果第一次训练 mAP 只有 0.42漏检的全是半埋在土里、只露一截青头的萝卜。这件事让我意识到白萝卜检测这个任务难点根本不在“萝卜长什么样”而在“萝卜和背景的边界有多模糊”。这个数据集的价值恰恰在于它把这种模糊场景固定下来了——1000张图像、带 YOLO 格式标签覆盖了露头、半埋、叶片遮挡、土壤反光几种典型工况。它适合两类人一类是想跑通 YOLO 训练全流程的新手拿它当第一个自定义数据集另一类是做农业视觉落地的工程师需要一个小规模、标注干净的基准来验证自己的数据增强和损失函数改动。如果你手里正好有类似数据或者想找一个不那么大、但足够真实的检测任务练手这个方向值得往下看。2. 拆开这个 zip1000张图像和标签的目录结构怎么摆拿到一个带标签的图像数据集第一件事不是急着写训练脚本而是把目录结构理清楚。YOLO 系列对数据组织方式有固定约定摆错了路径训练脚本会在第一轮就报“找不到标签”或者“类别数不匹配”。白萝卜检测数据集通常包含两个核心部分图像文件和对应的 txt 标签文件标签里每行是class_id x_center y_center width height坐标全部归一化到 0 到 1 之间。2.1 图像与标签的配对规则假设解压后得到的是images/和labels/两个平铺目录图像名是001.jpg、002.jpg标签名必须是001.txt、002.txt。YOLO 在训练时按文件名主干去匹配不关心扩展名是 jpg 还是 png但要求主干部一致。常见翻车点是有人把标签文件命名成001.jpg.txt或者图像是IMG_001.JPG而标签是img_001.txt大小写和前缀不一致训练时直接跳过这些样本最后模型只学到一半数据。我一般会先跑一段校验脚本确认配对率和标签合法性import os from pathlib import Path img_dir Path(dataset/images) lbl_dir Path(dataset/labels) img_stems {p.stem for p in img_dir.glob(*) if p.suffix.lower() in (.jpg, .png, .jpeg)} lbl_stems {p.stem for p in lbl_dir.glob(*.txt)} missing_lbl img_stems - lbl_stems missing_img lbl_stems - img_stems print(f图像总数: {len(img_stems)}, 标签总数: {len(lbl_stems)}) print(f缺标签的图像: {len(missing_lbl)}, 缺图像的标签: {len(missing_img)}) # 检查标签内容是否越界或格式错误 bad_lines [] for txt in lbl_dir.glob(*.txt): for i, line in enumerate(txt.read_text().strip().splitlines()): parts line.split() if len(parts) ! 5: bad_lines.append((txt.name, i, 字段数不对)) continue cls, x, y, w, h parts vals list(map(float, [x, y, w, h])) if any(v 0 or v 1 for v in vals): bad_lines.append((txt.name, i, 坐标越界)) print(f异常标签行数: {len(bad_lines)})这段脚本做三件事统计图像和标签的主干名集合找出单边缺失的文件逐行读取标签检查字段数是否为 5检查归一化坐标是否落在 0 到 1 区间。参数上img_dir和lbl_dir按你解压后的实际路径改如果图像分散在子目录里glob(*)要换成rglob(*)。跑完如果missing_lbl不为零先别往下走把配对问题解决掉否则后面训练日志里 loss 下降但 mAP 不动排查起来更费时间。2.2 划分训练集、验证集和测试集1000张图像不算多划分比例我一般用 8:1:1也就是 800 张训练、100 张验证、100 张测试。注意验证集和测试集要覆盖不同光照和遮挡程度不能随机切完了事。如果数据集里本身有按地块或日期分组的子目录优先按组划分避免同一株萝卜的多个角度同时出现在训练集和验证集里造成指标虚高。常见做法是写一个划分脚本把文件复制到train/、val/、test/三个子目录每个子目录下再分images/和labels/mkdir -p dataset/split/{train,val,test}/{images,labels} # 假设已经生成了三个列表文件 train.txt val.txt test.txt每行一个主干名 while read stem; do cp dataset/images/$stem.jpg dataset/split/train/images/ cp dataset/labels/$stem.txt dataset/split/train/labels/ done train.txt # val 和 test 同理替换目录名这里用cp而不是mv是为了保留原始平铺目录作为备份后面如果发现划分不合理还能重新切。划分完成后在数据集根目录建一个data.yaml内容如下path: ./dataset/split train: train/images val: val/images test: test/images nc: 1 names: [white_radish]nc是类别数白萝卜检测通常只有一类如果数据集里还标了杂草或石块按实际类别数改。names的顺序必须和标签里的class_id对应标错顺序会让模型把萝卜学成背景。3. 用 YOLOv8 在本地跑通白萝卜检测的最小训练命令环境配置是新手最容易卡住的地方。YOLOv8 依赖 PyTorch而 PyTorch 又和 CUDA 版本绑定。我一般建议用 conda 建一个独立环境Python 版本选 3.9 或 3.10这两个版本和主流 PyTorch 轮子兼容性最好。如果你机器上没有 GPU用 CPU 也能跑通只是 1000 张图像训练 100 轮大概要几个小时调参阶段会很难受。3.1 环境安装与版本对齐先确认显卡驱动支持的 CUDA 版本再装对应的 PyTorch。常见做法是去 PyTorch 官网查安装命令但更稳的方式是用 conda 装让 conda 自己解决依赖conda create -n radish python3.10 -y conda activate radish # 以 CUDA 11.8 为例具体版本按 nvidia-smi 右上角显示改 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics装完跑一句python -c import torch; print(torch.cuda.is_available())返回True才算 GPU 可用。如果返回False先别急着装 ultralytics把 PyTorch 和 CUDA 对齐了再说。血泪经验是ultralytics 本身对版本不敏感但 PyTorch 版本和 CUDA 驱动不匹配时训练会在第一个 epoch 报CUDA error: no kernel image is available这个报错信息很误导让人以为是模型问题其实是环境问题。3.2 训练命令与关键参数环境就绪后训练命令本身很短yolo detect train \ datadataset/split/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/radish \ nameexp1逐项说明modelyolov8n.pt用 nano 版本参数量小1000 张图像足够收敛如果漏检严重再换yolov8s.pt。imgsz640是输入分辨率白萝卜在图像里占比不大时可以提到 800 或 960但显存占用会明显上升。batch16在 8GB 显存上比较稳显存不够就降到 8。lr00.01是初始学习率YOLOv8 默认用 SGD 时这个值合适如果换成 AdamW要降到 0.001 量级。patience20表示验证集指标 20 轮不提升就早停防止过拟合。训练过程中重点看三个输出box_loss是否稳定下降、mAP50是否在 50 轮后还在涨、cls_loss是否异常低。如果cls_loss很快降到接近零但mAP50很低大概率是标签类别全标成了同一类或者data.yaml里nc和实际类别数不一致。3.3 推理验证与置信度门限调整训练完成后用验证集跑一次推理看实际检测效果yolo detect predict \ modelruns/radish/exp1/weights/best.pt \ sourcedataset/split/val/images \ conf0.25 \ saveTrueconf0.25是置信度门限低于这个值的检测框会被过滤掉。白萝卜检测里半埋的萝卜模型往往给出 0.3 到 0.5 的置信度如果门限设到 0.5这些萝卜全被滤掉看起来就像漏检。我一般会先用 0.1 跑一遍看模型在低门限下能召回多少再根据误检情况往上调。如果误检主要是土壤反光被当成萝卜门限调到 0.35 到 0.4 之间通常能压住如果误检是相邻萝卜被重复检测那要调 NMS 的 IoU 阈值而不是动置信度。4. 白萝卜检测的避坑与排查从 mAP 不涨到标签错位这个任务我前后调过三四次踩的坑集中在数据侧和评估侧模型结构本身反而没怎么动。下面几条是按“现象 → 原因 → 解决”整理的每条都对应真实训练日志里出现过的信号。4.1 训练 loss 正常下降但 mAP 始终低于 0.5现象是box_loss从 1.2 降到 0.3cls_loss也正常但mAP50卡在 0.4 左右不动。原因通常是验证集和训练集的分布差异太大比如训练集全是晴天顺光验证集里混了阴天逆光的图像。白萝卜在逆光下边缘发暗和土壤的对比度急剧下降模型在训练集上学到的纹理特征迁移不过去。解决办法是重新划分数据集按光照条件分层抽样保证训练集和验证集里都有顺光、逆光、侧光样本。如果数据量实在不够在训练时加hsv_v0.4和hsv_s0.7做色彩增强让模型对亮度变化更鲁棒。4.2 模型把土壤反光当成白萝卜现象是推理结果里出现大量小框集中在图像的高光区域置信度在 0.3 到 0.5 之间。原因是白萝卜表面光滑在阳光下有镜面反射和湿润土壤的反光在局部纹理上很像。解决分两步先在标注阶段把明显是反光而非萝卜的区域标成背景让模型学到负样本再在推理时把conf从 0.25 提到 0.4同时开agnostic_nmsTrue避免同一区域被多个类别重复框选。如果反光区域特别大可以在数据增强里加mosaic0.5和mixup0.1让模型见到更多反光和萝卜共存的场景。4.3 标签坐标归一化算错导致框全偏现象是训练时box_loss居高不下推理出来的框全部集中在图像左上角或中心。原因是标注工具导出时坐标没有除以图像宽高或者除错了维度。YOLO 格式要求x_center和width除以图像宽度y_center和height除以图像高度。如果标注时把宽高弄反框会横向或纵向拉伸。排查方法是随机抽几张图用脚本把标签框画回原图上看import cv2 img cv2.imread(dataset/images/001.jpg) h, w img.shape[:2] for line in open(dataset/labels/001.txt): cls, x, y, bw, bh map(float, line.split()) x1 int((x - bw / 2) * w) y1 int((y - bh / 2) * h) x2 int((x bw / 2) * w) y2 int((y bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.imwrite(check_001.jpg, img)画出来如果框和萝卜对不上就是归一化或宽高顺序的问题回到标注文件逐行核对。4.4 训练到一半显存溢出现象是前几十轮正常突然报CUDA out of memory。原因通常是mosaic增强在某个 batch 里拼出了超大图像或者验证阶段同时缓存了太多图像。解决是把batch降到 8或者在训练命令里加cacheFalse关掉图像缓存。如果显存实在紧张把imgsz从 640 降到 512mAP 会掉一两个点但训练能稳定跑完。另一个容易忽略的点是workers设得太大数据加载进程占用了显存映射设成 4 或 8 就够不要拉到 16。4.5 验证集 mAP 高但实际部署漏检严重现象是训练日志里mAP50到 0.85但拿手机拍的田间照片去测漏检一半以上。原因是验证集和实际场景的拍摄设备、焦距、角度不一致。白萝卜检测里验证集如果是用同一台相机、同一高度拍的模型学到的尺度先验在实际部署时完全失效。解决办法是在验证集里混入不同设备、不同距离拍的图像哪怕只有几十张也能把尺度鲁棒性拉回来。如果实在没有在推理时用imgsz960放大输入让小目标占更多像素同时把conf降到 0.15 先保召回。5. 把 1000 张用到极致小数据集上的增强策略与验证习惯1000 张图像在检测任务里算小数据如果只是按默认参数跑一遍模型很容易记住训练集的背景而不是萝卜本身。我后来养成的习惯是每次改数据增强参数前先固定随机种子跑一次基线把mAP50和各类的召回率记下来再动参数。YOLOv8 默认开启mosaic和scale对白萝卜这种形状规整的目标mosaic能显著提升小目标召回但也会让半埋萝卜的上下文被切断。我的做法是把mosaic从默认的 1.0 降到 0.5close_mosaic设成 20也就是最后 20 轮关掉 mosaic让模型在接近真实分布的图像上微调。另一个技巧是善用val阶段的save_jsonTrue把验证集的预测结果导出成 COCO 格式的 json然后用 pycocotools 按目标面积分段看 AP。白萝卜检测里面积小于 32x32 像素的萝卜往往是漏检重灾区如果small段的 AP 明显低于medium和large说明输入分辨率不够或者锚框尺度不匹配。这时候把imgsz提到 800同时在data.yaml里加anchors参数重新聚类比盲目加数据更有效。最后说一个验证习惯每次训练完不要只看mAP50一定把best.pt和last.pt分别跑一遍验证集对比两者的混淆矩阵。我遇到过best.pt的 mAP 比last.pt高 3 个点但last.pt在半埋萝卜上的召回反而更好原因是best.pt是在某一轮过拟合了露头萝卜。如果部署场景里半埋萝卜占比高选last.pt更稳。这个习惯帮我省过至少两次返工。希望帮到你。本文还有配套的精品资源点击获取
