From a2d51b52d623ecfc9563ce71b5943e3a6a4ab649 Mon Sep 17 00:00:00 2001 From: Hao Date: Fri, 7 Dec 2018 16:51:00 +0800 Subject: [PATCH 1/6] update sampling layers --- tensorlayer/layers/image_resampling.py | 46 ++++++++++++++++++++------ 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/tensorlayer/layers/image_resampling.py b/tensorlayer/layers/image_resampling.py index 84aa744d6..fc0f5833b 100644 --- a/tensorlayer/layers/image_resampling.py +++ b/tensorlayer/layers/image_resampling.py @@ -59,19 +59,31 @@ def __init__( if not isinstance(size, (list, tuple)) and len(size) == 2: raise AssertionError() - if len(self.inputs.get_shape()) == 3: if is_scale: - size_h = size[0] * tf.shape(self.inputs)[0] - size_w = size[1] * tf.shape(self.inputs)[1] + input_shape = self.inputs.shape.as_list() + if input_shape[0] is not None: + size_h = size[0] * input_shape[0] + else: + size_h = size[0] * tf.shape(self.inputs)[0] + if input_shape[1] is not None: + size_w = size[1] * input_shape[1] + else: + size_w = size[1] * tf.shape(self.inputs)[1] size = [size_h, size_w] elif len(self.inputs.get_shape()) == 4: if is_scale: - size_h = size[0] * tf.shape(self.inputs)[1] - size_w = size[1] * tf.shape(self.inputs)[2] + input_shape = self.inputs.shape.as_list() + if input_shape[1] is not None: + size_h = size[0] * input_shape[1] + else: + size_h = size[0] * tf.shape(self.inputs)[1] + if input_shape[2] is not None: + size_w = size[1] * input_shape[2] + else: + size_w = size[1] * tf.shape(self.inputs)[2] size = [size_h, size_w] - else: raise Exception("Donot support shape %s" % tf.shape(self.inputs)) @@ -135,14 +147,28 @@ def __init__( if len(self.inputs.get_shape()) == 3: if is_scale: - size_h = size[0] * tf.shape(self.inputs)[0] - size_w = size[1] * tf.shape(self.inputs)[1] + input_shape = self.inputs.shape.as_list() + if input_shape[0] is not None: + size_h = size[0] * input_shape[0] + else: + size_h = size[0] * tf.shape(self.inputs)[0] + if input_shape[1] is not None: + size_w = size[1] * input_shape[1] + else: + size_w = size[1] * tf.shape(self.inputs)[1] size = [size_h, size_w] elif len(self.inputs.get_shape()) == 4: if is_scale: - size_h = size[0] * tf.shape(self.inputs)[1] - size_w = size[1] * tf.shape(self.inputs)[2] + input_shape = self.inputs.shape.as_list() + if input_shape[1] is not None: + size_h = size[0] * input_shape[1] + else: + size_h = size[0] * tf.shape(self.inputs)[1] + if input_shape[2] is not None: + size_w = size[1] * input_shape[2] + else: + size_w = size[1] * tf.shape(self.inputs)[2] size = [size_h, size_w] else: From 21d9d6f42e629101c0f62702ff9990f9c418419e Mon Sep 17 00:00:00 2001 From: Hao Date: Fri, 7 Dec 2018 19:28:13 +0800 Subject: [PATCH 2/6] upadte zoom --- tensorlayer/prepro.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tensorlayer/prepro.py b/tensorlayer/prepro.py index b06759ae2..387896a25 100644 --- a/tensorlayer/prepro.py +++ b/tensorlayer/prepro.py @@ -416,8 +416,8 @@ def affine_zoom_matrix(zoom_range=(0.8, 1.1)): else: raise Exception("zoom_range: float or tuple of 2 floats") - zoom_matrix = np.array([[scale, 0, 0], \ - [0, scale, 0], \ + zoom_matrix = np.array([[1/scale, 0, 0], \ + [0, 1/scale, 0], \ [0, 0, 1]]) return zoom_matrix From 155a0a6eca1628aa9f3b13a3454d21fa15855de1 Mon Sep 17 00:00:00 2001 From: Hao Date: Sat, 8 Dec 2018 18:04:16 +0800 Subject: [PATCH 3/6] fix bug zoom --- tensorlayer/prepro.py | 51 +++++++++++++------------------------------ 1 file changed, 15 insertions(+), 36 deletions(-) diff --git a/tensorlayer/prepro.py b/tensorlayer/prepro.py index 387896a25..19b91c0d1 100644 --- a/tensorlayer/prepro.py +++ b/tensorlayer/prepro.py @@ -416,8 +416,8 @@ def affine_zoom_matrix(zoom_range=(0.8, 1.1)): else: raise Exception("zoom_range: float or tuple of 2 floats") - zoom_matrix = np.array([[1/scale, 0, 0], \ - [0, 1/scale, 0], \ + zoom_matrix = np.array([[scale, 0, 0], \ + [0, scale, 0], \ [0, 0, 1]]) return zoom_matrix @@ -1451,7 +1451,7 @@ def elastic_transform_multi(x, alpha, sigma, mode="constant", cval=0, is_random= # zoom -def zoom(x, zoom_range=(0.9, 1.1), row_index=0, col_index=1, channel_index=2, fill_mode='nearest', cval=0., order=1): +def zoom(x, zoom_range=(0.9, 1.1), flags=None, border_mode='constant'): """Zooming/Scaling a single image that height and width are changed together. Parameters @@ -1462,14 +1462,9 @@ def zoom(x, zoom_range=(0.9, 1.1), row_index=0, col_index=1, channel_index=2, fi The zooming/scaling ratio, greater than 1 means larger. - float, a fixed ratio. - tuple of 2 floats, randomly sample a value as the ratio between 2 values. - row_index col_index and channel_index : int - Index of row, col and channel, default (0, 1, 2), for theano (1, 2, 0). - fill_mode : str - Method to fill missing pixel, default `nearest`, more options `constant`, `reflect` or `wrap`, see `scipy ndimage affine_transform `__ - cval : float - Value used for points outside the boundaries of the input if mode='constant'. Default is 0.0. - order : int - The order of interpolation. The order has to be in the range 0-5. See ``tl.prepro.affine_transform`` and `scipy ndimage affine_transform `__ + border_mode : str + - `constant`, pad the image with a constant value (i.e. black or 0) + - `replicate`, the row or column at the very edge of the original is replicated to the extra border. Returns ------- @@ -1478,9 +1473,9 @@ def zoom(x, zoom_range=(0.9, 1.1), row_index=0, col_index=1, channel_index=2, fi """ zoom_matrix = affine_zoom_matrix(zoom_range=zoom_range) - h, w = x.shape[row_index], x.shape[col_index] + h, w = x.shape[0], x.shape[1] transform_matrix = transform_matrix_offset_center(zoom_matrix, h, w) - x = affine_transform(x, transform_matrix, channel_index, fill_mode, cval, order) + x = affine_transform_cv2(x, transform_matrix, flags=flags, border_mode=border_mode) return x @@ -1525,8 +1520,7 @@ def respective_zoom( def zoom_multi( - x, zoom_range=(0.9, 1.1), is_random=False, row_index=0, col_index=1, channel_index=2, fill_mode='nearest', - cval=0., order=1 + x, zoom_range=(0.9, 1.1), flags=None, border_mode='constant'): ): """Zoom in and out of images with the same arguments, randomly or non-randomly. Usually be used for image segmentation which x=[X, Y], X and Y should be matched. @@ -1544,29 +1538,14 @@ def zoom_multi( A list of processed images. """ - if len(zoom_range) != 2: - raise Exception('zoom_range should be a tuple or list of two floats. ' 'Received arg: ', zoom_range) - if is_random: - if zoom_range[0] == 1 and zoom_range[1] == 1: - zx, zy = 1, 1 - tl.logging.info(" random_zoom : not zoom in/out") - else: - zx, zy = np.random.uniform(zoom_range[0], zoom_range[1], 2) - else: - zx, zy = zoom_range - - zoom_matrix = np.array([[zx, 0, 0], [0, zy, 0], [0, 0, 1]]) - - h, w = x[0].shape[row_index], x[0].shape[col_index] - transform_matrix = transform_matrix_offset_center(zoom_matrix, h, w) - # x = affine_transform(x, transform_matrix, channel_index, fill_mode, cval) - # return x + zoom_matrix = affine_zoom_matrix(zoom_range=zoom_range) results = [] - for data in x: - results.append(affine_transform(data, transform_matrix, channel_index, fill_mode, cval, order)) - return np.asarray(results) - + for img in x: + h, w = x.shape[0], x.shape[1] + transform_matrix = transform_matrix_offset_center(zoom_matrix, h, w) + results.append(affine_transform_cv2(x, transform_matrix, flags=flags, border_mode=border_mode)) + return result # image = tf.image.random_brightness(image, max_delta=32. / 255.) # image = tf.image.random_saturation(image, lower=0.5, upper=1.5) From 637cba17a3cd24fbcb7f07cd87551b31a4695fb1 Mon Sep 17 00:00:00 2001 From: Hao Date: Sat, 8 Dec 2018 18:14:26 +0800 Subject: [PATCH 4/6] typo --- tensorlayer/prepro.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tensorlayer/prepro.py b/tensorlayer/prepro.py index 19b91c0d1..ff4fcdd59 100644 --- a/tensorlayer/prepro.py +++ b/tensorlayer/prepro.py @@ -1519,9 +1519,7 @@ def respective_zoom( return x -def zoom_multi( - x, zoom_range=(0.9, 1.1), flags=None, border_mode='constant'): -): +def zoom_multi(x, zoom_range=(0.9, 1.1), flags=None, border_mode='constant'): """Zoom in and out of images with the same arguments, randomly or non-randomly. Usually be used for image segmentation which x=[X, Y], X and Y should be matched. @@ -1547,6 +1545,7 @@ def zoom_multi( results.append(affine_transform_cv2(x, transform_matrix, flags=flags, border_mode=border_mode)) return result + # image = tf.image.random_brightness(image, max_delta=32. / 255.) # image = tf.image.random_saturation(image, lower=0.5, upper=1.5) # image = tf.image.random_hue(image, max_delta=0.032) From aa36d89ab6e207ccef023aa3b4aab8909a313d6b Mon Sep 17 00:00:00 2001 From: Hao Date: Sun, 9 Dec 2018 00:47:05 +0800 Subject: [PATCH 5/6] fix bug affine_transform_cv2 x and y --- docs/modules/prepro.rst | 2 +- tensorlayer/prepro.py | 24 +++++++++--------------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/docs/modules/prepro.rst b/docs/modules/prepro.rst index 2e4b739ab..ec65da066 100644 --- a/docs/modules/prepro.rst +++ b/docs/modules/prepro.rst @@ -165,7 +165,7 @@ The following is a typical Python program that applies rotation, shifting, flipp xx = tl.prepro.rotation(image, rg=-20, is_random=False) xx = tl.prepro.flip_axis(xx, axis=1, is_random=False) xx = tl.prepro.shear2(xx, shear=(0., -0.2), is_random=False) - xx = tl.prepro.zoom(xx, zoom_range=1/0.8) + xx = tl.prepro.zoom(xx, zoom_range=0.8) xx = tl.prepro.shift(xx, wrg=-0.1, hrg=0, is_random=False) tl.vis.save_image(xx, '_result_slow.png') diff --git a/tensorlayer/prepro.py b/tensorlayer/prepro.py index ff4fcdd59..68c577dd6 100644 --- a/tensorlayer/prepro.py +++ b/tensorlayer/prepro.py @@ -465,7 +465,7 @@ def affine_respective_zoom_matrix(w_range=0.8, h_range=1.1): # affine transform -def transform_matrix_offset_center(matrix, x, y): +def transform_matrix_offset_center(matrix, y, x): """Convert the matrix from Cartesian coordinates (the origin in the middle of image) to Image coordinates (the origin on the top-left of image). Parameters @@ -1479,10 +1479,7 @@ def zoom(x, zoom_range=(0.9, 1.1), flags=None, border_mode='constant'): return x -def respective_zoom( - x, h_range=(0.9, 1.1), w_range=(0.9, 1.1), row_index=0, col_index=1, channel_index=2, fill_mode='nearest', - cval=0., order=1 -): +def respective_zoom(x, h_range=(0.9, 1.1), w_range=(0.9, 1.1), flags=None, border_mode='constant'): """Zooming/Scaling a single image that height and width are changed independently. Parameters @@ -1497,14 +1494,9 @@ def respective_zoom( The zooming/scaling ratio of width, greater than 1 means larger. - float, a fixed ratio. - tuple of 2 floats, randomly sample a value as the ratio between 2 values. - row_index col_index and channel_index : int - Index of row, col and channel, default (0, 1, 2), for theano (1, 2, 0). - fill_mode : str - Method to fill missing pixel, default `nearest`, more options `constant`, `reflect` or `wrap`, see `scipy ndimage affine_transform `__ - cval : float - Value used for points outside the boundaries of the input if mode='constant'. Default is 0.0. - order : int - The order of interpolation. The order has to be in the range 0-5. See ``tl.prepro.affine_transform`` and `scipy ndimage affine_transform `__ + border_mode : str + - `constant`, pad the image with a constant value (i.e. black or 0) + - `replicate`, the row or column at the very edge of the original is replicated to the extra border. Returns ------- @@ -1513,9 +1505,11 @@ def respective_zoom( """ zoom_matrix = affine_respective_zoom_matrix(h_range=h_range, w_range=w_range) - h, w = x.shape[row_index], x.shape[col_index] + h, w = x.shape[0], x.shape[1] transform_matrix = transform_matrix_offset_center(zoom_matrix, h, w) - x = affine_transform(x, transform_matrix, channel_index, fill_mode, cval, order) + x = affine_transform_cv2( + x, transform_matrix, flags=flags, border_mode=border_mode + ) #affine_transform(x, transform_matrix, channel_index, fill_mode, cval, order) return x From 4065d1b348d5e449532a616add1675be7934b3c0 Mon Sep 17 00:00:00 2001 From: Hao Date: Mon, 10 Dec 2018 20:55:37 +0800 Subject: [PATCH 6/6] fix bug crop when crop size equal to image size --- tensorlayer/prepro.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tensorlayer/prepro.py b/tensorlayer/prepro.py index 68c577dd6..0d3e2938b 100644 --- a/tensorlayer/prepro.py +++ b/tensorlayer/prepro.py @@ -817,12 +817,12 @@ def crop(x, wrg, hrg, is_random=False, row_index=0, col_index=1): """ h, w = x.shape[row_index], x.shape[col_index] - if (h <= hrg) or (w <= wrg): - raise AssertionError("The size of cropping should smaller than the original image") + if (h < hrg) or (w < wrg): + raise AssertionError("The size of cropping should smaller than or equal to the original image") if is_random: - h_offset = int(np.random.uniform(0, h - hrg) - 1) - w_offset = int(np.random.uniform(0, w - wrg) - 1) + h_offset = int(np.random.uniform(0, h - hrg)) + w_offset = int(np.random.uniform(0, w - wrg)) # tl.logging.info(h_offset, w_offset, x[h_offset: hrg+h_offset ,w_offset: wrg+w_offset].shape) return x[h_offset:hrg + h_offset, w_offset:wrg + w_offset] else: # central crop @@ -857,12 +857,12 @@ def crop_multi(x, wrg, hrg, is_random=False, row_index=0, col_index=1): """ h, w = x[0].shape[row_index], x[0].shape[col_index] - if (h <= hrg) or (w <= wrg): - raise AssertionError("The size of cropping should smaller than the original image") + if (h < hrg) or (w < wrg): + raise AssertionError("The size of cropping should smaller than or equal to the original image") if is_random: - h_offset = int(np.random.uniform(0, h - hrg) - 1) - w_offset = int(np.random.uniform(0, w - wrg) - 1) + h_offset = int(np.random.uniform(0, h - hrg)) + w_offset = int(np.random.uniform(0, w - wrg)) results = [] for data in x: results.append(data[h_offset:hrg + h_offset, w_offset:wrg + w_offset]) @@ -1833,7 +1833,7 @@ def imresize(x, size=None, interp='bicubic', mode=None): interp : str Interpolation method for re-sizing (`nearest`, `lanczos`, `bilinear`, `bicubic` (default) or `cubic`). mode : str - The PIL image mode (`P`, `L`, etc.) to convert arr before resizing. + The PIL image mode (`P`, `L`, etc.) to convert image before resizing. Returns -------