Skip to content

Commit d58be67

Browse files
Internal change
PiperOrigin-RevId: 420130685
1 parent ded32f0 commit d58be67

File tree

2 files changed

+97
-1
lines changed

2 files changed

+97
-1
lines changed

official/vision/beta/ops/preprocess_ops.py

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"""Preprocessing ops."""
1616

1717
import math
18-
from typing import Optional
18+
from typing import Optional, Tuple, Union
1919
from six.moves import range
2020
import tensorflow as tf
2121

@@ -303,6 +303,86 @@ def resize_and_crop_image_v2(image,
303303
return output_image, image_info
304304

305305

306+
def resize_image(
307+
image: tf.Tensor,
308+
size: Union[Tuple[int, int], int],
309+
max_size: Optional[int] = None,
310+
method: tf.image.ResizeMethod = tf.image.ResizeMethod.BILINEAR):
311+
"""Resize image with size and max_size.
312+
313+
Args:
314+
image: the image to be resized.
315+
size: if list to tuple, resize to it. If scalar, we keep the same
316+
aspect ratio and resize the short side to the value.
317+
max_size: only used when size is a scalar. When the larger side is larger
318+
than max_size after resized with size we used max_size to keep the aspect
319+
ratio instead.
320+
method: the method argument passed to tf.image.resize.
321+
322+
Returns:
323+
the resized image and image_info to be used for downstream processing.
324+
image_info: a 2D `Tensor` that encodes the information of the image and the
325+
applied preprocessing. It is in the format of
326+
[[original_height, original_width], [resized_height, resized_width],
327+
[y_scale, x_scale], [0, 0]], where [resized_height, resized_width]
328+
is the actual scaled image size, and [y_scale, x_scale] is the
329+
scaling factor, which is the ratio of
330+
scaled dimension / original dimension.
331+
"""
332+
333+
def get_size_with_aspect_ratio(image_size, size, max_size=None):
334+
h = image_size[0]
335+
w = image_size[1]
336+
if max_size is not None:
337+
min_original_size = tf.cast(tf.math.minimum(w, h), dtype=tf.float32)
338+
max_original_size = tf.cast(tf.math.maximum(w, h), dtype=tf.float32)
339+
if max_original_size / min_original_size * size > max_size:
340+
size = tf.cast(
341+
tf.math.floor(max_size * min_original_size / max_original_size),
342+
dtype=tf.int32)
343+
else:
344+
size = tf.cast(size, tf.int32)
345+
346+
else:
347+
size = tf.cast(size, tf.int32)
348+
if (w <= h and w == size) or (h <= w and h == size):
349+
return tf.stack([h, w])
350+
351+
if w < h:
352+
ow = size
353+
oh = tf.cast(
354+
(tf.cast(size, dtype=tf.float32) * tf.cast(h, dtype=tf.float32) /
355+
tf.cast(w, dtype=tf.float32)),
356+
dtype=tf.int32)
357+
else:
358+
oh = size
359+
ow = tf.cast(
360+
(tf.cast(size, dtype=tf.float32) * tf.cast(w, dtype=tf.float32) /
361+
tf.cast(h, dtype=tf.float32)),
362+
dtype=tf.int32)
363+
364+
return tf.stack([oh, ow])
365+
366+
def get_size(image_size, size, max_size=None):
367+
if isinstance(size, (list, tuple)):
368+
return size[::-1]
369+
else:
370+
return get_size_with_aspect_ratio(image_size, size, max_size)
371+
372+
orignal_size = tf.shape(image)[0:2]
373+
size = get_size(orignal_size, size, max_size)
374+
rescaled_image = tf.image.resize(
375+
image, tf.cast(size, tf.int32), method=method)
376+
image_scale = size / orignal_size
377+
image_info = tf.stack([
378+
tf.cast(orignal_size, dtype=tf.float32),
379+
tf.cast(size, dtype=tf.float32),
380+
tf.cast(image_scale, tf.float32),
381+
tf.constant([0.0, 0.0], dtype=tf.float32)
382+
])
383+
return rescaled_image, image_info
384+
385+
306386
def center_crop_image(image):
307387
"""Center crop a square shape slice from the input image.
308388

official/vision/beta/ops/preprocess_ops_test.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,22 @@ def test_random_crop(self, input_height, input_width, num_boxes):
225225
np.random.randint(low=0, high=num_boxes, size=(num_boxes,)), tf.int64)
226226
_ = preprocess_ops.random_crop(image, boxes, labels)
227227

228+
@parameterized.parameters(
229+
((640, 640, 3), (1000, 1000), None, (1000, 1000, 3)),
230+
((1280, 640, 3), 320, None, (640, 320, 3)),
231+
((640, 1280, 3), 320, None, (320, 640, 3)),
232+
((640, 640, 3), 320, 100, (100, 100, 3)))
233+
def test_resize_image(self, input_shape, size, max_size, expected_shape):
234+
resized_img, image_info = preprocess_ops.resize_image(
235+
tf.zeros((input_shape)), size, max_size)
236+
self.assertAllEqual(tf.shape(resized_img), expected_shape)
237+
self.assertAllEqual(image_info[0], input_shape[:-1])
238+
self.assertAllEqual(image_info[1], expected_shape[:-1])
239+
self.assertAllEqual(
240+
image_info[2],
241+
np.array(expected_shape[:-1]) / np.array(input_shape[:-1]))
242+
self.assertAllEqual(image_info[3], [0, 0])
243+
228244

229245
if __name__ == '__main__':
230246
tf.test.main()

0 commit comments

Comments
 (0)