labelme json文件转换并制作语义分割数据集

项目场景:

【语义分割】用Pytorch deeplabv3+ 训练自己的数据

参考博文
PYTORCH 语义分割DEEPLABV3+ 训练自己的数据集 从数据准备到模型训练

关键在于数据集的制作:

  1. 在做实例分割或语义分割的时候,我们通常要用labelme进行标注,labelme标注的json文件与coco或voc数据集已经标注好的json文件的格式和内容有差异。如果要用这些数据集的信息,就要对json文件进行修改和转换。
    参考这两篇博文:
    语义分割数据集详解(PASCAL-VOC2012,Vocbenchmark,Cityscapes)
    labelme json文件转换_【数据相关】目标检测中的数据标注及格式转换代码

  2. 我们需要的label应该是单通道的二值图或灰度图,但转换之后生成的却是三通道的RGB图像。在这里插入图片描述


问题描述

RuntimeError: 1only batches of spatial targets supported (3D tensors) but got targets of size: : [1, 640, 959, 3]


原因分析:

损失函数 nn.CrossEntropyLoss()的输入应该是一个4维的张量(网络的输出)和一个三维的张量(target),而读取的数据集中的标签为RGB三通道的图片 [batch size,weight,height,RGB]。

需要将该四维张量的RGB图片输入转为单值的类别信息。

重新将标签制作为单值灰度图。

解决方案:

一、如果将labelme标注的标签转换生成了三通道的RGB图像,需要用下面的脚本重新将标签制作为单值灰度图

import os
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import cv2
 
 
color2class_dict = {   
        0: [64.0, 140.0, 214.0, 255.0],
        1: [2.0, 4.0, 244.0, 255.0],
        2: [210.0, 21.0, 28.0, 255],
        3: [9.0, 243.0, 25.0, 255.0]
 
    }   #自行设置类别对应的颜色字典
def get_keys1(value):   #按字典中的颜色对应关系分类
    p = 0
    for k, v in color2class_dict.items():
        if v == value:
            p = k
            break
    return p
def get_keys2(value):   #自行设置颜色范围
    if value[0] > 150:
        return 1
    elif value[1] > 150 and value[2] < 50:
        return 2
    elif value[1] < 50 and value[2] > 150:
        return 3
    else:
        return 0
 
def main(input_path, save_path, mode):
    get_keys = get_keys1 if mode == 0 else get_keys2
    img_list = os.listdir(input_path)
    for image in img_list:
        img_path = os.path.join(input_path, image)
        save_path_img = os.path.join(save_path, image.split(".")[0]+"_mask.png")
        img = plt.imread(img_path)*255.0
        img_label = np.zeros((img.shape[0], img.shape[1]))
        img_new_label = np.zeros((img.shape[0], img.shape[1]))
        for i in range(img.shape[0]):
            for j in range(img.shape[1]):
                value = list(img[i, j])
                img_label[i, j] = get_keys(value)
                img_new_label[i, j] = img_label[i, j]
        label0 = Image.fromarray(np.uint8(img_new_label))
        cv2.imwrite(save_path_img, img_label)
        print(image+" done")
 
 
input_path = ""
save_path = ""
mode = 0
main(input_path, save_path, mode)

二、利用labelme自带的脚本自动生成标签(推荐)

具体见文章开头提到的参考博文:

使用shell将生成的JSON文档转换成PNG、yaml和PNG_viz可视化格式
在这里插入图片描述

labelme_json_to_dataset  <文件名>.json

批量处理

num=100
for ((i=1;i<num;i++))
do
  python json_to_dataset.py dataset/img$i.json -o output/img$i
done
标签自动生成

利用阈值分割的思想处理原图得到像素级标签。这里的“原图”是在实验室的光照、背景合适的理想环境下得到,后续考虑采用迁移学习的方法增强在实际应用场景下的鲁棒性。

from PIL import Image
import cv2
import numpy as np
import os


