如何为 Tensorflow 2 中的每像素分类从 PNG 创建单热编码矩阵
How to create a One-hot Encoded Matrix from a PNG for Per Pixel Classification in Tensorflow 2
我正在尝试训练 Unet 为 256x256 图像的每个像素提供标签,这类似于给出的教程 here。在示例中,Unet 的预测是 (128x128x3) 输出,其中 3 表示分配给每个像素的分类之一。在我的例子中,我需要一个具有 10 个不同分类的 (256x256x10) 输出(本质上是图像中每个像素的单热编码数组)。
我可以加载图像,但我很难将每个图像的相应分割掩码转换为正确的格式。我通过定义一个名为 process_path
的映射函数创建了数据集,该函数采用掩码的保存 numpy
表示并创建维度张量 (256 256 10),但我得到一个 ValueError
时我调用 model.fit
,告诉我它不能调用 as_list
因为找不到 Tensor 的形状:
# --------------------------------------------------------------------------------------
# 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 个通道表示像素值,如tutorial?谁能解释这是如何实现的,无论是在 process_path
函数中还是在执行转换最有效的地方?
更新:
这是一个分割蒙版的例子。每个面具都包含相同的 10 种颜色:
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 是您发布的图片的名称。此代码片段根据图像创建一个单热矩阵。
您需要将此代码插入 decode_npy()
。但是,由于您向我发送了 png,因此上面的代码不适用于 npy 文件。您可以传入 png 的名称而不是 npys。不用担心使用 kerasUtils.to_categorical - 我发布的函数会生成分类标签。
您可以在纯 Tensorflow 中执行此操作,请参阅我的博文:https://www.spacefish.biz/2020/11/rgb-segmentation-masks-to-classes-in-tensorflow/
我正在尝试训练 Unet 为 256x256 图像的每个像素提供标签,这类似于给出的教程 here。在示例中,Unet 的预测是 (128x128x3) 输出,其中 3 表示分配给每个像素的分类之一。在我的例子中,我需要一个具有 10 个不同分类的 (256x256x10) 输出(本质上是图像中每个像素的单热编码数组)。
我可以加载图像,但我很难将每个图像的相应分割掩码转换为正确的格式。我通过定义一个名为 process_path
的映射函数创建了数据集,该函数采用掩码的保存 numpy
表示并创建维度张量 (256 256 10),但我得到一个 ValueError
时我调用 model.fit
,告诉我它不能调用 as_list
因为找不到 Tensor 的形状:
# --------------------------------------------------------------------------------------
# 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 个通道表示像素值,如tutorial?谁能解释这是如何实现的,无论是在 process_path
函数中还是在执行转换最有效的地方?
更新:
这是一个分割蒙版的例子。每个面具都包含相同的 10 种颜色:
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 是您发布的图片的名称。此代码片段根据图像创建一个单热矩阵。
您需要将此代码插入 decode_npy()
。但是,由于您向我发送了 png,因此上面的代码不适用于 npy 文件。您可以传入 png 的名称而不是 npys。不用担心使用 kerasUtils.to_categorical - 我发布的函数会生成分类标签。
您可以在纯 Tensorflow 中执行此操作,请参阅我的博文:https://www.spacefish.biz/2020/11/rgb-segmentation-masks-to-classes-in-tensorflow/