将YOLO格式转为VOC格式一键式脚本

在研究Faster-RCNN,SSD等算法要进行对比实验时候一般需要用到VOC格式的数据集,因此记录以下我的转换过程。

1.安装对应的库

2.导入源码

3.修改最下面的五个参数分别是

训练集图片存放路径,

训练集标注文件存放路径,

验证集图片存放路径,

验证集标注文件存放路径,

转换完成之后文件夹的路径。

4.一键运行即可

脚本功能:

  • 脚本会读取指定的训练集和验证集路径。
  • 将 YOLO 格式的标注转换为 VOC 格式的 XML 文件。
  • 图像会被复制到新的 VOC 格式目录结构中。
  • 在目标目录中创建 VOC 格式的目录结构(Annotations, JPEGImages, ImageSets/Main)。

注意事项:

  • 确保有足够的磁盘空间来存储转换后的数据集。
  • 脚本支持多种图像格式(.png, .jpg, .jpeg, .tif, .tiff)。
  • 如果输出目录已存在,脚本会在现有目录中添加或更新文件,而不是创建一个全新的目录。

如果对您有帮助的话,就点一个小小的赞把!

具体源码如下:

import os
import xml.etree.ElementTree as ET
from PIL import Image
import shutil
from tqdm import tqdm
import argparse


def create_voc_xml(image_path, boxes, labels, out_path):
    img = Image.open(image_path)
    width, height = img.size

    root = ET.Element("annotation")
    ET.SubElement(root, "folder").text = os.path.basename(os.path.dirname(os.path.dirname(out_path)))
    ET.SubElement(root, "filename").text = os.path.basename(image_path)

    size = ET.SubElement(root, "size")
    ET.SubElement(size, "width").text = str(width)
    ET.SubElement(size, "height").text = str(height)
    ET.SubElement(size, "depth").text = str(3)  # Assuming RGB images

    for box, label in zip(boxes, labels):
        obj = ET.SubElement(root, "object")
        ET.SubElement(obj, "name").text = label
        ET.SubElement(obj, "pose").text = "Unspecified"
        ET.SubElement(obj, "truncated").text = "0"
        ET.SubElement(obj, "difficult").text = "0"

        bbox = ET.SubElement(obj, "bndbox")
        ET.SubElement(bbox, "xmin").text = str(int(box[0]))
        ET.SubElement(bbox, "ymin").text = str(int(box[1]))
        ET.SubElement(bbox, "xmax").text = str(int(box[2]))
        ET.SubElement(bbox, "ymax").text = str(int(box[3]))

    tree = ET.ElementTree(root)
    tree.write(out_path)


def yolo_to_voc_format(yolo_box, img_width, img_height):
    x_center, y_center, w, h = yolo_box
    w *= img_width
    h *= img_height
    x_center *= img_width
    y_center *= img_height

    xmin = int(x_center - w / 2)
    ymin = int(y_center - h / 2)
    xmax = int(x_center + w / 2)
    ymax = int(y_center + h / 2)

    return [xmin, ymin, xmax, ymax]


def convert_dataset(img_path, label_path, output_path, image_set):
    os.makedirs(os.path.join(output_path, "Annotations"), exist_ok=True)
    os.makedirs(os.path.join(output_path, "JPEGImages"), exist_ok=True)
    os.makedirs(os.path.join(output_path, "ImageSets", "Main"), exist_ok=True)

    image_list = []

    for img_file in tqdm(os.listdir(img_path), desc=f"Processing {image_set}"):
        if img_file.lower().endswith(('.png', '.jpg', '.jpeg', '.tif', '.tiff')):
            img_filename = os.path.splitext(img_file)[0]
            image_list.append(img_filename)

            # Copy image
            shutil.copy(
                os.path.join(img_path, img_file),
                os.path.join(output_path, "JPEGImages", img_file)
            )

            # Process label
            label_file = os.path.join(label_path, f"{img_filename}.txt")
            if os.path.exists(label_file):
                with open(label_file, 'r') as f:
                    lines = f.readlines()

                img = Image.open(os.path.join(img_path, img_file))
                img_width, img_height = img.size

                boxes = []
                labels = []
                for line in lines:
                    data = line.strip().split()
                    label = data[0]
                    box = list(map(float, data[1:]))
                    voc_box = yolo_to_voc_format(box, img_width, img_height)
                    boxes.append(voc_box)
                    labels.append(label)

                # Create XML annotation
                xml_path = os.path.join(output_path, "Annotations", f"{img_filename}.xml")
                create_voc_xml(os.path.join(img_path, img_file), boxes, labels, xml_path)

    # Create ImageSets file
    with open(os.path.join(output_path, "ImageSets", "Main", f"{image_set}.txt"), 'w') as f:
        for item in image_list:
            f.write(f"{item}\n")


