由于我们使用labelme打标签工具生成的标签文件格式为json,但是在做语义分割训练任务的时候,是根据图像像素值种类训练,所以往往需要我们提供的标签labels是单通道8位标签图像。
要想将json转换成单通道8位图像,分为以下两步骤。
1、先将某一个文件夹下的一系列json文件转成png图片,再统一把这些抓好的png图片存到一个新创建的文件夹下,代码如下,其中你需要修改两个地方:json_file路径、label_name_to_value种类
import json
import os
import os.path as osp
import PIL.Image
import yaml
from labelme import utils
import base64
"""
先将某一个文件夹下的一系列json文件转成png图片
再统一把这些抓好的png图片存到一个新创建的文件夹下
需要修改:json_file路径、label_name_to_value
"""
def main():
# json_file = r"F:\datasets\Team_segmentation_datasets\static_category_02\json" # json文件夹下有很多json格式文件
json_file = r"F:\datasets\Team_segmentation_datasets\motion_static"
count = os.listdir(json_file)
for i in range(0, len(count)):
path = os.path.join(json_file, count[i]) # \image00005.json
if os.path.isfile(path):
data = json.load(open(path))
save_file_name = osp.basename(path).replace('.', '_') # image00001_json
# 创建\labelme_json文件夹
if not osp.exists(json_file + '\\' + 'labelme_json'):
os.mkdir(json_file + '\\' + 'labelme_json')
labelme_json = json_file + '\\' + 'labelme_json' # \labelme_json
# 创建\labelme_json\image00001_json文件夹
out_dir = labelme_json + '\\' + save_file_name
if not osp.exists(out_dir):
os.mkdir(out_dir)
if data['imageData']:
imageData = data['imageData']
else:
print(f"当前json文件没有查到imageData")
sys.exit()
img = utils.img_b64_to_arr(imageData) # 将Base64编码的图像数据解码为图像数组
# label_name_to_value = {'_background_': 0, 'road': 1, "solid_line": 2, "dotted_line": 3, "crosswalk": 4} # 静止类别
# label_name_to_value = {'_background_': 0, 'car': 1, "person": 2, "motorcycle": 3, "bus": 4, 'bicyclist': 5, 'tricycle': 6, "large_truck": 7, "small_truck": 8} # 运动类别
label_name_to_value = {'_background_': 0, 'road': 1, "solid_line": 2, "dotted_line": 3, "crosswalk": 4,
'car': 5, "person": 6, "motorcycle": 7, "bus": 8, 'bicyclist': 9,
'tricycle': 10, "large_truck": 11, "small_truck": 12}
for shape in data['shapes']:
label_name = shape['label']
if label_name in label_name_to_value:
label_value = label_name_to_value[label_name]
else:
print(f"当前label_name:{label_name}不在已设定的label_name_to_value中")
sys.exit()
# label_values must be dense
label_values, label_names = [], []
for ln, lv in sorted(label_name_to_value.items(), key=lambda x: x[1]):
label_values.append(lv) # [0, 1, 2, 3, 4]
label_names.append(ln) # ['_background_', 'road', 'solid_line', 'dotted_line', 'crosswalk']
# print(label_values,label_names)
lbl = utils.shapes_to_label(img.shape, data['shapes'], label_name_to_value)
captions = ['{}: {}'.format(lv, ln) for ln, lv in label_name_to_value.items()]
lbl_viz = utils.draw_label(lbl, img, captions)
PIL.Image.fromarray(img).save(out_dir + '\\' + save_file_name + '_img.png')
utils.lblsave(osp.join(out_dir, save_file_name + '_label.png'), lbl)
PIL.Image.fromarray(lbl_viz).save(out_dir + '\\' + save_file_name +'_label_viz.png')
with open(osp.join(out_dir, 'label_names.txt'), 'w') as f:
for lbl_name in label_names:
f.write(lbl_name + '\n')
info = dict(label_names=label_names)
with open(osp.join(out_dir, 'info.yaml'), 'w') as f:
yaml.safe_dump(info, f, default_flow_style=False)
# save png to another directory,创建\mask_png文件夹
if not osp.exists(json_file + '\\' + 'mask_png'):
os.mkdir(json_file + '\\' + 'mask_png')
mask_save2png_path = json_file + '\\' + 'mask_png'
# utils.lblsave(osp.join(mask_save2png_path, save_file_name + '_label.png'), lbl)
utils.lblsave(osp.join(mask_save2png_path, count[i].replace(".json", "")), lbl)
print('Saved to: %s' % out_dir)
if __name__ == '__main__':
main()
2、经过第一步操作得到的png图像如上,我们还需要转换成单通道8位图像。代码如下:
"""
首先遍历文件夹中的所有RGB图像文件,并将它们转换为灰度图像。
然后,我们统计所有灰度图像的像素值种类和个数,并生成映射规则。
最后,我们将映射规则应用于每张灰度图像,确保相同的像素值种类被映射为相同的值。
需要修改:
input_folder 和 output_folder 路径
"""
import os
import cv2
import numpy as np
input_folder = r"F:\datasets\Team_segmentation_datasets\motion_static\mask_png"
output_folder = r"F:\datasets\Team_segmentation_datasets\motion_static\gray"
# 确保输出文件夹存在,如果不存在则创建
os.makedirs(output_folder, exist_ok=True)
# 列出文件夹中的RGB图像文件
image_files = [f for f in os.listdir(input_folder) if f.endswith(".png")]
# 存储所有灰度图像的像素值
all_pixel_values = []
# 遍历图像文件
for index, image_file in enumerate(image_files):
# 输出当前正在处理的图片文件名
print(f"Processing image {index + 1}/{len(image_files)}: {image_file}")
# 读取RGB图像并转换为灰度图像
rgb_image = cv2.imread(os.path.join(input_folder, image_file), cv2.IMREAD_COLOR)
gray_image = cv2.cvtColor(rgb_image, cv2.COLOR_BGR2GRAY)
# 统计像素值种类和数量
all_pixel_values.extend(np.unique(gray_image))
# 保存灰度图像
cv2.imwrite(os.path.join(output_folder, image_file), gray_image)
# 统计所有灰度图像的像素值种类和个数
all_pixel_values = sorted(list(set(all_pixel_values)))
num_classes = len(all_pixel_values)
# 生成映射规则
mapping = {pixel_value: i for i, pixel_value in enumerate(all_pixel_values)}
print("映射规则:")
for pixel_value, mapped_value in mapping.items():
print(f"Original: {pixel_value}, Mapped: {mapped_value}")
# 将映射规则应用于每张灰度图像
for index, image_file in enumerate(image_files):
# 输出当前正在处理的图片文件名
print(f"Mapping image {index + 1}/{len(image_files)}: {image_file}")
# 读取灰度图像并映射像素值
gray_image = cv2.imread(os.path.join(output_folder, image_file), cv2.IMREAD_GRAYSCALE)
mapped_image = np.vectorize(mapping.get)(gray_image)
# 打印原始值和映射后的新值
for unique_value in np.unique(gray_image):
mapped_value = mapping[unique_value]
print(f"Original: {unique_value}, Mapped: {mapped_value}")
# 保存映射后的图像
cv2.imwrite(os.path.join(output_folder, image_file), mapped_image)
转换好的单通道8位标签图像:
温馨小提示:转换好后你可以检查一下上面的图像各类别的像素值,代码如下:
import os
import cv2
import numpy as np
folder_path = r"F:\datasets\Team_segmentation_datasets\motion_static\gray"
unique_values_all = []
# 遍历文件夹下的图像文件
for filename in os.listdir(folder_path):
if filename.endswith(".png") or filename.endswith(".jpg"):
file_path = os.path.join(folder_path, filename)
# print(f"Processing image: {filename}")
# 读取灰度图像
image = cv2.imread(file_path, cv2.IMREAD_GRAYSCALE)
# 统计像素值种类和个数
unique_values, counts = np.unique(image, return_counts=True)
print(f"{filename}包含的像素值为{unique_values}{counts}")
# 将当前图像的像素值种类和个数添加到整体统计结果中
unique_values_all.extend(unique_values)
# 统计整个文件夹下所有图像的像素值种类和个数
unique_values_all = np.array(unique_values_all)
print(np.unique(unique_values_all))
num_unique_all = len(np.unique(unique_values_all))
print("整个文件夹下所有图像的像素值种类个数:", num_unique_all)
参考文章:Labelme json 批量转datasets 解决默认显示不同色和id问题,包含五个结果(img_png,label_png,label_viz_png,info,names)_json转png颜色不对_中科哥哥的博客-CSDN博客