
简介本资源为面向YOLO系列目标检测算法学习者的白萝卜检测数据集适用于yolov5、yolov8、yolov9、yolov7、yolov10及yolo11等主流框架可直接用于模型训练与验证测试帮助读者快速搭建农作物目标检测实验环境。压缩包共2000个文件包含1000个xml标注文件、999个txt标签文件及1个yaml配置文件整体约32.8MB其中yaml文件为数据集配置入口xml与txt分别对应VOC与YOLO两种标注格式便于不同训练流程直接调用。数据集已完成训练集与验证集划分标签覆盖目标类别索引及归一化后的中心点坐标、宽高比例无需额外预处理即可投入训练。目前已有63人学习下载适合需要真实场景标注数据、希望快速验证检测模型效果的学生与开发者参考使用。1. 白萝卜检测数据集到底长什么样1000 张带标签图像能撑起什么拿到「YOLO算法-白萝卜检测数据集-1000张图像带标签.zip」这个标题多数人第一反应是1000 张够不够训一个能用的检测模型我去年秋天帮一个做农机视觉分选的朋友处理过类似规模的根茎类作物数据集结论是——够但前提是你得先搞清楚这 1000 张的分布、标注格式和场景一致性。白萝卜检测在农业视觉里属于「类内差异大、类间差异小」的典型任务同一根萝卜带泥和不带泥、横放和竖放、单根和堆叠在图像里长得完全不一样而萝卜和胡萝卜、甚至和白色塑料筐的局部在低分辨率下又容易混淆。这个数据集的价值不在于「大」而在于它把 YOLO 训练里最费时间的标注环节替你省掉了让你能把精力放在数据增强、锚框调整和部署验证上。适合谁用做农产品分选设备、采摘机器人视觉模块、或者单纯想跑通 YOLO 自定义数据集流程的工程师。如果你手头正好有 1000 张左右的白萝卜图像想快速验证一个检测方案能不能落地这篇笔记就是按这个思路写的。2. 从 zip 到 YOLO 可训练格式目录结构、标签解析与最小转换脚本2.1 先看清 zip 里到底装了什么拿到压缩包别急着解压到训练目录先做一次「体检」。常见的数据集打包方式有三种一种是 images 和 labels 分开两个文件夹标签是 YOLO 格式的 txt一种是 images 里混着 jpg 和同名 txt还有一种是给的是 VOC 格式的 xml需要自己转。白萝卜检测数据集因为标注对象单一大概率是第一种或第二种。我一般会先用一条命令把文件类型和数量摸清楚# 统计压缩包内文件类型分布不解压 unzip -l 白萝卜检测数据集.zip | awk {print $4} | grep -oE \.[a-zA-Z]$ | sort | uniq -c | sort -rn这条命令的逻辑是unzip -l列出压缩包内容但不解压awk取第四列文件名grep -oE提取扩展名最后按出现次数排序。如果输出里.txt和.jpg数量接近 1:1说明是 YOLO 格式如果.xml占多数就得走 VOC 转 YOLO 的流程。参数上没什么可调的唯一注意的是如果文件名里有空格awk的列号可能要改成$NF。2.2 YOLO 标签格式的四个关键字段YOLO 的 txt 标签每行代表一个目标格式是class_id x_center y_center width height后四个值都是归一化到 0~1 的相对坐标不是像素值。白萝卜检测通常只有一类所以class_id全是 0。这里最容易翻车的地方是有些标注工具导出的坐标是左上角宽高VOC 风格但文件扩展名也是 txt直接拿去训 YOLO 会得到一堆飘在天上的框。验证方法很简单写个脚本抽查几个标签import os label_dir labels for fname in os.listdir(label_dir)[:5]: with open(os.path.join(label_dir, fname)) as f: for line in f: parts line.strip().split() vals list(map(float, parts[1:])) # YOLO 格式要求所有坐标在 0~1 之间 if any(v 0 or v 1 for v in vals): print(f{fname} 坐标越界: {vals}) # 宽高一般不会超过 0.9超过可能是像素值没归一化 if vals[2] 0.9 or vals[3] 0.9: print(f{fname} 宽高异常: {vals})这段代码的逻辑是遍历前 5 个标签文件检查后四个值是否在合理范围内。如果出现大于 1 的值说明没归一化如果宽高接近图像像素尺寸说明是像素坐标。参数上[:5]可以改成[:20]提高抽查覆盖率但别全量跑浪费时间。2.3 划分训练集、验证集和测试集的比例1000 张图像我一般按 8:1:1 划分也就是 800 张训练、100 张验证、100 张测试。如果白萝卜的拍摄场景比较单一比如同一个传送带、同一种光照可以适当减少验证集比例把更多数据留给训练。划分时要注意同一根萝卜的多个角度图像不能跨集否则验证集精度会虚高。常见做法是先按图像文件名聚类再按簇划分。如果数据集里没有这种多角度信息那就随机划分但固定随机种子保证可复现import random import os import shutil random.seed(42) all_imgs [f for f in os.listdir(images) if f.endswith(.jpg)] random.shuffle(all_imgs) n len(all_imgs) train all_imgs[:int(n*0.8)] val all_imgs[int(n*0.8):int(n*0.9)] test all_imgs[int(n*0.9):] for split, files in [(train, train), (val, val), (test, test)]: os.makedirs(fdataset/{split}/images, exist_okTrue) os.makedirs(fdataset/{split}/labels, exist_okTrue) for f in files: shutil.copy(fimages/{f}, fdataset/{split}/images/{f}) label f.replace(.jpg, .txt) shutil.copy(flabels/{label}, fdataset/{split}/labels/{label})逻辑说明先固定random.seed(42)保证每次划分结果一致然后按 8:1:1 切分最后把图像和对应标签复制到 YOLO 训练所需的目录结构里。参数上0.8和0.9可以根据数据量调整但验证集不要少于 50 张否则 mAP 波动太大。3. 用 YOLOv8 跑通白萝卜检测配置文件、训练命令与三个必调参数3.1 写一个针对白萝卜的 data.yamlYOLOv8 训练自定义数据集核心是data.yaml。白萝卜检测只有一类所以nc: 1names: [radish]。路径建议用绝对路径避免训练时找不到文件path: /home/user/radish_dataset train: dataset/train/images val: dataset/val/images test: dataset/test/images nc: 1 names: [radish]这里有个细节path是数据集根目录train和val是相对于path的路径。如果你把data.yaml放在数据集根目录下path可以写成.。但我不建议这么做因为 YOLOv8 在不同版本里对相对路径的解析行为有过变化用绝对路径最稳。3.2 训练命令与 batch size 的显存账假设你用一张 8GB 显存的卡输入分辨率 640YOLOv8n 的 batch size 可以设到 16如果是 YOLOv8mbatch size 降到 8YOLOv8l 就只能设 4。白萝卜检测因为目标尺寸中等偏大640 分辨率足够不需要上 1280。训练命令yolo detect train \ data/home/user/radish_dataset/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ device0 \ projectradish_runs \ nameexp1参数说明epochs100是上限patience20表示 20 轮验证集 mAP 不提升就早停lr00.01是初始学习率YOLOv8 默认是 0.01如果 loss 震荡厉害可以降到 0.005device0指定第一张 GPU。这里最容易被忽略的是imgsz白萝卜如果占图像比例很小比如传送带远景拍摄那 640 下萝卜可能只有 30×30 像素这时候要么提高分辨率到 1280要么用切片推理否则召回率上不去。3.3 三个必调参数学习率、锚框和增强策略YOLOv8 虽然自带自适应锚框但白萝卜的长宽比比较特殊——通常细长接近 1:2 到 1:3。如果直接用 COCO 预训练模型的锚框初始匹配质量会差一些。我一般会在训练前用yolo detect train的anchor_t参数微调或者干脆跑一次 k-means 重新聚类锚框。不过 YOLOv8 的锚框机制和 v5 不同它用的是无锚框anchor-free的解耦头所以锚框调优的空间比 v5 小重点应该放在数据增强上。数据增强里mosaic对白萝卜检测帮助很大因为它能把多张图拼在一起增加小目标和遮挡场景。但mosaic的概率别设太高0.5 左右比较稳太高会让训练后期 loss 震荡。mixup对白萝卜这种颜色单一的物体要慎用容易把萝卜和背景混得连人都认不出来。degrees旋转角度可以开到 15~30因为萝卜在传送带上方向不固定。hsv_h色调增强可以稍微开大一点0.015 到 0.03模拟不同光照下的白萝卜颜色变化。4. 白萝卜检测的避坑与排查从 loss 不降到框飘的五个血泪经验4.1 现象训练 loss 一直不降mAP 卡在 0.1 以下原因最常见的是标签格式不对。白萝卜数据集如果是从 VOC 转过来的转换脚本里x_center和y_center算错或者忘了除以图像宽高。另一个可能是data.yaml里的nc和实际类别数不一致比如标签里出现了class_id1但nc写的是 1只允许 0。解决先跑一遍标签校验脚本确认所有class_id都在[0, nc-1]范围内所有坐标都在 0~1 之间。然后拿一张训练图用 YOLO 的plotting工具把标签画出来肉眼确认框的位置对不对。4.2 现象验证集 mAP 正常但推理时框飘到萝卜外面原因训练时的图像预处理和推理时的预处理不一致。YOLOv8 默认训练时用了rect模式保持长宽比填充推理时如果直接 resize 到 640×640坐标映射就会错位。解决推理时用yolo detect predict命令它会自动处理 letterbox如果自己写 Python 推理脚本记得用LetterBox类别手动 resize。4.3 现象白萝卜堆叠时漏检严重只检出最上面几根原因堆叠场景下被遮挡的萝卜在标注时可能被标成了「不可见」或直接没标导致模型学不到遮挡特征。另外NMS 的iou_thres设得太低比如 0.3会把相邻的萝卜框合并掉。解决检查标注里堆叠区域的标签是否完整推理时把iou_thres调到 0.5~0.6给相邻目标更多保留机会。如果还是漏考虑用agnostic_nms或者换用 Soft-NMS。4.4 现象训练到 50 轮以后 loss 突然变成 NaN原因学习率太高或者某批数据里出现了损坏的图像比如半截 jpg。白萝卜数据集如果是网络爬取或手机拍摄偶尔会有截断文件。解决先用PIL遍历所有图像能打开且尺寸正常的才保留然后把lr0降到 0.001加warmup_epochs5让学习率慢慢升上去。4.5 现象模型在测试集上表现很好但换一批新拍的萝卜就崩了原因数据集的 1000 张图像可能全部来自同一台相机、同一个光照条件模型过拟合到了背景纹理上。白萝卜检测里传送带的颜色、相机的白平衡、甚至萝卜上的泥点分布都可能成为「捷径特征」。解决训练时加强hsv_v亮度增强和hsv_s饱和度增强模拟不同光照如果条件允许在新场景下拍 50 张图做微调比重新训 1000 张效果更好。5. 把 1000 张用到极致小样本下的增强技巧与部署前验证5.1 用「复制-粘贴」增强扩充堆叠场景1000 张图像里堆叠场景可能只占 10%~20%模型对遮挡的鲁棒性不够。我常用的一个技巧是从标注好的萝卜里抠出 mask随机粘贴到其他图像的传送带背景上生成新的堆叠样本。YOLOv8 的copy_paste增强参数可以开到 0.3但要注意粘贴后的标签要重新计算别直接用原图的框。# 简化版 copy-paste 思路从源图抠出萝卜区域粘贴到目标图 import cv2 import numpy as np def copy_paste(src_img, src_mask, dst_img, dst_bbox): x, y, w, h dst_bbox roi cv2.resize(src_img, (w, h)) mask cv2.resize(src_mask, (w, h)) # 用 mask 做 alpha 混合保留萝卜边缘 for c in range(3): dst_img[y:yh, x:xw, c] ( dst_img[y:yh, x:xw, c] * (1 - mask) roi[:, :, c] * mask ) return dst_img逻辑说明src_mask是萝卜区域的二值掩码dst_bbox是粘贴位置。参数上粘贴位置要避开已有萝卜的框否则标签会重叠。这个技巧对白萝卜检测特别有效因为萝卜形状规则抠图边缘干净。5.2 部署前必须做的三项验证第一项是分辨率验证把测试集图像缩放到实际部署相机的分辨率再跑一遍 mAP。很多人在 640 上训的模型部署到 1080p 相机上直接 resize小目标全丢。第二项是帧率验证用 TensorRT 或 ONNX Runtime 跑一遍看单帧推理时间。YOLOv8n 在 T4 上 640 分辨率大概能到 200 FPS 以上但如果你要同时跑多路得按路数除一下。第三项是误检分析把置信度 0.3~0.5 之间的框全部导出来人工看一遍这些是模型「犹豫」的样本往往对应着标注模糊或场景边缘情况。5.3 一个我踩过的坑别用测试集调参最后说个血泪教训。我刚开始做白萝卜检测时看到测试集 mAP 只有 0.6就反复回去调学习率、改增强参数调了十几轮测试集 mAP 涨到 0.85但换一批新数据直接掉到 0.4。后来才明白测试集一旦参与调参就不再是测试集了。正确做法是训练集和验证集用来调参测试集只在最后跑一次跑完就封存。如果测试集结果不理想回去看验证集的错误样本别动测试集。希望帮到你。本文还有配套的精品资源点击获取