香烟品牌识别和规格识别设计思路

简介: 基于YOLOv8实现香烟品牌与规格(条装/单盒装)识别,采用“品牌+规格”组合为60类的复合类别方案,结合充足标注数据(每类300-500张)、数据增强与反例优化,进行端到端联合训练,提升模型在复杂场景下的检测与分类精度。


识别香烟目标检测



使用 YOLOv8 实现香烟品牌和规格(条装/单盒装)识别是一个典型的 多标签目标检测任务。下面我将从整体思路、数据准备、标注方法、训练策略等方面系统地为你梳理整个流程。

一、总体思路

你希望实现的目标是:

  • 在图像中检测出香烟包装;
  • 同时识别其 品牌(如中华、玉溪、黄鹤楼等)规格(条装 / 单盒装)

这可以看作一个 多分类属性联合检测任务,即每个检测框输出两个标签信息:brandpackaging_type

YOLOv8 支持多类别检测,但默认只支持单一类别标签。因此我们需要通过以下方式扩展:

✅ 解决方案:将“品牌+规格”组合成复合类别(例如:“中华_条装”、“中华_单盒装”),或者使用 多输出头 的方式分别预测品牌和规格。

我们推荐采用 复合类别 + YOLOv8 分类能力增强 的方式,兼顾精度与工程实现简便性。

二、训练模型的整体过程

1. 数据准备阶段

(1)需要多少张标注图片?

全屏复制

类别数 建议每类样本数量
约30种品牌 × 2种规格 = 最多60个复合类别 每类建议 50~100张带标注的图片

✅ 总体建议:

  • 总图像数量 ≥ 3000 张(理想为 4000~6000)
  • 每张图可包含多个香烟实例(提高效率)
  • 图像来源应多样化:不同角度、光照、遮挡、背景复杂度、清晰度等
  • 包括真实场景拍摄(超市货架、便利店柜台、桌面摆放等)

🔍 小贴士:

  • 若某些品牌数据较少,可通过数据增强(旋转、模糊、亮度调整、仿射变换)补充。
  • 可加入网络爬虫获取电商图片(注意版权问题,仅用于训练且脱敏处理)。

2. 是否需要设置反例(Negative Examples)?

不需要专门标注“反例”图像(空标签图像)

原因如下:

  • YOLO 训练机制本身对负样本(无物体区域)已有处理(通过置信度损失自动学习背景);
  • 加入少量不含香烟的图像有助于防止误检,但不宜过多;
  • ✅ 建议:在训练集中混入 约5%~10%的无香烟图像(即标签为空),帮助模型更好地区分背景。

👉 这些图像无需标注边界框,对应 .txt 标签文件为空即可。

三、标注策略:如何同时标注品牌和规格?

方法一:【推荐】合并为复合类别(Compound Class)

将品牌和规格组合成一个新的类别名称:

text

类别列表示例:
0: 中华_条装
1: 中华_单盒装
2: 玉溪_条装
3: 玉溪_单盒装
...
58: 黄鹤楼_条装
59: 黄鹤楼_单盒装

✅ 优点:

  • 兼容标准 YOLOv8 训练流程;
  • 不需修改模型结构;
  • 易于部署和推理。

⚠️ 缺点:

  • 如果品牌或规格变化频繁,类别数增长快;
  • 推理后需解析字符串提取品牌和规格。

📌 示例标注文件(.txt)格式:


0 0.5 0.6 0.2 0.3    # 表示类别0(中华_条装),中心x=0.5, y=0.6, 宽=0.2, 高=0.3
2 0.7 0.4 0.15 0.25  # 玉溪_条装

方法二:双标签输出(高级用法,需自定义模型)

修改 YOLOv8 的 Head,使其输出两个独立的分类结果:

  • 一个分支预测品牌(30类)
  • 一个分支预测规格(2类:条装/单盒装)

✅ 优点:

  • 更灵活,便于后续扩展;
  • 减少类别爆炸(从最多60类 → 30+2=32类);
  • 可共享特征提取器,提升泛化能力。

