Tensorflow / Keras 均值图像减法

4
在生成训练数据时,会计算出一个平均图像(而不是每个通道的平均像素值)。
为了改善学习过程,我想应用一种简化方法来对网络输入数据进行零中心化和归一化处理,这些数据主要由RGB图像组成。
image = (image - meanImage + 1.0) / 2.0

作为一个深度学习框架,我使用Keras——按照这里描述的方法加载训练数据tfrecords文件。
在我的加载管道的某个阶段,我有输入(X)和输出(Y)张量:
def datasetLoader(dataSetPath, batchSize):
   dataset = tf.data.TFRecordDataset(dataSetPath)

   dataset = dataset.map(_ds_parser, num_parallel_calls=8)

   # This dataset will go on forever
   dataset = dataset.repeat()

   # Set the batchsize
   dataset = dataset.batch(batchSize)

   # Create an iterator
   iterator = dataset.make_one_shot_iterator()

   # Create your tf representation of the iterator
   X, Y = iterator.get_next()  

   # Bring the date back in shape
   X = tf.reshape(I, [-1, 66, 198, 3])
   Y = tf.reshape(Y,[-1,1])

   return X, Y

变量X和Y只是张量,在后面的tensorflow会话中填充。

问题是:我如何使用我的本地png均值图像来执行零中心化和归一化任务?

2个回答

4

张量减法

要从一批图像数据中减去平均图像,您可以直接使用减法运算符 (它只是tf.subtract的语法糖):

In [28]: x = tf.zeros((2, 3, 3))

In [29]: x
Out[29]: 
<tf.Tensor: id=38, shape=(2, 3, 3), dtype=float32, numpy=
array([[[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]],

       [[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]]], dtype=float32)>

In [30]: mean = tf.eye(3)

In [31]: mean
Out[31]: 
<tf.Tensor: id=42, shape=(3, 3), dtype=float32, numpy=
array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]], dtype=float32)>

In [32]: x - mean
Out[32]: 
<tf.Tensor: id=44, shape=(2, 3, 3), dtype=float32, numpy=
array([[[-1.,  0.,  0.],
        [ 0., -1.,  0.],
        [ 0.,  0., -1.]],

       [[-1.,  0.,  0.],
        [ 0., -1.,  0.],
        [ 0.,  0., -1.]]], dtype=float32)>

将图像读入张量

要将PNG图像转换为TensorFlow张量,只需使用tf.constant将numpy数组包装起来:

import cv2

mean_img = cv2.imread('/path/to/the/image')
mean_img_tensor = tf.constant(mean_img)

请注意,OpenCV默认将图像读取为BGR颜色空间。您可能希望将其转换为RGB:

mean_img = cv2.cvtColor(mean_img, cv2.COLOR_BGR2RGB))

或者使用Python图像库:

from PIL import Image
import numpy as np
mean_img = Image.open('/path/to/image')
mean_img_tensor = tf.constant(np.array(mean_img))

把所有东西都整合在一起

由于您使用的是TF Dataset API,我相信map_and_batch必须是性能更好的解决方案:

def datasetLoader(dataSetPath, batchSize, mean_image_path):
   dataset = tf.data.TFRecordDataset(dataSetPath)
   mean_img = cv2.cvtColor(cv2.imread(mean_image_path), cv2.COLOR_BGR2RGB)
   mean = tf.constant(mean_img)

   dataset = dataset.map(_ds_parser, num_parallel_calls=8)

   # This dataset will go on forever
   dataset = dataset.repeat()

   def preprocess(X, Y):
        # Bring the date back in shape
        X = tf.reshape(X, [-1, 66, 198, 3])
        Y = tf.reshape(Y,[-1,1])
        X = X - mean
        return X, Y

   # Set the batchsize
   dataset = dataset.apply(tf.contrib.data.map_and_batch(map_func=preprocess, batch_size=batchSize, num_parallel_calls=8))

   return dataset.make_one_shot_iterator().get_next()

感谢您的解决方案!非常有效。 - johni07

0
import cv2
import numpy as np

img = img.astype(np.float32)
img -= img.mean()
img /= img.std()

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