7
votes

I am trying to read some image input for an image classification problem with TensorFlow.

Of course, I am doing this with tf.image.decode_jpeg(...). My images have variable size and hence I am not able to specify a fixed shape for the image tensor.

But I need to scale the images depending on their actual size. Specifically, I want to scale the shorter side to a fixed value and the longer side in a way that the aspect ratio is preserved.

I can get the actual shape of a certain image by shape = tf.shape(image). I am also able to do the computation for the new longer edge like

shape = tf.shape(image)
height = shape[0]
width = shape[1]
new_shorter_edge = 400
if height <= width:
    new_height = new_shorter_edge
    new_width = ((width / height) * new_shorter_edge)
else:
    new_width = new_shorter_edge
    new_height = ((height / width) * new_shorter_edge)

My problem now is that I cannot pass new_height and new_width to tf.image.resize_images(...) because one of them is a tensor and resize_images expects integers as height and width inputs.

Is there a way to "pull out" the integer of the tensor or is there any other way to do my task with TensorFlow?

Thanks in advance.


Edit

Since I also had some other issues with tf.image.resize_images, here's the code that worked for me:

shape = tf.shape(image)
height = shape[0]
width = shape[1]
new_shorter_edge = tf.constant(400, dtype=tf.int32)

height_smaller_than_width = tf.less_equal(height, width)
new_height_and_width = tf.cond(
    height_smaller_than_width,
    lambda: (new_shorter_edge, _compute_longer_edge(height, width, new_shorter_edge)),
    lambda: (_compute_longer_edge(width, height, new_shorter_edge), new_shorter_edge)
)

image = tf.expand_dims(image, 0)
image = tf.image.resize_bilinear(image, tf.pack(new_height_and_width))
image = tf.squeeze(image, [0])
1

1 Answers

6
votes

The way to do this is to use the (currently experimental, but available in the next release) tf.cond()* operator. This operator is able to test a value computed at runtime, and execute one of two branches based on that value.

shape = tf.shape(image)
height = shape[0]
width = shape[1]
new_shorter_edge = 400
height_smaller_than_width = tf.less_equal(height, width)

new_shorter_edge = tf.constant(400)
new_height, new_width = tf.cond(
    height_smaller_than_width,
    lambda: new_shorter_edge, (width / height) * new_shorter_edge,
    lambda: new_shorter_edge, (height / width) * new_shorter_edge)

Now you have Tensor values for new_height and new_width that will take the appropriate value at runtime.


*  To access the operator in the current released version, you'll need to import the following:

from tensorflow.python.ops import control_flow_ops

...and then use control_flow_ops.cond() instead of tf.cond().