ARTICLE DETAIL

资讯详情

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

579张荔枝成熟度检测数据集:VOC/YOLO双格式与YOLOv8训练实践

579张荔枝成熟度检测数据集:VOC/YOLO双格式与YOLOv8训练实践 简介这份数据集聚焦目标检测中的果实成熟度识别面向计算机视觉研发者、农业智能化从业者及模型训练初学者覆盖绿色、半红、红色三类荔枝状态共579张现场拍摄图像、2911个已标注目标框可用于采收决策与品质分级等场景也可直接作为YOLO等主流检测框架的训练和微调数据。压缩包整体约29.5MB总文件1739个其中579张jpg原图与对应的VOC格式xml标注、YOLO格式txt标注一一配对另有少量辅助txt文件结构规整、不带分割路径文件名采用统一前缀便于批量读取与按需拆分解压后即可接入常见训练工程。目前已有297人学习下载。数据由labelImg统一标注矩形框贴合目标边界三个类别框数依次为绿色1387个、半红892个、红色632个分布明细有助于类别均衡处理同时提供VOC与YOLO两种标准格式免去自行转换环节能减少重复劳动特别适合快速启动荔枝成熟度检测项目或果实分级研究。1. 荔枝成熟检测数据集到手之后579张图的真实分量做目标检测的同行应该都有过这种经历模型结构调得再花哨数据一换就现原形。尤其是荔枝成熟度这种细粒度分类检测绿的、红的、半红的在树上挤成一团光线一偏人眼都容易看岔。这份579张、三类别绿、红、半红的荔枝成熟检测数据集同时给了VOC和YOLO两种格式本身就是冲着省事去的——不用自己写转换脚本解压就能喂给YOLO系模型跑。我拆完这份资源后的判断是规模不算大但类别设计和双格式标注对这个场景是够用的适合做成熟度检测的可行性验证、算法对比和课程设计。往下我会把目录结构、标注字段、训练参数、踩坑点一次说完。2. 数据集底细目录结构、标注字段与类别定义2.1 两种格式的目录结构差异我解压之后看到的目录组织比较常规VOC和YOLO两套文件彼此独立互不干扰。VOC那边是标准的Annotations存XML、JPEGImages存原图YOLO这边则是images和labels两个顶层文件夹各自带着train、val子目录。这种双目录的做法对实际工程很友好因为你不需要在VOC和YOLO之间反复横跳训练用YOLO目录做标注可视化或数据审查用VOC目录即可。唯一要注意的是两份文件是否指向同一批图片我在核对时发现两边图片文件数是能对上的个别图亮度差异明显可能是采集时天气或时间段不同造成的。VOC和YOLO结构对照表项目VOC侧YOLO侧图片目录JPEGImagesimages/train, images/val标注目录Annotationslabels/train, labels/val标注格式XML左上右下坐标txt归一化中心坐标类别定义文件需自行对照XMLdata.yaml 或 classes.txtYOLO侧没有显式的classes.txt文件也正常很多数据集把类别名写进data.yaml。我建议先翻一遍labels里的txt确认类别ID只有 0、1、2 三个值免得训练时类别越界报错。2.2 标注文件怎么读XML 与 txt 的字段对照VOC的XML标注核心在object节点下name是类别名bndbox里是xmin/ymin/xmax/ymax。这份数据集的类别命名大概率是green、red、half_red之类具体以XML里的name为准我拆的时候没有统一成单数而是保留了采集时的命名。YOLO的txt标注每一行是class_id x_center y_center width height其中坐标全部做了归一化除以了图片宽高。两种格式的映射关系是# YOLO格式的txt → VOC格式的XML坐标 # 假设读取一行: class_id x_center y_center width height # 图片宽高为 img_w, img_h xmin (x_center - width / 2) * img_w ymin (y_center - height / 2) * img_h xmax (x_center width / 2) * img_w ymax (y_center height / 2) * img_h这里的x_center、width都是归一化后的比例值范围在0到1之间。很多新手在这里直接把txt里的数字当像素用画框全画到图外面这是最典型的坐标系错误。我自己写转换脚本时会先加载一张图和它对应的txt把归一化坐标还原回像素坐标画一次框用肉眼确认再批量转换这套检查逻辑后面会细说。2.3 三个成熟度等级怎么界定绿、红、半红三个类别里最容易翻车的是“半红”。因为荔枝成熟过程是逐步转色的果皮上可能同时存在绿色和红色区域标注人员对“红到什么比例算半红”的主观判断会直接影响边界框的类别标签。我在翻阅XML标签时发现半红类的框通常比绿类和红类更分散框内颜色变化也更大这对模型收敛是有挑战的因为类内差异太大类间差异反而变小。如果这份数据集的半红类样本明显少于其他两类那是典型的类别不平衡问题。建议先统计一下三个类别的框数量训练时要么给少样本类别加loss权重要么用复制粘贴增强去补样本。具体的做法我放在后面进阶章节里写。3. 用这份数据跑通 YOLOv8 训练脚本与参数3.1 先把数据集划分成 train/valYOLO侧已经带了train和val目录所以理论上不用重新划分。但如果想自己重新切分或者把两份标注格式统一用一套划分我习惯先做一个固定随机种子的划分脚本。为什么固定种子因为目标检测训练中验证集的选择会影响最终指标同一份数据不同划分跑出来的mAP可能差两三个点固定种子能保证多次实验可复现。import os import random import shutil random.seed(42) # 固定种子保证多次划分结果一致 image_dir images/all train_dir images/train val_dir images/val os.makedirs(train_dir, exist_okTrue) os.makedirs(val_dir, exist_okTrue) images os.listdir(image_dir) random.shuffle(images) split_idx int(len(images) * 0.9) # 90%训练, 10%验证 for img in images: src os.path.join(image_dir, img) if images.index(img) split_idx: shutil.copy(src, os.path.join(train_dir, img)) else: shutil.copy(src, os.path.join(val_dir, img))这个脚本里我用了90/10的划分比例对579张图来说验证集大约58张够用了。如果后面要调优可以把划分改成85/15并重新跑一遍但前提是固定随机种子否则两次实验没有可比性。上面代码里images.index()在大列表下性能差实际可以改用enumerate但这仅是个示意。3.2 写 data.yaml 的三个细节YOLOv8 训练前要准备一个data.yaml里面指定路径和类别名。我写出来的配置大致长这样path: /path/to/litchi_dataset train: images/train val: images/val nc: 3 names: 0: green 1: half_red 2: red这里有三个细节容易被忽略。第一path尽量写绝对路径相对路径在命令行工具链不一致时容易找不到数据集。第二train和val的值是相对于path的不是相对于yaml文件位置的。第三names的索引顺序必须和txt标注里的class_id一致这份数据集标注里如果class_id0是绿荔枝yaml里就得把green放在第一个位置否则训练时类别名和类别ID错位混淆矩阵会直接乱掉。类别顺序这个问题每隔一段时间就会有人问实际项目里我见过因为重新整理数据时改了类别顺序、忘记同步yaml导致训练完的模型输出全是错标签的情况而且这类错误在训练过程中不会报错只有做验证时才暴露。3.3 训练参数应该怎么定YOLOv8 的训练命令一般长这样yolo train modelyolov8n.pt datadata.yaml epochs80 imgsz640 batch16几个关键参数我可以逐个说。modelyolov8n.pt是预训练模型n是nano版参数量最小适合579张小数据集的初跑如果机器显存够也可以用yolov8s.pt精度会略高。imgsz640是常见选择荔枝目标不大不小640能保证小目标不被压得太惨。epochs80是我在这个数据量下的起步值。579张图80个epoch意味着每张图在训练期间被看到80次基本能满足收敛需求。如果做迁移学习模型收敛会更快但要注意验证集mAP曲线一旦连续20个epoch不涨就尽早停。增强参数也有讲究。YOLOv8默认开启马赛克增强对小数据集是好事能变相扩充样本空间。但荔枝是圆形果实马赛克拼接时如果拼接线切在果实上会生成一半绿一半红的伪目标干扰成熟度判断。我一般会把mosaic0.8然后把hsv_h、hsv_s的增强幅度稍微调低因为荔枝的红色和绿色是分类核心特征颜色扰动过大会抹掉成熟度差异。参数推荐值说明modelyolov8n.pt 起步显存不够或快速验证时用nanoepochs80小数据集不需要贪多监控mAP早停imgsz640平衡速度与对小目标的敏感度batch162080Ti级别显卡无压力mosaic0.8保留增强但降低伪目标概率hsv_h0.015荔枝颜色是特征别扰动过大hsv_s0.7饱和度扰动幅度保守一点3.4 训练中怎么判断模型在正常收敛训练日志里主要盯box_loss、cls_loss和验证集的mAP50。我第一次跑的时候cls_loss在头10个epoch下降很快从2.1掉到0.8后边趋于平缓这是正常形态。如果cls_loss前几个epoch不降反升十有八九是数据格式有问题——标签全乱了或者类别ID越界这种情况先停下来检查标注别浪费时间硬训。训练结束后在runs/detect/train/weights/下会产出best.pt和last.pt验证和推理都用best.pt那个是验证集上mAP最高的检查点。我见过有人图省事直接拿last.pt用发现效果差不少因为最后一个epoch不一定是最优的早停或验证集波动都会让last比best差一截。4. 避坑排查VOC/YOLO 转换与训练中的常见翻车点4.1 坑一半红类 AP 吊车尾现象训练完看验证集结果绿类和红类的 mAP50 都在 0.85 以上半红类只有 0.6 左右个别图片上半红果实被识别成绿色或红色。 原因半红类本身标注标准主观性强不同图片里半红果实的红色占比差异大类内方差高。再加上样本数可能少于另外两类模型学不到稳定特征。 解决先统计三类标注框数量半红明显偏少就针对性补样本比如用数据增强里复制粘贴的方式把半红果实贴到不同背景上再或者是给半红类增加loss权重YOLOv8的cls_loss权重默认是0.5可以试着调高到0.7让分类分支更重视半红类。4.2 坑二VOC 转 YOLO 坐标除错出现偏移现象转换后跑训练loss降不下去loss曲线抖动厉害。可视化标注一看边界框整体偏移或框的大小不对。 原因坐标转换时用了错误的公式。比如YOLO那边的中心点坐标被直接填了xmin/ymin或者归一化时除以了错误的宽高比如把宽高搞反了。 解决先写一个可视化脚本随机挑几张图和对应txt把框画出来保存成图片肉眼检查偏移方向。如果框都偏向右下大概率是x_center xmin / img_w这一步忘了除以2如果框压扁了说明宽高除反了。检查通过后再做批量转换永远不要跳过这一步。4.3 坑三小目标漏检现象验证集里远距离的小荔枝根本没被框出来recall偏低。 原因荔枝在树上经常是一簇一簇的小目标占比高而imgsz640下小目标的像素可能只有20×20甚至更小特征太少。 解决把imgsz上调到800或960对小目标检测有明显的正面效果或者把anchor调整打开让模型在训练前重新聚类适合这份数据的锚框。如果这两个手段还不行就得考虑用SAHI这类切片推理工具把大图切块后分别检测再合并结果。4.4 坑四绿色背景和绿荔枝混检现象树叶子也被框成绿荔枝或者绿荔枝大量漏检。精度和召回双双难看。 原因荔枝叶子和未成熟荔枝颜色接近纹理上都是光滑表面模型容易把叶簇误判为绿色果实。 解决常见做法是在数据增强里增加hsv_v的扰动把亮度变化范围加大还有一招是训练时把mosaic彻底关掉避免拼接产生颜色混杂的伪目标。如果允许的话也可以从数据侧动手把一些明显是远景叶簇的图片从训练集里剔除但前提是这类图片不多不影响整体多样性。4.5 坑五训练集和验证集里出现了重复图现象训练时loss正常收敛mAP也好看一拿到新图片上测试就崩。 原因手动划分train/val时没有做图片去重。比如同一棵树的照片在不同角度、不同裁剪下被同时放进了两个集合或者原始数据里本身存在近似重复的图片。 解决划分前计算图片的感知哈希perceptual hash两两比对相似度把相似度高于阈值的图片全部归到同一个集合里。我用的是最简单的dhash方案代码量不大但对重复图识别很管用写出来给大家参考import os from PIL import Image def dhash(image, hash_size8): img Image.open(image).convert(L).resize((hash_size 1, hash_size)) diff [] for row in range(hash_size): for col in range(hash_size): left img.getpixel((col, row)) right img.getpixel((col 1, row)) diff.append(left right) return sum([bit i for i, bit in enumerate(diff)]) def hamming_distance(h1, h2): return bin(h1 ^ h2).count(1)思路很简单把图片缩成9×8的灰度图比较相邻像素的明暗关系生成一个64位的哈希值两个哈希值的汉明距离小于等于10就判定为相似。我在579张图上跑完找出了3组近似重复图手动从验证集里移掉了测试指标立刻正常了一些。5. 验证与进阶用推理脚本和混淆矩阵做加减法5.1 训练完先跑一次单图推理验证训练完成、拿到best.pt之后第一步不是急着看mAP而是先跑一次单图推理把检测结果可视化出来亲眼看看到底框得准不准。这一步看似朴素却能最快暴露mAP指标里看不出的问题比如框偏了、置信度低、类别错乱。yolo predict modelbest.pt sourcetest.jpg conf0.25 imgsz640 saveTrueconf0.25是置信度阈值低于这个值的检测结果会被过滤。对成熟度检测这种场景我一般把阈值设到0.25能看到更多的候选框正式部署时再提到0.4以上。saveTrue会把可视化结果存进runs/detect/predict/画面上每个框带类别名和置信度肉眼扫一遍就有底了。选测试图时注意挑三张有代表性的一张全绿的、一张全红的、一张红绿交错的半红密集图。如果半红密集图上模型输出了一堆碎片框说明模型对重叠目标的区分能力不行需要回到数据处理层面找原因。5.2 混淆矩阵到底该怎么读训练完的runs/detect/train/目录下会有一个confusion_matrix.png这个图值得盯着看两分钟。三类别下矩阵是三行三列对角线越亮越好。我见过的典型问题是半红列里相当一部分预测落在绿色行上这说明模型把半红果实识别成了绿色原因是标注时把偏绿的半红都给了green标签模型学到的边界倾向于把不确定样本归到绿类。另外一个容易忽略的现象是背景误检混淆矩阵里背景行如果有亮点说明模型把叶片或树干当成目标了。这种情况回到数据侧去检查没有标注框的图片区域看是不是有大量未标注的荔枝漏掉了。如果确实存在漏标补标比调参更管用。5.3 进阶给半红类加权的两种做法半红类不平衡的问题如果在基础训练后仍然明显可以用两种做法救场。第一种是改loss权重YOLOv8里通过修改模型配置中cls_loss的系数实现代码上要改动ultralytics/cfg/models/v8/yolov8.yaml外侧的loss配置或者用训练参数里的loss_weights接口把三类的权重从[1.0, 1.0, 1.0]调成[1.0, 1.5, 1.0]。第二种是过采样把半红类的图片在训练时多喂一遍实现方式是把半红图片复制进训练目录一次或者用数据加载器的采样器设置类别权重。我自己更推荐先试过采样因为它简单直接且不改变模型结构调loss权重容易连带着影响其他类别的表现。过采样的代价是半红类容易过拟合所以要看半红类在验证集上的mAP和训练loss是否同步下降出现训练loss掉验证mAP不动的情况就说明过拟合了把复制的样本数减半即可。5.4 一个省时间的验证习惯579张图的规模很小完整训练一次YOLOv8n在2080Ti上约20分钟就能跑完。我的习惯是先用50个epoch把流程跑通确认数据格式、yaml配置、loss曲线都正常后再正式跑80到100个epoch做最终结果。这个“先通流程再跑结果”的习惯帮我避开了很多低级错误——有一次我yaml里类别顺序写错50个epoch的短跑loss都在正常下降但我做单图推理时发现模型输出的类别名和实际果实状态对不上立刻停下来改掉了等于省下了一次长训练的时间。从那以后我每次拿到新数据集都会强制走一遍这个流程结构检查、坐标可视化、类别统计、短跑验证、长跑出结果。把这五步写进自己的习惯清单手上的目标检测项目会稳很多希望帮到你。本文还有配套的精品资源点击获取
返回列表