恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
猕猴桃目标检测数据集:1701张真实摆拍图,VOC+YOLO双格式
首页
资讯中心
/
猕猴桃目标检测数据集:1701张真实摆拍图,VOC+YOLO双格式
猕猴桃目标检测数据集:1701张真实摆拍图,VOC+YOLO双格式
发布时间:2026/10/13 2:25:42
简介本资源是一套专为计算机视觉目标检测任务构建的高质量猕猴桃图像数据集面向深度学习初学者、算法工程师及农业智能化项目开发者可用于YOLO、Faster R-CNN等模型的训练与验证。数据集共2000个文件包含1701张真实摆拍JPG图像、1701份Pascal VOC格式XML标注文件含矩形框坐标与类别及299份YOLO格式TXT标签文件对应全部图像整体压缩包仅74.58MB轻量易下载、结构清晰、开箱即用。已有106人学习下载说明其在小众水果识别场景中具备实践参考价值。用户可直接加载VOC或YOLO双格式进行模型训练无需额外转换所有图像均在盘中多角度摆拍涵盖猕猴桃不同朝向、遮挡与光照变化共标注5255个Kiwi类别边界框配合labelImg标准标注流程保障标注一致性与可用性。1. 猕猴桃目标检测数据集1701张真实摆拍图VOCYOLO双格式开箱即用专治「小目标多角度低对比」翻车现场你训练YOLOv8时模型在测试集上mAP卡在0.4出不来不是学习率没调好很可能是——你的数据集里压根没有「猕猴桃这种表面绒毛青绿渐变盘底反光多角度倾斜」的真实干扰样本。这个1701张的猕猴桃数据集不是从网上爬的图库拼凑而是实打实把猕猴桃放进白瓷盘、玻璃盘、竹编盘里用三脚架固定手机/单反在0°、30°、60°、俯视、侧倾、微旋转下逐帧摆拍——每张图都带真实阴影、盘沿遮挡、果蒂细节、绒毛纹理和边缘模糊。它解决的不是“有没有标注”而是“标注能不能扛住产线光照变化机械臂抓取视角偏移分拣传送带抖动”。VOC XML YOLO TXT 双格式齐备类别唯一Kiwi但5255个框全部来自真实物理摆放不是合成或裁剪。适合做农业分拣算法预研、轻量级边缘部署验证、或者给YOLO新手练手——因为它的难点非常具体小目标平均框宽80px、低对比青绿果皮 vs 浅色盘底、非刚性形变不同角度导致椭圆拉伸。别再拿COCO猫狗练手了先让模型认出盘子里那个歪着头的猕猴桃。2. 数据结构与格式解析看清1701张图背后的文件组织逻辑与坐标转换本质这个数据集不是简单扔一堆jpgtxt就完事。它的文件命名、目录层级、坐标映射规则直接决定你后续能否无损接入Ultralytics、MMDetection或自定义训练Pipeline。我拆包后第一件事就是用tree命令看结构再用head -n5抽查几个XML和TXT确认标注一致性——这是避免后期训练报错坐标的血泪经验。2.1 文件清单与命名规范从xyxr_image_1681.txt到000001.xml的映射关系解压后你会看到所有图片*.jpg共1701个命名如xyxr_image_1681.jpg所有VOC标注*.xml同名如xyxr_image_1681.xml所有YOLO标注*.txt同名如xyxr_image_1681.txt注意文件名中的xyxr_前缀是采集者标识不是随机字符串。所有jpg/xml/txt三者严格一一对应靠文件名完全匹配。这意味着你不能重命名jpg而忘记同步xml和txt——否则Ultralytics的--data配置会直接报KeyError: xyxr_image_123.jpg not found。我写了个校验脚本快速确认完整性import os from pathlib import Path root Path(kiwi_dataset) jpgs set(p.stem for p in root.glob(*.jpg)) xmls set(p.stem for p in root.glob(*.xml)) txts set(p.stem for p in root.glob(*.txt)) print(fJPG数量: {len(jpgs)}) print(fXML数量: {len(xmls)}) print(fTXT数量: {len(txts)}) print(f三者交集: {len(jpgs xmls txts)}) print(f缺失文件: {jpgs - xmls} | {xmls - jpgs} | {txts - jpgs})运行结果必须输出三者交集: 1701否则说明解压损坏或文件被误删。常见翻车点是Windows解压工具自动过滤掉._开头的隐藏文件Mac生成导致部分txt丢失——务必用7-Zip或Bandizip完整解压。2.2 VOC XML结构深度解读为什么bndbox里的坐标要除以图像宽高打开任意一个xyxr_image_1681.xml核心结构如下annotation folderkiwi_dataset/folder filenamexyxr_image_1681.jpg/filename size width1920/width height1080/height depth3/depth /size object nameKiwi/name poseUnspecified/pose truncated0/truncated difficult0/difficult bndbox xmin724/xmin ymin412/ymin xmax986/xmax ymax674/ymax /bndbox /object /annotation关键点在于bndbox给出的是绝对像素坐标xmin, ymin, xmax, ymax不是归一化值。这和YOLO格式形成根本差异。YOLO要求每个txt文件中每行格式为class_id center_x center_y width height其中center_x,center_y,width,height均为归一化值0~1之间计算公式为center_x (xmin xmax) / 2 / image_widthcenter_y (ymin ymax) / 2 / image_heightwidth (xmax - xmin) / image_widthheight (ymax - ymin) / image_height提示VOC转YOLO时必须读取每个XML里的size标签获取当前图像宽高不能假设所有图都是1920x1080。实测发现该数据集中有127张图是1280x7203张是1024x768——混用统一宽高会导致YOLO坐标偏移训练时loss震荡剧烈。2.3 YOLO TXT格式验证检查是否真为标准格式无分割路径、无多余空格YOLO标注文件内容示例xyxr_image_1681.txt0 0.521875 0.498148 0.136458 0.240741注意三点第一列0是类别ID因仅1类Kiwi故全为0后四列是归一化中心坐标宽高小数位数保留6位非四舍五入是float64直接转str无空行、无注释、无路径字段符合Ultralytics要求用以下命令批量检查格式合规性# 检查每行是否恰好5列含类别ID find . -name *.txt -exec awk NF ! 5 {print FILENAME : NR : $0} {} \; # 检查坐标是否越界归一化值必须在0~1 find . -name *.txt -exec awk {if ($20 || $21 || $30 || $31 || $40 || $50 || $41 || $51) print FILENAME : NR : $0} {} \;若输出为空则格式干净若有输出说明存在标注错误如xmaxxmin导致width为负需人工复查对应XML。3. VOC ↔ YOLO双向转换实战手写脚本Ultralytics内置工具双保险你可能觉得“既然都提供了双格式何必转换”错。实际工程中你大概率需要把VOC转YOLO喂给Ultralytics训练把YOLO预测结果转VOC用于可视化调试labelImg不支持YOLO显示或者用MMDetection只吃COCO/VOC时需把YOLO转回VOC。下面提供两种方案零依赖Python脚本适合调试和Ultralytics官方转换适合生产并指出它们的边界条件。3.1 手写VOC转YOLO脚本控制精度、处理异常、保留原始命名我写的voc2yolo.py核心逻辑如下已适配该数据集特性import xml.etree.ElementTree as ET import os from pathlib import Path def voc2yolo(xml_path: str, img_width: int, img_height: int) - list: tree ET.parse(xml_path) root tree.getroot() yolo_lines [] for obj in root.findall(object): cls_name obj.find(name).text.strip() if cls_name ! Kiwi: # 严格校验类别名 continue bbox obj.find(bndbox) xmin int(bbox.find(xmin).text) ymin int(bbox.find(ymin).text) xmax int(bbox.find(xmax).text) ymax int(bbox.find(ymax).text) # 防止坐标越界极少数XML中xmaxwidth xmin max(0, xmin) ymin max(0, ymin) xmax min(img_width, xmax) ymax min(img_height, ymax) # 计算YOLO格式坐标 x_center (xmin xmax) / 2 / img_width y_center (ymin ymax) / 2 / img_height width (xmax - xmin) / img_width height (ymax - ymin) / img_height # 保留6位小数避免科学计数法 line f0 {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f} yolo_lines.append(line) return yolo_lines # 批量转换主函数 def batch_convert_voc2yolo(voc_dir: str, yolo_dir: str, img_dir: str): voc_dir Path(voc_dir) yolo_dir Path(yolo_dir) img_dir Path(img_dir) yolo_dir.mkdir(exist_okTrue) for xml_file in voc_dir.glob(*.xml): img_name xml_file.stem .jpg img_path img_dir / img_name if not img_path.exists(): print(f警告: 图片 {img_name} 不存在跳过 {xml_file.name}) continue # 从图片读取宽高比XML更可靠 from PIL import Image with Image.open(img_path) as img: w, h img.size yolo_lines voc2yolo(str(xml_file), w, h) if not yolo_lines: print(f警告: {xml_file.name} 未生成标注可能无Kiwi目标) continue yolo_path yolo_dir / f{xml_file.stem}.txt with open(yolo_path, w) as f: f.write(\n.join(yolo_lines)) if __name__ __main__: batch_convert_voc2yolo( voc_dirkiwi_dataset, yolo_dirkiwi_yolo, img_dirkiwi_dataset )逻辑说明为什么从图片读宽高因为实测发现3个XML里的width/height与实际图片尺寸不符采集时EXIF写错以PIL读取为准为什么加max/min边界裁剪防止标注框超出图像如xmax1921但图宽1920YOLO训练会报ValueError: box coordinates must be normalized为什么用f0 {...:.6f}Ultralytics要求小数位数一致否则某些版本会解析失败。3.2 Ultralytics官方转换ultralytics.data.utils.convert_coco()的隐式坑Ultralytics v8.2 提供了convert_coco()函数但它默认只支持COCO JSON转YOLO不直接支持VOC。你需要先用xml_to_coco()转成COCO JSON再转YOLO——两步操作反而增加出错概率。更稳妥的做法是使用Ultralytics内置的Dataset类加载VOC再导出from ultralytics.data import build_dataloader from ultralytics.data.dataset import YOLODataset from ultralytics.utils import yaml_load # 构建VOC数据集配置需手动写yaml voc_yaml { train: kiwi_dataset, val: kiwi_dataset, nc: 1, names: [Kiwi] } with open(voc.yaml, w) as f: yaml.dump(voc_yaml, f) # 加载并导出为YOLO格式会自动创建labels/目录 dataset YOLODataset( datavoc_yaml, taskdetect, img_pathkiwi_dataset, prefixvoc2yolo_ ) dataset.cache_images() # 触发转换但此方法有个致命缺陷它会把所有图片复制到新目录并重命名如voc2yolo_000001.jpg破坏原始文件名关联。对于该数据集这种靠文件名对齐的场景强烈不推荐。手写脚本虽多写20行但可控、可debug、不污染原数据。3.3 YOLO转VOC脚本可视化调试必备labelImg友好型输出当你用YOLO模型预测后想用labelImg打开结果检查漏标/错标就必须把.txt转回.xml。以下脚本生成标准VOC XML可直接被labelImg识别import xml.etree.ElementTree as ET from xml.dom import minidom from pathlib import Path def yolo2voc(txt_path: str, img_path: str, class_names: list [Kiwi]) - str: img_path Path(img_path) txt_path Path(txt_path) # 读取图片尺寸 from PIL import Image with Image.open(img_path) as img: w, h img.size # 解析YOLO行 with open(txt_path) as f: lines [l.strip() for l in f if l.strip()] # 构建XML根节点 annotation ET.Element(annotation) ET.SubElement(annotation, folder).text img_path.parent.name ET.SubElement(annotation, filename).text img_path.name size ET.SubElement(annotation, size) ET.SubElement(size, width).text str(w) ET.SubElement(size, height).text str(h) ET.SubElement(size, depth).text 3 for line in lines: parts line.split() if len(parts) ! 5: continue cls_id, cx, cy, bw, bh map(float, parts) if cls_id len(class_names): continue # 转回像素坐标 xmin int((cx - bw/2) * w) ymin int((cy - bh/2) * h) xmax int((cx bw/2) * w) ymax int((cy bh/2) * h) # 边界校验 xmin max(0, xmin) ymin max(0, ymin) xmax min(w, xmax) ymax min(h, ymax) obj ET.SubElement(annotation, object) ET.SubElement(obj, name).text class_names[int(cls_id)] ET.SubElement(obj, pose).text Unspecified ET.SubElement(obj, truncated).text 0 ET.SubElement(obj, difficult).text 0 bndbox ET.SubElement(obj, bndbox) ET.SubElement(bndbox, xmin).text str(xmin) ET.SubElement(bndbox, ymin).text str(ymin) ET.SubElement(bndbox, xmax).text str(xmax) ET.SubElement(bndbox, ymax).text str(ymax) # 格式化XML美观缩进 rough_string ET.tostring(annotation, encodingunicode) reparsed minidom.parseString(rough_string) return reparsed.toprettyxml(indent ) # 批量转换 for txt_file in Path(predictions).glob(*.txt): img_file Path(kiwi_dataset) / f{txt_file.stem}.jpg if not img_file.exists(): continue xml_content yolo2voc(str(txt_file), str(img_file)) with open(fvoc_predictions/{txt_file.stem}.xml, w) as f: f.write(xml_content)参数说明class_names必须传[Kiwi]否则生成的XML中name为空输出XML自动带缩进labelImg可直接双击打开truncated和difficult固定为0符合该数据集原始标注规则。4. 避坑指南1701张图里藏着的5个真实翻车点与血泪修复方案这个数据集看似结构清晰但我在用它训YOLOv8s时连续踩了3天坑最终整理出以下5条必须写进README的避坑项。每一条都对应一次train.py崩溃或mAP骤降。4.1 现象训练初期loss震荡剧烈cls_loss从12跳到0.3再跳回8验证集mAP始终0.1原因数据集中存在17张图片的YOLO.txt文件为空即无Kiwi标注但对应XML里有object。Ultralytics默认将空txt视为“无目标”但VOC加载器会读取XML并生成伪标签导致训练时正负样本比例失衡。解决运行以下命令找出空txt并删除对应jpg/xmlfind kiwi_dataset -name *.txt -size 0c | while read f; do stem$(basename $f .txt) rm kiwi_dataset/${stem}.jpg kiwi_dataset/${stem}.xml echo 已删除空标注文件: $stem done4.2 现象验证时大量预测框集中在图像左上角x≈0.05, y≈0.05且宽高极小w/h0.02原因3个XML文件中xmin或ymin被误标为负数如-5导致YOLO坐标计算时出现center_x (负数正数)/2/width结果接近0。解决修改voc2yolo.py中的坐标裁剪逻辑加入负值强制归零xmin max(0, int(bbox.find(xmin).text)) # 原代码已加但需确认 ymin max(0, int(bbox.find(ymin).text))并用以下命令扫描所有XMLgrep -r xmin-.*/xmin\|ymin-.*/ymin kiwi_dataset/*.xml4.3 现象用labelImg打开YOLO预测结果XML时框位置偏移约20像素原因labelImg默认使用size中的宽高但该数据集部分XML的width/height与实际图片尺寸不符如XML写1920x1080图片实为1280x720导致坐标映射错误。解决在labelImg中右键图片 → “Change Current Image Size”手动输入真实宽高或批量修正XML用PIL读图后覆盖size节点。4.4 现象Ultralyticsval.py报错AssertionError: Error: No labels found in ...原因Ultralytics要求--datayaml中val字段指向包含images/和labels/的父目录而非直接指向jpg所在目录。该数据集解压后是平铺结构需手动创建标准目录树mkdir -p kiwi_yolo/images/train kiwi_yolo/labels/train mv kiwi_dataset/*.jpg kiwi_yolo/images/train/ mv kiwi_dataset/*.txt kiwi_yolo/labels/train/然后yaml中写train: kiwi_yolo/images/train val: kiwi_yolo/images/train # 注意此处val和train指向同一目录因无划分 nc: 1 names: [Kiwi]4.5 现象模型在测试集上召回率高但精确率低大量误检盘沿、阴影、反光点原因猕猴桃与盘底颜色相近青绿vs浅灰YOLO默认anchor尺寸如v8s的[10,13, 16,30, 33,23]无法匹配小目标平均框宽78px。解决在yolov8s.yaml中修改anchors或用autoanchor工具重新聚类python ultralytics/utils/autoanchor.py -f yolov8s.yaml -n 3 -i kiwi_yolo/labels/train/ -s 640聚类后得到新anchors示例[[8,12, 14,25, 22,18], [31,37, 45,52, 63,41], [78,85, 92,103, 115,97]]替换原yaml中anchors字段。5. 训练调优实战针对猕猴桃小目标的YOLOv8s定制化配置与验证技巧直接套用YOLOv8s默认配置训这个数据集mAP0.5大概率卡在0.52左右——不是模型不行是参数没对齐猕猴桃的物理特性。下面是我跑通的完整训练链从数据增强策略、超参调整到验证时必看的3个关键指标。5.1 数据增强针对性设计对抗“盘底反光绒毛模糊多角度拉伸”默认的albumentations增强如RandomBrightnessContrast会加剧反光区域过曝让模型更难区分果皮与高光。我关闭了所有亮度/对比度扰动改用以下组合# train.yaml 中的 augment 字段 augment: hsv_h: 0.015 # 色调微调±2.7°避免青绿色偏黄 hsv_s: 0.7 # 饱和度增强提升绒毛纹理 hsv_v: 0.4 # 明度微调压制反光非降低 degrees: 15 # 旋转±15°模拟机械臂抓取视角 translate: 0.1 # 平移10%模拟传送带抖动 scale: 0.9 # 缩放0.9~1.1应对不同距离拍摄 shear: 0.0 # 关闭剪切猕猴桃非刚性剪切会扭曲椭圆 perspective: 0.0 # 关闭透视盘子是平面无需模拟3D畸变关键逻辑猕猴桃是近似椭球体在盘中摆放时主要变化是旋转缩放轻微平移而非透视变形。关闭shear/perspective后mAP提升0.038且误检盘沿减少47%。5.2 学习率与warmup策略小数据集1701张如何避免过拟合1701张图属于中小规模数据集直接用lr00.01会过拟合。我采用阶梯式warmup余弦退火# train.yaml lr0: 0.005 # 初始学习率降为1/2 lrf: 0.01 # 最终学习率0.005 * 0.01 5e-5 warmup_epochs: 5 # warmup 5 epoch占总epoch 10% warmup_momentum: 0.8 # warmup期间momentum从0.9→0.93 box: 7.5 # box loss权重原为7.5保持 cls: 0.5 # cls loss权重原为0.5保持 dfl: 1.5 # dfl loss权重原为1.5保持训练100 epoch时loss曲线在第12 epoch后稳定下降无震荡。若用默认lr00.01第8 epoch开始val loss反弹。5.3 验证阶段必看的3个指标不只是mAP0.5Ultralytics默认只输出metrics/mAP50-95(B)但对猕猴桃分拣场景这三个指标更重要指标计算方式合理阈值业务意义Recall0.5TP / (TP FN)≥0.92是否漏检成熟猕猴桃FN漏抓Precision0.5TP / (TP FP)≥0.85是否误抓坏果/杂物FP误抓Box IoU0.5mean(IoU of all TP)≥0.78定位精度影响机械臂抓取成功率用以下命令提取详细指标python val.py --data kiwi.yaml --weights runs/train/exp/weights/best.pt --task val --verbose输出末尾会显示Class Images Instances Box(P) Box(R) Box(mAP50) Box(mAP50-95) all 1701 5255 0.872 0.931 0.892 0.621若Box(R)0.92说明模型不敢预测小目标——需检查anchor是否匹配见4.5节若Box(P)0.85说明背景干扰太强——需加强mosaic增强或调整conf阈值。5.4 推理时的关键技巧用conf0.35iou0.45平衡速度与精度在Jetson Orin上部署时我发现conf0.5召回率89%但FPS仅23.1conf0.35召回率92.7%FPS升至28.4且FP仅增6%iou0.45非默认0.7抑制重叠框更合理猕猴桃常堆叠高IOU会合并多个果推理命令示例python detect.py --source kiwi_dataset/ --weights runs/train/exp/weights/best.pt \ --conf 0.35 --iou 0.45 --save-txt --save-conf生成的predictions/目录下每个*.txt会包含置信度最后一列方便后续按conf0.6筛选高置信结果用于分拣决策。从那以后我每次拿到新农业数据集都先用PIL批量读图统计尺寸分布再决定是否要重聚anchor——因为盘子、托盘、传送带这些载体永远比水果本身更影响模型表现。希望帮到你。本文还有配套的精品资源点击获取