目标检测实战:多格式数据集(VOC/YOLO/JSON/COCO)转换与YOLO系列算法模型训练指南

1次阅读
没有评论

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

image.webp

数据集格式混乱的工程痛点

在目标检测(Object Detection)任务中,数据集格式的多样性常常成为开发者的第一个拦路虎。不同的标注工具产生的数据格式不同(比如 LabelImg 生成 VOC 格式,Labelbox 导出 COCO 格式),而主流算法框架对输入格式的要求也存在差异(如 YOLO 系列需要.txt 标注文件,Detectron2 偏好 COCO 格式)。这种割裂导致:

目标检测实战:多格式数据集 (VOC/YOLO/JSON/COCO) 转换与 YOLO 系列算法模型训练指南

  • 重复转换耗时:同一个数据集在不同框架中使用时需反复转换
  • 标注信息丢失:格式转换过程中可能丢失关键属性(如遮挡 / 截断标志)
  • 训练流程中断:因格式解析失败导致的异常往往在训练中途才暴露

四大格式深度解析

1. VOC 格式

PASCAL VOC(Visual Object Classes)是最早的标准格式之一,采用 XML 文件存储标注,典型结构如下:

<annotation>
  <object>
    <name>dog</name>
    <bndbox>
      <xmin>48</xmin>
      <ymin>240</ymin>
      <xmax>195</xmax>
      <ymax>371</ymax>
    </bndbox>
  </object>
</annotation>

特点
– 使用绝对像素坐标
– 支持 difficult/truncated 等属性标注
– 每个 XML 对应一张图片

2. YOLO 格式

YOLO 要求的.txt 文件每行表示一个物体,格式为:

<class_id> <x_center> <y_center> <width> <height>

其中坐标和尺寸均为归一化值(0- 1 之间)。例如:

0 0.344 0.612 0.322 0.415

3. COCO 格式

COCO(Common Objects in Context)采用 JSON 存储所有标注,核心字段包括:

{"images": [{"id": 1, "file_name": "0001.jpg"}],
  "annotations": [{
    "id": 1,
    "image_id": 1,
    "bbox": [x,y,width,height],
    "category_id": 1
  }]
}

优势
– 支持全景分割等扩展任务
– 单个文件包含整个数据集信息

4. JSON 格式

泛指自定义 JSON 结构,常见于商业标注工具。典型示例:

{
  "version": "1.0",
  "shapes": [{
    "label": "car",
    "points": [[x1,y1], [x2,y2]]
  }]
}

格式转换实战代码

COCO 转 YOLO 格式

import json
from pathlib import Path

def coco2yolo(coco_path, output_dir):
    """Convert COCO format to YOLO format"""
    with open(coco_path) as f:
        data = json.load(f)

    # Create category mapping
    cat_map = {cat['id']: idx for idx, cat in enumerate(data['categories'])}

    # Process each image
    for img in data['images']:
        img_id = img['id']
        anns = [a for a in data['annotations'] if a['image_id'] == img_id]

        txt_path = Path(output_dir) / f"{Path(img['file_name']).stem}.txt"
        with open(txt_path, 'w') as f:
            for ann in anns:
                # Convert COCO bbox [x,y,w,h] to YOLO [x_center,y_center,w,h]
                x, y, w, h = ann['bbox']
                x_center = (x + w/2) / img['width']
                y_center = (y + h/2) / img['height']
                w_norm = w / img['width']
                h_norm = h / img['height']

                line = f"{cat_map[ann['category_id']]} {x_center} {y_center} {w_norm} {h_norm}\n"
                f.write(line)

VOC 转 YOLO 格式

import xml.etree.ElementTree as ET

