labelme生成json文件转mask图像标签

正文

目前在做医学影像分割,采用labelme进行数据标注,标注后的数据为json格式,包含了大量标注点数据信息。
现通过代码形式批量将json数据转换为mask图像数据。labelme自带的转换工具不知道为啥只会根据点集形成连接到线条而不会生成mask图,所以干脆自己写了一个。
因为是做虹膜分割,标注时是两个标签 角膜和瞳孔 且角膜包含了瞳孔,所以在做mask时先根据角膜点集做了255mask然后根据瞳孔做0mask来实现角膜分割,如果是别的多类别分割,可根据代码自行修改。

代码如下

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
import argparse
import json
import os
import os
import PIL.Image
import yaml
from labelme import utils
import base64
import numpy as np
import cv2 as cv
from skimage import img_as_ubyte


def parse_arguments():
parser = argparse.ArgumentParser(description="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.add_argument("--input_path", type=str,default='segmentation')
parser.add_argument("--output_path", type=str,default='seg2_mask')
return parser.parse_args()

def main():


args = parse_arguments()
target = args.output_path
if not os.path.exists(target):
os.mkdir(target)
if not os.path.exists(target+'/img/'):
os.mkdir(target+'/img/')
if not os.path.exists(target+'/label/'):
os.mkdir(target+'/label/' )

json_file = args.input_path
count = [e for e in os.listdir(json_file) if e.endswith('.json')]
for i in range(0, len(count)):
path = os.path.join(json_file, count[i])
name = count[i].split('.')[0]
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_b64decode = base64.b64decode(imageData) # base64解码
img_array = np.frombuffer(img_b64decode, np.uint8) # 转换np序列
img = cv.imdecode(img_array, cv.COLOR_BGR2RGB) # 转换Opencv格式

# create mask
mask = np.zeros_like(img, dtype=np.uint8)
# get the points
if len(data["shapes"])<2:
print(count[i])
continue
if data["shapes"][0]['label'] == 'pupil':
points = data["shapes"][1]["points"]
points = np.array(points, dtype=np.int32) # tips: points location must be int32
cv.fillPoly(mask, [points], (255, 255, 255))

points = data["shapes"][0]["points"]
points = np.array(points, dtype=np.int32) # tips: points location must be int32
cv.fillPoly(mask, [points], (0, 0, 0))
else:
points = data["shapes"][0]["points"]
points = np.array(points, dtype=np.int32) # tips: points location must be int32
cv.fillPoly(mask, [points], (255, 255, 255))

points = data["shapes"][1]["points"]
points = np.array(points, dtype=np.int32) # tips: points location must be int32
cv.fillPoly(mask, [points], (0, 0, 0))

cv.imwrite('%s/img/%s.png' % (target, name), img)
cv.imwrite('%s/label/%s.png' % (target, name), mask)




if __name__ == '__main__':
main()

PS: 原始数据路径文件夹中同时包含图像和同名的json数据

格式如下

执行后会在目标文件夹下生成img 和label两个文件夹