news 2026/9/27 23:09:36

4592张超市秤盘水果检测数据集:VOC+YOLO双格式与YOLOv8训练实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
4592张超市秤盘水果检测数据集:VOC+YOLO双格式与YOLOv8训练实战

简介:面向超市智能秤盘与目标检测应用场景,这份数据集涵盖苹果、香蕉、黑莓、辣椒、葡萄、柠檬、树莓、番茄等14类常见水果,并区分带包装(wb)与不带包装(wob)状态,共对应4592张图片的VOC与YOLO格式标注。压缩包内共2000个文件,以XML标注文件为主,另附使用前必读的TXT说明,整体约515.89MB;XML便于在LabelImg等工具中复核,TXT类别清单可直接对应YOLO训练配置,省去格式转换环节。已有291人学习下载,适合正在做零售称重识别、水果分类检测的学生或工程师作为模型训练与验证数据。拿到后可按照14类标注划分训练集与验证集,快速迭代检测模型;真实秤盘摆放带来的光照、遮挡和角度差异也能帮助提升模型在实体门店环境中的泛化能力,尤其适合需要区分包装与否的视觉称重方案。

1. 超市秤盘水果检测数据集:4592张、14类的VOC+YOLO双格式,先看清楚再动手

「超市秤盘水果检测数据集」解决的是自助称重最核心的问题:水果往秤盘上一放,摄像头要先认出苹果、香蕉、橙子,再对着单价表算钱。这场景看着简单,实际做检测比想象中麻烦——秤盘反光、水果遮挡、同品类还有不同品种,都直接影响识别率。

这份数据集用4592张实拍图覆盖14个类别,同时提供VOC和YOLO两种标注格式,把数据整理和格式转换提前做完了。适合在做自助称重、无人零售、水果分拣的开发者,也适合想拿真实业务数据跑一遍YOLO训练流程的人。拆完我的体会是:数据不复杂,真正花时间的是解压、校验和训练参数调整这几步,坑不少。

2. 数据集结构拆解:VOC与YOLO双格式到底存了什么

2.1 VOC格式目录:JPEGImages、Annotations与ImageSets三件套

解压之后最先看到的通常是一个VOCdevkit风格的目录。VOC格式源自PASCAL VOC竞赛的标注约定,现在几乎所有检测框架都保留了读取接口,所以很多公开数据集都拿它当发布格式。展开目录大概是这个结构:

VOCdevkit/ └── VOC2007/ ├── JPEGImages/ # 4592张jpg原图 ├── Annotations/ # 与图片同名的xml标注,也是4592个 ├── ImageSets/ │ └── Main/ # train.txt / val.txt / test.txt └── labels.txt # 按行排列的14个类名清单

JPEGImages放原始图片,Annotations放同名XML标注,ImageSets/Main下的txt记录每张图归属哪个集合,内容就是不带扩展名的文件名,一行一个。labels.txt是本数据集额外附上的类别清单,从第0行开始按索引排列,后面转YOLO格式和写训练配置都要靠它,先别删。

打开任意一个XML看标注细节:

<annotation> <folder>JPEGImages</folder> <filename>IMG_00001.jpg</filename> <size> <width>1280</width> <height>720</height> <depth>3</depth> </size> <object> <name>apple</name> <truncated>0</truncated> <difficult>0</difficult> <bndbox> <xmin>412</xmin> <ymin>258</ymin> <xmax>589</xmax> <ymax>431</ymax> </bndbox> </object> </annotation>

<size>里的宽高是后续坐标换算的基准,<object>可以重复出现,表示一张图里框了多个目标,<name>是类别名,<bndbox>是左上角和右下角的像素坐标。我拿到手会先做一件事:把所有<name>去重打印一遍,和labels.txt逐行对照,检查有没有大小写、带空格、中文别名这类隐蔽差异。

# 统计XML里出现过的所有类名,按出现次数排序 grep -h '<name>' Annotations/*.xml | sort | uniq -c

这个命令两分钟出结果,能提前暴露类名不一致的问题,省掉后面训练时类别错位的排查时间。

2.2 YOLO格式标签:归一化坐标与类别索引

