对了,我最近开通了微信公众号,计划是两边会同步更新,并逐步的会将博客上的文章同步至公众号中。
感兴趣的朋友可以扫描下方的二维码或者搜索“里先森sements”来关注,欢迎来玩~!
为了实现批量将 labelme 工具标注的数据转换为图像,本文的代码通过循环调用 labelme 库中原有的 labelme_json_to_dataset 方法,转换指定文件夹中的所有 json 文件,并抽取对应图片至各自文件夹。此外,还介绍了如何修改标签在图像中的颜色的方法。
目录
1 - 源码
2 - 使用方法
3 - 如何替换图中标签的颜色
# 调用labelme库中原有的 labelme_json_to_dataset 为核心
# 批量将文件夹中的json文件转换,并抽取对应图片至各自文件夹
import os
import shutil
import argparse
def GetArgs():
parser = argparse.ArgumentParser(description='将labelme标注后的json文件批量转换为图片')
parser.add_argument('--input', '-i', required=True, help='json文件目录')
parser.add_argument('--out-mask', '-m', required=True, help='mask图存储目录')
parser.add_argument('--out-img', '-r', help='json文件中提取出的原图存储目录')
parser.add_argument('--out-viz', '-v', help='mask与原图合并viz图存储目录')
return parser.parse_args()
if __name__ == '__main__':
_args = GetArgs()
_jsonFolder = _args.input
input_files = os.listdir(_jsonFolder)
for sfn in input_files: # single file name
if (os.path.splitext(sfn)[1] == ".json"): # 是否为json文件
# 调用labelme_json_to_dataset执行转换,输出到 temp 文件夹
os.system("labelme_json_to_dataset %s -o temp" % (_jsonFolder + '/' + sfn))
# 复制json文件中提取出的原图到存储目录
if _args.out_img:
if not os.path.exists(_args.out_img): # 文件夹是否存在
os.makedirs(_args.out_img)
src_img = "temp\img.png"
dst_img = _args.out_img + '/' + os.path.splitext(sfn)[0] + ".png"
shutil.copyfile(src_img, dst_img)
# 复制mask图到存储目录
if _args.out_mask:
if not os.path.exists(_args.out_mask): # 文件夹是否存在
os.makedirs(_args.out_mask)
src_mask = "temp\label.png"
dst_mask = _args.out_mask + '/' + os.path.splitext(sfn)[0] + ".png"
shutil.copyfile(src_mask, dst_mask)
# 复制viz图到存储目录
if _args.out_viz:
if not os.path.exists(_args.out_viz): # 文件夹是否存在
os.makedirs(_args.out_viz)
src_viz = "temp\label_viz.png"
dst_viz = _args.out_viz + '/' + os.path.splitext(sfn)[0] + ".png"
shutil.copyfile(src_viz, dst_viz)
首先,请按照 labelme 项目 (GitHub - wkentaro/labelme: Image Polygonal Annotation with Python (polygon, rectangle, circle, line, point and image-level flag annotation).) 中的说明,在 Anaconda 的虚拟环境中完成安装步骤。将上面的代码保存为 python 文件,在安装了 labelme 的虚拟环境中执行。
该代码会调用 labelme 库中原有的 labelme_json_to_dataset 程序,批量将文件夹中的JSON 数据文件转换为图像,并抽取对应图片存放至用户设定的路径下。最终生成的 temp 文件夹是临时产物,可以选择保留或者删除。
例如,待转换的 JSON 文件同本代码保存在同一目录,希望抽取出的原图存储在 /img 路径下,标注图存储在 /mask 路径下,标注可视化图存储在 /viz 路径下。那么,可以在终端中执行如下指令:
python trans.py -i ./ -r img -m mask -v viz
在使用 labelme_json_to_dataset 对 labelme 标注得到的 JSON 文件进行转换时,默认会根据 label 顺序生成一颜色表 (colormap)。在 labelme 4.6.0 版本下,如若想自定义导出图中各标签颜色,仅需对该颜色表进行修改。
打开你已安装好 labelme 的 Anaconda 环境文件夹,找到其下的 labelme 包。在 Windows 下的完整路径为:
anaconda安装目录\envs\安装了labelme的环境名\Lib\site-packages\labelme
打开 utils_io.py 文件,其内容如下:
import os.path as osp
import numpy as np
import PIL.Image
def lblsave(filename, lbl):
import imgviz
if osp.splitext(filename)[1] != ".png":
filename += ".png"
# Assume label ranses [-1, 254] for int32,
# and [0, 255] for uint8 as VOC.
if lbl.min() >= -1 and lbl.max() < 255:
lbl_pil = PIL.Image.fromarray(lbl.astype(np.uint8), mode="P")
colormap = imgviz.label_colormap()
lbl_pil.putpalette(colormap.flatten())
lbl_pil.save(filename)
else:
raise ValueError(
"[%s] Cannot save the pixel-wise class label as PNG. "
"Please consider using the .npy format." % filename
)
其中,imgviz 为 labelme 作者自己编写的库,imgviz.label_colormap 方法可以根据 label 的数量生成用于赋值颜色的 colormap。
imgviz.label_colormap方法的文件链接:imgviz/label.py at main · wkentaro/imgviz · GitHub
关于 PIL (Python Imaging Library) 中 putpalette 的介绍:Image Module — Pillow (PIL Fork) 9.0.0 documentation
知道了原理,接下来便可着手对其修改。例如在我们的标注中仅有一个标签,并且想要将其颜色修改为白色 (255,255,255),我们仅需在 imgviz.label_colormap() 操作后对 colormap 变量修改即可。注意,colormap 的第一个元素标记的是背景色,因此在修改第一个标签时,应当修改的元素下标为 "1" 而非 "0"。
...
colormap = imgviz.label_colormap()
colormap[1] = [255,255,255] # change label color
lbl_pil.putpalette(colormap.flatten())
...
colormap[1] = [255,255,255]
colormap[0] = [255,255,255]
值得一提的是,labelme_json_to_dataset 命令所调用的 json_to_dataset.py 文件存放于 Lib\site-packages\labelme\cli 文件夹下,参阅该文件可以了解更多将标注数据转换为图像的具体细节。