如何从 PNG 为 Tensorflow 2 中的每个像素分类创建 One-hot 编码矩阵

Posted

技术标签:

【中文标题】如何从 PNG 为 Tensorflow 2 中的每个像素分类创建 One-hot 编码矩阵【英文标题】:How to create a One-hot Encoded Matrix from a PNG for Per Pixel Classification in Tensorflow 2 【发布时间】:2020-02-24 19:53:51 【问题描述】:

我正在尝试训练 Unet 为 256x256 图像的每个像素提供标签,类似于给出的教程 here。在该示例中,Unet 的预测是 (128x128x3) 输出,其中 3 表示分配给每个像素的分类之一。就我而言,我需要一个 (256x256x10) 输出,它具有 10 个不同的分类(本质上是图像中每个像素的单热编码数组)。

我可以加载图像,但我正在努力将每个图像的相应分割掩码转换为正确的格式。我通过定义一个名为process_path 的映射函数创建了数据集,该函数采用已保存的numpy 表示掩码并创建一个维度张量(256 256 10),但是当我调用model.fit 时,我得到一个ValueError,告诉我它不能调用as_list,因为找不到张量的形状:

# --------------------------------------------------------------------------------------
# DECODE A NUMPY .NPY FILE INTO THE REQUIRED FORMAT FOR TRAINING
# --------------------------------------------------------------------------------------
def decode_npy(npy):
  filename = npy.numpy()
  data = np.load(filename)
  data = kerasUtils.to_categorical(data, 10)
  return data

# --------------------------------------------------------------------------------------
# DECODE AN IMAGE (PNG) FILE INTO THE REQUIRED FORMAT FOR TRAINING
# --------------------------------------------------------------------------------------
def decode_img(img):
  img = tf.image.decode_png(img, channels=3)
  return tf.image.convert_image_dtype(img, tf.float32)

# --------------------------------------------------------------------------------------
# PROCESS A FILE PATH FOR THE DATASET
# input - path to an image file
# output - an input image and output mask
# --------------------------------------------------------------------------------------
def process_path(filePath):
  parts = tf.strings.split(filePath, '/')
  fileName = parts[-1]
  parts = tf.strings.split(fileName, '.')
  prefix = tf.convert_to_tensor(maskDir, dtype=tf.string)
  suffix = tf.convert_to_tensor("-mask.png", dtype=tf.string)
  maskFileName = tf.strings.join((parts[-2], suffix))
  maskPath = tf.strings.join((prefix, maskFileName), separator='/')

  # load the raw data from the file as a string
  img = tf.io.read_file(filePath)
  img = decode_img(img)
  mask = tf.py_function(decode_npy, [maskPath], tf.float32)
  return img, mask

trainDataSet = allDataSet.take(trainSize)
trainDataSet = trainDataSet.map(process_path).batch(4)
validDataSet = allDataSet.skip(trainSize)
validDataSet = validDataSet.map(process_path).batch(4)

如何获取每个图像对应的 (256 256 3) 分割掩码(存储为 png)并将其转换为 (256 256 10) 张量,其中第 i 个通道表示像素值,如 @987654322 @?谁能解释这是如何实现的,无论是在process_path 函数中还是在执行转换最有效的地方?

更新:

这是一个分割掩码的例子。每个蒙版都包含相同的 10 种颜色:

【问题讨论】:

你能发布一个示例分割掩码吗?它是只有 10 个像素值的 png 吗? 我添加了一个示例分段掩码。没错,它们都是 10 像素值和相同大小 256x256 像素的 png。 【参考方案1】:

您可以在纯 Tensorflow 中执行此操作,请参阅我的博文:https://www.spacefish.biz/2020/11/rgb-segmentation-masks-to-classes-in-tensorflow/

【讨论】:

不打开。你能更新链接吗?【参考方案2】:
import numpy as np
from cv2 import imread

im = imread('hfoa7.png', 0) # read as grayscale to get 10 unique values
n_classes = 10
one_hot = np.zeros((im.shape[0], im.shape[1], n_classes))
for i, unique_value in enumerate(np.unique(im)):
    one_hot[:, :, i][im == unique_value] = 1

hfao7 是您发布的图片的名称。此代码 sn-p 从图像中创建一个单热矩阵。 您需要将此代码插入decode_npy()。但是,由于您向我发送了 png,因此上面的代码不适用于 npy 文件。您可以传入 pngs 的名称而不是 npys。不用担心使用 kerasUtils.to_categorical - 我发布的函数可以制作分类标签。

【讨论】:

非常感谢,它的工作就像一个魅力!无论如何,我宁愿直接使用 png 文件而不是 .npy 文件。 tf.one_hot() 也可以做到这一点。我们在这个例子中使用了它:keras.io/examples/generative/gaugan.

以上是关于如何从 PNG 为 Tensorflow 2 中的每个像素分类创建 One-hot 编码矩阵的主要内容,如果未能解决你的问题,请参考以下文章

如何从tensorflow 2.0中的tf.function获取图形?

如何修复 Tensorflow 2.0 中的“OperatorNotAllowedInGraphError”错误

TensorFlow 中的基本添加?

如何保存使用Tensorflow 1.xx中的.meta检查点模型作为部分的Tensorflow 2.0模型?

如何使用队列方法(没有 feed_dict)#tensorflow 在保存的模型上使用测试数据?

Tensorflow 2.3:如何并行读取大文件中的文本?