YOLO训练不吃XML,吃的是纯文本标签。数据集在VOC之外直接给了转换好的YOLO目录:

yolo_dataset/ ├── images/ │ ├── train/ # 训练集图片 │ └── val/ # 验证集图片 ├── labels/ │ ├── train/ # 与images/train一一对应的txt │ └── val/ └── classes.txt # 14个类别,每行一个

每个txt与同名图片对应,内容形如:

0 0.3906 0.4785 0.1383 0.2403 3 0.7312 0.5208 0.1214 0.2146

五个数字依次是类别索引、归一化中心x、归一化中心y、归一化宽、归一化高。类别索引从0开始,对应classes.txt的行号;四个坐标全部除以图片宽高,范围在0到1之间。这种设计的价值在于:模型训练时不管输入图缩放成640还是1280,标签都不用跟着改,因为坐标是相对值。

4592张图14个类别,平均每类300多张,放到检测任务里属于中小规模。框的密度也值得留意,秤盘场景一般一张图是单个水果或小堆水果,框的数量不会像街景那样动辄十几个。想算平均目标数,可以用Python统计所有txt的总行数除以4592,这个数字会直接影响你对模型召回率的预期——目标越多,漏检风险越高。

2.3 双格式并存的转换关系:VOC转YOLO脚本

数据集既然已经给好了YOLO格式,大部分情况下直接用就行。但我建议把VOC转YOLO的脚本留一份,因为你后续一定会往数据集里补自己的标注——比如给一批新的芒果特写打框,打标工具导出的大概率是VOC或COCO格式。转换逻辑不复杂,核心是XML里的像素坐标除以图片宽高:

# voc2yolo.py:把VOC格式XML转成YOLO格式txt import xml.etree.ElementTree as ET from pathlib import Path def convert_voc_annotation(xml_path, class_names, out_dir): tree = ET.parse(xml_path) root = tree.getroot() size = root.find('size') w = int(size.find('width').text) h = int(size.find('height').text) lines = [] for obj in root.iter('object'): name = obj.find('name').text if name not in class_names: # 忽略类别表之外的目标 continue cls_id = class_names.index(name) # 类名映射到数字索引 box = obj.find('bndbox') xmin = float(box.find('xmin').text) ymin = float(box.find('ymin').text) xmax = float(box.find('xmax').text) ymax = float(box.find('ymax').text) x_center = (xmin + xmax) / 2 / w y_center = (ymin + ymax) / 2 / h bw = (xmax - xmin) / w bh = (ymax - ymin) / h lines.append(f"{cls_id} {x_center:.6f} {y_center:.6f} {bw:.6f} {bh:.6f}") out_path = out_dir / (xml_path.stem + '.txt') out_path.write_text('\n'.join(lines))

逻辑说明:ET解析XML拿到size和所有object;class_names是从classes.txt读出来的列表,用列表index完成类名到索引的映射;坐标转换就是中心点等于两端坐标均值除以宽高,宽高等于差值除以宽高。参数说明:class_names顺序必须和后续训练用的yaml完全一致,顺序错一位标签全错;out_dir要提前创建,不然write_text直接报错。转换完必须跑一遍第三章的标签校验脚本再入训练,别跳过。

3. 解压、校验、划分:拿到7z之后的三步落地操作

3.1 7z解压:先查看、再测试、后解压

压缩包是7z格式,Linux上默认没装解压工具,先装p7zip-full。我的习惯是解压前做三步:查看内容、测试完整性、正式解压。

# Ubuntu/Debian 安装 p7zip sudo apt install p7zip-full # 列出压缩包内容,确认有没有顶层目录 7z l 超市秤盘水果检测数据集VOC+YOLO格式4592张14类别.7z # 测试CRC完整性,提前发现下载损坏 7z t 超市秤盘水果检测数据集VOC+YOLO格式4592张14类别.7z # 正式解压到指定目录;-o后面没有空格,路径不存在会自动创建 7z x 超市秤盘水果检测数据集VOC+YOLO格式4592张14类别.7z -o./fruit_dataset

