Source code for fusionlab.utils.labelme
from typing import Sequence
import json
import numpy as np
import os
from glob import glob
from tqdm.auto import tqdm
[docs]
def convert_labelme_json2mask(
class_names: Sequence[str],
json_dir: str,
output_dir: str,
single_mask: bool = True
):
"""
Convert labelme json files to mask files(.png)
Args:
class_names (list): list of class names, background class must be included at first
json_dir (str): path to json files directory
output_dir (str): path to output directory
single_mask (bool): if True, save single mask file with class index(uint8), otherwise save multiple mask files with class index(uint8)
"""
try:
import cv2
except ImportError:
raise ImportError("opencv-python package is not installed")
num_classes = len(class_names)
if num_classes > 255:
raise ValueError("Maximum number of classes is 255")
cls_map = {name: i for i, name in enumerate(class_names)}
print(f"Number of classes: {num_classes}")
print("class name to index: ", cls_map)
json_paths = glob(os.path.join(json_dir, '*.json'))
for path in tqdm(json_paths):
json_data = json.load(open(path))
h = json_data['imageHeight']
w = json_data['imageWidth']
# Draw Object mask
mask = np.zeros((len(class_names), h, w), dtype=np.uint8)
for shape in json_data['shapes']:
if shape["shape_type"] != "polygon":
continue
cls_name = shape['label']
cls_idx = cls_map[cls_name]
points = shape['points']
cv2.fillPoly(
mask[cls_idx],
np.array([points], dtype=np.int32),
255
)
# update backgroud mask
mask[0] = 255-np.max(mask[1:], axis=0)
# Save Mask File
filename = ".".join(os.path.split(path)[-1].split('.')[:-1])
if single_mask:
mask_single = np.argmax(mask, axis=0).astype(np.uint8)
cv2.imwrite(os.path.join(output_dir, f"{filename}.png"), mask_single)
else:
for i, m in enumerate(mask):
cv2.imwrite(os.path.join(output_dir, f'{filename}_{i:03d}.png'), m.astype(np.uint8))
if __name__ == '__main__':
convert_labelme_json2mask(
['bg', 'dog', 'cat'],
"json",
"mask",
single_mask=True,
)