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])
This is achieved by using the "tf. image. resize()" function available in the tensorflow. It will resize the images to the size using the specified method.
To flatten the tensor, we're going to use the TensorFlow reshape operation. So tf. reshape, we pass in our tensor currently represented by tf_initial_tensor_constant, and then the shape that we're going to give it is a -1 inside of a Python list.
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()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With