基于YOLOv5的6类生活垃圾检测数据集标注实战指南

1次阅读
没有评论

共计 2856 个字符,预计需要花费 8 分钟才能阅读完成。

image.webp

背景痛点:为什么我们需要更好的标注数据集

在垃圾分类检测任务中,数据质量直接影响模型性能。现有的公开数据集普遍存在以下问题:

基于 YOLOv5 的 6 类生活垃圾检测数据集标注实战指南

  • 类别不平衡 :可回收物样本远多于有害垃圾,导致模型对少数类识别率低
  • 标注不一致 :不同标注人员对 ” 破碎垃圾 ” 是否算独立物体存在分歧
  • 边界模糊 :厨余垃圾常因粘连导致标注框包含背景(如塑料袋)

我们通过 YOLO 格式标注解决这些问题,其优势在于:

  1. 标准化归一化坐标,便于跨数据集训练
  2. 文本格式轻量,适合嵌入式设备部署
  3. 支持矩形框旋转(对倾斜垃圾箱场景重要)

工具对比:主流标注工具横评

LabelImg

  • 优点:
  • 本地运行无需联网
  • 快捷键操作流畅
  • 支持 YOLO/PascalVOC 格式导出

  • 缺点:

  • 无团队协作功能
  • 无法处理视频帧

CVAT

  • 优点:
  • 支持视频逐帧标注
  • 内置智能分割工具
  • 可分配标注任务给团队成员

  • 缺点:

  • 需要部署服务器
  • 学习曲线较陡

Roboflow

  • 优点:
  • 在线协同标注
  • 内置数据增强流水线
  • 支持自动标注建议

  • 缺点:

  • 免费版有导出次数限制
  • 需上传数据到云端

推荐方案 :小型团队选用 LabelImg+Git 版本控制,企业级项目用 CVAT

标注规范:六类垃圾标注细则

类别定义

class_names = [
    'recyclable',  # 可回收物(如易拉罐)'hazardous',   # 有害垃圾(如电池)'kitchen',     # 厨余垃圾(如菜叶)'other',       # 其他垃圾(如纸巾)'electronic',  # 电子废弃物(如手机)'textile'      # 纺织物(如旧衣服)]

关键规则

  1. 遮挡处理
  2. 可见部分 >50%:标完整物体
  3. 可见部分 <50%:不标注

  4. 多物体策略

  5. 粘连垃圾:按物理分隔标注多个框
  6. 套装物品(如盒装牛奶):外包装和内容物分开标注

  7. 边界判定

  8. 带液体的垃圾:标注到容器边缘
  9. 松散垃圾(如碎纸):整体视为一个对象

代码实现:从标注到校验全流程

格式转换脚本

import json
import os

def coco2yolo(json_path, output_dir):
    """将 COCO 格式转换为 YOLO 格式"""
    with open(json_path) as f:
        data = json.load(f)

    # 创建类别 ID 映射
    cat_id_map = {cat['id']: i for i, cat in enumerate(data['categories'])}

    for img in data['images']:
        img_id = img['id']
        img_w, img_h = img['width'], img['height']

        # 筛选当前图片的标注
        anns = [a for a in data['annotations'] if a['image_id'] == img_id]

        # 生成 YOLO 格式文本
        txt_content = []
        for ann in anns:
            x, y, w, h = ann['bbox']
            x_center = (x + w/2) / img_w
            y_center = (y + h/2) / img_h
            w_norm = w / img_w
            h_norm = h / img_h

            class_id = cat_id_map[ann['category_id']]
            txt_content.append(f"{class_id} {x_center:.6f} {y_center:.6f} {w_norm:.6f} {h_norm:.6f}")

        # 写入文件
        txt_path = os.path.join(output_dir, f"{img['file_name'].split('.')[0]}.txt")
        with open(txt_path, 'w') as f:
            f.write('\n'.join(txt_content))

质量校验方法

import cv2
import matplotlib.pyplot as plt

def visualize_annotations(img_path, txt_path):
    """可视化标注框检查错漏"""
    img = cv2.imread(img_path)
    h, w = img.shape[:2]

    with open(txt_path) as f:
        lines = f.readlines()

    for line in lines:
        class_id, xc, yc, bw, bh = map(float, line.strip().split())

        # 转换回像素坐标
        x1 = int((xc - bw/2) * w)
        y1 = int((yc - bh/2) * h)
        x2 = int((xc + bw/2) * w)
        y2 = int((yc + bh/2) * h)

        # 绘制矩形框
        color = (0, 255, 0) if class_id == 0 else (0, 0, 255)
        cv2.rectangle(img, (x1, y1), (x2, y2), color, 2)

    plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    plt.show()

数据分布分析

from collections import Counter
import seaborn as sns

def plot_class_distribution(annotations_dir):
    """绘制类别分布直方图"""
    class_counts = Counter()

    for txt_file in os.listdir(annotations_dir):
        with open(os.path.join(annotations_dir, txt_file)) as f:
            for line in f:
                class_id = int(line.split()[0])
                class_counts[class_id] += 1

    sns.barplot(x=list(class_counts.keys()),
        y=list(class_counts.values())
    )
    plt.xlabel('Class ID')
    plt.ylabel('Count')
    plt.title('Class Distribution')
    plt.show()

避坑指南:典型错误案例

案例 1:破碎物体标注

错误做法 :将打碎的玻璃瓶标注为多个小物体
正确做法 :视为一个整体标注,添加 ”broken” 属性标签

案例 2:透视变形处理

错误做法 :直接标注倾斜垃圾袋的视觉外轮廓
正确做法 :估计袋口平面后标注直立状态下的矩形

案例 3:阴影误标

错误做法 :将物体阴影包含在标注框内
正确做法 :仅标注实体部分,可通过 HSV 色彩空间分离

性能优化:数据增强策略

实验对比不同增强方法对 mAP 的影响:

  1. 基础增强 (翻转 + 色变):mAP@0.5=0.73
  2. Mosaic 增强 :提升小物体检测,mAP@0.5=0.81
  3. CutMix 增强 :改善类别不平衡,mAP@0.5=0.79

推荐组合策略:

# data_aug.yaml
train:
  mosaic: 0.8  # 80% 概率启用
  mixup: 0.2
  hsv_h: 0.015
  hsv_s: 0.7
  hsv_v: 0.4
  degrees: 10.0
  translate: 0.1

开放问题

如何处理垃圾分类中的细粒度子类(如 PET 塑料瓶 vs.PP 塑料盒)?可以考虑:
– 二级分类网络
– 多标签标注体系
– 材质识别辅助模块

期待读者在实践中探索更多解决方案。

正文完
 0
评论(没有评论)