【Python-实操】LabelMe to YOLOv8 Converter

news2024/9/22 3:32:54

LabelMe to YOLOv8 Converter

这是一个 Python 脚本,用于将 LabelMe 标注工具导出的 JSON 文件转换为 YOLOv8 格式的标注文件,并同时在图像上绘制标注的多边形。

在这里插入图片描述

功能

  • 读取 LabelMe JSON 文件。
  • 解码并显示图像。
  • classes.txt 文件加载类别标签。
  • 将多边形标注转换为 YOLOv8 的格式。
  • 在图像上绘制多边形标注。
  • 将原始图像和带有标注的图像拼接在一起并保存。
  • 保存 YOLOv8 格式的标注文件。

安装

确保安装了以下依赖包:

  • OpenCV (pip install opencv-python)
  • NumPy (pip install numpy)

使用方法

  1. 将此脚本放置在包含 LabelMe JSON 文件的目录内。
  2. 在同一目录下创建一个 classes.txt 文件,每行一个类别标签。
  3. 运行脚本,并指定 JSON 文件所在的目录作为命令行参数。

命令行参数

  • /path/to/json/files: 包含 LabelMe JSON 文件的目录路径。

示例

python script.py /path/to/json/files

代码

import os
import json
import base64
import cv2
import numpy as np


def draw_polygon(image, points, color=(0, 255, 0), thickness=2):
    """
    在给定图像上绘制一个多边形。

    :param image: 待绘制多边形的图像(numpy数组)
    :param points: 多边形顶点坐标列表
    :param color: 多边形的颜色 (B, G, R)
    :param thickness: 边缘线条厚度
    """
    # 绘制多边形轮廓
    cv2.polylines(image, [np.int32(points)], isClosed=True, color=color, thickness=thickness)
    # 绘制多边形内部
    cv2.fillPoly(image, [np.int32(points)], color=color)


def concat_images(image1, image2):
    """
    拼接两个图像为一个垂直堆叠的图像。

    :param image1: 第一张图像(numpy数组)
    :param image2: 第二张图像(numpy数组)
    :return: 垂直拼接后的图像(numpy数组)
    """
    # 确保两个图像的宽度相同
    max_height = max(image1.shape[0], image2.shape[0])
    max_width = max(image1.shape[1], image2.shape[1])

    # 调整图像大小以匹配最大宽度
    if image1.shape[1] < max_width:
        image1 = cv2.copyMakeBorder(image1, 0, 0, 0, max_width - image1.shape[1], cv2.BORDER_CONSTANT, value=[255, 255, 255])
    if image2.shape[1] < max_width:
        image2 = cv2.copyMakeBorder(image2, 0, 0, 0, max_width - image2.shape[1], cv2.BORDER_CONSTANT, value=[255, 255, 255])

    # 如果需要,调整图像高度以匹配最大高度
    if image1.shape[0] < max_height:
        image1 = cv2.copyMakeBorder(image1, 0, max_height - image1.shape[0], 0, 0, cv2.BORDER_CONSTANT, value=[255, 255, 255])
    if image2.shape[0] < max_height:
        image2 = cv2.copyMakeBorder(image2, 0, max_height - image2.shape[0], 0, 0, cv2.BORDER_CONSTANT, value=[255, 255, 255])

    # 拼接图像
    return np.vstack((image1, image2))