7z l只列出内容不解压,先看有没有顶层目录,避免解压后一堆文件散落得到处都是;7z t做CRC校验,下载不完整、文件损坏在这步直接暴露;7z x保留目录结构解压,和7z e的区别是e会把所有文件平铺到当前目录,数据集这种带目录结构的必须用x。Windows用户装7-Zip后右键解压即可,如果包设了密码,先单独解压classes.txt这种小文件验证,不要一上来全量解压。

注意:7z x的-o参数后面直接跟路径,没有空格;写成-o ./fruit_dataset会被解析成输出到当前目录再拼一个多余路径,解压位置就错了。

3.2 标签完整性校验:图片和标签必须一一对应

解压后第一件事不是急着训练,而是确认图片和标签的对应关系。这个数据集4592张图,如果某几张图缺标签、或者标签文件没有对应图片,YOLO训练时空标签会被跳过,验证集里多一张无标签图还会把mAP莫名拉低。我习惯用脚本扫一遍:

# check_dataset.py:核对图片与标签是否一一对应 from pathlib import Path img_dir = Path('fruit_dataset/yolo_dataset/images') label_dir = Path('fruit_dataset/yolo_dataset/labels') for split in ['train', 'val']: imgs = {p.stem for p in (img_dir / split).glob('*.jpg')} lbls = {p.stem for p in (label_dir / split).glob('*.txt')} print(f"[{split}] 图片 {len(imgs)} 张, 标签 {len(lbls)} 个") print(f" 有图片无标签: {sorted(imgs - lbls)[:5]}") print(f" 有标签无图片: {sorted(lbls - imgs)[:5]}")

逻辑说明:用不带扩展名的文件名stem做集合比对,差集就是问题文件。参数说明:glob里的*.jpg只匹配jpg后缀,如果数据集混入了jpeg或png会漏统计,稳妥做法是先rglob('*')列出所有文件按类型过滤。两个集合的差集如果非空,先手工看图是不是空文件或损坏图,再决定补标签还是删图。

3.3 标签内容合法性检查

数量和对应关系对上还不够,标签内容本身也可能有雷。常见的三类问题:类别索引越界(14类文本的有效索引是0到13)、坐标小于0或大于1、一行凑不够5个字段。这些问题直接导致训练损失异常或崩溃。

# check_labels.py:检查YOLO标签内容合法性 from pathlib import Path def check_label_file(txt_path, num_classes=14): bad = 0 with open(txt_path) as f: for line_no, line in enumerate(f, 1): parts = line.strip().split() if len(parts) != 5: print(f" {txt_path} 第{line_no}行字段数不对: {line.strip()}") bad += 1 continue cls_id = int(parts[0]) coords = [float(p) for p in parts[1:]] if cls_id < 0 or cls_id >= num_classes: print(f" {txt_path} 类别越界: {cls_id}") bad += 1 if any(c < 0 or c > 1 for c in coords): print(f" {txt_path} 坐标越界: {parts[1:]}") bad += 1 return bad total_bad = 0 for txt in Path('fruit_dataset/yolo_dataset/labels').rglob('*.txt'): total_bad += check_label_file(txt) print(f"共发现 {total_bad} 处问题")

逻辑说明:逐行切分字段,先查长度再查范围,避免用错误字段继续算。参数说明:num_classes按数据集的14传,以后自己加类别要同步改。坐标越界最常见的来源是VOC转YOLO时读错了size,比如把显示分辨率当成原图分辨率,转出来的坐标就会超1。

3.4 训练集划分:随机划分有风险,按类分层更稳

如果数据集的YOLO目录已经分好train和val,直接用;如果想重新划分,注意两点:固定随机种子、按类别分层。直接random.shuffle在类别不均衡时容易翻车——某个类别样本少,随机一抽可能把它的验证样本全抽走。

# split_dataset.py:按类别组合分层划分train/val import random from collections import defaultdict from pathlib import Path random.seed(42) # 固定随机种子,保证可复现 img_dir = Path('images_all') label_dir = Path('labels_all') val_ratio = 0.2 samples = defaultdict(list) for lbl in label_dir.glob('*.txt'): with open(lbl) as f: classes = {int(line.split()[0]) for line in f if line.strip()} samples[tuple(sorted(classes))].append(lbl.stem) val_set = set() for key, stems in samples.items(): random.shuffle(stems) val_set.update(stems[:max(1, int(len(stems) * val_ratio))]) with open('val.txt', 'w') as f: f.write('\n'.join(val_set)) with open('train.txt', 'w') as f: train_stems = [s for s in sum(samples.values(), []) if s not in val_set] f.write('\n'.join(train_stems))

