csv数据集转换成VOC(xml)与yolo格式(txt)

  最近找到了一个目标检测的数据集,但是打开后发现里面只有图片和一个csv文件。标签信息都在csv里面,需要转换成xml和txt才能拿来训练。所以在网上找了一些资料,将数据成功转换成了xml与txt格式。

  具体转换方式是先将csv转换成xml,再将xml转换成txt。csv跟xml数值一样,只需要调整一下顺序,txt则需要对坐标进行转化。

下面是将csv文件转换为xml格式:

import os
import csv
from xml.etree import ElementTree as ET

path = ' '    # 数据集路径
label_list = []    # 标签种类

def pretty_xml(element, indent, newline, level=0):  # elemnt为传进来的Elment类,参数indent用于缩进,newline用于换行
    '''
    用于对生成的xml文件进行遍历、换行和缩进,并不是必须的
    '''
    if element:  # 判断element是否有子元素
        if (element.text is None) or element.text.isspace():  # 如果element的text没有内容
            element.text = newline + indent * (level + 1)
        else:
            element.text = newline + indent * (level + 1) + element.text.strip() + newline + indent * (level + 1)
            # else:  # 此处两行如果把注释去掉,Element的text也会另起一行
            # element.text = newline + indent * (level + 1) + element.text.strip() + newline + indent * level
    temp = list(element)  # 将element转成list
    for subelement in temp:
        if temp.index(subelement) < (len(temp) - 1):  # 如果不是list的最后一个元素,说明下一个行是同级别元素的起始,缩进应一致
            subelement.tail = newline + indent * (level + 1)
        else:  # 如果是list的最后一个元素, 说明下一行是母元素的结束,缩进应该少一个
            subelement.tail = newline + indent * level
        pretty_xml(subelement, indent, newline, level=level + 1)  # 对子元素进行递归操作

def create_xml(objects, anno_dir, name):
    """
    xml的具体格式
    """
    save_xml_path = os.path.join(anno_dir, "%s.xml" % name.split('.')[0])
    root = ET.Element("annotation")
    # root.set("version", "1.0")
    folder = ET.SubElement(root, "folder")
    folder.text = "datasets"
    filename = ET.SubElement(root, "filename")
    filename.text = name
    source = ET.SubElement(root, "source")
    source.text = 'Unknow'
    # owner = ET.SubElement(root, "owner")
    # owner.text = "WPY"
    size = ET.SubElement(root, "size")
    width = ET.SubElement(size, "width")
    width.text = str(objects[1])
    height = ET.SubElement(size, "height")
    height.text = str(objects[2])
    depth = ET.SubElement(size, "depth")
    depth.text = "3"
    segmented = ET.SubElement(root, "segmented")
    segmented.text = "0"

    object = ET.SubElement(root, "object")
    name = ET.SubElement(object, "name")  # number
    id = objects[7]
    name.text = str(label_list[int(id)])
    # meaning = ET.SubElement(object, "meaning")  # name
    # meaning.text = inf_value[0]
    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(objects[3])
    ymin = ET.SubElement(bndbox, "ymin")
    ymin.text = str(objects[4])
    xmax = ET.SubElement(bndbox, "xmax")
    xmax.text = str(objects[5])
    ymax = ET.SubElement(bndbox, "ymax")
    ymax.text = str(objects[6])
    tree = ET.ElementTree(root)
    pretty_xml(root, '  ', '\n')
    tree.write(save_xml_path)

def csv_xml(csv_dir, anno_dir):
    if not os.path.exists(anno_dir):
        os.mkdir(anno_dir)
    with open(csv_dir, 'r') as f:
        reader = csv.reader(f)
        labels = list(reader)
        for label in labels[1:]:
            create_xml(label, anno_dir, name=label[0])
            print(label[0].split('.')[0] + ".xml" + 'is finish')

接下来就将xml转换成txt:

def convert(size, box):
    """
    对宽高、坐标进行转化
    """
    dw = 1.0 / size[0]
    dh = 1.0 / size[1]
    x = (box[0] + box[1]) / 2.0
    y = (box[2] + box[3]) / 2.0
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = x * dw
    w = w * dw
    y = y * dh
    h = h * dh
    return (x, y, w, h)


def xml_txt(anno_dir, label_dir):
    if not os.path.exists(label_dir):
        os.mkdir(label_dir)
    for i in os.listdir(anno_dir):
        xml = open(os.path.join(anno_dir, i))
        txt = open(os.path.join(label_dir, i.split('.')[0] + '.txt'), 'w')
        xml_text = xml.read()
        root = ET.fromstring(xml_text)  # 将字符串转化为Element对象
        xml.close()
        size = root.find('size')
        w = int(size.find('width').text)
        h = int(size.find('height').text)
        for obj in root.iter('object'):
            cls = obj.find('name').text
            b = label_list[5]
            if cls not in label_list:
                print(cls)
                continue
            cls_id = label_list.index(cls)
            xmlbox = obj.find('bndbox')
            box = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text),
                   float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
            bbox = convert((w, h), box)
            txt.write(str(cls_id) + " " + " ".join([str(a) for a in bbox]) + '\n')


if __name__ == '__main__':
    csv_dir = os.path.join(path, "annotations.csv")
    img_dir = os.path.join(path, "JPEGImages")
    anno_dir = os.path.join(path, "Annotations")
    label_dir = os.path.join(path, "labels")
    csv_xml(csv_dir=csv_dir, anno_dir=anno_dir)
    xml_txt(anno_dir, label_dir)

  • 5
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要将YOLO格式数据集换为VOC格式数据集,需要按照以下步骤进行操作: 1. 根据YOLO格式数据集的标注文件,将每个图像中的目标对象的位置、类别和置信度信息提取出来,存储在一个文本文件中。每行包含一个目标对象的信息,格式如下: ``` <class> <x_center> <y_center> <width> <height> ``` 其中,`<class>`表示目标对象所属的类别,`<x_center>`和`<y_center>`表示目标对象中心点在图像中的坐标,`<width>`和`<height>`表示目标对象的宽度和高度,所有这些值都是相对于图像大小的比例。 2. 将每个图像的文件名和对应的标注文件名存储在一个XML文件中,格式如下: ``` <annotation> <folder>image_folder</folder> <filename>image_name.jpg</filename> <size> <width>image_width</width> <height>image_height</height> <depth>3</depth> </size> <object> <name>object_class</name> <bndbox> <xmin>xmin_value</xmin> <ymin>ymin_value</ymin> <xmax>xmax_value</xmax> <ymax>ymax_value</ymax> </bndbox> </object> ... </annotation> ``` 其中,`<folder>`表示图像文件所在的文件夹,`<filename>`表示图像文件名,`<width>`和`<height>`表示图像的宽度和高度,`<object>`表示一个目标对象,`<name>`表示目标对象所属的类别,`<bndbox>`表示目标对象的边界框,`<xmin>`、`<ymin>`、`<xmax>`和`<ymax>`分别表示边界框左上角和右下角的坐标。 3. 将所有XML文件和对应的图像文件存储在一个文件夹中,这样就得到了一个VOC格式数据集。 需要注意的是,YOLO格式数据集VOC格式数据集的标注信息格式不同,因此需要进行格式换。此外,VOC格式数据集还需要包含图像文件本身,因此需要将YOLO格式数据集中的图像文件也复制到VOC格式数据集中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值