正样本、负样本 与 ROC 、AUC之间的关系:
        正样本和负样本构成了分类 问题的基础,ROC 曲线和 AUC 是用于评估二分类模型性能的工具。ROC 曲线通过不同的阈值来评估模型的性能,而 AUC 是对整个 ROC 曲线性能的一个综合度量(AUC 是 ROC 曲线下方的面积),ROC、AUC、越大,模型性能越好,表示模型在分类问题中的能力越强。

ROC 曲线、真阳性率 (True Positive Rate, TPR)、假阳性率 (False Positive Rate, FPR)  )

        本文档针对目标检测任务(如电梯门缝、烟头检测)中负样本的采集、标注及数据准备提供详细说明,并附带一个批量生成空标签文件的 Python 脚本,帮助快速构建符合 YOLO 训练要求的负样本数据集。


1. 负样本的作用

正样本和负样本通常与二分类问题相关联

        正样本: 与真值对应的目标类别来说该样本为正样本。 (正样本是在二分类问题中我们要寻找的目标类 别)

        负样本: 与真值不对应的其他所有目标类别来说该样本为负样本。(负样本是不属于目标类别的类别)

例如:图片二分类任务(比如判断1张图片是否为猫)。

                如果样本对应的标签为1,则该样本为正样本(positive sample)。

                如果样本对应的标签为0,则该样本为负样本(negative sample)。

        负样本(即不包含任何待检测目标的图像)在目标检测中至关重要,它帮助模型学习“背景”的特征,有效减少误检(False Positive),提升模型的鲁棒性和精确率。


2. 负样本的采集策略

2.1 覆盖所有可能的背景场景

  • 不同电梯类型:内饰、照明、品牌等。

  • 不同时间/光照:白天、夜晚、逆光等。

  • 不同视角:摄像头安装高度、角度。

  • 不同状态:门开/关、有人/无人、有杂物等。

2.2 包含干扰物(难例负样本)

  • 对烟头:类似烟头的纸屑、瓜子壳、石子、反光点、污渍、硬币等。

  • 对电梯门缝:装饰条纹、划痕、地砖缝隙、光影线条等。

2.3 从实际运行视频中提取

  • 连续录制监控视频,截取不包含目标的帧。

  • 确保涵盖不同时段和场景。

2.4 利用公开数据集或网络图片

  • 选择与目标场景相近的室内图像作为补充。

2.5 数据增强生成负样本(辅助手段)

  • 裁剪正样本中的目标区域,保留背景。


3. 负样本的标注要求

对于负样本图像:

  • 不需要标注任何目标区域(即不画框)。

  • 但必须为每张负样本图像提供一个同名的空标签文件.txt,内容为空),以便 YOLO 训练框架正确读取。

为什么需要空标签文件?
大多数 YOLO 训练脚本会为每张图像查找对应的标签文件。若缺失,可能导致数据加载错误或跳过该图像。提供空标签文件可确保数据管道的一致性。


4. 批量生成空标签文件的 Python 脚本

以下脚本可递归遍历指定图像目录,为每张图像生成一个同名的空 .txt 文件(若文件不存在或为空则跳过,若已存在非空文件则警告并跳过)。

4.1 脚本代码

将以下代码保存为 generate_empty_labels.py

import os
import argparse
from pathlib import Path

# 支持的图像扩展名
IMAGE_EXTENSIONS = {'.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.webp'}

