
简介本资源为可口可乐与百事可乐标志目标检测数据集面向从事目标检测算法练习、品牌识别或零售场景分析的学生与开发者可用于训练和验证两类别检测模型。数据集共2223张jpg图片每张均配有对应的VOC格式xml标注与YOLO格式txt标注标注类别为CocaCola和Pepsi其中CocaCola框数2268、Pepsi框数2398总框数4666采用labelImg工具按矩形框规则完成标注。压缩包内文件总数约2000个以xml标注文件为主另含说明文件整体大小120.84MB目录结构简洁便于直接接入常见检测框架。目前已有347人学习下载适合需要快速获取双类别标注数据、验证模型训练流程或进行迁移学习实验的读者参考使用。1. 可口可乐与百事可乐标志检测2220 张双标签数据集到底能做什么快消品货架审核、自动售货柜库存盘点、广告植入统计这些场景里最常被问到的一个问题就是画面里到底有没有可口可乐或百事可乐的标志在哪个位置。要回答这个问题绕不开目标检测数据集。手上这份「可口可乐与百事可乐标志检测数据集2220张2个标签VOCYOLO格式」就是为这类任务准备的2220 张图像2 个类别标签同时提供 VOC 与 YOLO 两套标注格式。它解决的不是「识别饮料瓶」这种粗粒度问题而是把品牌标志当作独立目标框出来属于典型的细粒度小目标检测。适合谁用想跑通 yolov8目标检测数据集处理流程的新手想验证品牌 logo 检测方案的算法工程师以及需要快速搭一个货架识别原型的开发者。下面按「先立住原理、再动手复现、最后讲坑」的顺序拆开讲。2. 双标签 VOCYOLO 数据集的结构与选型逻辑2.1 2220 张、2 个标签意味着什么先把数字翻译成工程语言。2220 张图像、2 个类别平均每类样本量在千级属于中小规模数据集。这个量级决定了它不适合从零训练一个大 backbone而是更适合迁移学习加载 yolo预训练模型下载得到的权重冻结主干、微调检测头。2 个标签的好处是类别极度聚焦模型不需要在几十个类之间分配容量收敛快、混淆矩阵干净很适合用来验证「小目标 相似外观」这个难点。需要提前有心理预期的是类别不平衡。可口可乐和百事可乐在真实图像里的出现频次往往不对等如果某一类只有几百张训练时该类召回会明显偏低。动手前先统计每类实例数别等训练完看混淆矩阵才发现某一类几乎没学到。2.2 VOC 与 YOLO 两套格式的差异与转换VOC 格式用 XML 描述每个目标一个object节点坐标是绝对像素值xmin/ymin/xmax/ymaxYOLO 格式用 txt每行class cx cy w h坐标是归一化到 0~1 的相对值。两者不是简单缩放关系还涉及类别名到类别索引的映射。常见做法是保留一份类别映射表转换时严格按表来避免索引错位。维度VOCYOLO文件形式每图一个 XML每图一个 txt坐标绝对像素 xmin,ymin,xmax,ymax归一化 cx,cy,w,h类别字符串 name整数索引目录Annotations / JPEGImagesimages / labels提示转换前先备份原始标注。VOC 转 YOLO 是不可逆的有损操作浮点归一化会丢精度一旦覆盖原始 XML后悔药没有。2.3 目录组织与最小校验脚本拿到数据集先别急着训练跑一遍完整性校验确认每张图都有对应标注、坐标不越界、类别名统一。下面这段脚本做三件事统计图像与标注配对情况、检查 VOC 坐标是否越界、输出每类实例数。import os, glob import xml.etree.ElementTree as ET from collections import Counter IMG_DIR JPEGImages ANN_DIR Annotations imgs {os.path.splitext(os.path.basename(p))[0] for p in glob.glob(f{IMG_DIR}/*.jpg)} xmls {os.path.splitext(os.path.basename(p))[0] for p in glob.glob(f{ANN_DIR}/*.xml)} # 1. 配对检查找出有图无标注、有标注无图 print(有图无标注:, imgs - xmls) print(有标注无图:, xmls - imgs) cls_counter Counter() bad_box 0 for x in glob.glob(f{ANN_DIR}/*.xml): root ET.parse(x).getroot() size root.find(size) W, H int(size.find(width).text), int(size.find(height).text) for obj in root.findall(object): cls_counter[obj.find(name).text] 1 b obj.find(bndbox) x1, y1 int(b.find(xmin).text), int(b.find(ymin).text) x2, y2 int(b.find(xmax).text), int(b.find(ymax).text) # 2. 越界检查坐标必须落在图像范围内且左上小于右下 if x1 0 or y1 0 or x2 W or y2 H or x1 x2 or y1 y2: bad_box 1 print(每类实例数:, dict(cls_counter)) print(越界框数量:, bad_box)逻辑说明先用集合差集找出配对缺失这是数据集最常见的低级错误再遍历 XML 检查坐标合法性。参数上IMG_DIR、ANN_DIR按实际目录名改bad_box大于 0 就要人工回看通常是标注时框拖出了边界。类别名如果出现「coca」「Coca」「cocacola」这类不一致写法必须在转换前统一否则会被当成多个类。3. 从 VOC 转 YOLO 到跑通 yolov8 训练3.1 VOC 转 YOLO 的转换脚本与四个边界坑转换脚本本身不长坑都在边界上。下面这段把 VOC 的 XML 批量转成 YOLO 的 txt同时生成classes.txt。import os, glob import xml.etree.ElementTree as ET CLASSES [coca_cola, pepsi] # 顺序即索引务必与后续训练配置一致 cls2id {c: i for i, c in enumerate(CLASSES)} ANN_DIR Annotations OUT_DIR labels os.makedirs(OUT_DIR, exist_okTrue) for x in glob.glob(f{ANN_DIR}/*.xml): root ET.parse(x).getroot() size root.find(size) W, H int(size.find(width).text), int(size.find(height).text) lines [] for obj in root.findall(object): name obj.find(name).text.strip() if name not in cls2id: continue # 未登记类别直接跳过避免索引错位 b obj.find(bndbox) x1, y1 float(b.find(xmin).text), float(b.find(ymin).text) x2, y2 float(b.find(xmax).text), float(b.find(ymax).text) # 裁剪到图像范围内防止归一化后出现负值或大于1 x1, y1 max(0, x1), max(0, y1) x2, y2 min(W, x2), min(H, y2) cx, cy (x1 x2) / 2 / W, (y1 y2) / 2 / H w, h (x2 - x1) / W, (y2 - y1) / H lines.append(f{cls2id[name]} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) stem os.path.splitext(os.path.basename(x))[0] with open(f{OUT_DIR}/{stem}.txt, w) as f: f.write(\n.join(lines))四个边界坑一是类别索引顺序CLASSES列表顺序必须和训练时的data.yaml完全一致错一位整个训练白跑二是坐标裁剪标注框偶尔会超出图像边界不裁剪归一化后会出现负值YOLO 会直接报错或静默丢弃三是空标注文件某张图没有目标时也要生成空 txt否则 YOLO 会把它当负样本处理逻辑不一致四是浮点精度保留 6 位小数足够截断太狠会让小目标框偏移。3.2 data.yaml 与目录结构YOLO 训练靠data.yaml找数据路径写错是最常见的翻车点。推荐结构如下dataset/ images/ train/ val/ labels/ train/ val/ data.yamlpath: ./dataset train: images/train val: images/val nc: 2 names: 0: coca_cola 1: pepsinc是类别数必须等于names的条目数names的索引要和转换脚本里的cls2id对齐。path用相对路径时训练命令要在dataset的上一级目录执行否则会找不到文件。3.3 用 yolov8 跑通第一次训练环境配置建议用 conda 隔离避免和系统里的其他 torch 版本打架。conda create -n logo python3.10 -y conda activate logo pip install ultralytics训练命令yolo detect train \ datadataset/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ patience20 \ namecoke_pepsi参数说明modelyolov8n.pt用 nano 版预训练权重2220 张的量级足够想提精度再换yolov8s.ptimgsz640是标准输入标志属于中小目标不建议降到 416会丢细节batch16按显存调V100 上可以拉到 32 甚至 64patience20表示 20 轮无提升就早停省时间。训练中重点看mAP50和每类的P/R如果某一类召回长期为 0回去查类别索引和该类样本数。3.4 推理与结果验证训练完用验证集跑一遍确认模型真的学到了东西而不是只记住了背景。yolo detect predict \ modelruns/detect/coke_pepsi/weights/best.pt \ sourcedataset/images/val \ conf0.25 \ saveTrueconf0.25是置信度阈值标志检测建议先设低一点看召回再根据误检情况往上调。验证时别只看 mAP 数字把预测图翻一遍重点看两类标志是否互相误判——这是本数据集最典型的失败模式两个品牌配色和字体风格接近模型容易混淆。4. 训练中的避坑与排查清单4.1 混淆矩阵总合不唯一现象跑完训练看混淆矩阵行和列加起来对不上或者某一类的总数和验证集实际实例数不一致。原因通常是验证集里存在被裁掉边界的框或者转换时坐标越界被丢弃导致实际参与评估的实例数少于标注数。解决回到 2.3 的校验脚本把越界框全部修掉再重新转换确保验证集标注和图像严格对应。4.2 训练中 BN 崩溃现象loss 突然变成 NaN日志里出现 batch norm 相关的异常。原因多半是某个 batch 里有效目标太少或者学习率过高导致梯度爆炸。解决先把batch调大让每个 batch 有足够样本再把初始学习率降到0.001甚至更低同时开启ampFalse排除混合精度干扰定位是不是精度问题。4.3 小目标召回上不去现象mAP 看着还行但小尺寸标志经常漏检。原因标志在整图里占比小下采样后特征几乎消失。解决把imgsz提到 800 或 960或者开启多尺度训练scale0.5让模型见到不同尺寸的目标数据层面可以对小目标图像做裁剪增强人为放大标志占比。4.4 两类互相误判现象可口可乐被识别成百事可乐反之亦然。原因两个品牌视觉特征接近且训练样本里某一类偏少。解决检查类别是否真的不平衡必要时对少样本类做过采样推理时适当提高conf阈值宁可漏检也别错判因为品牌错判在业务上比漏检更严重。4.5 验证集指标虚高现象验证集 mAP 很高换一批真实货架图就崩。原因验证集和训练集来自同一批拍摄条件分布太接近模型过拟合了场景而不是目标。解决手动留出一部分不同光照、不同角度的图做独立测试集别用随机划分的验证集当最终结论。5. 把这份数据集用出上限的几个技巧想让 2220 张发挥更大价值关键在数据增强和评估策略。增强上颜色抖动要慎用——两个品牌的标志颜色本身就是判别特征HSV 扰动过大会把红色调成橙色反而制造噪声更安全的是随机缩放、平移和轻微旋转模拟货架拍摄的角度变化。 mosaic 增强对 YOLO 很有效但小目标场景下四图拼接会让标志更小建议把mosaic概率从默认 1.0 降到 0.5。评估上别只信 mAP。品牌检测业务里误检和漏检的代价不对称我会单独统计两个指标一是每类在conf0.5下的精确率二是把conf从 0.1 扫到 0.9 画 P-R 曲线找到业务能接受的平衡点。如果要做部署导出 ONNX 后用onnxruntime跑一遍确认推理结果和 PyTorch 一致这一步能提前暴露算子不支持的问题。还有一个容易被忽略的点把类别名和索引固化到配置文件里别散落在脚本各处。我吃过这个亏——转换脚本改了类别顺序训练配置忘了同步跑了一晚上发现两类标签整体错位只能重来。现在我的习惯是类别映射只维护一份classes.txt转换、训练、推理全部读它。希望帮到你。本文还有配套的精品资源点击获取