⚠️ 缺点:

  • 需要修改模型结构(如添加额外分类头);
  • 训练代码更复杂(通常基于 Ultralytics 源码开发);
  • 推理时需同步解码两个输出。

🔧 实现路径(进阶):

  • 使用 Ultralytics 的 Python API 自定义 DetectionModel
  • 修改 head 输出结构;
  • 修改损失函数,支持多任务学习。

👉 初期建议使用 方法一(复合类别),后期再考虑升级为方法二。


四、训练策略:一起训练 or 独立训练?

全屏复制

方案 是否推荐 说明
联合训练(一起训练) ✅ 强烈推荐 使用复合类别,一次性检测并识别品牌+规格,端到端训练,效果最好
分步训练(先检测位置,再分类) ⚠️ 不推荐 两阶段流程复杂,误差累积,速度慢
独立训练品牌和规格模型 ❌ 不推荐 规格依赖品牌上下文,分开训练难以保证一致性

🎯 结论:统一进行联合训练(end-to-end)是最优选择


五、完整训练流程步骤

Step 1: 数据收集

  • 收集香烟实物照片(实拍为主,辅以电商平台图);
  • 覆盖各种品牌、包装风格、角度、光照条件;
  • 注意避免侵权图片(可自行拍摄或使用授权数据集);

Step 2: 数据标注

  • 工具推荐:LabelImg、CVAT、Roboflow、MakeSense.ai;
  • 每张图标注所有可见香烟对象;
  • 使用复合类别命名规则(品牌_规格);
  • 导出为 YOLO 格式(.txt + classes.txt);

Step 3: 数据划分

  • 划分训练集(70%)、验证集(20%)、测试集(10%);
  • 确保各类别分布均衡(尤其小众品牌不要集中在某一子集);

Step 4: 数据增强(可选)

  • 使用 Albumentations 或 YOLO 内置增强:
  • 随机翻转、色彩抖动、缩放、裁剪、Mosaic、MixUp;
  • 提高模型鲁棒性;

Step 5: 模型选择与训练


# 使用 ultralytics 库
pip install ultralytics


# 开始训练(假设共60个复合类别)
yolo detect train data=smoke_config.yaml model=yolov8m.pt epochs=100 imgsz=640 batch=16


smoke_config.yaml 示例:


train: ./datasets/train/images
val: ./datasets/val/images
nc: 60
names:
  - "中华_条装"
  - "中华_单盒装"
  - "玉溪_条装"
  - ...


Step 6: 模型评估与调优

  • 查看 mAP@0.5、Precision、Recall;
  • 分析混淆矩阵,查看易混淆品牌(如颜色相近的软包 vs 硬包);
  • 对低召回率类别补充数据或增强;
  • 可尝试更大的模型(yolov8l / yolov8x)提升精度;

Step 7: 推理与后处理


from ultralytics import YOLO
model = YOLO("runs/detect/train/weights/best.pt")
results = model("test.jpg")
for r in results:
    boxes = r.boxes
    for box in boxes:
        cls_id = int(box.cls)
        label = model.names[cls_id]  # 如 "中华_条装"
        brand, packaging = label.split("_")  # 解析出品牌和规格
        print(f"检测到:{brand}, {packaging}")


六、优化建议

  1. 关注细节特征区分
  • 条装 vs 单盒装:通常条装更大、有透明膜包裹、排列整齐;
  • 品牌差异:主色调、Logo、字体、防伪标识等;
  1. 增加困难样本
  • 部分遮挡、反光、倾斜视角;
  • 相似品牌对比训练(如芙蓉王系列);
  1. 部署时考虑实时性
  • 若需边缘设备运行(如 Jetson),可用 yolov8s 或量化模型(ONNX/TensorRT);
  1. 持续迭代更新
  • 新增品牌时,增量训练(fine-tune)已有模型;

七、总结

全屏复制

项目 建议方案
数据量 每类50~100张,总数≥3000张
是否加反例 可加入5%~10%无香烟图像
标注方式 使用“品牌_规格”作为复合类别
模型训练 联合训练,不拆分任务
模型选择 YOLOv8s/m(平衡速度与精度)
后续扩展 可升级为多头输出架构




空间结构理解-识别香烟的摆放




