Reputation: 771
During training data generation a mean image (not mean pixel values per channel) is calculated.
In order to improve the learning process, I would like to apply a simplified method to zero-center and normalize my network input data, which mainly consists of RGB images:
image = (image - meanImage + 1.0) / 2.0
As DL Framework, I'm using Keras - to load the training data tfrecords files like described here are used.
At some point of my loading pipeline, I've the input (X) and output (Y) tensors:
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
The variables X and Y are just tensors which get populated during a tensorflow session later on.
The question is: How can I use my local png mean image to perform the zero-center and normalize task? .
Upvotes: 4
Views: 3583
Reputation: 1001
import cv2
import numpy as np
img = img.astype(np.float32)
img -= img.mean()
img /= img.std()
Upvotes: 0
Reputation: 5064
Tensor subtraction
To subtract your mean image from a batch of your image data, you can simply use the minus operator (which is just a syntax sugar for 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)>
Reading an image into tensor
To get your PNG image as a TensorFlow tensor, just wrap a numpy array with tf.constant
:
import cv2
mean_img = cv2.imread('/path/to/the/image')
mean_img_tensor = tf.constant(mean_img)
Pay attention that OpenCV will read the image into BGR color space by default. You may want to convert it into RGB then:
mean_img = cv2.cvtColor(mean_img, cv2.COLOR_BGR2RGB))
Or use Python image library:
from PIL import Image
import numpy as np
mean_img = Image.open('/path/to/image')
mean_img_tensor = tf.constant(np.array(mean_img))
Putting it all together
Since you use TF Dataset API, I believe map_and_batch
must be a better solution for performance:
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()
Upvotes: 4