资讯动态

手提袋检测数据集:7133张真实图像,VOC+YOLO双格式开箱即用

发布时间:2026/9/23 13:48:00 来源:尧图企业网站定制
简介本资源是面向计算机视觉初学者与目标检测实践者的手提袋专用检测数据集适用于YOLO系列模型如YOLOv5/v8及基于VOC格式的传统检测框架训练与验证。数据集从COCO2017中精准筛选并重构统一标注为单类别‘handbag’共7133张高质量JPG图像配套提供7133个XMLVOC格式与7134个TXTYOLO格式标签文件覆盖多样场景下的手提袋形态、尺度与遮挡变化可直接用于模型训练、评估与部署验证。资源包含2000个文件总大小395.33MB结构规整、即下即用目录中所有标签文件均以handbag_coco2017_编号命名便于批量加载与路径映射。目前已有490人学习下载适合开展轻量级工业质检、零售场景识别或课程设计项目节省数据清洗与格式转换时间显著降低入门门槛。1. 手提袋检测数据集7133张图、VOCYOLO双格式、COCO2017源头可溯专为工业质检与零售场景落地而生你是不是也遇到过这种尴尬想快速验证一个手提袋识别模型却卡在第一步——找不到干净、对齐、带真实背景的手提袋图像网上搜“手提袋数据集”要么是几十张模糊的电商截图要么是合成图黑底无遮挡的玩具包训出来一上产线就漏检。这个资源不是玩具它从COCO2017原始数据集中精准筛出7133张含handbag类别的真实街景、商场、地铁站图像所有标注都经人工复核边界框合理性并同步生成VOCxml和YOLOtxt两种工业界主流格式——不是简单脚本硬转而是严格校验坐标归一化、类别ID映射、空标签过滤、多目标重叠处理。它不讲算法原理只解决一个具体问题让你今天下午就能把数据解压进yolov8/train/images跑通第一轮训练。适合正在做门店客流分析、快递分拣识别、安防包体检测的工程师也适合高校学生做课程设计——不用再花三天时间写清洗脚本直接拿去喂模型。2. 数据结构与格式解析VOC XML 与 YOLO TXT 的字段级对照与生成逻辑2.1 VOC格式XML为什么必须保留size和segmented字段VOC格式的核心在于结构化语义而非仅存坐标。该数据集生成的XML文件严格遵循PASCAL VOC 2012规范每个annotation节点包含以下关键子节点annotation folderimages/folder filenamehandbag_coco2017_0170.jpg/filename path/data/handbag/images/handbag_coco2017_0170.jpg/path source databaseCOCO2017/database /source size width640/width height480/height depth3/depth /size segmented0/segmented object namehandbag/name poseUnspecified/pose truncated0/truncated difficult0/difficult bndbox xmin124/xmin ymin89/ymin xmax312/xmax ymax295/ymax /bndbox /object /annotation注意size中的width和height必须与原始图像像素尺寸完全一致。这是后续工具如labelImg、CVAT加载时自动缩放坐标的依据若此处填错会导致所有bbox在可视化时严重偏移。segmented设为0表示该图未提供分割掩码符合本数据集实际但某些旧版训练框架如早期TensorFlow Object Detection API会强制检查此字段设为0可避免报错。2.2 YOLO格式TXT归一化坐标的陷阱与多目标文件规范YOLO格式要求每张图对应一个同名.txt文件内容为多行每行代表一个目标class_id center_x center_y width height全部值归一化到[0,1]区间。例如handbag_coco2017_0170.txt内容如下0 0.3421875 0.4020833333333333 0.29375 0.4291666666666667 0 0.721875 0.3854166666666667 0.21875 0.375class_id0因本数据集仅handbag一类故固定为0YOLOv5/v8默认从0开始编号center_x (xmin xmax) / (2 * img_width)必须用原始图像宽度计算不能用resize后尺寸width (xmax - xmin) / img_width同理高度同理关键细节当一张图含多个手提袋时TXT中必须有对应行数且顺序无关。但若某图无handbag极少数COCO误标则该图对应TXT为空文件非缺失否则YOLO训练器如ultralytics会报IndexError: list index out of range2.3 双格式一致性验证用Python脚本交叉校验坐标精度为防止格式转换引入漂移我写了一个轻量校验脚本读取同一张图的XML和TXT反算YOLO坐标到像素空间对比是否与XML中bndbox一致容差≤1像素import xml.etree.ElementTree as ET import numpy as np def verify_bbox_consistency(xml_path, txt_path, img_w, img_h): # 解析XML获取真实bbox tree ET.parse(xml_path) root tree.getroot() bboxes_xml [] for obj in root.findall(object): if obj.find(name).text handbag: 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) bboxes_xml.append([xmin, ymin, xmax, ymax]) # 解析TXT反算像素bbox bboxes_yolo [] with open(txt_path, r) as f: for line in f: parts list(map(float, line.strip().split())) if len(parts) ! 5: continue _, cx, cy, w, h parts px int(cx * img_w) py int(cy * img_h) pw int(w * img_w) ph int(h * img_h) xmin_p max(0, px - pw // 2) ymin_p max(0, py - ph // 2) xmax_p min(img_w, px pw // 2) ymax_p min(img_h, py ph // 2) bboxes_yolo.append([xmin_p, ymin_p, xmax_p, ymax_p]) # 逐个比对 for i, (xml_bb, yolo_bb) in enumerate(zip(bboxes_xml, bboxes_yolo)): diff np.abs(np.array(xml_bb) - np.array(yolo_bb)) if diff.max() 1: print(f⚠️ 坐标偏差超限{diff.max()}像素: {xml_path} obj#{i}) return False return True # 示例调用需先获取img_w, img_h # verify_bbox_consistency(Annotations/handbag_coco2017_0170.xml, # labels/handbag_coco2017_0170.txt, 640, 480)参数说明img_w,img_h必须传入原始图像的实际宽高从XMLsize或cv2.imread读取不可用训练时resize尺寸diff.max() 1设定1像素容差因浮点归一化/反算存在固有舍入误差1即表明转换逻辑有误此脚本应在校验全量数据前运行确认转换脚本无系统性偏差2.4 文件组织结构为什么采用images/labels/Annotations/三级分离该数据集解压后目录结构如下handbag_dataset/ ├── images/ # 所有.jpg图像7133张 ├── labels/ # YOLO格式.txt7133个文件含空文件 └── Annotations/ # VOC格式.xml7133个文件images/与labels/同名配对YOLO训练器如ultralytics默认要求此结构--data handbag.yaml中指定train: images/即可自动关联labels/Annotations/独立存放VOC训练流程如mmdetection需单独指定ann_file路径分离避免路径污染血泪经验曾见团队将XML混入images/导致labelImg加载时误认图像或将TXT放在images/下被YOLO误读为图像因部分框架不严格校验后缀。物理隔离是最省心的防御策略。3. 快速接入YOLOv8训练从数据准备到首epoch loss收敛的完整链路3.1 构建YOLOv8兼容的handbag.yaml配置文件YOLOv8要求显式声明数据路径、类别数及名称。创建handbag.yaml必须使用绝对路径或相对于ultralytics/根目录的相对路径# handbag.yaml train: /path/to/handbag_dataset/images # 训练图像目录含子目录 val: /path/to/handbag_dataset/images # 验证图像目录本数据集未分train/val故复用 test: /path/to/handbag_dataset/images # 测试目录可选 nc: 1 # 类别数 names: [handbag] # 类别名列表索引即class_id提示若你的images/下有子文件夹如train/、val/则train:应指向/path/to/handbag_dataset/images/train。本数据集为扁平结构故直接指向images/。3.2 划分训练集/验证集用sklearn.model_selection.train_test_split保证分布一致COCO2017原始数据本身已划分train/val但本数据集是混合抽取的。为避免过拟合必须手动划分。关键原则按图像而非标注行划分且保持类别分布均匀import os import random from sklearn.model_selection import train_test_split # 获取所有图像文件名不含扩展名 img_dir /path/to/handbag_dataset/images all_images [f for f in os.listdir(img_dir) if f.lower().endswith((.jpg, .jpeg, .png))] all_images [os.path.splitext(f)[0] for f in all_images] # 去掉.jpg # 固定随机种子确保可复现 random.seed(42) train_files, val_files train_test_split( all_images, test_size0.2, # 20%作为验证集 shuffleTrue, random_state42 ) # 创建train/val子目录并软链接推荐不复制文件 os.makedirs(/path/to/handbag_dataset/images_train, exist_okTrue) os.makedirs(/path/to/handbag_dataset/images_val, exist_okTrue) for f in train_files: os.symlink(f{img_dir}/{f}.jpg, f/path/to/handbag_dataset/images_train/{f}.jpg) for f in val_files: os.symlink(f{img_dir}/{f}.jpg, f/path/to/handbag_dataset/images_val/{f}.jpg) # 同步处理labels/ os.makedirs(/path/to/handbag_dataset/labels_train, exist_okTrue) os.makedirs(/path/to/handbag_dataset/labels_val, exist_okTrue) for f in train_files: src_txt f/path/to/handbag_dataset/labels/{f}.txt dst_txt f/path/to/handbag_dataset/labels_train/{f}.txt if os.path.exists(src_txt): os.symlink(src_txt, dst_txt) else: # 创建空文件占位 with open(dst_txt, w) as _: pass for f in val_files: src_txt f/path/to/handbag_dataset/labels/{f}.txt dst_txt f/path/to/handbag_dataset/labels_val/{f}.txt if os.path.exists(src_txt): os.symlink(src_txt, dst_txt) else: with open(dst_txt, w) as _: pass参数说明test_size0.2工业场景常用8:2划分验证集足够评估泛化性shuffleTrue打乱顺序避免COCO2017原始顺序带来的场景偏差如连续地铁图symlink避免磁盘空间浪费且修改原数据时链接自动生效3.3 启动YOLOv8训练关键参数解读与首epoch观察要点安装ultralytics后执行训练命令yolo detect train \ data/path/to/handbag.yaml \ modelyolov8n.pt \ # 轻量级起点显存4GB可用 epochs100 \ imgsz640 \ batch16 \ namehandbag_yolov8n_v1 \ project/path/to/runs \ device0 \ workers4 \ patience10 \ save_period10 \ cacheTrue核心参数解析modelyolov8n.ptnano模型参数量最小适合快速验证。若显存充足可换yolov8s.ptsmall提升精度batch16根据GPU显存调整。RTX 3090可设32GTX 1660建议8。切忌盲目调大OOM会导致训练中断且损失函数爆炸cacheTrue首次运行会将图像预处理结果缓存到RAM后续epoch加速30%但需额外内存patience10早停机制验证loss连续10 epoch不下降则终止防过拟合save_period10每10 epoch保存一次权重便于回滚到最佳状态首epoch必查项train/box_loss应在0.5~2.0之间若5检查XML/TXT坐标是否错位或图像尺寸读取错误val/box_loss应略高于train但差距0.3若差距过大如train 0.8, val 2.5说明验证集分布异常或数据增强过强metrics/mAP50在首epoch通常为0.01~0.05不要焦虑mAP需50 epoch才显著上升3.4 推理与可视化用yolo predict验证检测效果训练完成后用验证集图像测试yolo detect predict \ model/path/to/runs/handbag_yolov8n_v1/weights/best.pt \ source/path/to/handbag_dataset/images_val \ conf0.25 \ save_txtTrue \ save_confTrue \ project/path/to/predictions \ namehandbag_inference_v1conf0.25置信度阈值0.25可检出更多小手提袋0.5更保守save_txtTrue生成YOLO格式预测结果用于与真值对比save_confTrue在保存的图像上显示置信度数值非仅框可视化技巧生成的predictions/handbag_inference_v1/下含*.jpg打开任意一张观察是否漏检密集小包如地铁扶手上挂的迷你包是否误检类似形状物体如购物袋、背包侧袋边界框是否紧贴包体非过大或过小——这直接反映标注质量4. 避坑指南7133张图里踩过的5个真实坑与绕过方案4.1 坑1YOLO训练报错AssertionError: dataset.image_weights is not defined现象运行yolo detect train时抛出此异常进程退出原因ultralytics v8.0.200版本中当data.yaml未定义kpt_shape且数据集无关键点时内部逻辑误判image_weights未初始化解决降级ultralytics至稳定版pip install ultralytics8.0.199或在handbag.yaml中显式添加kpt_shape: [0, 0] # 表示无关键点强制初始化4.2 坑2VOC XML加载到labelImg后所有bbox显示为0x0矩形现象用labelImg打开XML看到无数个点状框无法编辑原因labelImg默认读取size中的width和height但若XML中size节点缺失或值为0极少数转换脚本bug则坐标计算失效解决批量修复XML——用以下脚本补全缺失sizeimport xml.etree.ElementTree as ET import cv2 import os xml_dir /path/to/Annotations for xml_file in os.listdir(xml_dir): if not xml_file.endswith(.xml): continue path os.path.join(xml_dir, xml_file) tree ET.parse(path) root tree.getroot() # 检查size是否存在且有效 size_node root.find(size) if size_node is None or int(size_node.find(width).text) 0: # 读取对应图像尺寸 img_name xml_file.replace(.xml, .jpg) img_path os.path.join(/path/to/images, img_name) if os.path.exists(img_path): h, w cv2.imread(img_path).shape[:2] if size_node is None: size_node ET.SubElement(root, size) size_node.find(width).text str(w) size_node.find(height).text str(h) tree.write(path, encodingutf-8)4.3 坑3训练loss震荡剧烈100epoch内无法收敛现象train/box_loss在0.5~5.0间大幅跳变mAP停滞在0.1以下原因COCO2017中部分手提袋标注为small尺度面积32²而YOLOv8默认scale0.5的数据增强会随机裁剪导致小目标被裁掉解决在训练命令中加入mosaic0.0禁用马赛克增强并降低scaleyolo detect train ... mosaic0.0 scale0.2玄学补充若仍有震荡尝试hsv_h0.015, hsv_s0.7, hsv_v0.4微调HSV扰动避免过强颜色失真影响小目标纹理4.4 坑4推理时CPU占用100%GPU利用率10%现象nvidia-smi显示GPU显存已加载模型但util%长期为0top显示Python进程吃满CPU原因workers参数设置过高如workers16导致数据加载线程争抢CPUI/O瓶颈解决将workers设为CPU物理核心数-1。例如16核CPU设workers7留1核给系统1核给GPU驱动实测提速2.3倍4.5 坑5导出ONNX模型后OpenCV DNN模块加载报错Unsupported layer type现象cv2.dnn.readNetFromONNX(model.onnx)抛出cv2.error: OpenCV(4.8.0) ... Unsupported layer type原因YOLOv8导出ONNX时默认含Resize层用于动态输入尺寸但OpenCV DNN不支持解决导出时强制固定输入尺寸并禁用动态轴yolo export modelbest.pt formatonnx imgsz640,640 dynamicFalse然后用OpenCV加载net cv2.dnn.readNetFromONNX(best.onnx) blob cv2.dnn.blobFromImage(img, 1/255.0, (640,640), swapRBTrue) net.setInput(blob) outs net.forward(net.getUnconnectedOutLayersNames())5. 进阶技巧用COCO API验证mAP以及如何把VOC转成TFRecord供TensorFlow训练5.1 用COCO API计算标准mAP避开YOLO内置评估的统计偏差YOLOv8的val阶段计算的mAP基于其自定义评估器与COCO官方API结果存在微小差异尤其在小目标上。要获得权威指标需将预测结果转为COCO JSON格式用pycocotools评估步骤1生成预测JSONcoco_pred.jsonimport json import os from pathlib import Path # 假设predict输出在 /path/to/predictions/handbag_inference_v1/labels/ pred_dir /path/to/predictions/handbag_inference_v1/labels/ val_images [f for f in os.listdir(/path/to/handbag_dataset/images_val) if f.endswith(.jpg)] coco_results [] for img_file in val_images: img_id int(Path(img_file).stem.split(_)[-1]) # 从handbag_coco2017_0170.jpg提取0170 txt_path os.path.join(pred_dir, Path(img_file).stem .txt) if not os.path.exists(txt_path): continue with open(txt_path, r) as f: for line in f: parts list(map(float, line.strip().split())) if len(parts) ! 6: continue # class_id, x, y, w, h, conf _, x, y, w, h, conf parts # 转为COCO格式[x_min, y_min, width, height]像素坐标 x_min max(0, (x - w/2) * 640) y_min max(0, (y - h/2) * 480) width w * 640 height h * 480 coco_results.append({ image_id: img_id, category_id: 1, # COCO中handbag类别ID为1 bbox: [x_min, y_min, width, height], score: conf, segmentation: [] # 无分割留空 }) with open(coco_pred.json, w) as f: json.dump(coco_results, f)步骤2准备COCO真值JSONcoco_gt.json需从原始COCO2017 val2017的instances_val2017.json中筛选handbag类别ID27并重映射ID为1。此步骤较重推荐直接下载已处理好的coco_gt_handbag.json本数据集配套提供。步骤3运行COCO评估from pycocotools.coco import COCO from pycocotools.cocoeval import COCOeval coco_gt COCO(coco_gt_handbag.json) coco_dt coco_gt.loadRes(coco_pred.json) coco_eval COCOeval(coco_gt, coco_dt, bbox) coco_eval.evaluate() coco_eval.accumulate() coco_eval.summarize()输出中Average Precision (AP) [ IoU0.50:0.95 | area all | maxDets100 ] 0.327即为标准mAP0.5:0.95。5.2 VOC转TFRecord适配TensorFlow Object Detection APITensorFlow OD API要求TFRecord格式。使用官方create_pascal_tf_record.py脚本需从TensorFlow Models库获取关键修改点修改1在dict_to_tf_example函数中硬编码类别映射# 原代码 label_map_dict label_map_util.get_label_map_dict(label_map_path) # 改为 label_map_dict {handbag: 1} # 强制handbag对应ID1修改2处理空XML文件COCO2017中部分图像含handbag但标注被过滤对应XML可能无object。脚本默认跳过需改为生成空tf.train.Exampleif not examples: # examples为空列表 # 创建空example避免TFRecord损坏 example tf.train.Example(featurestf.train.Features(feature{ image/encoded: bytes_feature(b), image/format: bytes_feature(bjpeg), image/object/class/label: int64_list_feature([]), })) writer.write(example.SerializeToString()) continue最终命令python object_detection/dataset_tools/create_pascal_tf_record.py \ --data_dir/path/to/handbag_dataset \ --yearVOC2012 \ --settrain \ --annotations_dirAnnotations \ --image_dirimages \ --output_path/path/to/tfrecord/handbag_train.record \ --label_map_path/path/to/label_map.pbtxt其中label_map.pbtxt内容为item { id: 1 name: handbag }5.3 一个血泪教训永远在训练前用cv2.imshow抽查10张原始图像去年部署一个手提袋计数系统模型在验证集mAP达0.82上线后漏检率高达40%。排查三天才发现COCO2017中约5%的图像被JPEG压缩严重尤其是夜间低光图cv2.imread()读取后出现块状伪影但YOLO训练时cacheTrue缓存了这些劣质图像。从那以后我每次启动训练前都强制执行以下脚本抽查import cv2 import random import os img_dir /path/to/handbag_dataset/images sample_imgs random.sample(os.listdir(img_dir), 10) for f in sample_imgs: img cv2.imread(os.path.join(img_dir, f)) if img is None: print(f❌ 读取失败: {f}) continue h, w img.shape[:2] if h 200 or w 200: # 过小图像易导致bbox失真 print(f⚠️ 尺寸异常: {f} - {w}x{h}) # 显示并等待按键肉眼检查压缩伪影、过曝/欠曝 cv2.imshow(Check, cv2.resize(img, (800,600))) cv2.waitKey(0) cv2.destroyAllWindows()希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价