首页 前端知识 将labelme导出的json标签文件转换成分割训练所需要的png格式

将labelme导出的json标签文件转换成分割训练所需要的png格式

2024-05-14 23:05:47 前端知识 前端哥 821 922 我要收藏

由于我们使用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博客

转载请注明出处或者链接地址:https://www.qianduange.cn//article/8719.html
标签
评论
发布的文章

video 自定义视频播放控件

2024-05-26 01:05:25

HTML5 画布绘制海报

2024-05-26 01:05:13

HTML5学习(三)

2024-05-26 01:05:43

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!