ARTICLE DETAIL

资讯详情

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

苹果检测数据集:1662张图双格式标签,YOLO训练直接开跑

苹果检测数据集:1662张图双格式标签,YOLO训练直接开跑 简介本资源为面向目标检测学习者的苹果检测数据集从COCO2017数据集中提取整理而成专用于YOLO等算法的苹果目标检测训练与验证。数据集中目标类别统一为apple共包含1662张标注图像每张图像均配有对应的标签文件方便直接接入主流检测框架进行模型训练与效果评估。压缩包内共4987个文件其中jpg图像1662张、xml标签1662个、txt标签1663个xml与txt双格式并存可同时满足Pascal VOC与YOLO两种标注读取方式整体包大小约265.75MB目录结构清晰便于按需检索与批量处理。目前已有775人学习下载适合计算机视觉入门者、课程设计或科研实验中使用。借助该数据集读者可快速完成数据加载、格式转换、模型训练与精度对比省去自行采集与标注的成本为苹果检测相关项目提供可靠的数据基础。1. 苹果检测数据集1662 张图、双格式标签YOLO 训练直接开跑手上有个农业视觉项目要落地第一步往往不是调模型而是找一份能直接喂给 YOLO 的苹果检测数据集。我最近拆的这份资源从 COCO2017 里把 apple 类单独抽出来整理成 1662 张图标签同时给了 txt 和 xml 两套格式目标类别就一个apple。这意味着你不用再写脚本从 COCO 的 json 里做类别过滤也不用纠结 YOLO 和 VOC 两套标注怎么互转——拿到手就能分别对接 YOLOv5/v8 和 SSD/Faster R-CNN 这类框架。适合谁做果园计数、采摘机器人视觉、农产品分拣的从业者以及想拿真实数据跑通检测全流程的学生。文件名是 000000526955.jpg 这种纯数字串说明它保留了 COCO 原始命名好处是能溯源坏处是肉眼分不清哪张是哪张后面我会讲怎么处理。2. 数据集结构与标签格式txt 和 xml 到底怎么对应2.1 目录组织与文件命名规律这份数据集的图片命名沿用了 COCO2017 的 12 位数字 ID比如 000000526955.jpg。这种命名方式在训练时没有任何问题YOLO 只认文件名和标签文件的一一对应关系不关心名字好不好看。但你在做数据清洗、可视化抽检的时候会很痛苦——打开文件夹全是数字根本不知道哪张图里苹果多、哪张图里苹果少。常见做法是先用脚本统计每张图的标注框数量把框数异常比如 0 框或超过 20 框的样本挑出来单独看。我一般会生成一个image_id - bbox_count的映射表按框数排序优先检查头尾两端的样本。这一步能帮你快速发现漏标、错标或者图片本身损坏的情况。标签格式方面txt 是 YOLO 格式每行class_id x_center y_center width height坐标全部归一化到 0~1xml 是 PASCAL VOC 格式包含size和object节点坐标是绝对像素值。两套标签描述的是同一批标注框只是坐标系和存储方式不同。你不需要同时用两套选一套跟你的训练框架匹配的就行。2.2 从 xml 转 YOLO txt 的校验脚本虽然数据集已经给了 txt但如果你拿到的是 xml 版本或者想验证两套标签是否一致下面这个转换加校验的脚本可以直接抄。它的作用是读 xml 里的绝对坐标除以图片宽高做归一化再按 YOLO 格式写出 txt同时对比已有 txt 的差异。import os import xml.etree.ElementTree as ET from PIL import Image def xml_to_yolo(xml_path, img_path, out_txt_path): tree ET.parse(xml_path) root tree.getroot() # 读取图片真实宽高不要信 xml 里的 size有些标注工具会写错 with Image.open(img_path) as im: w, h im.size lines [] for obj in root.findall(object): cls_name obj.find(name).text.strip() if cls_name ! apple: continue # 这份数据集只有 apple 一类其他类别直接跳过 bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 归一化并转为中心点宽高 x_c (xmin xmax) / 2.0 / w y_c (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h # 裁剪到 [0,1]防止标注越界导致训练报错 x_c min(max(x_c, 0.0), 1.0) y_c min(max(y_c, 0.0), 1.0) bw min(max(bw, 0.0), 1.0) bh min(max(bh, 0.0), 1.0) lines.append(f0 {x_c:.6f} {y_c:.6f} {bw:.6f} {bh:.6f}) with open(out_txt_path, w) as f: f.write(\n.join(lines)) # 批量处理示例 img_dir images xml_dir annotations_xml out_dir labels_yolo os.makedirs(out_dir, exist_okTrue) for name in os.listdir(xml_dir): if not name.endswith(.xml): continue stem name[:-4] xml_path os.path.join(xml_dir, name) img_path os.path.join(img_dir, stem .jpg) out_txt_path os.path.join(out_dir, stem .txt) if os.path.exists(img_path): xml_to_yolo(xml_path, img_path, out_txt_path)逻辑说明核心是坐标归一化YOLO 要求所有值在 0~1 之间且格式为class_id x_center y_center width height。参数方面class_id固定为 0因为只有 apple 一类min(max(...))是保险操作防止个别标注框超出图片边界导致训练时 loss 爆炸。如果你发现转换后的 txt 和数据集自带的 txt 有差异优先信图片真实尺寸算出来的结果因为 xml 里的size字段有可能是标注工具随手填的。2.3 标签一致性抽检别等训练崩了才回头查我习惯在正式训练前抽 20 张图做可视化把 txt 里的框画回原图肉眼确认框的位置和大小对不对。这一步花不了十分钟但能帮你避开后面几小时的无效训练。具体做法是用 OpenCV 读图按 txt 里的归一化坐标反算像素坐标画矩形框并保存。import cv2 import os def draw_yolo_boxes(img_path, txt_path, out_path): img cv2.imread(img_path) h, w img.shape[:2] if os.path.exists(txt_path): with open(txt_path) as f: for line in f: parts line.strip().split() if len(parts) ! 5: continue _, x_c, y_c, bw, bh map(float, parts) x1 int((x_c - bw / 2) * w) y1 int((y_c - bh / 2) * h) x2 int((x_c bw / 2) * w) y2 int((y_c bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.imwrite(out_path, img) # 抽检前 20 张 for i, name in enumerate(sorted(os.listdir(images))[:20]): stem name[:-4] draw_yolo_boxes( fimages/{name}, flabels_yolo/{stem}.txt, fcheck_{i:02d}.jpg )这段代码的关键参数是(0, 255, 0)绿色框和线宽2方便在复杂背景里看清。如果你发现某张图的框明显偏了大概率是 xml 里的size和真实尺寸不一致或者标注时用的坐标系不是左上角原点。这种样本要么修正要么直接剔除别硬塞进训练集。3. 用这份数据跑 YOLOv8配置、训练与指标解读3.1 数据集 YAML 配置与目录划分YOLOv8 对目录结构有固定要求训练集和验证集分开图片和标签分目录存放标签目录名必须是labels图片目录名必须是images。这份数据集原始状态是 1662 张图混在一起你需要先做划分。我一般按 8:2 切训练集 1329 张验证集 333 张。如果数据里包含连续帧比如视频抽帧一定要按时间顺序切别随机打乱否则验证集里出现训练集的相邻帧指标会虚高。# 目录结构规划 dataset/ ├── images/ │ ├── train/ # 1329 张 │ └── val/ # 333 张 └── labels/ ├── train/ # 对应 txt └── val/划分脚本很简单用random.shuffle打乱后按比例复制文件即可。注意图片和标签要同步移动别只移了 jpg 忘了 txt。import os import random import shutil random.seed(42) # 固定随机种子保证每次划分一致 img_dir images txt_dir labels_yolo out_root dataset train_ratio 0.8 names [n for n in os.listdir(img_dir) if n.endswith(.jpg)] random.shuffle(names) split int(len(names) * train_ratio) train_names names[:split] val_names names[split:] for subset, subset_names in [(train, train_names), (val, val_names)]: os.makedirs(f{out_root}/images/{subset}, exist_okTrue) os.makedirs(f{out_root}/labels/{subset}, exist_okTrue) for name in subset_names: stem name[:-4] shutil.copy(f{img_dir}/{name}, f{out_root}/images/{subset}/{name}) txt_src f{txt_dir}/{stem}.txt if os.path.exists(txt_src): shutil.copy(txt_src, f{out_root}/labels/{subset}/{stem}.txt)然后写apple.yaml这是 YOLOv8 训练时指定的数据配置文件path: /absolute/path/to/dataset train: images/train val: images/val nc: 1 names: 0: applepath必须写绝对路径相对路径在部分环境下会找不到文件。nc: 1表示只有一类names里的 0 对应 apple和 txt 里的 class_id 一致。3.2 训练命令与关键参数设置YOLOv8 的训练入口是yolo detect train下面这条命令是我在单卡 8G 显存下跑这份数据集的常用配置yolo detect train \ dataapple.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/apple \ nameexp1参数逐个说modelyolov8n.pt用 nano 版先跑通流程显存不够就降到batch8imgsz640是 YOLO 系列的默认输入尺寸苹果目标通常不会太小640 够用lr00.01是初始学习率如果你用预训练权重这个值合适如果从零训可以降到 0.001patience20表示 20 个 epoch 指标不提升就早停省时间。project和name控制输出目录跑完在runs/apple/exp1/weights/best.pt拿到最优权重。训练过程中重点看三个指标box_loss是否稳定下降、mAP50是否在 50 个 epoch 后趋于平缓、precision和recall是否差距过大。如果 recall 远低于 precision说明漏检多可能是苹果被遮挡或者太小需要检查标注是否漏框如果 precision 低说明误检多可能是背景里有类似苹果的圆形物体被误判。3.3 推理验证与结果导出训练完别只看指标拿几张验证集里的图跑推理肉眼确认效果。YOLOv8 的推理命令yolo detect predict \ modelruns/apple/exp1/weights/best.pt \ sourcedataset/images/val \ conf0.25 \ saveTrue \ projectruns/apple/predictconf0.25是置信度阈值低于这个值的框不显示。实际部署时这个值要根据业务调果园计数怕漏检就降到 0.1分拣线怕误抓就提到 0.5。跑完在runs/apple/predict里能看到带框的图重点看小目标、遮挡目标和边缘目标的表现。如果发现某类场景系统性漏检回到标注环节查那批图的标签是不是有问题。4. 避坑与排查这份数据集用起来容易翻车的五个点4.1 图片和标签数量对不上现象训练时报No labels found或者某些图没有对应标签loss 异常。原因COCO 提取过程中可能有些图没有 apple 类标注但图片文件被保留了导致 jpg 有、txt 空或不存在。解决跑一遍配对检查脚本统计有图无标签、有标签无图、标签为空文件的数量把无标签的图从训练集剔除或者确认是否应该保留作为负样本。import os img_names {n[:-4] for n in os.listdir(images) if n.endswith(.jpg)} txt_names {n[:-4] for n in os.listdir(labels_yolo) if n.endswith(.txt)} no_label img_names - txt_names no_img txt_names - img_names empty_label {n for n in txt_names if os.path.getsize(flabels_yolo/{n}.txt) 0} print(f有图无标签: {len(no_label)}) print(f有标签无图: {len(no_img)}) print(f空标签文件: {len(empty_label)})4.2 坐标越界导致训练 loss 变 NaN现象训练几个 epoch 后 loss 突然变成 NaN或者框画出来跑到图片外面。原因xml 转 txt 时没做坐标裁剪个别标注框的 xmax 超过图片宽度归一化后值大于 1。解决在转换脚本里加min(max(...))裁剪或者在训练前统一扫一遍所有 txt把超出 [0,1] 的值截断。YOLOv8 对越界坐标的容忍度有限别指望它自动修正。4.3 验证集指标虚高现象mAP50 跑到 0.95 以上但实际推理效果很差。原因划分数据集时随机打乱训练集和验证集里存在几乎相同的图片比如同一场景连拍模型相当于在验证集上“见过”这些图。解决按场景或时间顺序划分确保验证集的图片和训练集不来自同一段连续拍摄。如果数据里有多张图背景几乎一样用感知哈希去重后再划分。4.4 小目标漏检严重现象大苹果能检出远处的小苹果全部漏掉。原因COCO 里 apple 类本身小目标就多640 输入尺寸下小目标特征在深层特征图上几乎消失。解决训练时把imgsz提到 1280或者用 YOLOv8 的 P2 检测头需要改模型配置再或者对训练集做 mosaic 增强时保留小目标。推理时降低conf阈值也能捞回一部分但会引入误检要权衡。4.5 类别名写错导致训练报错现象yolo detect train启动时报Class names must be unique或nc不匹配。原因apple.yaml里nc写了 2 但names只有一行或者 names 里的 key 不是从 0 开始。解决这份数据集只有 apple 一类nc: 1names: {0: apple}别多写也别少写。如果你后面要加其他水果类别记得同步改nc和 txt 里的 class_id。5. 进阶技巧用这份数据做迁移学习和难例挖掘跑通基础训练后如果你手头还有别的水果检测任务这份苹果数据集可以当预训练权重用。具体做法是先用 apple.yaml 训一个模型然后把 backbone 权重冻结换掉检测头在目标数据集上微调。YOLOv8 里通过modelruns/apple/exp1/weights/best.pt加载权重再指定新的 data yaml 即可。冻结层数用freeze10控制表示前 10 层不更新适合目标域和苹果域差异不大的场景。另一个实用技巧是难例挖掘。训练完第一轮后用best.pt在训练集上跑推理把漏检和误检的图挑出来人工补标或修正后加入下一轮训练。YOLOv8 的推理结果里有个save_txtTrue选项会把预测框写成 txt你可以写脚本对比预测框和真实标签的 IoU把 IoU 低于 0.3 的样本筛出来重点看。我一般会迭代两到三轮mAP 通常能再涨 3~5 个点。最后说个我自己的习惯每次拿到新数据集先跑一遍yolo detect train的 1 epoch 快速验证确认数据加载、标签解析、类别配置都没问题再开长训练。这个 1 epoch 花不了几分钟但能帮你避开 90% 的低级错误。从那以后我每次换数据集都强制走一遍这个流程省下的时间够跑好几轮实验了。希望帮到你。本文还有配套的精品资源点击获取
返回列表