如何在 Keras 中加载用于图像分割的图像遮罩(标签)
How to load Image Masks (Labels) for Image Segmentation in Keras
我正在使用 Tensorflow 作为 Keras 的后端,我正在尝试了解如何引入我的标签以进行图像分割训练。
我正在使用 LFW Parts Dataset,它同时具有地面实况图像和地面实况掩模,看起来像这样 * 1500 个训练图像:
据我了解,在训练过程中,我同时加载了
- (X) 图片
- (Y) 蒙版图像
分批进行,满足我的需求。现在我的问题是,将它们(图像和蒙版图像)都加载为 NumPy 数组(N、N、3)是否足够,或者我是否需要以某种方式 process/reshape 蒙版图像。实际上,mask/labels 表示为 [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
用于背景、头发和面部。
这里可能是重复的(类似quesiton/answers的组合):
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(这个 link one-hot 的值)
Keras 要求标签进行单热编码。所以你的输入必须是 (N x N x n_classes) 维度。
由于这是语义分割,您要对图像中的每个像素进行分类,因此您很可能会使用交叉熵损失。
Keras 以及 TensorFlow 要求您的掩码是一个热编码的,而且,您的掩码的输出维度应该类似于 [batch, height, width, num_classes] <- 你将不得不重塑与计算交叉熵掩码之前的掩码相同,这实际上意味着您必须将 logits 和掩码重塑为张量形状 [-1, num_classes],其中 -1 表示 'as many as required'。
由于你的问题是关于加载你自己的图像,我刚刚自己构建了一个用于分割的输入管道,虽然它是在TensorFlow中,所以我不知道它是否对你有帮助,如果你有兴趣看看:
Tensorflow input pipeline for segmentation
我遇到了同样的问题,我想出了一个纯 Tensorflow 解决方案,它将 RGB 值从加载的蒙版图像 (128,128,3) Tensor 转换为 128x128 RGB 图像的 (128,128) Tensor,其中 Tensor在区间 [0...number_of_classes] 中编码 class..
请看我的博文:https://www.spacefish.biz/2020/11/rgb-segmentation-masks-to-classes-in-tensorflow/
您也可以通过省略最后一个“tf.argmax”步骤来获得单热编码张量,例如 (128,128,number_of_classes)。
我正在使用 Tensorflow 作为 Keras 的后端,我正在尝试了解如何引入我的标签以进行图像分割训练。
我正在使用 LFW Parts Dataset,它同时具有地面实况图像和地面实况掩模,看起来像这样 * 1500 个训练图像:
据我了解,在训练过程中,我同时加载了
- (X) 图片
- (Y) 蒙版图像
分批进行,满足我的需求。现在我的问题是,将它们(图像和蒙版图像)都加载为 NumPy 数组(N、N、3)是否足够,或者我是否需要以某种方式 process/reshape 蒙版图像。实际上,mask/labels 表示为 [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
用于背景、头发和面部。
这里可能是重复的(类似quesiton/answers的组合):
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(这个 link one-hot 的值)
Keras 要求标签进行单热编码。所以你的输入必须是 (N x N x n_classes) 维度。
由于这是语义分割,您要对图像中的每个像素进行分类,因此您很可能会使用交叉熵损失。 Keras 以及 TensorFlow 要求您的掩码是一个热编码的,而且,您的掩码的输出维度应该类似于 [batch, height, width, num_classes] <- 你将不得不重塑与计算交叉熵掩码之前的掩码相同,这实际上意味着您必须将 logits 和掩码重塑为张量形状 [-1, num_classes],其中 -1 表示 'as many as required'。
由于你的问题是关于加载你自己的图像,我刚刚自己构建了一个用于分割的输入管道,虽然它是在TensorFlow中,所以我不知道它是否对你有帮助,如果你有兴趣看看: Tensorflow input pipeline for segmentation
我遇到了同样的问题,我想出了一个纯 Tensorflow 解决方案,它将 RGB 值从加载的蒙版图像 (128,128,3) Tensor 转换为 128x128 RGB 图像的 (128,128) Tensor,其中 Tensor在区间 [0...number_of_classes] 中编码 class.. 请看我的博文:https://www.spacefish.biz/2020/11/rgb-segmentation-masks-to-classes-in-tensorflow/
您也可以通过省略最后一个“tf.argmax”步骤来获得单热编码张量,例如 (128,128,number_of_classes)。