数据格式转换(labelme、labelimg、yolo格式相互转换)

news2025/1/20 14:57:12

👨‍💻个人简介: 深度学习图像领域工作者
🎉总结链接:
             链接中主要是个人工作的总结,每个链接都是一些常用demo,代码直接复制运行即可。包括:
                    📌1.工作中常用深度学习脚本
                    📌2.torch、numpy等常用函数详解
                    📌3.opencv 图片、视频等操作
                    📌4.个人工作中的项目总结(纯干活)
              链接: https://blog.csdn.net/qq_28949847/article/details/128552785
🎉视频讲解: 以上记录,通过B站等平台进行了视频讲解使用,可搜索 ‘Python图像识别’ 进行观看
              B站:Python图像识别
              抖音:Python图像识别
              西瓜视频:Python图像识别


目录

  • 1. 目标检测矩形框转换
    • (1)labelme标注的数据json文件转为labelimg格式的xml文件
    • (2)labelimg xml文件转 labelme json文件

1. 目标检测矩形框转换

(1)labelme标注的数据json文件转为labelimg格式的xml文件

目前只能支持 json中 ‘rectangle’ 和 ‘polygon’ 两种模式的转换,其中 ‘polygon’ 的转换方式为,替换成最小外接矩形的左上角和右下角坐标。

输入:由labelme的rectangle或这polygon方式标注生成的json文件;

输出:类似于labelImg的rectangle方式标注生成的xml文件,是左上角和右下角的坐标。

个人只需修改相应的路径。

# -*- coding: utf-8 -*-
import numpy as np
import json
from lxml import etree
import os
from tqdm import tqdm


class ReadJson(object):
    '''
    读取json文件,获取相应的标签信息
    '''

    def __init__(self, json_path):
        self.json_data = json.load(open(json_path, encoding="utf-8"))
        self.filename = self.json_data['imagePath']
        self.width = self.json_data['imageWidth']
        self.height = self.json_data['imageHeight']

        self.coordis = []
        # 构建坐标
        self.process_shapes()

    def process_shapes(self):
        for single_shape in self.json_data['shapes']:
            if single_shape['shape_type'] == "rectangle":
                bbox_class = single_shape['label']
                xmin = single_shape['points'][0][0]
                ymin = single_shape['points'][0][1]
                xmax = single_shape['points'][1][0]
                ymax = single_shape['points'][1][1]
                self.coordis.append([xmin, ymin, xmax, ymax, bbox_class])
            elif single_shape['shape_type'] == 'polygon':
                bbox_class = single_shape['label']
                temp_points = single_shape['points']
                temp_points = np.array(temp_points)
                xmin, ymin = temp_points.min(axis=0)
                xmax, ymax = temp_points.max(axis=0)
                self.coordis.append([xmin, ymin, xmax, ymax, bbox_class])
            else:
                print("shape type error, shape_type not in ['rectangle', 'polygon']")

    def get_width_height(self):
        return self.width, self.height

    def get_filename(self):
        return self.filename

    def get_coordis(self):
        return self.coordis


class labelimg_Annotations_xml:
    def __init__(self, folder_name, filename, path, database="Unknown"):
        self.root = etree.Element("annotation")
        child1 = etree.SubElement(self.root, "folder")
        child1.text = folder_name
        child2 = etree.SubElement(self.root, "filename")
        child2.text = filename
        child3 = etree.SubElement(self.root, "path")
        child3.text = path
        child4 = etree.SubElement(self.root, "source")
        child5 = etree.SubElement(child4, "database")
        child5.text = database

    def set_size(self, width, height, channel):
        size = etree.SubElement(self.root, "size")
        widthn = etree.SubElement(size, "width")
        widthn.text = str(width)
        heightn = etree.SubElement(size, "height")
        heightn.text = str(height)
        channeln = etree.SubElement(size, "channel")
        channeln.text = str(channel)

    def set_segmented(self, seg_data=0):
        segmented = etree.SubElement(self.root, "segmented")
        segmented.text = str(seg_data)

    def set_object(self, label, x_min, y_min, x_max, y_max,
                   pose='Unspecified', truncated=0, difficult=0):
        object = etree.SubElement(self.root, "object")
        namen = etree.SubElement(object, "name")
        namen.text = label
        posen = etree.SubElement(object, "pose")
        posen.text = pose
        truncatedn = etree.SubElement(object, "truncated")
        truncatedn.text = str(truncated)
        difficultn = etree.SubElement(object, "difficult")
        difficultn.text = str(difficult)
        bndbox = etree.SubElement(object, "bndbox")
        xminn = etree.SubElement(bndbox, "xmin")
        xminn.text = str(x_min)
        yminn = etree.SubElement(bndbox, "ymin")
        yminn.text = str(y_min)
        xmaxn = etree.SubElement(bndbox, "xmax")
        xmaxn.text = str(x_max)
        ymaxn = etree.SubElement(bndbox, "ymax")
        ymaxn.text = str(y_max)

    def savefile(self, filename):
        tree = etree.ElementTree(self.root)
        tree.write(filename, pretty_print=True, xml_declaration=False, encoding='utf-8')


