labelme语义分割标注json文件转labelimg目标检测XML文件

labelme语义分割标注的json文件转labelimg目标检测的XML文件

介绍

自己写了一个简易的代码来实现从labelme语义分割标注的json文件转为labelimg目标检测的XML文件,思路十分简单,通过将原分割区域的最小外接矩形转化为检测的目标框实现。

调用

import json
import os
from xml.etree.ElementTree import Element, SubElement, ElementTree

寻找最小外接矩形

由于我的数据集是分部件进行标注的,所以存放在不同的文件夹下

file_path="D:\\0datasets\\oil"

#读取文件列表
file_list = os.listdir(file_path)
#遍历文件列表中的文件夹
for file in file_list:
    # 如果文件是目录
    if os.path.isdir(file_path+"\\"+file):
        # 获取文件夹路径
        dir_path = file_path+"\\"+file
        # 获取文件夹中的文件列表
        dir_list = os.listdir(dir_path)
        # 遍历文件夹中的文件
        for dir_file in dir_list:
            if dir_file.endswith('.json'):
                files = dir_path + "\\" + dir_file
                with open(files, 'r', encoding='utf-8') as f:
                    data = json.load(f)

                shapes = data['shapes']
                w = data['imageWidth']
                h = data['imageHeight']
                sizes = []
                for i in range(len(shapes)):
                    op = shapes[i]
                    # 在这里设置你原来的标签
                    if op['label'] == "oil":
                        map = op['points']
                        xmax, ymax = 0, 0
                        xmin, ymin = w, h
                        # 获取每个标注的最小外接矩形
                        for m in range(len(map)):
                            x = map[m][0]
                            y = map[m][1]
                            if x > xmax:
                                xmax = x
                            if x < xmin:
                                xmin = x
                            if y > ymax:
                                ymax = y
                            if y < ymin:
                                ymin = y
                        cc = [int(xmin), int(ymin), int(xmax), int(ymax)]
                        sizes.append(cc)
                # 假如存在标注,就会将json文件转为xml文件
                if sizes:
                    json_xml(dir_file, dir_path, w, h, sizes)
                    os.remove(files)
                else:
                    # 删除文件
                    os.remove(files)
                    os.remove(files.replace("json", "jpg"))

XML格式定义

由于我不太懂XML文件的操作,所以自己写了一遍labelimg的XML格式

def json_xml(fname,file_path,w,h,sizes):

    root = Element('annotation')
    folder = SubElement(root, 'folder')
    folder.text="op"
    filename=SubElement(root, 'filename')
    filename.text=fname
    path = SubElement(root, 'path')
    path.text=file_path+"\\"+fname.replace("json","jpg")
    source = SubElement(root, 'source')
    database = SubElement(source, 'database')
    database.text = 'Unknown'
    size = SubElement(root, 'size')
    width = SubElement(size, 'width')
    width.text = str(w)
    height = SubElement(size, 'height')
    height.text = str(h)
    depth = SubElement(size, 'depth')
    depth.text = '3'
    for i in range(len(sizes)):
        xmi, ymi, xma, yma = sizes[i]
        object = SubElement(root, 'object')
        name = SubElement(object, 'name')
        #这里这里设置你的标签名称
        name.text = 'labelname'
        pose = SubElement(object, 'pose')
        pose.text = 'Unspecified'
        truncated = SubElement(object, 'truncated')
        truncated.text = '1'
        difficult = SubElement(object, 'difficult')
        difficult.text = '0'
        bndbox = SubElement(object, 'bndbox')
        xmin = SubElement(bndbox, 'xmin')
        xmin.text = str(xmi)
        ymin = SubElement(bndbox, 'ymin')
        ymin.text = str(ymi)
        xmax = SubElement(bndbox, 'xmax')
        xmax.text = str(xma)
        ymax = SubElement(bndbox, 'ymax')
        ymax.text = str(yma)
    pretty_xml(root, "\t", "\n")
    tree = ElementTree(root)
    fname = path.text.replace(".jpg", ".xml")
    tree.write(fname, encoding="utf-8")

XML格式美化

调整换行和缩进使其符合labelimg生成的形式

def pretty_xml(element, indent, newline, level=0):  # elemnt为传进来的Elment类,参数indent用于缩进,newline用于换行
    if element is not None:  # 判断element是否有子元素
        if (element.text is None) or element.text.isspace():  # 如果element的text没有内容
            element.text = 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)  # 对子元素进行递归操作

结语

希望能对大家的工作起到一点点帮助。

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,您可以使用以下代码实现: ```python import os import json import xml.etree.ElementTree as ET # 定义标签和颜色 LABELS = {'circle': 0} COLORS = {'circle': '0,255,0'} # 定义json文件路径和xml文件路径 json_dir = '/path/to/json/dir' xml_dir = '/path/to/xml/dir' # 遍历json文件夹中的所有文件 for json_file in os.listdir(json_dir): # 如果不是json文件,则跳过 if not json_file.endswith('.json'): continue # 读取json文件内容 with open(os.path.join(json_dir, json_file), 'r') as f: data = json.load(f) # 获取文件名(去掉扩展名) filename = os.path.splitext(json_file)[0] # 创建xml文件 root = ET.Element('annotation') # 添加filename元素 ET.SubElement(root, 'filename').text = filename + '.jpg' # 添加size元素 size = ET.SubElement(root, 'size') ET.SubElement(size, 'width').text = str(data['imageWidth']) ET.SubElement(size, 'height').text = str(data['imageHeight']) ET.SubElement(size, 'depth').text = '3' # 遍历shapes for shape in data['shapes']: label = shape['label'] if label not in LABELS: continue # 添加object元素 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' # 添加bndbox元素 bndbox = ET.SubElement(obj, 'bndbox') if shape['shape_type'] == 'circle': # 如果是圆形,获取外切矩形 x, y = shape['points'][0] r = shape['points'][1][0] - x ET.SubElement(bndbox, 'xmin').text = str(round(x - r)) ET.SubElement(bndbox, 'ymin').text = str(round(y - r)) ET.SubElement(bndbox, 'xmax').text = str(round(x + r)) ET.SubElement(bndbox, 'ymax').text = str(round(y + r)) else: # 否则,获取矩形 x1, y1 = shape['points'][0] x2, y2 = shape['points'][1] ET.SubElement(bndbox, 'xmin').text = str(round(min(x1, x2))) ET.SubElement(bndbox, 'ymin').text = str(round(min(y1, y2))) ET.SubElement(bndbox, 'xmax').text = str(round(max(x1, x2))) ET.SubElement(bndbox, 'ymax').text = str(round(max(y1, y2))) # 添加difficult元素 ET.SubElement(obj, 'difficult').text = '0' # 添加bndbox颜色 ET.SubElement(obj, 'color').text = COLORS[label] # 保存xml文件 xml_file = os.path.join(xml_dir, filename + '.xml') tree = ET.ElementTree(root) tree.write(xml_file) ``` 这段代码会将指定文件夹中的所有json文件换为xml文件,并将xml文件保存到指定文件夹中。处理圆形标注时,会将圆形换为外切矩形。同时,会为每个标注添加颜色信息,以便在标注时更加直观。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值