def auto_label(dirPic, width, height):
    file_list = os.listdir(dirPic + 'gray/')
    color = [255, 255, 255]
    print('start labelling!!!')
    for filename in file_list:
        path = ''
        path = dirPic + 'gray/' + filename
        path2 = dirPic + 'gray_512/' + filename
        try:
            image = cv2.imread(path)
            print(f'{filename} is on precessing.')

            # resize image
            width = 512
            height = 512
            dim = (width, height)
            gray = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)

            # 单通道转换3通道
            # # gray_BGR = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
            # image = np.expand_dims(gray, axis=2)
            # gray_BGR = np.concatenate((image, image, image), axis=-1)
            # print('BGR is ok!')

            # OTSU阈值分割
            ret, th = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU)
            print(f'ret = {ret}')

            # 开/闭运算
            kernel = np.ones((5, 5), np.uint8)
            kernel2 = np.ones((5, 5), np.uint8)
            opening2 = cv2.morphologyEx(th, cv2.MORPH_OPEN, kernel)
            closing2 = cv2.morphologyEx(opening2, cv2.MORPH_CLOSE, kernel2)

        except:
        # mac系统自带.DS_Store隐藏文件
            print('find .DS_Store!')
            continue

if __name__ == '__main__':
    dirPic = '/Users/Sigrid/Desktop/stones/dataset/'
    auto_label(dirPic, 512, 512)

从原图即可得到二值化后的标签样本:
在这里插入图片描述

这里最终要求label.png的像素值在[0~255]中连续,因此0表示背景,即无类别;1表示二分类的对象,这里是stones。如果是多分类就再次基础上2, 3…

可以用PIL包可视化最终的标签结果:

from PIL import Image
imagePath = '/Users/Sigrid/Desktop/stones/dataset/0806_png/gray2/IMG_3709.png'
im = Image.open(imagePath)
im = Image.fromarray(np.uint8(im))
# im = Image.fromarray(np.uint8(im)*20)  # 可以看到灰色的标签对象
# 同时实现图像位深度24到8位转换
im.save(imagePath)
im.show()
  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要使用Imgaug库对labelme标注后的json格式的数据集进行语义分割的扩充,你需要对标注的掩码进行增强。 首先,你可以按照前面提到的方法加载labelme标注后的json数据集。然后,你需要将标注的掩码转换为可处理的形式,例如使用Numpy数组。 下面是一个示例代码,用于将labelme标注后的json掩码转换为Numpy数组: ```python import numpy as np from labelme import utils def json_to_mask(json_data): height = json_data['imageHeight'] width = json_data['imageWidth'] mask = np.zeros((height, width), dtype=np.uint8) for shape in json_data['shapes']: label = shape['label'] polygon = shape['points'] mask = utils.shape_to_mask((height, width), polygon, shape_type='polygon') mask = np.where(mask, label, mask) return mask mask = json_to_mask(json_data) ``` 接下来,你可以使用Imgaug库来定义并应用各种图像增强技术。例如,你可以使用以下代码来实现随机水平翻转和随机旋转的图像增强: ```python import imgaug.augmenters as iaa # 定义图像增强器 augmenter = iaa.Sequential([ iaa.Fliplr(0.5), # 随机水平翻转概率为50% iaa.Affine(rotate=(-45, 45)) # 随机旋转角度范围为-45到45度 ]) # 对每个标注的掩码进行增强 augmented_masks = [] for mask in masks: augmented_mask = augmenter.augment_image(mask) augmented_masks.append(augmented_mask) ``` 在这个示例中,我们将增强后的掩码存储在一个列表中,你可以根据自己的需求进行后续处理,例如保存增强后的掩码。 需要注意的是,语义分割的标注通常是像素级别的,因此你需要确保图像增强器同时应用于图像和对应的掩码,以保持它们的一致性。 希望这个回答能对你有帮助!如果你还有其他问题,请继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘梓枫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值