• 【数据集制作】用于语义分割,labelme4.5.13版本,实现按照指定颜色生成分割颜色批量转换json文件


    实现按照指定颜色生成分割颜色批量转换json文件、并生成对应的颜色卡(会比原始转换文件多生成mask、pure两个文件夹)


    参考链接


    以下步骤,均在安装了labelme 4.5.13版本下的环境中操作


    我是在相关环境中,找到了labelme这个文件夹,然后用pycharm打开,进行操作的

    (不用跟着我单独创建环境哈,只要在任意一个环境下,安装了labelme,然后再用打开labelme文件夹就可以了)

    本来直接在cmd中指定好labelme的json_to_dataset.py位置运行就可以,但是因为我想要打断点看看具体情况,所以就用pycharm打开工程来查看了

    ❀❀❀❀❀❀❀❀❀❀❀❀❀一点废话分割线❀❀❀❀❀❀❀❀❀❀❀❀❀

    我是单独创建了一个labelme的环境,安装步骤可参考:👉labelme的安装、批量转换方法(版本号4.5.13)

    然后进入到D:\SoftWareInstallMenu\Anaconda3\envs\labelme\Lib\site-packages,右键在pycharm中打开项目,将json_to_dataset.py的内容直接按照我的代码做更改即可(也可以新建一个py文件),然后改为自己待转换的json文件地址即可

    在这里插入图片描述


    如果想像往常一样,直接调用json_to_dataset.py脚本运行,则按照下图进行更改即可

    实现:将指定文件夹下的所有json文件,转化为相应的单个文件夹 + 全部都是标注图像的文件夹

    共有3个参数需要您输入,输入格式为:python json_to_dataset.py --json [xxxx] --out [xxxx]

    • 运行方式1:python json_to_dataset.py --json [xxxx] 将会默认在json的根目录下生成out、mask文件夹
    • 运行方式2:python json_to_dataset.py --json [xxxx] --out [xxxx] 将会在指定目录下生成out、mask文件夹

    在这里插入图片描述


    操作步骤

    建议还是先在pycharm中打开,再做更改,比较方便,也利于阅读代码

    1. 【批量转换】新建一个py文件,复制以下代码,例如json_to_dataset_new.py

    import argparse
    import base64
    import json
    import os
    import os.path as osp
    
    import imgviz
    import PIL.Image
    
    from labelme.logger import logger
    from labelme import utils
    
    import numpy as np
    from PIL import Image, ImageFont, ImageDraw
    
    # 自己的类别英文名称,注意:'_background_'要保留
    cls_name = ['_background_', 'Support', 'Bolt_hole', 'Grouting_hole', 'Cable', 'Pipe', 'Sign', 'Signal_light', 'Railway',
                'PJB', 'Instrument_box', 'Crack', 'Falling_block', 'segment_joint']
    
    # 自己的类别英文名称对应的中文名称
    ch_name = {'_background_': '背景', 'Support': '支架', 'Bolt_hole': '螺栓孔', 'Grouting_hole': '注浆孔', 'Cable': '线缆',
               'Pipe': '罐道', 'Sign': '标识', 'Signal_light': '信号灯', 'Railway': '铁轨', 'PJB': '接线盒', 'Instrument_box': '设备箱',
               'Crack': '裂缝', 'Falling_block': '掉块', 'segment_joint': '管片缝'}
    
    # (255,255,0) 太黄了,就没要
    ctuple = [(0, 0, 0), (255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 0, 255), (0, 255, 255), (128, 0, 0), (0, 128, 0),
              (0, 0, 128), (128, 128, 0), (128, 0, 128), (0, 128, 128), (128, 128, 128), (255, 64, 128)]
    
    
    def create_purepic(colorlist, out_dir, dict=None, add_font=False):
        """
        将colorlist给出的颜色做成颜色图片并保存 (并且拼接在一起)
        :param colorlist: 要转换的颜色列表
        :param out_dir: 保存纯色图片的文件
        :return: 无
        """
        if not os.path.exists(out_dir):
            os.makedirs(out_dir)
    
        pure_size = (300, 300, 3)  # HMC
        # 将纯色图像拼接在一起 尺寸是 WH
        row, col = 3, 5  # 自定义颜色卡上的行数、列数
        new_img = Image.new(mode="RGB", size=(pure_size[1] * col, pure_size[0] * row), color=(255, 255, 255))  # 竖着拼接,固定宽度
        keys = [key for key in dict]  # 字典的keys
    
        for i, color in enumerate(colorlist):
            image = np.zeros(pure_size, dtype=np.uint8)
            for x in range(3):
                if color[x] != 0:
                    image[..., x] = color[x]
    
            image = Image.fromarray(image)
            # add_font=True时,在图片上添加文字
            if add_font:
                font_en = ImageFont.truetype('C:/Windows/Fonts/timesbd.ttf', size=30)  # 粗体
                font_zh = ImageFont.truetype('C:/Windows/Fonts/msyhbd.ttc', 30)  # 微软雅黑 粗体
                draw = ImageDraw.Draw(image)
                if not keys:  # 如果没有指定dict,也就是没有其它的颜色顺序,就按照默认的ctuple中颜色顺序来
                    draw.text((30, 30), f'{i - 1}: {cls_name[i]}' if i > 0 else cls_name[i], font=font_en,
                              fill=(255, 255, 255))  # 英文名
                    draw.text((30, 70), ch_name[cls_name[i]], font=font_zh, fill=(255, 255, 255))  # 中文名
                else:  # 如果指定了颜色顺序,就要按照指定的来
                    draw.text((30, 30), f'{i - 1}: {keys[i]}' if i > 0 else keys[i], font=font_en,
                              fill=(255, 255, 255))  # 英文名
                    draw.text((30, 70), ch_name[keys[i]], font=font_zh, fill=(255, 255, 255))  # 中文名
                draw.text((30, 110), str(color), font=font_en, fill=(255, 255, 255))  # 写上RGB值
    
            image.save(os.path.join(out_dir, f'pure_{i}.jpg'))
            print(f'pure_{i}.jpg had saved.')
    
            new_img.paste(image, (i % col * pure_size[1], i // col * pure_size[0]))
    
        new_img.save(os.path.join(out_dir, 'color.jpg'))
        print('color.jpg is done.')
    
    
    def main():
        # --------------------设置命令行参数---------------------- #
        parser = argparse.ArgumentParser()
        parser.add_argument("--json")
        parser.add_argument("--out", default=None)
        args = parser.parse_args()
        # ----------------------------------------------------- #
    
        # -----------------------设置目录------------------------ #
        # json_dir = args.json  # 待转换的json目录
        json_dir = r'D:\ChromeDownloads\unet-pytorch-main\datasets\before'
    
        root_jsondir = osp.dirname(json_dir)  # 待转换的json目录的上一级目录
    
        assert osp.exists(json_dir), f'\"{json_dir}\" not exists!'
    
        # if args.out is None:
        #     all_out_dir = osp.join(osp.join(root_jsondir, 'out'))  # 默认路径
        # else:
        #     all_out_dir = args.out  # 指定路径
    
        all_out_dir = 'caogao'
    
        if not osp.exists(all_out_dir):
            os.mkdir(all_out_dir)
    
        mask_dir = osp.join(all_out_dir, 'mask')  # 所有mask的存放路径,在out_dir中
        if not osp.exists(mask_dir):
            os.makedirs(mask_dir)
    
        pure_dir = osp.join(all_out_dir, 'pure')  # 类别对应的颜色卡
        if not osp.exists(pure_dir):
            os.makedirs(pure_dir)
        # ------------------------------------------------------ #
    
        # -----------------------开始转换------------------------- #
        filelist = os.listdir(json_dir)  # 文件列表
        label_name_to_value = {"_background_": 0}
    
        for file in filelist:  # 遍历文件列表
            filename, _ = osp.splitext(file)
            path = os.path.join(json_dir, file)  # 文件路径
    
            if os.path.isdir(path) or not file.endswith('.json'):  # 如果是目录或者不是json文件则读取下一个
                continue
    
            son_out = file.replace(".", "_")  # 单个文件目录名称
            out_dir = osp.join(all_out_dir, son_out)  # 兼容out参数  --  总目录 + 文件目录
            if not osp.exists(out_dir):
                os.mkdir(out_dir)
    
            data = json.load(open(path))  # 读取目录标注文件
            imageData = data.get("imageData")
    
            if not imageData:
                imagePath = os.path.join(os.path.dirname(json_dir), data["imagePath"])
                with open(imagePath, "rb") as f:
                    imageData = f.read()
                    imageData = base64.b64encode(imageData).decode("utf-8")
            img = utils.img_b64_to_arr(imageData)
    
            # for shape in sorted(data["shapes"], key=lambda x: x["label"]):  # 将label进行排序
            for shape in data["shapes"]:  # 将label进行排序
                label_name = shape["label"]
                if label_name not in label_name_to_value:
                    label_value = len(label_name_to_value)
                    label_name_to_value[label_name] = label_value
    
            # 存类别名索引
            lbl, _ = utils.shapes_to_label(
                img.shape, data["shapes"], label_name_to_value
            )
    
            # 为了写入label_names.txt,记录该图上有哪些类别
            label_names = [None] * (max(label_name_to_value.values()) + 1)
            for name, value in label_name_to_value.items():
                label_names[value] = name
    
            # 为了做可视化图像label_viz.png,将label、原始图像、类别名称都加到同一张图上进行可视化
            lbl_viz = imgviz.label2rgb(
                lbl, imgviz.asgray(img), label_names=label_names, loc="rb"
            )
    
            PIL.Image.fromarray(img).save(osp.join(out_dir, "img.png"))
            utils.lblsave(osp.join(out_dir, "label.png"), lbl)  # 做label.png,最有用的标签图
            PIL.Image.fromarray(lbl_viz).save(osp.join(out_dir, "label_viz.png"))
    
            with open(osp.join(out_dir, "label_names.txt"), "w") as f:
                for lbl_name in label_names:
                    f.write(lbl_name + "\n")
    
            utils.lblsave(osp.join(mask_dir, filename + ".png"), lbl)  # 保存label.png到maks文件夹
    
            logger.info("Saved to: {}".format(all_out_dir))
    
        # ---------------------绘制类别对应的颜色卡------------------------------ #
        dictlen = len(label_name_to_value)
        create_purepic(ctuple[:dictlen], pure_dir, label_name_to_value, True)  # 只选取类别个数的颜色
    
    
    if __name__ == "__main__":
        main()
    
    	# 可把下面注释打开,把上一行main()先注释掉,看一下纯色图像是什么样子的
        # dict = {'_background_': 0, 'Bolt_hole': 0, 'Support': 0, 'Signal_light': 0, 'Cable': 0, 'Pipe': 0, 'PJB': 0,
        #         'Grouting_hole': 0, 'Sign': 0, 'Railway': 0, 'Falling_block': 0, 'Instrument_box': 0, 'Crack': 0,
        #         'segment_joint': 0}
        #
        # pure_dir = 'caogao_pure'
        # create_purepic(ctuple, pure_dir, dict, True)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187

    2. 【指定颜色映射】⭐

    参考链接:图像分割标注工具labelme各个版本改变标注颜色

    • 在步骤1的文件中,找到utils.lblsave(osp.join(out_dir, "label.png"), lbl),大约100行的位置,在该行的lblsave处,Ctrl+鼠标跳至相应文件中
    • 跳转后,找到16行左右的colormap = imgviz.label_colormap(),在label_colormap()处按下Ctrl+鼠标跳至相应文件中
    • 最终跳转至imgviz/label.py文件中,如下图,在43行左右的下方,添加如下代码:
        color = [(0, 0, 0), (255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 0, 255), (0, 255, 255), (128, 0, 0), (0, 128, 0),
                 (0, 0, 128), (128, 128, 0), (128, 0, 128), (0, 128, 128), (128, 128, 128), (255, 64, 128)]
        for i, c in enumerate(color):
            cmap[i, :] = c
    
    • 1
    • 2
    • 3
    • 4

    注意:这里的ctuple要与步骤1的ctuple保持一致!!!

    在这里插入图片描述


    3. 最终结果

    3.1 结果保存文件夹

    在这里插入图片描述

    3.2 mask文件夹

    在这里插入图片描述

    3.3 pure文件夹

    在这里插入图片描述

    3.4 单个json文件夹

    在这里插入图片描述

  • 相关阅读:
    革命带来的:机械化、电气化、自动化、智能化
    探花交友_第3章_今日佳人功能实现
    GhostNet实战:使用GhostNet实现图像分类任务(一)
    SpringBoot 整合 Dozer 映射框架
    图形学中一些基本知识的总结与复习
    执行ls /dev/pts为什么这么慢?
    uniapp——list列表分页,数据是rows
    Spring Cloud Alibaba 2021.0.1.0 发布:版本号再也不迷糊了
    癫痫脑电信号基础知识
    Spring Cloud Alibaba Nacos注册中心(单机)
  • 原文地址:https://blog.csdn.net/LWD19981223/article/details/126048333