labelimage xml转 labelme json

#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
@author:cong
@time: 2024/10/23
@project: image_demo.py
@theme:xml2json 
"""

import cv2
import xml.etree.ElementTree as ET
import numpy as np
import os
import json
import shutil
import base64

'''
该脚本实现将xml类型标签(或者yolo格式标签)转为json格式标签
需要的数据:原始图像 原始xml标签(原始txt标签)

'''


# 解析数据集,输入单张图片路径,图片路径不能出现中文,因为是cv2读取的。和对应xml文件的路径
# 返回图片 该图所有的目标框[[x1,y1,x2,y2],....]  每个框的类别[label1, label2, label3,.....]  注意是label而不是索引
def parse_img_label(img_path, xml_path):  # 绝对路径
    img = cv2.imread(img_path)
    tree = ET.parse(xml_path)
    root = tree.getroot()
    objs = root.findall('object')
    bboxes = []  # 坐标框
    h, w = img.shape[0], img.shape[1]
    # gt_labels = []  # 标签名
    for obj in objs:  # 遍历所有的目标
        label = obj[0].text  # <name>这个tag的值,即标签
        label = label.strip(' ')
        box = [int(obj[4][i].text) for i in range(4)]
        box.append(label)  # box的元素 x1 y1 x2 y2 类别
        bboxes.append(box)
    return img, bboxes


# 该函数用于将yolo的标签转回xml需要的标签。。即将归一化后的坐标转为原始的像素坐标
def convert_yolo_xml(box, img):  #
    x, y, w, h = box[0], box[1], box[2], box[3]
    # 求出原始的x1 x2 y1 y2
    x2 = (2 * x + w) * img.shape[1] / 2
    x1 = x2 - w * img.shape[1]

    y2 = (2 * y + h) * img.shape[0] / 2
    y1 = y2 - h * img.shape[0]
    new_box = [x1, y1, x2, y2]
    new_box = list(map(int, new_box))
    return new_box


# 该函数用于解析yolo格式的数据集,即txt格式的标注 返回图像 边框坐标 真实标签名(不是索引,因此需要预先定义标签)
def parse_img_txt(img_path, txt_path):
    name_label = ['class0', 'class1', 'class2']  # 需要自己预先定义,它的顺序要和实际yolo格式的标签中0 1 2 3的标签对应 yolo标签的类别是索引 而不是名字
    img = cv2.imread(img_path)
    f = open(txt_path)
    bboxes = []
    for line in f.readlines():
        line = line.split(" ")
        if len(line) == 5:
            obj_label = name_label[int(line[0])]  # 将类别索引转成其名字
            x = float(line[1])
            y = float(line[2])
            w = float(line[3])
            h = float(line[4])
            box = convert_yolo_xml([x, y, w, h], img)
            box.append(obj_label)
            bboxes.append(box)
    return img, bboxes


# 制作labelme格式的标签
# 参数说明 img_name: 图像文件名称
# txt_name: 标签文件的绝对路径,注意是绝对路径
# prefix: 图像文件的上级目录名。即形如/home/xjzh/data/ 而img_name是其下的文件名,如00001.jpg
# prefix+img_name即为图像的绝对路径。不该路径能出现中文,否则cv2读取会有问题
#
def get_json(img_name, txt_name, prefix, yolo=False):
    # 图片名 标签名 前缀
    label_dict = {}  # json字典,依次填充它的value
    label_dict["imagePath"] = prefix + img_name  # 图片路径

    label_dict["fillColor"] = [255, 0, 0, 128]  # 目标区域的填充颜色 RGBA
    label_dict["lineColor"] = [0, 255, 0, 128]  # 线条颜色
    label_dict["flag"] = {}
    label_dict["version"] = "3.16.7"  # 版本号,随便
    with open(prefix + img_name, "rb") as f:
        img_data = f.read()
        base64_data = base64.b64encode(img_data)
        base64_str = str(base64_data, 'utf-8')
        label_dict["imageData"] = base64_str  # labelme的json文件存放了图像的base64编码。这样如果图像路径有问题仍然能够打开文件

    img, gt_box = parse_img_label(prefix + img_name, txt_name) if not yolo else parse_img_txt(prefix + img_name,
                                                                                              txt_name)  # 读取真实数据

    label_dict["imageHeight"] = img.shape[0]  # 高度
    label_dict["imageWidth"] = img.shape[1]

    shape_list = []  # 存放标注信息的列表,它是 shapes这个键的值。里面是一个列表,每个元素又是一个字典,字典内容是该标注的类型 颜色 坐标点等等
    # label_dict["shapes"] = [] # 列表,每个元素是字典。
    # box的元素 x1 y1 x2 y2 类别
    for box in gt_box:
        shape_dict = {}  # 表示一个目标的字典
        shape_dict["shape_type"] = "rectangle"  # 因为xml或yolo格式标签是矩形框标注,因此是rectangle
        shape_dict["fill_color"] = None  # 该类型的填充颜色
        shape_dict["line_color"] = None  # 线条颜色 可以设置,或者根据标签名自己预先设定labe_color_dict
        shape_dict["flags"] = {}
        shape_dict["label"] = box[-1]  # 标签名
        shape_dict["points"] = [[box[0], box[1]], [box[2], box[3]]]
        # 通常contours是长度为1的列表,如果有分块,可能就有多个  # [[x1,y1], [x2,y2]...]的列表
        shape_list.append(shape_dict)

    label_dict["shapes"] = shape_list  #
    return label_dict


# 设置参数:图像文件路径、xml文件路径、保存的json文件路径
imgs_path = "D:\\handsignal_train\\ObjectDetection\\my_data\\VOCdevkit\\VOC2007\\JPEGImages\\"  # 图像路径
xmls_path = "D:\\handsignal_train\\ObjectDetection\\my_data\\VOCdevkit\\VOC2007\\Annotations\\"  # xml文件路径

img_path = os.listdir(imgs_path)
out_json = 'C:\\Users\\Administrator\\Desktop\\CodeX AI\\jsons\\'  # 保存的json文件路径
out_imgs = 'C:\\Users\\Administrator\\Desktop\\CodeX AI\\images\\'
if not os.path.exists(out_json):
    os.makedirs(out_json)

for nums, name in enumerate(img_path):

    if nums == 500:
        
        print(f"processed {nums} images")
        break

    if name.endswith(".png"):
        continue
    else:
        print("name:", name)
        image_path = os.path.join(imgs_path, name)
        out_img_path = os.path.join(out_imgs, name)
        shutil.copy(image_path, out_img_path)

        xml_path = xmls_path + name.replace('jpg', 'xml')  # xml文件的绝对路径
        label_dict = get_json(name, xml_path, prefix=imgs_path)  #
        with open(out_json + name.replace("jpg", "json"), 'w') as f:  # 写入一个json文件
            f.write(json.dumps(label_dict, ensure_ascii=False, indent=4, separators=(',', ':')))

XML文件换为LabelMeJSON文件可以使用以下步骤: 1. 安装Python的xmltodict和json模块,可以使用以下命令进行安装: ```python pip install xmltodict pip install json ``` 2. 读取XML文件并将其换为字典格式: ```python import xmltodict with open('example.xml') as xml_file: data_dict = xmltodict.parse(xml_file.read()) ``` 3. 从字典中提取有用的信息并将其换为LabelMeJSON格式: ```python import json # 从字典中提取有用的信息 image_name = data_dict['annotation']['filename'] image_height = int(data_dict['annotation']['size']['height']) image_width = int(data_dict['annotation']['size']['width']) shapes = [] for obj in data_dict['annotation']['object']: label = obj['name'] xmin = int(obj['bndbox']['xmin']) ymin = int(obj['bndbox']['ymin']) xmax = int(obj['bndbox']['xmax']) ymax = int(obj['bndbox']['ymax']) points = [[xmin, ymin], [xmax, ymin], [xmax, ymax], [xmin, ymax]] shape = { "label": label, "points": points, "group_id": None, "shape_type": "polygon", "flags": {} } shapes.append(shape) # 将信息换为LabelMeJSON格式 labelme_data = { "version": "4.5.6", "flags": {}, "shapes": shapes, "imagePath": image_name, "imageData": None, "imageHeight": image_height, "imageWidth": image_width } # 将JSON数据写入文件 with open('example.json', 'w') as json_file: json.dump(labelme_data, json_file) ``` 这将生成一个名为“example.json”的LabelMe JSON文件,其中包含从XML文件中提取的有用信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值