def json_transform_xml(json_path, xml_path):
    json_anno = ReadJson(json_path)
    width, height = json_anno.get_width_height()
    channel = 3
    filename = json_anno.get_filename()
    coordis = json_anno.get_coordis()

    anno = labelimg_Annotations_xml('JPEGImages', filename, 'JPEGImages')
    anno.set_size(width, height, channel)
    anno.set_segmented()
    for data in coordis:
        x_min, y_min, x_max, y_max, label = data
        anno.set_object(label, int(x_min), int(y_min), int(x_max), int(y_max))
    anno.savefile(xml_path)


if __name__ == "__main__":
    '''
        目前只能支持 json中 rectangle 和 polygon 两种模式的转换,其中 polygon 的转换方式为,替换成最小外接矩形的左上角和右下角坐标
    '''
    root_json_dir = r"C:\Users\JoelYang\Desktop\111111\bbox_20230417_gjx"
    # root_save_xml_dir = r"\\SHARE\public\Time_Plus\traindata\bbox\tiaoshui3m\20230418_zxl"
    root_save_xml_dir = root_json_dir
    for json_filename in tqdm(os.listdir(root_json_dir)):
        if not json_filename.endswith(".json"):
            continue
        json_path = os.path.join(root_json_dir, json_filename)
        save_xml_path = os.path.join(root_save_xml_dir, json_filename.replace(".json", ".xml"))
        json_transform_xml(json_path, save_xml_path)

效果如下图:

json文件:
在这里插入图片描述

xml文件:
在这里插入图片描述

(2)labelimg xml文件转 labelme json文件

import xml.etree.ElementTree as ET
import os
import json


def xml_transform_json(xml_path, file, save_path):
    print(os.path.join(xml_path, file))
    # 读取xml文件
    path_file_xml = os.path.join(xml_path, file)
    # 解析读取xml函数
    root = ET.parse(path_file_xml)
    folder = root.find('folder').text
    filename = root.find('filename').text
    path = root.find('path').text
    sz = root.find('size')
    width = int(sz[0].text)
    height = int(sz[1].text)

    # 构建json数据
    data = {}
    data['flags'] = {}
    data['version'] = "4.5.6"
    data["shapes"] = []
    for child in root.findall('object'):  # 找到图片中的所有框
        sub = child.find('bndbox')  # 找到框的标注值并进行读取
        xmin = float(sub[0].text)
        ymin = float(sub[1].text)
        xmax = float(sub[2].text)
        ymax = float(sub[3].text)
        points = [[xmin, ymin], [xmax, ymax]]
        itemData = {'points': []}
        itemData['points'].extend(points)
        name = child.find("name").text
        itemData["flag"] = {}
        itemData["group_id"] = None
        itemData["shape_type"] = "rectangle"
        itemData["label"] = name
        data["shapes"].append(itemData)
    data['imageWidth'] = width
    data['imageHeight'] = height
    data['imageData'] = None
    data['imagePath'] = filename

    filename, extension = os.path.splitext(file)
    jsonName = ".".join([filename, "json"])
    # 写入json
    json_path = os.path.join(save_path, jsonName)
    with open(json_path, "w") as f:
        json.dump(data, f)
    print(json_path, "加载入文件完成...")


if __name__ == '__main__':
    xml_path = r"C:\Users\JoelYang\Desktop\111111\bbox_20230417_gjx"
    # save_path = r"C:\Users\JoelYang\Desktop\111111\bbox_20230417_gjx"
    save_path = xml_path
    for root, dirs, files in os.walk(xml_path):
        for file in files:
            if not file.endswith(".xml"):
                continue
            xml_transform_json(root, file, save_path)

效果如下:

xml文件
在这里插入图片描述
转后的json文件

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/434643.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【鸿蒙应用ArkTS开发系列】- 常量类定义和使用

本篇为入门基础知识介绍,作为代码学习记录使用,请选择性阅读。 一、常量类定义 在ArkTS中,定一个常量很简单,具体如下: export const TAB_HOME_INDEX : number 1;export const TAB_HOME_NAME : string "首…

MobileNetV2详细原理(含torch源码)

目录 MobilneNetV2原理 MobileNetV2的创新点: MobileNetV2对比MobileNetV1 MobilneNetV2源码(torch版) 训练10个epoch的效果 MobilneNetV2原理 MobileNetV2是由谷歌开发的一种用于移动设备的轻量级卷积神经网络。与传统卷积神经网络相比…

RapidOCR调优尝试教程

目录 引言常见错例种类个别字丢失调优篇个别字识别错误调优篇情况一:轻量中英文模型识别对个别汉字识别错误情况二:轻量中英文模型对个别英文或数字识别错误 相关链接 引言 由于小伙伴们使用OCR的场景多种多样,单一的参数配置往往不能满足要…

qt6.2.4下载在线安装

前言 qt官网声明5.15版本以后不提供安装包安装,均需在线安装:Due to The Qt Company offering changes, open source offline installers are not available any more since Qt 5.15。此文主要记录在线安装方法及遇到问题解决方式。 一. 在线安装执行文…

