Labelme标注工具 json文件批量转化 labelme_json_to_dataset 多个版本代码集合

一、Labelme标注工具安装

https://github.com/wkentaro/labelme
安装过程按照github教程就好,上面说的很详细,没遇到啥问题。

二、json文件批量执行转化

大家用到最多的就是 json文件的转化了,但是labelme自带转化工具,只能支持一次转化一个.json文件,所以需要修改代码,使得可以批量执行。
在lableme安装目录下有D:\Anaconda3\envs\labelme\Lib\site-packages\labelme\cli目录,可以看到json_to_dataset.py文件,将下面代码复制替换其中内容即可。

运行:

python D:\Anaconda3\envs\labelme\Scripts\labelme_json_to_dataset.exe I:\xj\Mask_RCNN_dataset\json

路径只需要输入到文件夹即可,不需要具体指定json文件。看你的根目录在哪里,就去哪里找输出文件,会生成一些跟.json同名的文件夹。

这里一共提供三个版本:
转自:https://blog.youkuaiyun.com/yql_617540298/article/details/81110685

代码1、

import argparse
import json
import os
import os.path as osp
import warnings
 
import PIL.Image
import yaml
 
from labelme import utils
import base64
 
def main():
    warnings.warn("This script is aimed to demonstrate how to convert the\n"
                  "JSON file to a single image dataset, and not to handle\n"
                  "multiple JSON files to generate a real-use dataset.")
    parser = argparse.ArgumentParser()
    parser.add_argument('json_file')
    parser.add_argument('-o', '--out', default=None)
    args = parser.parse_args()
 
    json_file = args.json_file
    if args.out is None:
        out_dir = osp.basename(json_file).replace('.', '_')
        out_dir = osp.join(osp.dirname(json_file), out_dir)
    else:
        out_dir = args.out
    if not osp.exists(out_dir):
        os.mkdir(out_dir)
 
    count = os.listdir(json_file) 
    for i in range(0, len(count)):
        path = os.path.join(json_file, count[i])
        if os.path.isfile(path):
            data = json.load(open(path))
            
            if data['imageData']:
                imageData = data['imageData']
            else:
                imagePath = os.path.join(os.path.dirname(path), 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)
            label_name_to_value = {'_background_': 0}
            for shape in data['shapes']:
                label_name = shape['label']
                if label_name in label_name_to_value:
                    label_value = label_name_to_value[label_name]
                else:
                    label_value = len(label_name_to_value)
                    label_name_to_value[label_name] = label_value
            
            # label_values must be dense
            label_values, label_names = [], []
            for ln, lv in sorted(label_name_to_value.items(), key=lambda x: x[1]):
                label_values.append(lv)
                label_names.append(ln)
            assert label_values == list(range(len(label_values)))
            
            lbl = utils.shapes_to_label(img.shape, data['shapes'], label_name_to_value)
            
            captions = ['{}: {}'.format(lv, ln)
                for ln, lv in label_name_to_value.items()]
            lbl_viz = utils.draw_label(lbl, img, captions)
            
            out_dir = osp.basename(count[i]).replace('.', '_')
            out_dir = osp.join(osp.dirname(count[i]), out_dir)
            if not osp.exists(out_dir):
                os.mkdir(out_dir)
 
            PIL.Image.fromarray(img).save(osp.join(out_dir, 'img.png'))
            #PIL.Image.fromarray(lbl).save(osp.join(out_dir, 'label.png'))
            utils.lblsave(osp.join(out_dir, 'label.png'), lbl)
            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')
 
            warnings.warn('info.yaml is being replaced by label_names.txt')
            info = dict(label_names=label_names)
            with open(osp.join(out_dir, 'info.yaml'), 'w') as f:
                yaml.safe_dump(info, f, default_flow_style=False)
 
            print('Saved to: %s' % out_dir)
if __name__ == '__main__':
    main()

但是存在两个问题

问题一:

对于多类分割任务,任意一张图可能不包含所有分类。因此整个文件夹下生成的所有label图像中,不同图像中的相同类别的目标在label.png中可能对应不同的灰度值,使标注的label不具备统一性,因而出错。如下图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
从以上三个图可以看出,有的猫和狗被标注成了同一种像素值,造成了标注错乱现象,所以大家使用时候这里注意。

问题二:

生成的 label.png,为 rgb三通道彩色图,并不是灰度图,想要灰度图,请看代码2

代码2、

转自:https://blog.youkuaiyun.com/u010103202/article/details/81635436#commentsedit

import argparse
import json
import os
import os.path as osp
import warnings
import copy