群体行为理解(Group Behavior Detection),即识别“盒装香烟”的摆放是 U型 还是 T型

这类问题属于 场景结构理解(Scene Layout Understanding)空间模式识别(Spatial Pattern Recognition),不依赖单个物体,而是分析多个同类物体之间的 空间分布关系


目标

给定一组 YOLO 检测出的“单盒装香烟”边界框(bounding boxes),

自动判断它们是否组成一个 U型排列T型排列


一、核心思路(三步走)

我们将整个过程分为以下三个阶段:

全屏复制

阶段 任务 方法
1️⃣ 分组 按品牌和位置聚类 过滤条装 + 按品牌分组 + 空间聚类
2️⃣ 特征提取 提取几何结构特征 中心点分布、方向性、密度、空缺区域
3️⃣ 形状分类 判断是否为 U型 / T型 使用规则引擎 或 轻量级分类器



二、详细实现步骤

Step 1:预处理 —— 筛选目标检测框

只保留你要分析的“单盒装香烟”,并提取其位置信息。

python

# 假设 results 是 YOLOv8 的输出
target_boxes = []
for box in results[0].boxes:
    cls_id = int(box.cls)
    label = model.names[cls_id]
    
    # 只保留 单盒装
    if "单盒装" in label:
        x1, y1, x2, y2 = box.xyxy[0].cpu().numpy()
        cx = (x1 + x2) / 2  # 中心x
        cy = (y1 + y2) / 2  # 中心y
        w = x2 - x1
        h = y2 - y1
        
        brand = label.split("_")[0]
        target_boxes.append({
            "center": (cx, cy),
            "bbox": (x1, y1, x2, y2),
            "size": (w, h),
            "brand": brand
        })


Step 2:按品牌 + 空间位置分组

同一个品牌的香烟可能在柜台不同区域有多组陈列(比如左边一组U型,右边一组T型),所以需要先分组。

方法:DBSCAN 聚类(推荐)

python

from sklearn.cluster import DBSCAN
import numpy as np
def cluster_by_position(boxes, eps=80):
    points = np.array([b["center"] for b in boxes])
    if len(points) == 0:
        return []
    clustering = DBSCAN(eps=eps, min_samples=3).fit(points)
    labels = clustering.labels_
    
    clusters = []
    for cluster_id in set(labels):
        if cluster_id == -1:  # 噪声点
            continue
        cluster_boxes = [boxes[i] for i, lbl in enumerate(labels) if lbl == cluster_id]
        clusters.append(cluster_boxes)
    return clusters


eps 是最大距离阈值(单位像素),可根据图像分辨率调整(如图像宽1920,则80px ≈ 4cm)


Step 3:对每组进行“U型 / T型”判断

我们现在有一组“同品牌、邻近摆放”的香烟中心点,接下来判断它们的排列形状。


🔍 三、U型 与 T型 的几何特征分析

全屏复制

类型 几何特征
U型 三个边有排列,中间空缺(像字母U),两端对称,底部连通
T型 横向一排 + 垂直向下延伸一列,交点居中
直线型 所有点基本在一条直线上
散乱型 无明显规律

我们可以基于以下特征来区分:

特征1:点云主成分分析(PCA)

判断整体方向性和延展性。

python

def get_orientation_score(points):
    points = np.array(points)
    mean = np.mean(points, axis=0)
    centered = points - mean
    cov_matrix = np.cov(centered.T)
    eigenvals, eigenvecs = np.linalg.eigh(cov_matrix)
    # 主轴方向
    major_axis = eigenvecs[:, np.argmax(eigenvals)]
    aspect_ratio = eigenvals[1] / (eigenvals[0] + 1e-6)
    return aspect_ratio, major_axis


  • 高长宽比 → 可能是线性或U/T的主干


特征2:密度分布 + 空洞检测(U型关键)

U型的特点是:中间有空缺。

方法:网格化统计 + 找空洞

python