def create_empty_labels(image_dir="./train", labels_dir="./labels/train"):
    """
    为指定目录下的所有图像生成空标签文件(YOLO格式),并输出到 labels_dir。

    参数:
        image_dir: 图像所在的根目录(递归搜索),默认 "./train"
        labels_dir: 标签输出目录,默认 "./labels/train"
    """
    image_dir = Path(image_dir).resolve()
    labels_dir = Path(labels_dir).resolve()

    if not image_dir.exists():
        print(f"错误:图像目录 '{image_dir}' 不存在。")
        return

    # 创建标签根目录
    labels_dir.mkdir(parents=True, exist_ok=True)

    # 统计
    total_images = 0
    created = 0
    skipped_existing = 0
    warned_nonempty = 0

    for root, dirs, files in os.walk(image_dir):
        for file in files:
            ext = Path(file).suffix.lower()
            if ext not in IMAGE_EXTENSIONS:
                continue

            total_images += 1
            img_path = Path(root) / file
            # 计算图像相对于 image_dir 的路径,用于在 labels_dir 下保持相同子目录结构
            rel_path = img_path.relative_to(image_dir)

            # 标签文件路径:labels_dir + 相对路径(仅替换扩展名为 .txt)
            label_path = labels_dir / rel_path.with_suffix('.txt')
            label_path.parent.mkdir(parents=True, exist_ok=True)

            # 处理标签文件
            if label_path.exists():
                if label_path.stat().st_size == 0:
                    # 已存在空文件,跳过
                    skipped_existing += 1
                else:
                    # 已存在非空文件,警告并跳过
                    print(f"警告:标签文件已存在且非空,跳过:{label_path}")
                    warned_nonempty += 1
            else:
                # 创建空文件
                label_path.touch()
                created += 1
                print(f"创建:{label_path}")

    print("\n处理完成。")
    print(f"找到图像文件:{total_images} 张")
    print(f"新创建标签:{created} 个")
    print(f"跳过已存在的空标签:{skipped_existing} 个")
    print(f"警告(已存在非空标签):{warned_nonempty} 个")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="为负样本图像生成YOLO格式的空标签文件。")
    parser.add_argument("--image_dir", default="./train", help="图像目录(默认 ./train)")
    parser.add_argument("--labels_dir", default="./labels/train", help="标签输出目录(默认 ./labels/train)")
    args = parser.parse_args()

    create_empty_labels(args.image_dir, args.labels_dir)

4.2 使用方法

  • 直接运行(使用默认路径)
    假设当前目录下存在 train 文件夹(内含负样本图像),运行:

    python generate_empty_labels.py

    脚本将在 ./labels/train 下生成对应的空 .txt 文件,并保持原 train 内的子目录结构。

  • 自定义路径
    例如为验证集生成空标签:

    python generate_empty_labels.py --image_dir ./val --labels_dir ./labels/val

4.3 脚本说明

  • 递归扫描 image_dir 下的所有图像(支持常见格式)。

  • 在 labels_dir 中创建与图像相对路径一致的目录结构。

  • 若标签文件已存在且为空,则跳过(避免重复创建)。

  • 若标签文件已存在且非空,则打印警告并跳过(防止覆盖已有的正样本标注)。

  • 自动创建缺失的父目录。


5. 标注工具与操作系统选择

5.1 常用标注工具

  • LabelImg:跨平台(Windows/Linux/macOS),轻量级,适合单人标注。

  • CVAT:基于 Web,适合团队协作,与操作系统无关。

  • Label StudioMakeSense.ai 等。

5.2 操作系统建议

  • Ubuntu:如果后续训练也在 Linux 环境下进行,建议直接在 Ubuntu 下标注,避免数据传输。

  • Windows:对新手更友好,标注后可通过共享或云存储将数据传给训练服务器。

  • 团队协作:推荐使用 Web 工具(如 CVAT),统一访问,不受本地系统限制。


6. 注意事项

  • 标签一致性:所有负样本的标签文件必须为空(0 字节),且与图像文件名一一对应。

  • 数据平衡:负样本数量通常与正样本比例在 1:1 到 3:1 之间,具体可通过实验调整。

  • 难例挖掘:训练初期模型误检的图像可作为“难例负样本”加入训练集,迭代优化。

  • 版本管理:建议对数据集进行版本控制(如 DVC、Git LFS),便于回溯和协作。


7. 快速开始

  1. 将所有负样本图像放入 ./train 文件夹(可含子目录)。

  2. 运行脚本生成空标签:

    python generate_empty_labels.py
  3. 确认 ./labels/train 下已生成对应的 .txt 文件。

  4. 在 YOLO 训练配置中,将 train 图像路径和 labels/train 标签路径正确设置即可。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