import numpy as np
import PIL.Image
from skimage import io
import yaml

from labelme import utils

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('json_file')
    parser.add_argument('-o', '--out', default=None)
    args = parser.parse_args()

    json_file = args.json_file

    list = os.listdir(json_file)
    for i in range(0, len(list)):
        path = os.path.join(json_file, list[i])
        filename = list[i][:-5]       # .json
        if os.path.isfile(path):
            data = json.load(open(path))
            img = utils.image.img_b64_to_arr(data['imageData'])
            lbl, lbl_names = utils.shape.labelme_shapes_to_label(img.shape, data['shapes'])  # labelme_shapes_to_label

            captions = ['%d: %s' % (l, name) for l, name in enumerate(lbl_names)]
            lbl_viz = utils.draw.draw_label(lbl, img, captions)
            out_dir = osp.basename(list[i]).replace('.', '_')
            out_dir = osp.join(osp.dirname(list[i]), out_dir)
            if not osp.exists(out_dir):
                os.mkdir(out_dir)

            PIL.Image.fromarray(img).save(osp.join(out_dir, '{}.png'.format(filename)))
            PIL.Image.fromarray(lbl).save(osp.join(out_dir, '{}_gt.png'.format(filename)))
            PIL.Image.fromarray(lbl_viz).save(osp.join(out_dir, '{}_viz.png'.format(filename)))

            with open(osp.join(out_dir, 'label_names.txt'), 'w') as f:
                for lbl_name in lbl_names:
                    f.write(lbl_name + '\n')

            warnings.warn('info.yaml is being replaced by label_names.txt')
            info = dict(label_names=lbl_names)
            with open(osp.join(out_dir, 'info.yaml'), 'w') as f:
                yaml.safe_dump(info, f, default_flow_style=False)

            print('Saved to: %s' % out_dir)


if __name__ == '__main__':
    main()

这个能生成灰度图,但是还是存在 标注的label不具备统一性 的问题,请看代码3。

代码3、

为了解决以上问题,修改代码如下,

import argparse
import json
import os
import os.path as osp
import warnings
import copy

import numpy as np
import PIL.Image
from skimage import io
import yaml

from labelme import utils

NAME_LABEL_MAP = {
    '_background_': 0,
    "baseball_diamond": 1,
    "tennis_court": 2,
    "basketball_court": 3,
    "ground_track_field": 4,
}

LABEL_NAME_MAP = {
    0: '_background_',
    1: "airplane",
    2: "ship",
    3: "storage_tank",
    4: "baseball_diamond",
    5: "tennis_court",
    6: "basketball_court",
    7: "ground_track_field",
    8: "harbor",
    9: "bridge",
    10: "vehicle",
}


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('json_file')
    parser.add_argument('-o', '--out', default=None)
    args = parser.parse_args()

    json_file = args.json_file

    list = os.listdir(json_file)
    for i in range(0, len(list)):
        path = os.path.join(json_file, list[i])
        filename = list[i][:-5]       # .json
        if os.path.isfile(path):
            data = json.load(open(path))
            img = utils.image.img_b64_to_arr(data['imageData'])
            lbl, lbl_names = utils.shape.labelme_shapes_to_label(img.shape, data['shapes'])  # labelme_shapes_to_label

            # modify labels according to NAME_LABEL_MAP
            lbl_tmp = copy.copy(lbl)
            for key_name in lbl_names:
                old_lbl_val = lbl_names[key_name]
                new_lbl_val = NAME_LABEL_MAP[key_name]
                lbl_tmp[lbl == old_lbl_val] = new_lbl_val
            lbl_names_tmp = {}
            for key_name in lbl_names:
                lbl_names_tmp[key_name] = NAME_LABEL_MAP[key_name]

            # Assign the new label to lbl and lbl_names dict
            lbl = np.array(lbl_tmp, dtype=np.int8)
            lbl_names = lbl_names_tmp

            captions = ['%d: %s' % (l, name) for l, name in enumerate(lbl_names)]
            lbl_viz = utils.draw.draw_label(lbl, img, captions)
            out_dir = osp.basename(list[i]).replace('.', '_')
            out_dir = osp.join(osp.dirname(list[i]), out_dir)
            if not osp.exists(out_dir):
                os.mkdir(out_dir)

            PIL.Image.fromarray(img).save(osp.join(out_dir, '{}.png'.format(filename)))
            PIL.Image.fromarray(lbl).save(osp.join(out_dir, '{}_gt.png'.format(filename)))
            PIL.Image.fromarray(lbl_viz).save(osp.join(out_dir, '{}_viz.png'.format(filename)))

            with open(osp.join(out_dir, 'label_names.txt'), 'w') as f:
                for lbl_name in lbl_names:
                    f.write(lbl_name + '\n')

            warnings.warn('info.yaml is being replaced by label_names.txt')
            info = dict(label_names=lbl_names)
            with open(osp.join(out_dir, 'info.yaml'), 'w') as f:
                yaml.safe_dump(info, f, default_flow_style=False)

            print('Saved to: %s' % out_dir)