def has_hole_in_middle(points, grid_size=5):
    points = np.array(points)
    # 归一化到局部坐标
    min_x, max_x = points[:,0].min(), points[:,0].max()
    min_y, max_y = points[:,1].min(), points[:,1].max()
    
    if max_x - min_x < 1 or max_y - min_y < 1:
        return False
    
    # 划分网格
    x_bins = np.linspace(min_x, max_x, grid_size)
    y_bins = np.linspace(min_y, max_y, grid_size)
    H, _, _ = np.histogram2d(points[:,0], points[:,1], bins=[x_bins, y_bins])
    
    # 检查中心区域是否有空
    center_region = H[1:-1, 1:-1]  # 去掉边缘
    hole_ratio = np.sum(center_region == 0) / center_region.size
    
    return hole_ratio > 0.5  # 中心一半以上为空


U型通常满足:有主轴 + 中间空洞



特征3:T型 —— 分支结构检测

T型 = 一行横排 + 一列竖排,且垂直相交于中点。

方法:投影分析(Projection Profile)

python

def is_t_shape(points, tolerance=0.3):
    points = np.array(points)
    
    # X轴投影(垂直方向有多少点)
    x_proj = np.histogram(points[:,0], bins=10)[0] > 0
    y_proj = np.histogram(points[:,1], bins=10)[0] > 0
    # 主轴判断
    dx = np.std(points[:,0])
    dy = np.std(points[:,1])
    is_horizontal_main = dx > dy
    # 找最长线(主干)
    if is_horizontal_main:
        main_dir = points[:,0]
        cross_dir = points[:,1]
    else:
        main_dir = points[:,1]
        cross_dir = points[:,0]
    # 主干上点密集,分支上也有集中
    main_hist, _ = np.histogram(main_dir, bins=10)
    cross_hist, _ = np.histogram(cross_dir, bins=10)
    # 主干连续性强
    consecutive_main = np.sum(np.diff(main_hist > 0) == 1) <= 2  # 最多两次断开
    # 分支在中间有一个高峰
    mid_idx = len(cross_hist) // 2
    peak_in_center = cross_hist[mid_idx-1:mid_idx+2].max() > 0 and \
                     np.argmax(cross_hist) in [mid_idx-1, mid_idx, mid_idx+1]
    return consecutive_main and peak_in_center


Step 4:综合判断逻辑(规则引擎)

python

def classify_arrangement(cluster_boxes):
    points = np.array([b["center"] for b in cluster_boxes])
    n = len(points)
    
    if n < 4:
        return "散乱型"  # 数量太少
    
    # 特征提取
    aspect_ratio, _ = get_orientation_score(points)
    has_hole = has_hole_in_middle(points)
    is_t = is_t_shape(points)
    if aspect_ratio < 0.4:
        return "密集堆叠"  # 几乎是方形分布
    if has_hole and aspect_ratio > 0.6:
        return "U型"
    elif is_t:
        return "T型"
    elif aspect_ratio > 0.8:
        return "直线型"
    else:
        return "散乱型"



四、最终输出示例

python

results = model("counter.jpg")
target_boxes = [b for b in parse_boxes(results) if "单盒装" in b["label"]]
clusters = cluster_by_position(target_boxes)
arrangements = []
for cluster in clusters:
    shape = classify_arrangement(cluster)
    brand = cluster[0]["brand"]  # 同一组品牌一致
    
    # 计算包围整个陈列区域的bbox
    xs = [b["bbox"][0] for b in cluster] + [b["bbox"][2] for b in cluster]
    ys = [b["bbox"][1] for b in cluster] + [b["bbox"][3] for b in cluster]
    area_bbox = [min(xs), min(ys), max(xs), max(ys)]
    
    arrangements.append({
        "brand": brand,
        "count": len(cluster),
        "arrangement": shape,
        "bbox": area_bbox
    })
# 输出
import json
print(json.dumps(arrangements, indent=2, ensure_ascii=False))


五、进阶优化方向(可选)

全屏复制

方法 说明
用Hough Line检测辅助 检测是否存在多条平行线或垂直交叉线
使用GNN(图神经网络)建模关系 把每个盒子当节点,空间邻近当边,学习拓扑结构
训练轻量分类器(SVM/MLP) 提取特征后用带标签数据训练分类模型
引入深度信息(RGB-D相机) 区分前后层,避免重叠误判
模板匹配 + 形变模型 预定义U/T型模板,做弹性匹配