def convert_labelme_to_yolov8(json_dir):
    """
    将 LabelMe 格式的标注转换为 YOLOv8 格式,并绘制多边形到图像上。

    :param json_dir: 包含 LabelMe JSON 文件的目录路径
    """
    # 生成颜色列表
    color_list = [
        (0, 0, 255),  # Red
        (0, 255, 0),  # Green
        (255, 0, 0),  # Blue
        (0, 255, 255),  # Yellow
        (255, 255, 0),  # Cyan
        (255, 0, 255),  # Magenta
        (0, 165, 255),  # Orange
        (203, 192, 255),  # Pink
        (42, 42, 165),  # Brown
        (0, 128, 128),  # Olive
        (128, 128, 0),  # Teal
        (238, 130, 238),  # Violet
        (128, 128, 128),  # Gray
        (192, 192, 192),  # Silver
        (0, 0, 128),  # Maroon
        (128, 0, 128),  # Purple
        (0, 0, 128),  # Navy
        (0, 255, 0),  # Lime
        (0, 255, 255),  # Aqua
        (255, 0, 255),  # Fuchsia
        (255, 255, 255),  # White
        (0, 0, 0),  # Black
        (235, 206, 135),  # Light Blue
        (144, 238, 144),  # Light Green
        (193, 182, 255),  # Light Pink
        (224, 255, 255),  # Light Yellow
        (216, 191, 216),  # Light Purple
        (0, 128, 128),  # Light Olive
        (30, 105, 210),  # Light Brown
        (211, 211, 211)  # Light Gray
    ]

    # 加载类别文件
    classes_file = os.path.join(json_dir, 'classes.txt')
    
    if not os.path.exists(classes_file):
        print("Error: Could not find 'classes.txt' in the specified directory.")
        exit(1)

    with open(classes_file, 'r') as f:
        class_names = [line.strip() for line in f.readlines()]

    # 获取 JSON 文件列表
    json_files = [f for f in os.listdir(json_dir) if f.endswith('.json')]

    for json_file in json_files:
        json_file_path = os.path.join(json_dir, json_file)
        
        # 输出文件名
        output_file_name = json_file.replace('.json', '.txt')
        output_file_path = os.path.join(json_dir, output_file_name)

        # 读取 JSON 文件
        with open(json_file_path, 'r') as f:
            data = json.load(f)

        image_width = data['imageWidth']
        image_height = data['imageHeight']

        # 解码图像数据
        imageData = data.get('imageData')
        if imageData is not None:
            image_data = base64.b64decode(imageData)
            image_np = np.frombuffer(image_data, dtype=np.uint8)
            image = cv2.imdecode(image_np, cv2.IMREAD_COLOR)
            
            # 创建一个副本用于绘制标注
            annotated_image = image.copy()

            # 绘制标注
            for i, shape in enumerate(data['shapes']):
                if shape['shape_type'] == 'polygon':
                    points = np.array(shape['points'], dtype=np.int32)
                    label = shape['label']
                    class_index = class_names.index(label)
                    color = color_list[class_index % len(color_list)]
                    draw_polygon(annotated_image, points, color=color)

            # 保存原始图像
            image_file_name = json_file.replace('.json', '.jpg')
            image_file_path = os.path.join(json_dir, image_file_name)
            cv2.imwrite(image_file_path, image)

            # 将原始图像和带有标注的图像上下拼接
            concatenated_image = concat_images(image, annotated_image)

            # 保存拼接后的图像
            concatenated_image_file_name = json_file.replace('.json', '_check.jpg')
            concatenated_image_file_path = os.path.join(json_dir, concatenated_image_file_name)
            cv2.imwrite(concatenated_image_file_path, concatenated_image)
            
            # 显示带有标注的图像
            cv2.imshow('Annotated Image', concatenated_image)
            cv2.waitKey(0)
            cv2.destroyAllWindows()

        # 开始写入 YOLOv8 格式的文本文件
        with open(output_file_path, 'w') as f:
            for shape in data['shapes']:
                if shape['shape_type'] == 'polygon':
                    label = shape['label']
                    points = shape['points']
                    
                    # 获取类别索引
                    try:
                        class_index = class_names.index(label)
                    except ValueError:
                        print(f"Warning: Label '{label}' not found in 'classes.txt'. Skipping this label.")
                        continue
                    
                    # 归一化坐标
                    normalized_points = []
                    for point in points:
                        x = point[0] / image_width
                        y = point[1] / image_height
                        normalized_points.extend([x, y])

                    # 写入 YOLOv8 格式的行
                    line = f"{class_index} {' '.join(map(str, normalized_points))}\n"
                    f.write(line)

if __name__ == '__main__':
    import sys

    # 从命令行参数获取 JSON 目录
    if len(sys.argv) != 2:
        print("Usage: python script.py /path/to/json/files")
        exit(1)

    json_dir = sys.argv[1]
    convert_labelme_to_yolov8(json_dir)

代码结构

draw_polygon 函数

该函数在给定图像上绘制一个多边形,并填充颜色。

concat_images 函数

该函数将两张图像拼接为一个垂直堆叠的图像。

convert_labelme_to_yolov8 函数

该函数执行以下操作:

  • 读取 classes.txt 文件中的类别标签。
  • 遍历目录中的所有 JSON 文件。
  • 对每个 JSON 文件执行以下操作:
    • 解码并显示图像。
    • 读取 JSON 文件的内容。
    • 在图像上绘制标注的多边形。
    • 将原始图像与带标注的图像拼接。
    • 保存拼接后的图像。
    • 将多边形标注转换为 YOLOv8 格式,并保存为 .txt 文件。

