如何在Keras中加载用于图像分割的图像蒙版(标签)

时间:2017-07-18 23:08:25

标签: tensorflow keras image-segmentation

我使用Tensorflow作为Keras的后端,我正在尝试了解如何引入我的标签进行图像分割培训。

我正在使用LFW Parts Dataset,其中包含地面实况图像和地面实况蒙版,看起来像这样的1500张训练图像:

Aaron_Peirsol_0002_Image Aaron_Peirsol_0002_Mask

据我了解这个过程,在训练期间,我加载了

  • (X)图片
  • (Y)Mask Image

分批进行以满足我的需求。现在我的问题是,将它们(图像和蒙版图像)加载为NumPy数组(N,N,3)是否足够,或者我是否需要以某种方式处理/重塑Mask图像。实际上,掩模/标签表示为[R,G,B]像素,其中:

  • [255,0,0]头发
  • [0,255,0] Face
  • [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] Face
  • [0,0,1]背景

我在网上找到的所有内容都使用tensorflow或keras中的现有数据集。如果您拥有可以被认为是自定义数据集的东西,那么就没有什么能够解决问题。

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

他们主张将蒙版图像转换为(H, W, 1)(HWC)?其中我的类分别为0, 1 ,2用于背景,头发和脸部。

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

How to implement multi-class semantic segmentation?

Tensorflow: How to create a Pascal VOC style image

我找到了一个将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(此链接是热门的值)

3 个答案:

答案 0 :(得分:2)

由于这是语义分割,因此您要对图像中的每个像素进行分类,因此您最有可能使用交叉熵丢失。 Keras以及TensorFlow要求你的面具是一个热编码的,而且,你的面具的输出尺寸应该像[batch,height,width,num_classes]< - 你必须像以下一样重塑形状。在计算交叉熵掩码之前你的掩码,这实际上意味着你必须重新塑造你的logits并掩盖到张量形状[-1,num_classes],其中-1表示'尽可能多的'。 / p>

Have a look here at the end

由于你的问题是关于加载你自己的图像,我刚刚完成了一个用于分割的输入管道,虽然它在TensorFlow中,所以我不知道它是否对你有所帮助,看看你是否感兴趣: Tensorflow input pipeline for segmentation

答案 1 :(得分:0)

Keras要求标签是单热编码的。所以你的输入必须是(N x N x n_classes)维度。

答案 2 :(得分:0)

我遇到了同样的问题,我想出了一个纯的Tensorflow解决方案,该解决方案将RGB值从128x128 RGB图像的已加载蒙版图像(128,128,3)张量转换为(128,128)Tensor,Tensor在其中编码在[0 ... number_of_classes]间隔内分类。 请参阅我的博客文章:https://www.spacefish.biz/2020/11/rgb-segmentation-masks-to-classes-in-tensorflow/

您还可以通过省略最后一个“ tf.argmax”步骤来获得一个热编码的Tensor,例如(128,128,number_of_classes)。