YOLOv8数据集标签统计:用Python脚本一键分析各类别数量分布(附完整代码)
YOLOv8数据集标签统计用Python脚本一键分析各类别数量分布附完整代码在目标检测项目中数据质量往往比模型架构更能决定最终效果。想象一下你花费两周标注了5000张图片训练时却发现某个关键类别只有几十个样本——这种数据陷阱会直接导致模型在该类别上的识别率惨不忍睹。本文将手把手教你用Python脚本快速诊断数据集健康状态避免因类别不均衡导致的训练翻车事故。1. 为什么需要标签统计分析工具目标检测数据集的标注文件就像医院的体检报告单而我们的脚本就是解读这些数据的诊断仪器。以YOLOv8为例每个标注的.txt文件都遵循特定格式class_id x_center y_center width height当处理包含数十个类别、数万张图像的数据集时人工检查每个文件的类别分布几乎不可能。这就是自动化统计分析工具的价值所在——它能快速生成以下关键指标各类别样本总量识别长尾分布中的弱势群体各子集训练/验证/测试分布确保数据划分的均衡性单图标注密度发现过度拥挤或过于稀疏的图像最近在为某工业缺陷检测项目做咨询时就遇到一个典型案例客户抱怨模型总是漏检划痕缺陷分析发现其20000张训练图中只有83张包含该类别。这种隐形的数据问题正是我们需要用工具提前排查的。2. 实战代码解析下面这个增强版统计脚本不仅能计数还会生成可视化报告。建议在项目根目录创建dataset_analyzer.py文件import os import matplotlib.pyplot as plt from collections import defaultdict def analyze_yolo_labels(label_root, class_namesNone): 增强版YOLO标签分析工具 参数: label_root: labels文件夹路径 class_names: 可选类别名称列表 stats { total: defaultdict(int), per_set: {train: defaultdict(int), valid: defaultdict(int), test: defaultdict(int)}, per_image: [] } for set_name in [train, valid, test]: set_path os.path.join(label_root, set_name) if not os.path.exists(set_path): continue for label_file in os.listdir(set_path): if not label_file.endswith(.txt): continue with open(os.path.join(set_path, label_file), r) as f: lines [line.strip().split() for line in f.readlines()] img_classes set() for line in lines: if not line: # 跳过空行 continue class_id line[0] stats[total][class_id] 1 stats[per_set][set_name][class_id] 1 img_classes.add(class_id) stats[per_image].append(len(img_classes)) # 打印统计结果 print(\n 基础统计 ) for class_id, count in sorted(stats[total].items()): name class_names[int(class_id)] if class_names else class_id print(f类别 {name}: {count}个实例 (训练:{stats[per_set][train][class_id]}, f验证:{stats[per_set][valid][class_id]}, 测试:{stats[per_set][test][class_id]})) # 可视化 if class_names: plt.figure(figsize(12, 6)) classes [class_names[int(c)] for c in stats[total].keys()] plt.bar(classes, stats[total].values()) plt.title(Class Distribution) plt.xticks(rotation45) plt.show() if __name__ __main__: # 示例用法 LABEL_ROOT path/to/your/dataset/labels CLASS_NAMES [person, car, dog] # 替换为你的实际类别 analyze_yolo_labels(LABEL_ROOT, CLASS_NAMES)提示将CLASS_NAMES替换为你的实际类别名称可以得到更直观的可视化结果3. 代码核心功能拆解这个增强版分析器包含三个关键模块3.1 多维度统计引擎采用defaultdict实现的三层统计结构总量统计所有数据集的类别汇总子集统计分别计算train/valid/test中的分布单图统计记录每张图像包含的独特类别数stats { total: defaultdict(int), # 总实例数 per_set: { # 各子集统计 train: defaultdict(int), valid: defaultdict(int), test: defaultdict(int) }, per_image: [] # 每图类别数 }3.2 智能路径处理自动跳过不存在的子目录如未设置测试集避免报错中断for set_name in [train, valid, test]: set_path os.path.join(label_root, set_name) if not os.path.exists(set_path): # 智能跳过 continue3.3 可视化输出当提供类别名称时自动生成柱状图。例如处理COCO数据集的部分类别可能得到4. 解读统计结果与应对策略拿到统计报告后需要重点关注以下异常模式典型问题场景极端不均衡某类别样本量总量的5%解决方案过采样(oversampling)或合成数据(SynthAug)子集分布不均某类别在验证集中占比异常解决方案重新分层划分数据集单图过载存在大量15个标注的拥挤图像解决方案考虑图像裁剪或调整anchor大小实际操作建议对于样本量100的类别优先检查标注质量考虑主动学习标注策略当发现验证集缺失某些类别使用sklearn的StratifiedShuffleSplit示例代码from sklearn.model_selection import StratifiedShuffleSplit sss StratifiedShuffleSplit(n_splits1, test_size0.2, random_state42)5. 工程化扩展建议将脚本升级为完整的数据质量监控工具class DatasetHealthCheck: def __init__(self, label_dir): self.label_dir label_dir self.report {} def run_analysis(self): self._count_instances() self._check_balance() self._generate_report() def _count_instances(self): # 实现计数逻辑 pass def _check_balance(self): # 实现平衡性检查 pass def save_report(self, path): with open(path, w) as f: json.dump(self.report, f)这个类可以进一步扩展以下功能与TensorBoard集成支持COCO/VOC格式转换自动生成数据增强建议6. 常见问题排查Q1运行脚本时报FileNotFoundError检查路径是否包含中文或特殊字符确认labels目录结构符合YOLOv8标准Q2可视化图表显示乱码添加字体设置代码plt.rcParams[font.sans-serif] [SimHei] # 中文显示 plt.rcParams[axes.unicode_minus] FalseQ3如何处理非数值类别ID使用映射字典转换class_map {person: 0, car: 1} reverse_map {v: k for k, v in class_map.items()}在最近的一个交通标志识别项目中这套工具帮我们提前发现了施工标志类别的样本不足问题。通过针对性补充200张该场景图像最终使该类别的mAP提升了37%。