注意事项

  • 确保 classes.txt 文件正确无误地列出了所有的类别标签。
  • 请确保脚本有足够的权限来读写文件。

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

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

相关文章

超有效!这样选的宠物空气净化器真能去浮毛?一款家电助力呼吸道

我那哥们儿&#xff0c;最近家里多了个毛茸茸的小成员——一只小猫。他对这猫好得不得了&#xff0c;俩人几乎是形影不离。可问题来了&#xff0c;小猫一长大&#xff0c;那毛啊&#xff0c;掉得满屋子都是。哥们儿最近就老抱怨&#xff0c;说晚上睡觉喉咙不舒服&#xff0c;问…

LVS是什么?以及LVS-NAT以及DR模式实验

目录 NAT LVS LVS集群的类型&#xff1a; LVS-NAT模式实验 环境准备&#xff1a; 实验步骤&#xff1a; LVS-DR模式实验 题目&#xff1a; 环境准备&#xff1a; 实验步骤&#xff1a; LVS-防火墙标签解决轮询调度问题 环境准备&#xff1a; 实验步骤&#xff1…

springboot疫情隔离酒店管理系统的开发--论文源码调试讲解

1系统成功运行案例 2 相关技术介绍 2.1 B/S模式 B/S模式是一种比较常用的网络结构模式[7]。B/S模式是由MVC结构组成&#xff0c;即模型、视图、控制器是构成该模式的主要结构[8]。模型主要是指业务模型&#xff0c;视图是面向用户而显示的相关界面&#xff0c;控制器主要是控制…