if __name__ == '__main__':
    main()

但是此代码可能会报类似错:
IndexError: index 6 is out of bounds for axis 0 with size 4
我已经修改了代码中bug(大神可自行修改),修改后的代码连接:json_to_dataset.py, (请原谅需要挣点积分的我,真的穷)
执行后的图像,如下图所示:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
其中,生成的图片名称跟原标注图片一致,那种黑色的背景图,其实是有图像的,只不过猫咪的像素值为1,狗狗像素值为2。从三个图中可以对比看出,猫咪都被标记为了1,狗狗都被标记为了2,而且生成的为灰度图,解决了代码1出现的两个问题。

<think>嗯,用户的问题是关于在Anaconda环境下安装Labelme工具,并批量转换Labelme生成的JSON文件为数据集的方法。首先,我需要确认安装步骤是否正确。根据引用[1]和[2],用户可能已经尝试过安装但遇到了问题,比如提到的unexpected keyword argument 'width'错误,这可能是因为版本不兼容。所以需要确保安装正确的Labelme版本和相关依赖库,如albumentations、matplotlib等。 然后,用户提到批量转换的问题。Labelme自带的命令只能处理单个JSON文件,用户可能需要编写脚本来自动化处理多个文件。这涉及到如何遍历目录下的所有JSON文件,并逐个调用转换命令。可能需要使用Python的os模块或者shell脚本,不过用户使用的是Anaconda环境,所以Python脚本可能更合适。 另外,用户提供的引用[3]提到了自定义模型的生成,虽然和转换数据没有直接关系,但可能用户后续需要训练模型,所以转换后的数据格式是否符合要求也需要考虑。例如,确保输出的单通道图像正确,可能需要检查转换后的PNG文件是否符合预期。 需要注意的是,引用[1]中的错误信息可能是因为Labelme的某个版本存在bug,所以建议用户安装指定版本,比如5.1.1或更低,以避免出现参数错误。同时,引用[2]提到的安装其他库可能在数据增强或处理时有用,但转换过程中可能不需要,不过最好一并安装以防万一。 总结步骤应该是:创建并激活conda环境,安装Labelme和相关依赖,处理可能的版本问题,然后编写批量转换脚本。此外,还要提醒用户检查输出目录的结构是否正确,以及如何处理转换中的错误,比如文件路径中的空格或特殊字符可能导致的问题。</think>### 步骤详解:Anaconda安装Labelme批量转换方法 #### 1. 创建并激活Anaconda环境 ```bash conda create -n labelme_env python=3.8 # 推荐Python 3.6-3.8版本 conda activate labelme_env ``` #### 2. 安装Labelme及相关依赖 ```bash pip install labelme==5.1.1 # 指定版本避免兼容性问题[^1] pip install albumentations matplotlib imageio opencv-python # 必须的辅助库[^2] ``` #### 3. 验证安装 ```bash labelme --version # 应显示5.x版本 labelme_json_to_dataset --help # 确认转换工具存在 ``` #### 4. 单文件转换测试 ```bash labelme_json_to_dataset input.json -o output_dir # 生成带img.png/label.png的文件夹 ``` #### 5. 批量转换脚本实现 创建`batch_convert.py`: ```python import os import subprocess json_dir = "path/to/json_files" output_root = "path/to/dataset" for filename in os.listdir(json_dir): if filename.endswith(".json"): json_path = os.path.join(json_dir, filename) output_dir = os.path.join(output_root, filename[:-5]) cmd = f"labelme_json_to_dataset {json_path} -o {output_dir}" subprocess.run(cmd, shell=True, check=True) print(f"Converted: {filename}") ``` #### 6. 输出结构说明 ``` dataset/ ├── 1.json/ │ ├── img.png # 原始图像 │ ├── label.png # 单通道标注图 │ ├── label_names.txt │ └── label_viz.png ├── 2.json/ └── ... ``` #### 常见问题解决: - **报错`unexpected keyword argument 'width'`**:降级至labelme 5.1.1版本 - **中文路径问题**:确保路径不含中文/特殊字符 - **内存不足**:分批次处理大尺寸图片
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值