逻辑说明:以「类别组合」为key分组,再从每个组里按比例抽验证集,保证每个类在train和val里都有样本。参数说明:val_ratio取0.2是4592张图规模常用的8:2划分;如果目标总数少于1000,建议降到0.1,避免训练样本不够。

4. 接进YOLOv8/YOLOv5训练:从yaml配置到参数选择

4.1 数据集yaml配置:names顺序错了就全错了

YOLOv8和YOLOv5都吃同一个结构的yaml。最容易错的是names顺序,它必须和数据集classes.txt的行号完全一致,差一位整个标签就错位到别的类别上了。配置长这样:

# fruit_scale.yaml path: /home/user/fruit_dataset/yolo_dataset train: images/train val: images/val names: 0: apple 1: banana 2: orange 3: pear 4: kiwi 5: dragon_fruit 6: grape 7: strawberry 8: mango 9: watermelon 10: cantaloupe 11: lemon 12: cherry_tomato 13: peach

上面names里的类名是按常见超市水果整理的示例,真实类别以解压后的classes.txt为准,逐行替换。path建议写绝对路径;写相对路径时yolo命令的工作目录一变就会报train: not found。

提示:训练前先用随机权重跑一次yolo detect val,能快速验证yaml路径和标签格式,别等训练跑完才发现路径错。

4.2 训练命令与关键超参数

YOLOv8的命令行格式是key=value,YOLOv5是双横线参数,两者配置含义一致。4592张图这个量级,我从预训练权重开始,而不是从零初始化:

# YOLOv8 yolo detect train \ data=fruit_scale.yaml \ model=yolov8n.pt \ epochs=120 \ imgsz=640 \ batch=16 \ device=0 \ workers=4 \ patience=20 \ lr0=0.001
# YOLOv5 等价命令 python train.py \ --data fruit_scale.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 120 \ --device 0 \ --patience 20

关键参数取舍:

参数推荐值说明
imgsz640速度与精度平衡点;圣女果这类小目标多再试1280
batch16yolov8n在24G显存下够用,显存小降到8
epochs120配合patience早停,4592张图足够收敛
patience20验证mAP连续20轮不升就停,省时间
lr00.001预训练权重微调用0.001,从零训练才用0.01

这里多说一句预训练权重:14个类别平均每类300多张图,属于中小规模数据,用yolov8n.pt或yolov5s.pt做起点,收敛速度和最终精度都比从yaml随机初始化好很多。训练过程中重点看终端打印的box_loss、cls_loss和mAP50,前几十个epoch正常是稳定下降,如果loss震荡不降,优先怀疑lr0。

4.3 训练结果评估:混淆矩阵行和不是1才是常态

训练完先跑验证:

yolo detect val data=fruit_scale.yaml model=runs/detect/train/weights/best.pt

评估时不要只盯整体mAP。整体mAP50高不代表每个类都行,要打开runs目录下的混淆矩阵看一眼。这里有个高频困惑:为什么混淆矩阵每一行加起来不是100%?因为YOLO的混淆矩阵带了background列,行里除了预测到各类的比例,剩下的部分是被漏检的样本,所以行和小于1是正常的,不是bug,网上很多人问的「yolo混淆矩阵总合不唯一」就是这件事。

真正要看的是非对角线上的数值。比如苹果被大量预测成梨、橙子被预测成柠檬,这类视觉相似类别的混淆才是mAP上不去的直接原因。看到这种混淆,常规做法是先补对应的负样本数据,或者检查是不是标注框本身有类别标错的噪声,而不是急着换网络结构。每类单独的mAP在results.csv里也能查到,按类筛一遍比看整体数字有用得多。

5. 训练翻车排查:YOLO训练中五个高频坑的现象与解法

5.1 损失函数NaN与BN崩溃