mingw32-make -j$(nproc) 命令含义

系列文章目录 文章目录 系列文章目录前言一、具体操作二、使用步骤 前言 在使用krita源码编译时遇到报错: 这段代码是 Krita 源码中的一个 CMakeLists.txt 文件片段,用于配置 Krita 项目的构建系统。以下是对这段代码的解释: find_package(…

如何写科技论文?(以IEEE会议论文为例)

0. 写在前面 常言道,科技论文犹如“八股文”,有固定的写作模式。本篇博客主要是针对工程方面的论文的结构以及写作链条的一些整理,并不是为了提高或者润色一篇论文的表达。基本上所有的论文,都需要先构思好一些点子,有…

一文带你快速了解业务流程分析和流程建模

🔥业务流程分析与建模 01业务流程分析要了解的问题 有哪些业务流程?业务流程如何完成?业务流程有谁参与?流程中有哪些控制流(如判断、 同步分支和会合)?多个不同流程建的关系?完成…

JUC线程池之线程池架构

JUC线程池之线程池架构 在多线程编程中,任务都是一些抽象且离散的工作单元,而线程 是使任务异步执行的基本机制。随着应用的扩张,线程和任务管理也 变得非常复杂。为了简化这些复杂的线程管理模式,我们需要一个 “管理者”来统一…

SOLIDWORKS Composer如何实现可视化产品交互

SOLIDWORKS Composer是一款让工程师和非工程人员都能够直接访问 3D CAD 模型、并为技术交流材料创建图形内容的 3D 软件。现如今很多制造型企业都已逐步实现其产品设计流程的自动化,以期比竞争对手更快进入市场。但遗憾的是在很多企业中,技术交流内容&am…

Android之修改Jar包源码后再重新打Jar包

一、找到jar包使用框架的github源码,并下载 例如:原有jar包 找到框架源码的github地址: https://github.com/eclipse/paho.mqtt.android 使用git拉取源码项目到本地 二、New Module — 选择Java or Kotlin Library新建 (1&…

RabbitMQ安装教程

目录 Erlang官网 Erlang下载 RabbitMQ官网 windows RabbitMQ docker安装rabbitmq 最近入职新公司,要求会RabbitMQ,所以自学了一下,现将自学的结果总结如下: 安装RabbitMQ之前,需要先安装 Erlang,因为RabbitMQ使用…

【C++初阶】缺省参数与函数重载

一.缺省参数 C祖师爷在用C写代码的时候,就觉得有些地方用着很不方便,于是就在C设计了缺省参数,在实现一些功能时,用这个就方便了许多。 1.概念 缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时&#xff1a…

强训之【井字棋和密码强度等级】

目录 1.井字棋1.1题目1.2思路讲解1.3代码展示 2.密码强度判断2.1题目2.2思路讲解2.3代码 3.选择题 1.井字棋 1.1题目 链接: link 描述 给定一个二维数组board,代表棋盘,其中元素为1的代表是当前玩家的棋子,0表示没有棋子,-1代表…

C/C++每日一练(20230419)

目录 1. 插入区间 2. 单词拆分 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 插入区间 给你一个 无重叠的 ,按照区间起始端点排序的区间列表。 在列表中插入一个新的区间…

数据分析实战(二百零四):项目分析思路 —— 某线下连锁水果店销售数据分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 文章目录 一、问题确认与指标拆解:业务逻辑图 一、问题确认与指标拆解:业务逻辑图 版权声明:本文为博主原创文章,未经博主允许不得转载。

高精度(加法+减法+除法+乘法)合集

由于c/c语言特性,当数很大时,就要考虑精度问题,python和java则不用,因此c学会精度运算很重要的,这里作个总结 1.高精度加法 给定两个正整数(不含前导 0),计算它们的和。 输入格式…

一定要会的算法复杂度分析

本文首发自「慕课网」,想了解更多IT干货内容,程序员圈内热闻,欢迎关注"慕课网"! 原作者:s09g|慕课网讲师 我们知道面对同一道问题时可能有多种解决方案。自然地,我们会将多种方法进行比较。那么…

【Linux】网络协议(应用层与传输层)

应用层传输层协议 应用层HTTP协议格式请求格式响应格式头部字段中的 Cookie (请求头) & Set-Cookie(响应头)cookiesession:会话cookie vs session HTTPS 协议:对 HTTP 协议进行加密 传输层UDP 协议TCP 协议 应用层 序列化:指将多个数组对…

使用shell封装Linux命令实现自定义Linux命令

前言 在日常工作中,尤其是在Linux上做开发的同学或者运维的同学们肯定会遇到过如下场景,比如在Linxu下通过find查找一个文件并且想看这个文件的详细信息,如果直接使用命令可能会一时想不起来,或者想起来了但是有个别参数忘记了。…

SpringMVC02注解与Rest风格

SpringMVC02 SpringMVC的注解 一、RequestParam 1、RequestParam注解介绍 位置:在方法入参位置作用:指定参数名称,将该请求参数 绑定到注解参数的位置属性 name:指定要绑定的请求参数名称; name属性和value属性互为…