Ramraj Chandradevan
Ramraj Chandradevan

Reputation: 173

How to reverse the tf.image.per_image_standardization() function in tensorflow?

tf.image.per_image_standardization() in Tensorflow converts each image with zero mean & unit variance. So that this leads to a non-exploding gradients while training a deep learning model.But when we want to display the image array, how do we revert this z-score normalization step in Tensorflow?

Upvotes: 2

Views: 1445

Answers (2)

Peter Szoldan
Peter Szoldan

Reputation: 4868

The tf.image.per_image_standardization() layer will create some internal variables you can use to recover the original data. Please note that this is undocumented behavior and not guaranteed to stay the same. Still, for now, you can use the code below (tested) for reference how to get the relevant tensors and recover the original data:

import tensorflow as tf
import numpy as np

img_size = 3
a = tf.placeholder( shape = ( img_size, img_size, 1 ), dtype = tf.float32 )
b = tf.image.per_image_standardization( a )

with tf.Session() as sess:
    tensors, tensor_names = [], []
    for l in sess.graph.get_operations():
        tensors.append( sess.graph.get_tensor_by_name( l.name + ":0" ) )
        tensor_names.append( l.name )

    #mean_t = sess.graph.get_tensor_by_name( "per_image_standardization/Mean:0" )
    #variance_t = sess.graph.get_tensor_by_name( "per_image_standardization/Sqrt:0" )

    foobar = np.reshape( np.array( range( img_size * img_size ), dtype = np.float32 ), ( img_size, img_size, 1 ) )
    res =  sess.run( tensors, feed_dict = { a : foobar } )
    #for i in xrange( len( res ) ):
    #    print( i, tensor_names[ i ] + ":" )
    #    print( res[ i ] )
    #    print()

    mean = res[ 6 ] # "per_image_standardization/Mean:0"
    variance = res[ 13 ] # "per_image_standardization/Sqrt:0"
    standardized = res[ 18 ] # "per_image_standardization:0"
    original = standardized * variance + mean
    print( original )

You can uncomment the mean_t and variance_t lines to get the reference to the relevant tensors by name. (Needs some rewrite of the sess.run() part.) You can uncomment the four lines starting with for i in xrange(... (no rewrite needed) to print all the available created tensors for your edification. :)

The above code, as is, outputs:

[[[0.]
[1.]
[2.]]

[[3.]
[4.]
[5.]]

[[6.]
[7.]
[8.]]]

Which is exactly the data that was fed to the network.

Upvotes: 1

David Parks
David Parks

Reputation: 32081

By "display the image array" I assume you mean to display it in tensorboard. If this is the case then you don't need to do anything, tensorboard can handle images that have been standardized. If you want the original value for any other purpose why not just use the variable before you standardized it, such as:

img = tf.placeholder(...)
img_std = tf.image.per_image_standardization(img)

You can work with either img or img_std in any way you see fit.

If you somehow have a use case for denormalizing the standardized image that isn't covered above then you would need to compute the mean and standard deviation yourself, then multiply by the standard deviation and add the mean. Note that tf.image.per_image_standardization uses an adjusted_stddev that is defined in the documentation as:

adjusted_stddev = max(stddev, 1.0/sqrt(image.NumElements()))

Upvotes: 1

Related Questions