现象:训练到几十个epoch时loss突然变成NaN,终端打印出NaN,或者精度剧烈波动,模型权重文件越来越大但验证mAP一路往下掉。

原因:最常见是学习率过大导致梯度爆炸,其次是batch太小让BN统计量不稳定,再就是数据集里有坏图——纯黑图、损坏图——或者标签里出现宽度或高度为0的框。

解决:先把lr0降到0.001、batch提到16以上重跑;同时扫坏图:

from PIL import Image from pathlib import Path for p in Path('fruit_dataset/yolo_dataset/images').rglob('*.jpg'): try: img = Image.open(p) img.verify() # 只校验文件完整性,不加载像素 except Exception as e: print(f"坏图: {p} -> {e}")

再检查标签中有没有宽高为0的框。这三步走完,绝大多数NaN都能定位到根因。如果数据本身没问题,大概率是lr0的问题。

5.2 标签越界与类别数对不上

现象:训练刚开始报错,提示类别索引超出范围,或者某个类别的AP一直是0、一张都没检出。

原因:VOC转YOLO时class_names顺序和XML里的name实际顺序不一致;或者数据集里混入了labels.txt之外的类别名,常见于类名带空格、带中文。

解决:写脚本把所有XML的name去重打印,和classes.txt逐一对照。中文类名必须提前映射成拼音或英文。记住一个原则:模型训练真正读的是txt第一列的数字索引,yaml里的names只是给人看的,索引和classes.txt错位才是真问题。

5.3 mAP虚高或偏低:数据泄漏与背景域差异

现象:验证集mAP50高达0.95,部署到现场识别率掉一半;反过来mAP一直上不去,但随便拿一张图推理看着又很准。

原因:前者是数据泄漏——同一场景连拍的多帧被同时分进了train和val,模型等于把验证图内容背下来了;后者是训练和验证的拍摄背景差异大,比如训练图全是白底台面,现场是反光不锈钢。

解决:先按文件内容去重:

find images -type f -exec md5sum {} + | sort | awk '{print $1}' | uniq -d | wc -l

这个命令统计重复的md5数量。如果同一哈希出现多次,就是连拍帧泄漏。再按拍摄场景或时间段重新划分,而不是随机划分。背景域差异没有好办法,只能靠补充现场样本来拉平。

5.4 7z解压报错:密码正确却一直失败

现象:输入正确密码,7z依旧提示wrong password,或者解压到一半报cannot open file,同一个包换个机器反而能解出来。

原因:三选一——p7zip版本太老不支持压缩算法;压缩包内文件名是GBK编码而当前Linux系统是UTF-8,文件名解不出来被误报;密码在Windows上输入时带了全角字符或末尾空格。

解决:先升级p7zip再试;怕编码问题就Windows和Linux各试一次,哪个能解用哪个;密码末尾空格和全角字符是重灾区,手动重新输入一遍而不是从文本复制。实用技巧是只解压一个小文件先验证,比如7z x 包名.7z classes.txt,确认密码和编码都没问题再全量解压,避免解压到一半才发现是坏包。

5.5 图片分辨率不一致导致变慢或OOM

现象:训练时显存占用波动大,偶尔OOM;或者训练速度明显低于该imgsz应有的速度。

原因:数据集的4592张图原始分辨率参差不齐,从720p到4K都有。YOLO虽然会等比resize到640,但高分辨率图在数据加载和随机裁剪阶段开销更大,还会让batch间的计算量抖动。

解决:训练前先统计所有图片的分辨率分布,把过大的图统一缩放到长边不超过1920px:

ffmpeg -i input.jpg -vf "scale=1920:1920:force_original_aspect_ratio=decrease" -qscale 2 output.jpg

参数说明:scale目标框是1920x1920,force_original_aspect_ratio=decrease表示只缩不放,小图原样保留,大图等比缩到长边1920以内。因为YOLO标签是归一化坐标,等比缩放后txt完全不用改。如果OOM还是发生,就把batch降到8、workers降到2。

6. 从best.pt到秤盘实景:模型导出与边界验证

6.1 导出ONNX与TensorRT