def voc2yolo(xml_path, classes):
    """Convert single VOC XML to YOLO format string"""
    tree = ET.parse(xml_path)
    root = tree.getroot()

    size = root.find('size')
    width = int(size.find('width').text)
    height = int(size.find('height').text)

    lines = []
    for obj in root.iter('object'):
        cls = obj.find('name').text
        if cls not in classes:
            continue

        xmlbox = obj.find('bndbox')
        xmin = int(xmlbox.find('xmin').text)
        ymin = int(xmlbox.find('ymin').text)
        xmax = int(xmlbox.find('xmax').text)
        ymax = int(xmlbox.find('ymax').text)

        # Convert to YOLO format
        x_center = ((xmin + xmax) / 2) / width
        y_center = ((ymin + ymax) / 2) / height
        w = (xmax - xmin) / width
        h = (ymax - ymin) / height

        lines.append(f"{classes.index(cls)} {x_center} {y_center} {w} {h}")

    return '\n'.join(lines)

YOLO 算法选型指南

YOLOv5 vs v7 vs v8 对比

版本 优势 适用场景
v5 社区生态好,部署简单 快速原型开发
v7 精度提升明显 对准确率要求高的场景
v8 速度最快,支持实例分割 实时检测需求

选型建议
– 端侧部署优先考虑 YOLOv8-nano
– 研究项目建议尝试 YOLOv7-w6
– 工业应用可选用 YOLOv5x6

YOLOv5 训练全流程

1. 环境准备

# 官方仓库克隆
git clone https://github.com/ultralytics/yolov5
cd yolov5
pip install -r requirements.txt

2. 训练命令详解

python train.py \
  --data coco128.yaml \
  --cfg yolov5s.yaml \
  --weights '' \
  --batch-size 64 \
  --epochs 300 \
  --img 640 \
  --device 0,1 \
  --hyp data/hyps/hyp.scratch-low.yaml

关键参数说明
--img: 输入图像尺寸(必须为 32 的倍数)
--hyp: 超参数配置文件路径
--batch-size: 根据 GPU 显存调整(可用 --batch-size -1 自动检测)

3. 超参数调优

修改hyps/hyp.scratch-low.yaml:

lr0: 0.01  # 初始学习率
lrf: 0.1   # 最终学习率 = lr0 * lrf
momentum: 0.937
weight_decay: 0.0005

避坑指南

标注一致性检查

import os
from PIL import Image

def check_annotations(img_dir, label_dir):
    """验证图片与标注文件是否匹配"""
    img_files = set(Path(img_dir).glob('*.jpg'))
    label_files = set(Path(label_dir).glob('*.txt'))

    # 检查文件名对应关系
    img_stems = {f.stem for f in img_files}
    label_stems = {f.stem for f in label_files}

    missing_labels = img_stems - label_stems
    if missing_labels:
        print(f"警告:缺失 {len(missing_labels)} 个标注文件")

    # 检查标注内容有效性
    for txt_file in label_files:
        with open(txt_file) as f:
            for line in f:
                parts = line.strip().split()
                if len(parts) != 5:
                    print(f"{txt_file} 存在格式错误")

小样本增强策略

推荐使用 Albumentations 库:

import albumentations as A

transform = A.Compose([A.HorizontalFlip(p=0.5),
    A.RandomBrightnessContrast(p=0.2),
    A.RandomSnow(p=0.1),
    A.RGBShift(p=0.2)
], bbox_params=A.BboxParams(format='yolo'))

混合精度训练

在训练命令中添加:

--amp  # 自动混合精度训练

可减少约 30% 显存占用。如遇 NaN 问题,可尝试:
1. 降低学习率
2. 添加梯度裁剪--clip-grad 10.0

实践建议

  1. 自定义数据实验
  2. 从 100 张样本开始快速验证流程
  3. 逐步增加数据量观察性能变化

  4. Backbone 对比

  5. 轻量化:MobileNetV3
  6. 高精度:ConvNeXt
  7. 平衡型:EfficientNet

  8. 模型部署

  9. 使用 export.py 转换为 ONNX/TensorRT 格式
  10. 测试时考虑使用 TTA(Test Time Augmentation)

期待大家在评论区分享自己的训练结果和调参经验!

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