Deep learning Labelme json file to roLabelImg xml file


foreword

Recently, I want to change the previously trained YOLOV5 model to rotating target detection (YOLOV5_obb), but I don't want to relabel the data set, and I haven't found a suitable script on the Internet. So I wrote a script to convert the json file of the previously annotated dataset into an xml file, and then adjust it through the corresponding rotation annotation software.


1. Data set preparation

The premise of this conversion script is that you already have a data set for YOLOV5 training before, and the annotation file is a json file, and the annotation frame is a rectangular frame. Here, only the conversion of the rectangular frame to xml is realized. If it is a polygon, you need to change the script yourself. The data set is as follows:
insert image description here

2. Download the labeling tool

The tool we use here is roLabelImg, which adds the function of rotation angle on the basis of LabelImg. The format of the labeled data set is VOC. The reference link is: roLabelImg installation .

1. Source code download

The download link is: roLabelImg

2. Required dependency installation

The commands are as follows, for reference only:

pip install pyqt5-tools
pip install lxml

3. Start command

The command is as follows:

pyrcc5 -o resources.py resources.qrc 
python roLabelImg.py(第二次直接执行这个命令应该就可以了)

4. Commonly used shortcut keys

w: Create a horizontal rectangular target frame
e: Create a rotating rectangular target frame
zxcv: Rotate the target frame, keys z and x are used to rotate counterclockwise, keys c and v are used to rotate clockwise

3. File conversion:

The general idea here is to first parse out the original json file, then delete the redundant information in it, such as picture information, and then write the remaining information into the corresponding xml file. Change the path to the code and it should be able to run. The code is as follows:

import os,glob,json
import xml.etree.ElementTree as ET
from pathlib import Path
import numpy as np

#获得中心点的坐标
def get_cx_cy(points):
    cx=(points[0][0]+points[1][0])/2.
    cy=(points[0][1]+points[1][1])/2.
    points=np.array(points)
    w=max(points[:,0])-min(points[:,0])
    h=max(points[:,1])-min(points[:,1])
    return cx,cy,w,h

#美化内容(+换行)
def indent(elem,level=0):
    i = "\n" + level * "  "
    if len(elem):
        if not elem.text or not elem.text.strip():
            elem.text = i + "  "
        if not elem.tail or not elem.tail.strip():
            elem.tail = i
        for elem in elem:
            indent(elem, level + 1)
        if not elem.tail or not elem.tail.strip():
            elem.tail = i
    else:
        if level and (not elem.tail or not elem.tail.strip()):
            elem.tail = i



#写入xml文件
def write_xml(data,imgpath,savepath):
    root=ET.Element('annotation') #创建节点
    tree=ET.ElementTree(root) #创建文档

    #图片文件上一级目录
    folder=ET.Element("folder")
    img_folder=imgpath.split(os.sep)[-2]
    folder.text=img_folder
    root.append(folder)

    #文件名
    imgname=Path(imgpath).stem
    filename=ET.Element("filename")
    filename.text=imgname
    root.append(filename)

    #路径
    path=ET.Element("path")
    path.text=imgpath
    root.append(path)

    #source
    source=ET.Element("source")
    root.append(source)
    database=ET.Element("database")
    database.text="Unknown"
    source.append(database)

    #size
    size=ET.Element("size")
    root.append(size)
    width=ET.Element("width") #宽
    width.text=str(data["imageWidth"])
    size.append(width)
    height=ET.Element("height")#高
    height.text=str(data["imageHeight"])
    size.append(height)
    depth=ET.Element("depth") #深度
    depth.text=str(3)
    size.append(depth)

    #segmented
    segmented=ET.Element("segmented")
    segmented.text=str(0)
    root.append(segmented)

    # 目标
    for shape in data["shapes"]:
        object_=ET.Element("object")
        root.append(object_)
        #标注框类型
        type_=ET.Element("type")
        type_.text="robndbox"
        object_.append(type_)
        #目标类别
        name=ET.Element("name")
        name.text=shape["label"]
        object_.append(name)
        #pose
        pose=ET.Element("pose")
        pose.text="Unspecified"
        object_.append(pose)
        #截断情况
        truncated=ET.Element("truncated")
        truncated.text=str(0) #默认为0,表示未截断
        object_.append(truncated)
        #样本困难度
        difficult=ET.Element("difficult")
        difficult.text=str(0) #默认为0,表示非困难样本
        object_.append(difficult)
        #四个端点
        robndbox=ET.Element("robndbox")
        object_.append(robndbox)
        cx,cy,w,h=get_cx_cy(shape["points"])
        #cx
        cx_=ET.Element("cx")
        cx_.text=str(cx)
        robndbox.append(cx_)
        #cy
        cy_=ET.Element("cy")
        cy_.text=str(cy)
        robndbox.append(cy_)
        #w
        w_=ET.Element("w")
        w_.text=str(w)
        robndbox.append(w_)
        #h
        h_=ET.Element("h")
        h_.text=str(h)
        robndbox.append(h_)
        #angle
        angle=ET.Element("angle")
        angle.text=str(0.0)
        robndbox.append(angle)

    indent(root,0)
    tree.write(savepath+os.sep+imgname+".xml","UTF-8",xml_declaration=True)

#解析json文件
def load_json(jsonpath):
    data=json.load(open(jsonpath,"r"))
    del data["version"]
    try:
        del data["flags"]
    except Exception as e:
        del data["flag"]
    del data["imagePath"]
    del data["imageData"]
    return data



if __name__ == '__main__':
    img_dir=r"" #要转换的原json文件的路径
    save_dir=r"" #保存文件夹路径
    os.makedirs(save_dir,exist_ok=True)
    imglist=glob.glob(img_dir+"*.jpg")
    for imgpath in imglist:
        # print(imgpath)
        jsonpath=imgpath.replace(".jpg",".json")
        data=load_json(jsonpath)

        write_xml(data,imgpath,save_dir)

If the json file is marked with polygons, it needs to be changed in the get_cx_cy function


Summarize

The above is the whole content of this article. If you have any questions, please leave a message in the comment area, or join the QQ group: 995760755 to communicate.

Guess you like

Origin blog.csdn.net/qq_55068938/article/details/127513163