[YOLOv8] 缺陷检测之AnyLabeling标注格式转换成YOLO格式

18 篇文章 12 订阅

源代码说明

包含对应的python代码,测试用到的图像及其标注文件。

https://download.csdn.net/download/u011775793/88631532

如何使用AnyLabeling进行图像标注?

可以参考: [YOLOv8] - 使用AnyLabeling对数据集进行标注(含安装和使用技巧)

什么是YOLO格式数据集?

可以参考:[YOLOv8] - YOLO数据集格式介绍和案例

转换AnyLabeling的标注数据集为YOLO数据集

编程思路

读取AnyLabeling标注目录底下的所有json文件,遍历并逐个解释每个json文件,根据json中提供的数据(比如,被标注图像的相对路径,标注目标所在位置等),动态生成YOLO格式的图像和标注数据,分别保存到images和labels目录,最后把类别文件classes.txt也复制到目标目录。

源代码

import base64
import os
import json
import shutil
from pathlib import Path
from glob import glob

from wepy import GLOBAL_ENCODING, get_logger, init_logger
from wepy.helper import str_helper


def labelme_to_yolo(label_me_json_file, cls2id_dict):
    label_me_json = json.load(open(label_me_json_file, mode='r', encoding=GLOBAL_ENCODING))
    shapes = label_me_json['shapes']
    img_width, img_height = label_me_json['imageWidth'], label_me_json['imageHeight']
    img_path = label_me_json['imagePath']
    img_data = label_me_json['imageData'] if 'imageData' in label_me_json else ''

    labels = []
    for s in shapes:
        s_type = s['shape_type']
        s_type = s_type.lower()
        if s_type == 'rectangle':
            pts = s['points']
            x1, y1 = pts[0]  # left corner
            x2, y2 = pts[1]  # right corner
            x = (x1 + x2) / 2 / img_width
            y = (y1 + y2) / 2 / img_height
            w = abs(x2 - x1) / img_width
            h = abs(y2 - y1) / img_height
            cid = cls2id_dict[s['label']]
            labels.append(f'{cid} {x} {y} {w} {h}')

    return labels, img_path, img_data


class LabelMe2YoloConverter:
    def __init__(self, labelme_label_dir, labelme_classes_file, yolo_save_dir, clear_yolo_save_dir=False):
        self.labelme_label_dir = labelme_label_dir
        self.yolo_save_dir = yolo_save_dir
        self.labelme_classes_file = labelme_classes_file
        self.clear_yolo_save_dir = clear_yolo_save_dir

    def get_cls2id_dict(self):
        cls2id_dict = {}
        with open(self.labelme_classes_file) as f:
            for cls_id, cls_name in enumerate(f.readlines()):
                cls_name = cls_name.strip()
                if cls_name != '':
                    cls2id_dict[cls_name] = cls_id

        return cls2id_dict

    def convert(self):
        yolo_dir = Path(self.yolo_save_dir)
        if self.clear_yolo_save_dir:
            shutil.rmtree(yolo_dir)
            get_logger().info(f'clear yolo save dir. yolo_dir:{yolo_dir}')
        yolo_label_dir = yolo_dir.joinpath('labels')
        yolo_image_dir = yolo_dir.joinpath('images')
        os.makedirs(yolo_label_dir, exist_ok=True)
        os.makedirs(yolo_image_dir, exist_ok=True)
        label_dir = Path(self.labelme_label_dir)
        if label_dir.exists():
            cls2id_dict = self.get_cls2id_dict()
            json_files = glob(pathname='*.json', root_dir=self.labelme_label_dir)
            total = len(json_files)
            for idx, json_file in enumerate(json_files):
                try:
                    json_file = os.path.join(self.labelme_label_dir, json_file)
                    get_logger().info(f'convert label. total:{total}, idx:{idx + 1}, json_file:{json_file}')
                    filename = os.path.basename(json_file).rsplit('.', 1)[0]
                    labels, img_path, img_data = labelme_to_yolo(json_file, cls2id_dict)
                    img_prefix = str_helper.get_md5(img_path, prefix_len=8)
                    if len(labels) > 0:
                        src_img_path = Path(label_dir).joinpath(img_path)
                        src_img_path = os.path.normpath(src_img_path)  # 正规化路径,对路径中的.和..进行转换
                        src_img_name = os.path.basename(src_img_path)
                        target_img_path = Path(yolo_image_dir).joinpath(f'{img_prefix}_{src_img_name}')
                        if os.path.exists(src_img_path):
                            shutil.copy(src_img_path, target_img_path)
                            get_logger().info(f'save yolo img by imagePath. yolo_img_path:{target_img_path}')
                        elif img_data != '':
                            with open(target_img_path, mode='wb') as f:
                                f.write(base64.b64decode(img_data))
                            get_logger().info(f'save yolo img by imageData. yolo_img_path:{target_img_path}')
                        else:
                            get_logger().error(
                                f'save yolo img fail for no imagePath or imageData. json_file:{json_file}')
                            continue

                        yolo_label_path = Path(yolo_label_dir).joinpath(f'{img_prefix}_{filename}.txt')
                        with open(yolo_label_path, mode='w', encoding=GLOBAL_ENCODING) as f:
                            f.write('\n'.join(labels))
                        get_logger().info(f'save yolo label. yolo_label_path:{yolo_label_path}')
                    else:
                        get_logger().error(f'there is no labels found. json_file:{json_file}')
                except Exception as e:
                    get_logger().exception(f'exception happen when convert. ex:{e}, json_file:{json_file}')

            target_classes_file = Path(yolo_dir).joinpath('classes.txt')
            shutil.copy(self.labelme_classes_file, target_classes_file)
            get_logger().info(f'save yolo label classes. labelme_classes_file:{self.labelme_classes_file},'
                              f'yolo_classes_file:{target_classes_file}')
        else:
            get_logger().error(f'The labelme label dir is not found. labelme_label_dir:{self.labelme_label_dir}')


if __name__ == '__main__':
    init_logger('./logs/format_convert.log')
    g_labelme_classes_file = 'D:/YOLOv8Train/anylabeling_datasets/mktk_datasets/cut_640_labels/classes.txt'
    g_labelme_label_dir = 'D:/YOLOv8Train/anylabeling_datasets/mktk_datasets/cut_640_labels/'
    g_yolo_save_dir = 'D:/YOLOv8Train/v8_origin_datasets/mktk_dataset/'
    labelme_converter = LabelMe2YoloConverter(g_labelme_label_dir, g_labelme_classes_file, g_yolo_save_dir, True)
    labelme_converter.convert()

运行结果

AnyLabeling的图像目录:

AnyLabeling的标注目录和类别文件:

生成的YOLO格式数据集:

 

  • 22
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老狼IT工作室

你的鼓励将是我创作的最大动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值