json 파일 대량 변환 - labelme 제조 분할 데이터 집합
8579 단어 화상 분할
사용법
json 파일을 이미지 파일로 변환
labelme 상호작용 인터페이스를 사용하여 표시 결과를 저장하면
.json
파일을 얻을 수 있으며 그 중에서 표시 label 정보를 저장할 수 있습니다.이미지 분할 작업에 대응하는 마크업은 .png
/.bmp
등 형식의 이미지 파일이다.단일 json 파일의 변환은 다음 단계를 통해 수행할 수 있습니다.
(1) 열기
cmd
활성화labelme
환경(2) 실행 labelmejson_to_dataset .json 실제적으로 우리는 폴더 아래의 여러 json 파일을 대량으로 처리하기를 희망한다.이때 우리는
Anaconda \envs\Lib\site-packages\labelme\cli json_to_dataset.py
를 수정해야 한다.블로그의 코드를 참고하여 모듈의 호출에 문제가 있습니다. 모듈의 호출 관계를 수정함으로써 우리는 코드를 다음과 같은 내용으로 썼습니다. (수정 후 비주얼리즈의 label 색깔이 정확하지 않습니다.)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 + '
')
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()
이상의 코드는 json 파일의 label을
png
이미지 파일로 저장할 수 있습니다.그러나 문제가 하나 있다. 여러 종류의 분할 작업에 대해 임의의 그림은 모든 분류를 포함하지 않을 수도 있다.따라서 전체 폴더에서 생성된 모든 label 이미지에서 서로 다른 이미지의 같은 종류의 목표는 label.png
에서 서로 다른 그레이스케일 값에 대응하여 표시된 label이 통일성을 갖추지 못하여 오류가 발생했습니다.이 문제를 해결하기 위해 코드를 다음과 같은 형식으로 변경합니다.
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 + '
')
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 이미지의 목표가 같은 그레이스케일 값에 대응하는 것을 제어하여 모든 이미지에서 탭의 일치성을 확보할 수 있습니다.또한 그림이 저장될 때의 이름을 수정하여 원래 그림의 이름과 일치하도록 했습니다.
벌크 처리 단계는 다음과 같습니다.
labelme
환경을 활성화하고 파일 저장 경로에 들어갑니다.대량 활성화가 가능합니다.그중
E:\json
은 대량 처리를 기다리는 json 파일이 있는 폴더 디렉터리입니다.대량 처리된 파일은 cmd 환경에서 현재 디렉터리에 저장됩니다.폴더에서 ground truth 파일 벌크 가져오기
labelme_json_데이터셋이 생성한 태그 이미지 파일은 모든 json이 대응하는 폴더로 파일이 많으면 수동으로 한 장 한 장 복사하는 노동량이 많기 때문에 아래 코드를 써서 대량 복사를 진행합니다
import os
import random
import shutil
import re
GT_from_PATH = "./jsons"
GT_to_PATH = "./gts"
def copy_file(from_dir, to_dir, Name_list):
if not os.path.isdir(to_dir):
os.mkdir(to_dir)
# 1
# name_list = os.listdir(from_dir)
# # 2
# sample = random.sample(pathDir, 2)
# print(sample)
# 3
for name in Name_list:
try:
# print(name)
if not os.path.isfile(os.path.join(from_dir, name)):
print("{} is not existed".format(os.path.join(from_dir, name)))
shutil.copy(os.path.join(from_dir, name), os.path.join(to_dir, name))
# print("{} has copied to {}".format(os.path.join(from_dir, name), os.path.join(to_dir, name)))
except:
# print("failed to move {}".format(from_dir + name))
pass
# shutil.copyfile(fileDir+name, tarDir+name)
print("{} has copied to {}".format(from_dir, to_dir))
if __name__ == '__main__':
filepath_list = os.listdir(GT_from_PATH)
# print(name_list)
for i, file_path in enumerate(filepath_list):
gt_path = "{}/{}_gt.png".format(os.path.join(GT_from_PATH, filepath_list[i]), file_path[:-5])
print("copy {} to ...".format(gt_path))
gt_name = ["{}_gt.png".format(file_path[:-5])]
gt_file_path = os.path.join(GT_from_PATH, file_path)
copy_file(gt_file_path, GT_to_PATH, gt_name)
GTfrom_PATH를
json
로 설정하면 됩니다.참고 자료
-weixin_41831559 블로그