使用 defineNuxtComponent`定义 Vue 组件

title: 使用 defineNuxtComponent定义 Vue 组件 date: 2024/8/9 updated: 2024/8/9 author: cmdragon excerpt: 摘要&#xff1a;本文介绍了在Nuxt 3中使用defineNuxtComponent辅助函数定义类型安全的Vue组件的方法&#xff0c;适用于习惯Options API的开发者。defineNuxtCo…

【Deep-ML系列】Feature Scaling Implementation(特征缩放:standardization min-max)

题目链接&#xff1a;Deep-ML import numpy as np def feature_scaling(data: np.ndarray) -> (np.ndarray, np.ndarray):mean np.mean(data, axis0)std np.std(data, axis0)standardized_data (data - mean) / stdmaxnum np.max(data, axis0)minnum np.min(data, axi…

嵌入式人工智能(OpenCV-基于树莓派的人脸识别与入侵检测)

1、人脸识别 人脸识别是一种技术&#xff0c;通过检测、跟踪和识别人脸上的关键特征&#xff0c;以确认人脸的身份。它通常用于安保系统、身份验证、社交媒体和人机交互等领域。 人脸识别技术的基本原理是先通过图像处理和计算机视觉算法&#xff0c;提取人脸的特征点和特征描…

代理模式Proxy

一、代理模式&#xff08;Proxy&#xff09; 1.代理模式的定义 代理模式给某一个对象提供一个代理对象&#xff0c;并由代理对象控制对真实对象的访问&#xff0c;起到对代理对象已有功能的增强 通俗的来讲代理模式就是我们生活中常见的中介。 2.作用 中介隔离作用&#x…

2024 年的 Node.js 生态系统

数据来源于 Node.js Toolbox&#xff0c;网站展示了 Node.js 生态系统中积极维护且流行的库。

在 Duo S 上使用 TDL SDK 高效部署人脸检测模型

TDL SDK 是一款集成算法开发包&#xff0c;提供了便捷的编程接口&#xff0c;使开发者们能够更快、高效地将各种深度学习技术应用于自己的产品和服务中。无论开发者是否是深度学习领域的专家&#xff0c;有了TDL SDK作为助手&#xff0c;都能轻松构建智能应用。 Milk-V DuoS 是…

7.4.分支限界法概率算法近似算法数据挖掘算法智能优化算法

了解&#xff0c;没有考过&#xff0c;基本上不会考 分支限界法 分支限界法&#xff1a;与回溯法类似&#xff0c;同样是在问题的解空间树上搜索问题解的一种算法&#xff0c;它常以广度优先或以最小耗费&#xff08;最大效益&#xff09;优先的方式搜索问题的解空间树。回溯…

【AI大模型】LangChain框架:示例选择器与输出解析器携手,编织NLP高效精准之网

文章目录 前言一、示例选择器1.介绍及应用2.自定义示例选择器案例&#xff1a;AI点评姓名 3.基于长度的示例选择器案例&#xff1a;对输入内容取反 4.基于最大边际相关性(MMR)的示例选择器案例&#xff1a;得到输入的反义词 5.基于n-gram重叠的示例选择器6.综合案例 二、输出解…

深入探索String AOP想详情

一.AOP的概述 AOP是Spring框架的第⼆⼤核⼼(第⼀⼤核⼼是IoC&#xff09; Q:什么是AOP&#xff1f; A:Aspect Oriented Programming&#xff08;⾯向切⾯编程&#xff09; 什么是⾯向切⾯编程呢? 切⾯就是指某⼀类特定问题, 所以AOP也可以理解为⾯向特定⽅法编程. 什么是⾯向特…

鸿蒙HarmonyOS开发:@Observed装饰器和@ObjectLink装饰器:监听嵌套类对象属性变化

文章目录 一、装饰器二、概述三、限制条件四、装饰器说明五、Toggle组件1、子组件2、接口3、ToggleType枚举4、事件 六、示例演示1、代码2、效果 一、装饰器 State装饰器&#xff1a;组件内状态Prop装饰器&#xff1a;父子单向同步Link装饰器&#xff1a;父子双向同步Provide装…

Linux云计算 |【第二阶段】NETWORK-DAY1

主要内容&#xff1a; 计算机网络概述、网络拓扑结构、OSI参考模型、eNSP、交换机及原理 一、计算机网络概述 计算机网络是指将多台计算机或设备通过通信线路连接起来&#xff0c;以便它们能够相互交换信息和共享资源的系统。计算机网络的目的是实现数据通信和资源共享&#…

生成式人工智能安全评估体系构建

文章目录 前言一、人工智能安全治理的现状1.1 国际安全治理现状1.2 国内安全治理现状二、构建人工智能安全评估体系1.1 需要对生成式人工智能技术的安全性、可靠性、可控性、公平性等维度进行全面的考量。1.2 应对生成式人工智能全维度风险。1.3 在体系化应对框架中,应明确法律…

[Meachines] [Easy] Traverxec Nostromo RCE+SSH-私钥RSA解密+journalctl权限提升

信息收集 IP AddressOpening Ports10.10.10.165TCP:22,80 $ nmap -p- 10.10.10.165 --min-rate 1000 -sC -sV PORT STATE SERVICE VERSION …

nfc苹果手机怎么开启?3招就教会你

在数字化时代&#xff0c;nfc技术已成为智能手机的一项重要功能&#xff0c;它让我们的设备能够进行无线数据交换&#xff0c;实现便捷的移动支付、文件传输等操作。那么&#xff0c;nfc苹果手机怎么开启呢&#xff1f;如果你想要充分利用这一技术&#xff0c;那么本文将为你提…

git推送错误-->远程分支比本地的分支更新,无法直接推送

每次上传本地修改好的代码的时候,十次有八次都会出现这样的问题!!(暴躁!!!) 现在写个帖子记录一下,这个问题目前我还没有解决,欢迎懂的佬指点一下. 情景: 我在本地仓库做了一些代码的修改,准备上传到远程仓库上,下边是上传步骤: git add . # 将所有的修改都提交到缓冲区git …

免费获取!Windows10 32位纯净版:无捆绑更安全!

今日&#xff0c;系统之家小编给大家分享2024最新的Windows10纯净版32位系统&#xff0c;该版本系统不包含任何捆绑软件&#xff0c;系统资源占用少&#xff0c;运作流畅&#xff0c;适合老旧电脑安装。系统安装起来特别简单&#xff0c;推荐大家使用硬盘安装&#xff0c;即便是…

大黄蜂能飞的起来吗?

Bumblebee argument 虽然早期的空气动力学证明大黄蜂不能飞行——因为体重太重&#xff0c;翅膀太薄&#xff0c;但大黄蜂并不知道&#xff0c;所以照飞不误。 背景 在20世纪初&#xff0c;‌科学家们通过研究发现&#xff0c;‌大黄蜂的身体与翼展的比例失调&#xff0c;‌按照…