def main(train_img_path, train_label_path, val_img_path, val_label_path, output_path):
    # Convert training set
    convert_dataset(train_img_path, train_label_path, output_path, "train")

    # Convert validation set
    convert_dataset(val_img_path, val_label_path, output_path, "val")

    print("转换完成!VOC格式数据集已保存到", output_path)


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Convert YOLO format dataset to VOC format")
    parser.add_argument("--train_img", default="E:/Datasets/UCAS-AOD-yolo/train/images", help="Path to training images")
    parser.add_argument("--train_label", default="E:/Datasets/UCAS-AOD-yolo/train/labels",
                        help="Path to training labels")
    parser.add_argument("--val_img", default="E:/Datasets/UCAS-AOD-yolo/val/images", help="Path to validation images")
    parser.add_argument("--val_label", default="E:/Datasets/UCAS-AOD-yolo/val/labels", help="Path to validation labels")
    parser.add_argument("--output", default="E:/Datasets/VOCdata/VOC-USCA-AOD", help="Path to output VOC dataset")

    args = parser.parse_args()

    main(args.train_img, args.train_label, args.val_img, args.val_label, args.output)

注意事项:尽量使用相对路径 所有路径的斜杠使用 / 不然可能会报错

运行结果如下:

### 回答1: import os import shutil import glob#源数据路径 yolo_path = './yolo_data' #目标路径 voc_path = './voc_data' #检查路径是否存在,不存在则新建 if not os.path.exists(voc_path): os.mkdir(voc_path) #获取所有源数据文件 yolo_list = glob.glob(os.path.join(yolo_path, '*')) #检查每一个源文件 for yolo_file in yolo_list: #获取文件名 basename = os.path.basename(yolo_file) #获取文件名和后缀 basename, ext = os.path.splitext(basename) #拼接输出文件路径 voc_file = os.path.join(voc_path, basename + '.xml') #打开文件 with open(yolo_file) as f: #按行读取 lines = f.readlines() #检查文件是否为空 if len(lines) == 0: continue #读取每一行内容 for line in lines: #按空格分割 line_list = line.split(' ') #获取标签 label = line_list[0] #获取坐标 xmin = line_list[1] ymin = line_list[2] xmax = line_list[3] ymax = line_list[4] #创建voc格式文件 with open(voc_file, 'w') as fw: fw.write('<annotation>\n') fw.write('\t<filename>{}.jpg</filename>\n'.format(basename)) fw.write('\t<size>\n') fw.write('\t\t<width>1920</width>\n') fw.write('\t\t<height>1080</height>\n') fw.write('\t\t<depth>3</depth>\n') fw.write('\t</size>\n') fw.write('\t<object>\n') fw.write('\t\t<name>{}</name>\n'.format(label)) fw.write('\t\t<bndbox>\n') fw.write('\t\t\t<xmin>{}</xmin>\n'.format(xmin)) fw.write('\t\t\t<ymin>{}</ymin>\n'.format(ymin)) fw.write('\t\t\t<xmax>{}</xmax>\n'.format(xmax)) fw.write('\t\t\t<ymax>{}</ymax>\n'.format(ymax)) fw.write('\t\t</bndbox>\n') fw.write('\t</object>\n') fw.write('</annotation>\n') #复制图片 shutil.copy(os.path.join(yolo_path, basename+'.jpg'), voc_path) ### 回答2: YOLO格式VOC格式是两种用于物体检测的标注格式。下面是一个用Python编写的将YOLO格式转换为VOC格式的简单代码示例: ```python import xml.etree.ElementTree as ET def yolo_to_voc(yolo_path, output_path): with open(yolo_path, 'r') as yolo_file: lines = yolo_file.readlines() root = ET.Element("annotation") folder = ET.SubElement(root, "folder") folder.text = "VOC2007" filename = ET.SubElement(root, "filename") filename.text = "image.jpg" size = ET.SubElement(root, "size") width = ET.SubElement(size, "width") width.text = "416" # 替换为图片的宽度 height = ET.SubElement(size, "height") height.text = "416" # 替换为图片的高度 depth = ET.SubElement(size, "depth") depth.text = "3" for line in lines: label, x_center, y_center, w, h = line.split() object = ET.SubElement(root, "object") name = ET.SubElement(object, "name") name.text = label pose = ET.SubElement(object, "pose") pose.text = "Unspecified" truncated = ET.SubElement(object, "truncated") truncated.text = "0" difficult = ET.SubElement(object, "difficult") difficult.text = "0" bndbox = ET.SubElement(object, "bndbox") xmin = ET.SubElement(bndbox, "xmin") xmin.text = str(int(float(x_center) - (float(w) / 2.0))) ymin = ET.SubElement(bndbox, "ymin") ymin.text = str(int(float(y_center) - (float(h) / 2.0))) xmax = ET.SubElement(bndbox, "xmax") xmax.text = str(int(float(x_center) + (float(w) / 2.0))) ymax = ET.SubElement(bndbox, "ymax") ymax.text = str(int(float(y_center) + (float(h) / 2.0))) tree = ET.ElementTree(root) tree.write(output_path) yolo_path = "path/to/yolo.txt" # 替换为YOLO格式标注文件的路径 output_path = "path/to/output.xml" # 替换为转换后的VOC格式标注文件的保存路径 yolo_to_voc(yolo_path, output_path) ``` 在运行代码之前,请替换示例中的参量`yolo_path`和`output_path`为正确的文件路径。这段代码会将YOLO格式的标注文件转换成VOC格式,并将输出保存为一个XML文件。请确保YOLO格式的标注文件包含类别标签、边界框的中心坐标、宽度和高度信息。 ### 回答3: 下面是一个将YOLO格式转换为VOC格式Python代码段: ```python import os import xml.etree.ElementTree as ET def convert_yolo_to_voc(yolo_file, voc_dir): # 读取YOLO格式文件 with open(yolo_file, 'r') as f: lines = f.readlines() for line in lines: line = line.strip().split() image_name = line[0] labels = line[1:] # 创建VOC格式的XML文件 root = ET.Element("annotation") folder = ET.SubElement(root, "folder") folder.text = voc_dir filename = ET.SubElement(root, "filename") filename.text = image_name for label in labels: obj = ET.SubElement(root, "object") name = ET.SubElement(obj, "name") name.text = label # 保存VOC格式的XML文件 xml_path = os.path.join(voc_dir, os.path.splitext(image_name)[0] + ".xml") tree = ET.ElementTree(root) tree.write(xml_path) print("转换完成!") # 调用示例 yolo_file = "path/to/yolo.txt" voc_dir = "path/to/voc" convert_yolo_to_voc(yolo_file, voc_dir) ``` 请将代码中的路径替换为实际路径。该代码会读取YOLO格式的文件(假设为"yolo.txt"),将每行的第一个值作为图像名称,后续值作为标签,然后将其转换为对应的VOC格式的XML文件,存储在指定的目录(假设为"path/to/voc")中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值