总结:U/T型识别完整流程


image.png


附加建议

  • 数据标注时可手动标记“U/T型区域”,用于后期验证算法准确性;
  • 保存典型样本图像 + 聚类结果,用于调试和演示;
  • 可视化工具推荐:用 OpenCV 画出聚类结果、主轴方向、网格密度图;


如果你希望我提供:

  • 完整 Python 可运行代码;
  • OpenCV 可视化示例;
  • 使用 ONNX 部署 + 实时视频流处理;
  • Web API 接口封装;

欢迎继续提问,我可以一步步帮你实现!




相关文章
|
传感器 数据采集 物联网
MQTT 的 QoS 等级:QoS 0、QoS 1、QoS 2
MQTT 的 QoS 等级:QoS 0、QoS 1、QoS 2
5382 0
|
5月前
|
SQL Java 数据库
2025 年 Java 从零基础小白到编程高手的详细学习路线攻略
2025年Java学习路线涵盖基础语法、面向对象、数据库、JavaWeb、Spring全家桶、分布式、云原生与高并发技术,结合实战项目与源码分析,助力零基础学员系统掌握Java开发技能,从入门到精通,全面提升竞争力,顺利进阶编程高手。
1021 1
|
5月前
|
SQL 前端开发 关系型数据库
如何开发一套研发项目管理系统?(附架构图+流程图+代码参考)
研发项目管理系统助力企业实现需求、缺陷与变更的全流程管理,支持看板可视化、数据化决策与成本优化。系统以MVP模式快速上线,核心功能包括需求看板、缺陷闭环、自动日报及关键指标分析,助力中小企业提升交付效率与协作质量。
|
5月前
|
消息中间件 运维 监控
爆款游戏背后:尚娱如何借助阿里云 Kafka Serverless 轻松驾驭“潮汐流量”?
阿里云 Kafka 不仅为尚娱提供了高可靠、低延迟的消息通道,更通过 Serverless 弹性架构实现了资源利用率和成本效益的双重优化,助力尚娱在快速迭代的游戏市场中实现敏捷运营、稳定交付与可持续增长。
280 59
|
5月前
|
数据采集 机器学习/深度学习 人工智能
YOLOv11浅浅解析:架构创新
YOLOv11是YOLO系列最新升级版,通过C3k2模块、SPPF优化和解耦检测头等创新,显著提升检测精度与速度,mAP提高2-5%,推理更快,支持多平台部署,适用于工业、安防、自动驾驶等场景。
|
5月前
|
机器学习/深度学习 人工智能 自然语言处理
Step-Audio2 声音克隆 详细介绍
Step-Audio2是StepFun于2024年推出的中文语音克隆大模型,支持“一句话克隆+情感可控+实时流式”一体化生成,参数总量300M,首包延迟低至120ms,MOS达4.4+,采用Apache-2.0协议开源,适配商业应用,是当前中文TTS领域开源落地门槛最低的方案之一。
|
5月前
|
前端开发 API 定位技术
如何开发车辆管理系统中的用车申请板块(附架构图+流程图+代码参考)
本文详细解析了如何将传统纸质车辆管理流程数字化,涵盖业务规则、审批流、调度决策及数据留痕等核心环节。内容包括用车申请模块的价值定位、系统架构设计、数据模型构建、前端表单实现及后端开发技巧,助力企业打造可落地、易扩展的车辆管理系统。
|
5月前
|
人工智能 Java 数据库
Spring AI
Spring AI 为 Java 生态注入智能,提供统一抽象接口,简化大模型集成,助力开发者高效构建 AI 应用,推动企业智能化转型。
987 147
|
7月前
|
SQL 人工智能 数据可视化
开源AI BI可视化工具-WrenAI
Wren AI 是一款开源的 SQL AI 代理,支持数据、产品及业务团队通过聊天、直观界面和与 Excel、Google Sheets 的集成获取洞察。它结合大型语言模型(LLM)与检索增强生成(RAG)技术,助力用户高效处理复杂数据分析任务。