Ink
Ink

Reputation: 963

Is the input of `tf.image.resize_images` must have static shape?

I run the code below, it raises an ValueError: 'images' contains no shape. Therefore I have to add the line behind # to set the static shape, but img_raw may have different shapes and this line makes the tf.image.resize_images out of effect. I just want to turn images with different shapes to [227,227,3]. How should I do that?

def tf_read(file_queue):
    reader = tf.WholeFileReader()
    file_name, content = reader.read(file_queue)
    img_raw = tf.image.decode_image(content,3)
    # img_raw.set_shape([227,227,3])
    img_resized = tf.image.resize_images(img_raw,[227,227])
    img_shape = tf.shape(img_resized)
    return file_name, img_resized,img_shape

Upvotes: 1

Views: 7701

Answers (3)

Olivier Moindrot
Olivier Moindrot

Reputation: 28198

The issue here actually comes from the fact that tf.image.decode_image doesn't return the shape of the image. This was explained in these two GitHub issues: issue1, issue2.

The problem comes from the fact that tf.image.decode_image also handles .gif, which returns a 4D tensor, whereas .jpg and .png return 3D images. Therefore, the correct shape cannot be returned.


The solution is to simply use tf.image.decode_jpeg or tf.image.decode_png (both work the same and can be used on .png and .jpg images).

def _decode_image(filename):
    image_string = tf.read_file(filename)
    image_decoded = tf.image.decode_jpeg(image_string, channels=3)
    image = tf.cast(image_decoded, tf.float32)
    image_resized = tf.image.resize_images(image, [224, 224])

    return image_resized

Upvotes: 4

Misairu
Misairu

Reputation: 11

Of course you can use tensor object as size input for tf.image.resize_images.

So, by saying "turn images with different shapes to [227,227,3]", I suppose you don't want to lose their aspect ratio, right? To achieve this, you have to rescale the input image first, then pad the rest with zero.

It should be noted, though, you should consider perform image distortion and standardization before padding it.

# Rescale so that one side of image can fit one side of the box size, then padding the rest with zeros.
# target height is 227
# target width is 227
image = a_image_tensor_you_read
shape = tf.shape(image)
img_h = shape[0]
img_w = shape[1]
box_h = tf.convert_to_tensor(target_height)
box_w = tf.convert_to_tensor(target_width)
img_ratio = tf.cast(tf.divide(img_h, img_w), tf.float32)
aim_ratio = tf.convert_to_tensor(box_h / box_w, tf.float32)
aim_h, aim_w = tf.cond(tf.greater(img_ratio, aim_ratio),
                       lambda: (box_h,
                                tf.cast(img_h / box_h * img_w, tf.int32)),
                       lambda: (tf.cast(img_w / box_w * img_h, tf.int32),
                                box_w))
image_resize = tf.image.resize_images(image, tf.cast([aim_h, aim_w], tf.int32), align_corners=True)

# Perform image standardization and distortion
image_standardized_distorted = blablabla

image_padded = tf.image.resize_image_with_crop_or_pad(image_standardized_distorted, box_h, box_w)
return image_padded

Upvotes: 0

xxi
xxi

Reputation: 1510

No, tf.image.resize_images can handle dynamic shape

file_queue = tf.train.string_input_producer(['./dog1.jpg'])
# shape of dog1.jpg is (720, 720)

reader = tf.WholeFileReader()
file_name, content = reader.read(file_queue)
img_raw = tf.image.decode_jpeg(content, 3) # size (?, ?, 3)  <= dynamic h and w
# img_raw.set_shape([227,227,3])
img_resized = tf.image.resize_images(img_raw, [227, 227])
img_shape = tf.shape(img_resized)

with tf.Session() as sess:
    print img_shape.eval() #[227, 227, 3]

BTW, I am using tf v0.12, and there is no function called tf.image.decode_image, but I don't think it is important

Upvotes: 1

Related Questions