【labelme】批量将.json文件转换成mask.png等文件

目录

  • labelme安装(ubuntu)
  • 修改labelme环境中的代码文件
  • 批量转换
  • label.png图片可视化
  • 经验小记录
  • 参考

labelme安装(ubuntu)

如果你不是ubuntu系统,那你再自己百度下安装方法吧,也差不多的。

最好是新建一个专门用于标注工作的anaconda环境,方面管理。安装命令如下:

conda create -n labelme python=3.6
source activate labelme
conda install pyqt
pip install labelme

修改labelme环境中的代码文件

找到labelme环境安装位置的json_to_dataset.py文件,我这个文件所在的位置为/home/yee/anaconda3/envs/labelme/lib/python3.6/site-packages/labelme/cli/json_to_dataset.py,打开该文件,并将其中的代码替换为一下内容:

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')   # 标注文件json所在的文件夹
    parser.add_argument('-o', '--out', default=None)
    args = parser.parse_args()

    json_file = args.json_file

    list = os.listdir(json_file)   # 获取json文件列表
    for i in range(0, len(list)):
        path = os.path.join(json_file, list[i])  # 获取每个json文件的绝对路径
        filename = list[i][:-5]       # 提取出.json前的字符作为文件名,以便后续保存Label图片的时候使用
        extension = list[i][-4:]
        if extension == 'json':
            if os.path.isfile(path):
                data = json.load(open(path))
                img = utils.image.img_b64_to_arr(data['imageData'])  # 根据'imageData'字段的字符可以得到原图像
                # lbl为label图片(标注的地方用类别名对应的数字来标,其他为0)lbl_names为label名和数字的对应关系字典
                lbl, lbl_names = utils.shape.labelme_shapes_to_label(img.shape, data['shapes'])   # data['shapes']是json文件中记录着标注的位置及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])[:-5]+'_json'
                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, '{}_source.png'.format(filename)))
                PIL.Image.fromarray(lbl).save(osp.join(out_dir, '{}_mask.png'.format(filename)))
                #PIL.Image.fromarray(lbl_viz).save(osp.join(out_dir, '{}_viz.jpg'.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()

批量转换

安装好labelme之后,使用labelme对图片进行标注,可以得到与每张图片相对应的.json文件,一般所有的.json文件和所有的图片都放在同一个文件夹中。

  1. 创建一个文件夹(该文件夹是用来存放你转换后的文件的)
  2. 点击进去文件夹后右键并选择“打开终端
  3. 激活labelme环境
  4. 在终端输入命令:labelme_json_to_dataset + (.json文件所在的文件夹),例如我的命令是labelme_json_to_dataset ../JSONFiless(我的.json文件放在现在所在文件夹的上层目录的JSONFiless文件夹下)

label.png图片可视化

你会发现转换生成的label.png图片一团黑,不要怀疑,就是这样的,因为背景的像素值为0,而有标注目标的位置的像素值也是很小的,例如1、2、3等等,所以看不出来。如果你想查看到底转换后的效果是咋样的,一个方法是导入到matlab中,直接看图片的像素矩阵;另一个方法是将label.png转换为彩色图片,python代码如下:

## 查看PennFudanPed数据集中的图片和mask等数据
from PIL import Image
mask = Image.open('label.png').convert('L')

mask.putpalette([0, 0, 0,     # putpalette给对象加上调色板,相当于上色:背景为黑色,目标1为红色,目标2为黄色,目标3为橙色(如果你的图中有更多的目标,可以自行添加更多的调色值)
                 255, 0, 0,
                 255, 255, 0,
                 255, 153, 0])
mask.show()  # 查看mask上色后的效果

经验小记录

博主的项目中用到的是Mask R-CNN实例分割,采用的源码包为pytorch官方提供的torchvison0.4版本,在参考官方给出的使用Mask R-CNN进行训练的教程代码中可以看到它使用的数据集格式为原图和mask图(也是全黑的),而我的数据集是使用labelmepng图片进行标注得到的.json文件,如果完全按照教程的来做的话,那我得正如上面教程所做的那样先将.json文件转换为mask图,但其实不用。我们可以直接在代码中将.json文件转换为mask图,具体的方法是可以根据上面的代码进行修改,这里贴一贴数据集类的一小段代码吧:

def __init__(self, root, transforms=None):
    self.root = root
    self.transforms = transforms

    self.imgs = list(sorted(os.listdir(os.path.join(root, 'PNGImages'))))
    self.jsons = list(sorted(os.listdir(os.path.join(root, 'JSONFiles'))))

def __getitem__(self, idx):
    img_path = os.path.join(self.root, 'PNGImages', self.imgs[idx])
    json_path = os.path.join(self.root, 'JSONFiles', self.jsons[idx])
        
    img = Image.open(img_path).convert('RGB')
    data = json.load(open(json_path))
    #mask = Image.open(mask_path).convert('L')  # 使用mask.mode可以知道读进来的mask图片格式是I,也就是32位整形数据,因此要转化为L格式
    # 改成直接从json文件中读取的形式
    mask, label_names = utils.shape.labelme_shapes_to_label(img.size, data['shapes'])

    obj_ids = np.unique(mask)  # 去除数组中重复的数字,并进行排序
    obj_ids = obj_ids[1:]  # 去除第一个索引,因为它是背景
    masks = mask == obj_ids[:, None, None]  # split the color-encoded mask into a set of binary masks

参考

  1. labelme安装及使用
  2. 批量将.json文件转换成img.png;label.png;label_name.txt;label_viz.pgn;info.yaml文件
  3. 手把手教你训练自己的Mask R-CNN图像实例分割模型(PyTorch官方教程)

你可能感兴趣的:(深度视觉)