如何在Keras中加载图像掩码(标签)以进行图像分割

11

我正在使用Tensorflow作为Keras的后端,并尝试理解如何将图像分割训练的标签引入。

我正在使用LFW Parts数据集,它既有地面真实图像,也有地面真实掩码,看起来像这个* 1500张训练图像:

Aaron_Peirsol_0002_Image Aaron_Peirsol_0002_Mask

按照我的理解,在训练期间,我要同时加载

  • (X) 图像
  • (Y) 掩码图像

以批处理的方式满足我的需求。现在我的问题是,仅仅将它们(图像和掩码图像)作为NumPy数组(N,N,3)加载是否足够,还是需要以某种方式处理/重构掩码图像。实际上,掩码/标签表示为[R,G,B]像素,其中:

  • [255, 0, 0] 头发
  • [0, 255, 0] 脸部
  • [0, 0, 255] 背景

我可以像这样对其进行归一化为0-1,但我不知道是否应该:

im = Image.open(path)
label = np.array(im, dtype=np.uint8)
label = np.multiply(label, 1.0/255)

所以我最终得到:

  • [1, 0, 0] 发型
  • [0, 1, 0] 脸部
  • [0, 0, 1] 背景

在网上找到的所有内容都使用tensorflow或keras中的现有数据集。如果您拥有可能被认为是自定义数据集的数据,那么没有什么是真正清楚的。

我发现与Caffe有关:https://groups.google.com/forum/#!topic/caffe-users/9qNggEa8EaQ

他们提倡将掩码图像转换为(H,W,1)(HWC)?其中我的类分别为背景、发型和脸部,其值为0,1,2

可能这是一个重复的问题(类似问题/答案的组合):

如何实现多类语义分割?

Tensorflow:如何创建Pascal VOC风格的图像

我找到了一个处理PascalVOC的例子,将其转换为(N, N, 1):

LFW_PARTS_PALETTE = {
    (0, 0, 255) : 0 , # background (blue)
    (255, 0, 0) : 1 , # hair (red)
    (0, 0, 255) : 2 , # face (green)
}

def convert_from_color_segmentation(arr_3d):
    arr_2d = np.zeros((arr_3d.shape[0], arr_3d.shape[1]), dtype=np.uint8)
    palette = LFW_PARTS_PALETTE

    for i in range(0, arr_3d.shape[0]):
        for j in range(0, arr_3d.shape[1]):
            key = (arr_3d[i, j, 0], arr_3d[i, j, 1], arr_3d[i, j, 2])
            arr_2d[i, j] = palette.get(key, 0) # default value if key was not found is 0

    return arr_2d
我认为这可能接近我想要的,但不完全符合。我认为需要它是(N,N,3),因为我有3个类别?上面版本还有另一个来源于这两个位置:

https://github.com/martinkersner/train-CRF-RNN/blob/master/utils.py#L50

https://github.com/DrSleep/tensorflow-deeplab-resnet/blob/ce75c97fc1337a676e32214ba74865e55adc362c/deeplab_resnet/utils.py#L41 (此链接对值进行one-hot编码)

3个回答

9
由于这是语义分割,您将对图像中的每个像素进行分类,因此您很可能会使用交叉熵损失。Keras和TensorFlow要求您的掩码是单热编码的,而且掩码的输出维度应该是类似于[batch,height,width,num_classes]的东西<-在计算交叉熵掩码之前,您需要将其与掩码以相同的方式重塑,这基本上意味着您需要将logits和mask重塑为张量形状[-1,num_classes],其中-1表示'尽可能多'。

看看这里的结尾

由于您的问题涉及加载自己的图像,我刚刚完成了一个用于分割的输入管道,它是在TensorFlow中的,所以我不知道是否有帮助,如果您感兴趣,请查看: 用于分割的Tensorflow输入管道


0

我曾经遇到过同样的问题,后来我想出了一个纯Tensorflow解决方案,它将从加载的掩模图像(128,128,3)张量中转换RGB值,用于将128x128 RGB图像转换为(128,128)张量,其中张量在区间[0...number_of_classes]中编码类别。

请查看我的博客文章:https://www.spacefish.biz/2020/11/rgb-segmentation-masks-to-classes-in-tensorflow/

您也可以通过省略最后一个“tf.argmax”步骤,以这种方式获得一个one-hot编码的张量,例如(128,128,number_of_classes)。


0

Keras要求标签进行独热编码。因此,您的输入必须具有(N x N x n_classes)维度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接