训练完的best.pt要落到实际部署,第一站通常是导出ONNX,之后按推理设备决定要不要TensorRT。

# 导出ONNX yolo export model=best.pt format=onnx imgsz=640 opset=12 # 导出TensorRT engine(仅NVIDIA GPU) yolo export model=best.pt format=engine device=0 half=True

导出时imgsz必须和训练一致,否则有精度损失。half=True开FP16能显著提速,但建议先用FP32在真机跑一遍,确认mAP没有明显下降再切FP16。

6.2 秤盘实景的三个边界验证

数据集里是真实的秤盘照片,但部署还要补三门课。第一是反光:不锈钢秤盘和保鲜膜反光会制造高光区域,小目标容易在这里漏检,我一般带30张现场照片单独跑一遍,专挑反光最强的角度。第二是遮挡与叠加:多个水果堆叠时框容易漂,如果现场这种情况多,把imgsz从640提到1280,或者启动TTA(测试时增强)。第三是品种差异:训练集里的苹果可能只有红富士一个品种,现场来了青苹果,一个label覆盖多种外观时,如果该类别mAP偏低,要么补数据要么拆类。

6.3 一个保留至今的验收习惯

这个数据集项目让我养成一个习惯:每次拿到任何数据集,先跑标签校验脚本,再统计每类样本数和图片尺寸分布,然后才开始写训练配置;训练完不先看整体mAP,而是先看混淆矩阵和每类mAP,挑出最差的两类去翻原始图片,确认是标注噪声还是视觉混淆。这套流程帮我在好几个项目里提前避开了「模型看着准、上线就翻车」的尴尬。从那以后我每次拿到数据集都强制自己走一遍这套校验,再急也不跳步。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/27 23:09:22

YOLOv8布匹缺陷检测实战:污渍破洞精准识别与CPU部署

简介&#xff1a;本资源是一套基于YOLOv8实现的布匹缺陷&#xff08;污渍、破洞&#xff09;智能检测系统&#xff0c;面向计算机、人工智能、自动化等专业的在校学生、教师及企业开发者&#xff0c;适用于毕业设计、课程设计、大作业与工业质检入门实践。包内含完整Python源码…

作者头像 李华
网站建设 2026/9/27 23:05:45

YOLOv10打架行为检测实战:权重、数据集与全流程部署指南

简介&#xff1a;本资源面向计算机视觉学习者与安防场景开发者&#xff0c;提供一套可直接落地的YOLOv10打架行为检测方案&#xff0c;解决从数据准备到模型推理的完整链路问题。包内包含已训练好的权重文件&#xff0c;加载后即可对图像或视频进行正常与打架两类行为推理&…

作者头像 李华
网站建设 2026/9/27 23:05:23

Java外卖系统课程设计:Servlet+JSP+MySQL全流程源码解析

简介&#xff1a;一套基于Java技术栈的外卖系统APP完整项目&#xff0c;面向Java/Android方向的课程设计、毕业设计及自主提升。项目仿照主流外卖应用&#xff0c;覆盖用户下单、商家接单、配送员配送等核心业务闭环&#xff0c;后端基于Spring Boot构建&#xff0c;数据存储采…

作者头像 李华
网站建设 2026/9/27 23:03:35

压缩感知SAR成像:从稀疏重构到工程落地的全流程解析

简介&#xff1a;基于压缩感知理论的合成孔径雷达成像算法MATLAB实现&#xff0c;面向雷达信号处理、遥感成像与压缩感知方向的初学者及科研人员。针对传统SAR成像中采样数据量大、存储与处理成本高的问题&#xff0c;算法将压缩感知引入SAR成像流程&#xff0c;依次完成稀疏表…

作者头像 李华
网站建设 2026/9/27 23:03:20

医学影像报告多模态检索:从CLIP微调到向量索引落地

简介&#xff1a;一套面向毕业设计场景的深度学习多模态检索项目&#xff0c;聚焦医学影像与报告文本的跨模态匹配&#xff0c;适用于计算机视觉、医学信息处理方向的高年级本科生或研究生参考、复现与二次开发。压缩包共61个文件&#xff0c;约208MB&#xff0c;包含23个Pytho…

作者头像 李华