voc格式数据集转换到yolo格式

将VOC格式数据集转换为YOLO格式需要处理XML标注文件和图像文件,并将边界框坐标从绝对坐标转换为归一化坐标。以下是健壮的Python代码实现,支持主要的图像格式(如 .jpg, .png, .jpeg 等),并考虑了各种可能的异常情况。


VOC格式说明

  • 标注文件 :每个图像对应一个 .xml 文件,包含图像尺寸和边界框的绝对坐标。
  • 图像文件 :通常与标注文件同名,格式为 .jpg.png 等。
  • 类别文件 :VOC数据集通常包含一个 classes.txt 文件,列出所有类别名称。

YOLO格式说明

  • 标注文件 :每个图像对应一个 .txt 文件,每行格式为 class_id x_center y_center width height,其中坐标和尺寸是归一化的(相对于图像宽度和高度)。
  • 图像文件 :与标注文件同名,格式为 .jpg.png 等。
  • 类别文件classes.txt,每行一个类别名称。

转换代码

python 复制代码
import os
import xml.etree.ElementTree as ET
from tqdm import tqdm

def voc_to_yolo(voc_dir, output_dir):
    """
    将VOC格式数据集转换为YOLO格式。
    
    :param voc_dir: VOC格式数据集的根目录,包含Annotations和JPEGImages文件夹。
    :param output_dir: 输出的YOLO格式数据集目录。
    """
    # 路径设置
    annotations_dir = os.path.join(voc_dir, 'Annotations')
    images_dir = os.path.join(voc_dir, 'JPEGImages')
    classes_file = os.path.join(voc_dir, 'classes.txt')

    # 检查路径是否存在
    if not os.path.exists(annotations_dir):
        raise FileNotFoundError("Annotations 文件夹不存在!")
    if not os.path.exists(images_dir):
        raise FileNotFoundError("JPEGImages 文件夹不存在!")
    if not os.path.exists(classes_file):
        raise FileNotFoundError("classes.txt 文件不存在!")

    # 创建输出目录
    os.makedirs(output_dir, exist_ok=True)
    labels_dir = os.path.join(output_dir, 'labels')
    images_output_dir = os.path.join(output_dir, 'images')
    os.makedirs(labels_dir, exist_ok=True)
    os.makedirs(images_output_dir, exist_ok=True)

    # 读取类别
    with open(classes_file, 'r') as f:
        categories = [line.strip() for line in f.readlines()]
    category_to_id = {name: i for i, name in enumerate(categories)}

    # 遍历标注文件
    for xml_file in tqdm(os.listdir(annotations_dir)):
        if not xml_file.endswith('.xml'):
            continue

        # 解析XML文件
        xml_path = os.path.join(annotations_dir, xml_file)
        tree = ET.parse(xml_path)
        root = tree.getroot()

        # 获取图像尺寸
        size = root.find('size')
        width = int(size.find('width').text)
        height = int(size.find('height').text)

        # 获取图像文件名
        image_name = root.find('filename').text
        image_path = os.path.join(images_dir, image_name)
        if not os.path.exists(image_path):
            print(f"警告:图像文件 {image_name} 不存在,跳过该标注文件。")
            continue

        # 复制图像到输出目录
        image_output_path = os.path.join(images_output_dir, image_name)
        if not os.path.exists(image_output_path):
            os.system(f'cp "{image_path}" "{image_output_path}"')

        # 创建YOLO格式的标注文件
        label_name = os.path.splitext(image_name)[0] + '.txt'
        label_path = os.path.join(labels_dir, label_name)
        with open(label_path, 'w') as f:
            for obj in root.findall('object'):
                class_name = obj.find('name').text
                if class_name not in category_to_id:
                    print(f"警告:类别 {class_name} 不在 classes.txt 中,跳过该对象。")
                    continue

                class_id = category_to_id[class_name]
                bbox = obj.find('bndbox')
                x_min = float(bbox.find('xmin').text)
                y_min = float(bbox.find('ymin').text)
                x_max = float(bbox.find('xmax').text)
                y_max = float(bbox.find('ymax').text)

                # 计算归一化坐标
                x_center = (x_min + x_max) / 2 / width
                y_center = (y_min + y_max) / 2 / height
                bbox_width = (x_max - x_min) / width
                bbox_height = (y_max - y_min) / height

                # 写入YOLO格式的标注
                f.write(f"{class_id} {x_center:.6f} {y_center:.6f} {bbox_width:.6f} {bbox_height:.6f}\n")

    print(f"转换完成!YOLO格式数据集已保存到: {output_dir}")


# 示例调用
voc_dir = "path/to/voc_dataset"  # VOC数据集根目录
output_dir = "path/to/yolo_dataset"  # 输出的YOLO格式数据集目录
voc_to_yolo(voc_dir, output_dir)

代码说明

  1. 路径检查 :确保 AnnotationsJPEGImages 文件夹和 classes.txt 文件存在。
  2. 类别映射 :从 classes.txt 读取类别名称,并映射到YOLO格式的类别ID。
  3. XML解析 :解析每个 .xml 文件,提取图像尺寸和边界框的绝对坐标。
  4. 坐标转换:将绝对坐标转换为归一化坐标。
  5. 文件复制:将图像文件复制到输出目录。
  6. 标注写入 :将YOLO格式的标注写入 .txt 文件。

示例目录结构

输入(VOC格式)
voc_dataset/
├── Annotations/
│   ├── image1.xml
│   ├── image2.xml
├── JPEGImages/
│   ├── image1.jpg
│   ├── image2.jpg
└── classes.txt
输出(YOLO格式)
yolo_dataset/
├── images/
│   ├── image1.jpg
│   ├── image2.jpg
├── labels/
│   ├── image1.txt
│   ├── image2.txt
└── classes.txt

注意事项

  1. 图像格式支持 :代码支持 .jpg.png.jpeg 等常见图像格式。
  2. 类别一致性 :确保 classes.txt 中的类别名称与XML文件中的类别名称一致。
  3. 异常处理 :代码会跳过不存在的图像文件或未在 classes.txt 中定义的类别。
  4. 图像复制:如果输出目录中已存在同名图像文件,则不会重复复制。

运行代码后,生成的YOLO格式数据集可以直接用于训练YOLO模型。

相关推荐
CSJK-24 分钟前
模式识别与机器学习 | 第十章 半监督学习
人工智能·学习·机器学习
魔理沙偷走了BUG28 分钟前
【AI数学基础】线性代数:矩阵和线性变换
人工智能·线性代数·矩阵
XianxinMao31 分钟前
理解PDF文档的力量:使用LLM与RAG的本地应用
人工智能·语言模型·自然语言处理
春末的南方城市1 小时前
东京大学联合Adobe提出基于指令的图像编辑模型InstructMove,可通过观察视频中的动作来实现基于指令的图像编辑。
人工智能·计算机视觉·adobe·aigc·音视频·图像生成
Bowen_CV1 小时前
挖掘建模之分类与预测
大数据·人工智能·分类
无水先生1 小时前
两种分类代码:独热编码与标签编码
人工智能·深度学习
qq_273900232 小时前
pytorch索引操作函数介绍
人工智能·pytorch·python
HelloZheQ2 小时前
Java与AI:构建智能应用的强大组合
java·开发语言·人工智能
硬件技术我知道2 小时前
产品 防尘防水IP等级 划分与实验方法
网络·人工智能·嵌入式硬件·物联网·计算机视觉·硬件工程·智慧城市