From 62d7eb486d45736606f51cca648a6315a91d6665 Mon Sep 17 00:00:00 2001 From: gurpreet singh Date: Sun, 24 Mar 2019 17:07:41 +0530 Subject: [PATCH 01/15] added default parameter for tf.image.ssim --- tensorflow/python/ops/image_ops_impl.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tensorflow/python/ops/image_ops_impl.py b/tensorflow/python/ops/image_ops_impl.py index fc78a3e26f6c72..6a5c32168eb915 100644 --- a/tensorflow/python/ops/image_ops_impl.py +++ b/tensorflow/python/ops/image_ops_impl.py @@ -2873,7 +2873,7 @@ def _fspecial_gauss(size, sigma): return array_ops.reshape(g, shape=[size, size, 1, 1]) -def _ssim_per_channel(img1, img2, max_val=1.0): +def _ssim_per_channel(img1, img2, max_val=1.0, size = 11, sigma = 1.5): """Computes SSIM index between img1 and img2 per color channel. This function matches the standard SSIM implementation from: @@ -2895,8 +2895,8 @@ def _ssim_per_channel(img1, img2, max_val=1.0): A pair of tensors containing and channel-wise SSIM and contrast-structure values. The shape is [..., channels]. """ - filter_size = constant_op.constant(11, dtype=dtypes.int32) - filter_sigma = constant_op.constant(1.5, dtype=img1.dtype) + filter_size = constant_op.constant(size, dtype=dtypes.int32) + filter_sigma = constant_op.constant(sigma, dtype=img1.dtype) shape1, shape2 = array_ops.shape_n([img1, img2]) checks = [ @@ -2937,7 +2937,7 @@ def reducer(x): @tf_export('image.ssim') -def ssim(img1, img2, max_val): +def ssim(img1, img2, max_val, filter_size = 11, filter_sigma = 1.5): """Computes SSIM index between img1 and img2. This function is based on the standard SSIM implementation from: @@ -2962,12 +2962,12 @@ def ssim(img1, img2, max_val): im1 = tf.decode_png('path/to/im1.png') im2 = tf.decode_png('path/to/im2.png') # Compute SSIM over tf.uint8 Tensors. - ssim1 = tf.image.ssim(im1, im2, max_val=255) + ssim1 = tf.image.ssim(im1, im2, max_val=255, filter_size = 11, filter_sigma = 1.5) # Compute SSIM over tf.float32 Tensors. im1 = tf.image.convert_image_dtype(im1, tf.float32) im2 = tf.image.convert_image_dtype(im2, tf.float32) - ssim2 = tf.image.ssim(im1, im2, max_val=1.0) + ssim2 = tf.image.ssim(im1, im2, max_val=1.0, filter_size = 11, filter_sigma = 1.5) # ssim1 and ssim2 both have type tf.float32 and are almost equal. ``` @@ -2992,7 +2992,7 @@ def ssim(img1, img2, max_val): max_val = convert_image_dtype(max_val, dtypes.float32) img1 = convert_image_dtype(img1, dtypes.float32) img2 = convert_image_dtype(img2, dtypes.float32) - ssim_per_channel, _ = _ssim_per_channel(img1, img2, max_val) + ssim_per_channel, _ = _ssim_per_channel(img1, img2, max_val, size = filter_size, sigma = filter_sigma) # Compute average over color channels. return math_ops.reduce_mean(ssim_per_channel, [-1]) From 7363c885f14dbad5c758bd00bb86b82280d9953b Mon Sep 17 00:00:00 2001 From: gurpreet singh Date: Mon, 25 Mar 2019 20:31:41 +0530 Subject: [PATCH 02/15] added default parameter in SSIM including k1 and k2 --- tensorflow/python/ops/image_ops_impl.py | 46 +++++++++++++++++-------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/tensorflow/python/ops/image_ops_impl.py b/tensorflow/python/ops/image_ops_impl.py index 6a5c32168eb915..b6c7cdf562563d 100644 --- a/tensorflow/python/ops/image_ops_impl.py +++ b/tensorflow/python/ops/image_ops_impl.py @@ -2798,12 +2798,14 @@ def psnr(a, b, max_val, name=None): with ops.control_dependencies(checks): return array_ops.identity(psnr_val) -_SSIM_K1 = 0.01 -_SSIM_K2 = 0.03 +_SSIM_k1 = 0.01 +_SSIM_k2 = 0.03 +_SSIM_filter_size = 11 +_SSIM_sigma = 1.5 -def _ssim_helper(x, y, reducer, max_val, compensation=1.0): - r"""Helper function for computing SSIM. +def _ssim_helper(x, y, reducer, max_val, compensation = 1.0, SSIM_k1 = _SSIM_k1, SSIM_k2 = _SSIM_k2): + """Helper function for computing SSIM. SSIM estimates covariances with weighted sums. The default parameters use a biased estimate of the covariance: @@ -2827,12 +2829,16 @@ def _ssim_helper(x, y, reducer, max_val, compensation=1.0): max_val: The dynamic range (i.e., the difference between the maximum possible allowed value and the minimum allowed value). compensation: Compensation factor. See above. + SSIM_k1: Default value 0.01 + SSIM_k2: Default value 0.03 (SSIM is less sensitivity to K2 for + lower values, so it would be better if we taken the valuesin range + of 0< K2 <0.4). Returns: A pair containing the luminance measure, and the contrast-structure measure. """ - c1 = (_SSIM_K1 * max_val) ** 2 - c2 = (_SSIM_K2 * max_val) ** 2 + c1 = (SSIM_k1 * max_val) ** 2 + c2 = (SSIM_k2 * max_val) ** 2 # SSIM luminance measure is # (2 * mu_x * mu_y + c1) / (mu_x ** 2 + mu_y ** 2 + c1). @@ -2873,7 +2879,7 @@ def _fspecial_gauss(size, sigma): return array_ops.reshape(g, shape=[size, size, 1, 1]) -def _ssim_per_channel(img1, img2, max_val=1.0, size = 11, sigma = 1.5): +def _ssim_per_channel(img1, img2, max_val=1.0, size = _SSIM_filter_size, sigma = _SSIM_sigma, SSIM_k1 = _SSIM_k1, SSIM_k2 = _SSIM_k2): """Computes SSIM index between img1 and img2 per color channel. This function matches the standard SSIM implementation from: @@ -2890,6 +2896,12 @@ def _ssim_per_channel(img1, img2, max_val=1.0, size = 11, sigma = 1.5): img2: Second image batch. max_val: The dynamic range of the images (i.e., the difference between the maximum the and minimum allowed values). + size: size of Gaussian filter. + sigma: width of filter. + SSIM_k1: Default value 0.01 + SSIM_k2: Default value 0.03 (SSIM is less sensitivity to K2 for + lower values, so it would be better if we taken the valuesin range + of 0< K2 <0.4). Returns: A pair of tensors containing and channel-wise SSIM and contrast-structure @@ -2927,7 +2939,7 @@ def reducer(x): return array_ops.reshape(y, array_ops.concat([shape[:-3], array_ops.shape(y)[1:]], 0)) - luminance, cs = _ssim_helper(img1, img2, reducer, max_val, compensation) + luminance, cs = _ssim_helper(img1, img2, reducer, max_val, compensation, SSIM_k1 = SSIM_k1, SSIM_k2 = SSIM_k2) # Average over the second and the third from the last: height, width. axes = constant_op.constant([-3, -2], dtype=dtypes.int32) @@ -2937,7 +2949,7 @@ def reducer(x): @tf_export('image.ssim') -def ssim(img1, img2, max_val, filter_size = 11, filter_sigma = 1.5): +def ssim(img1, img2, max_val, filter_size = _SSIM_filter_size, filter_sigma = _SSIM_sigma, k1 = _SSIM_k1, k2 = _SSIM_k2): """Computes SSIM index between img1 and img2. This function is based on the standard SSIM implementation from: @@ -2959,15 +2971,15 @@ def ssim(img1, img2, max_val, filter_size = 11, filter_sigma = 1.5): ```python # Read images from file. - im1 = tf.decode_png('path/to/im1.png') - im2 = tf.decode_png('path/to/im2.png') + im1 = tf.image.decode_png('path/to/im1.png') + im2 = tf.image.decode_png('path/to/im2.png') # Compute SSIM over tf.uint8 Tensors. - ssim1 = tf.image.ssim(im1, im2, max_val=255, filter_size = 11, filter_sigma = 1.5) + ssim1 = tf.image.ssim(im1, im2, max_val=255, filter_size = 11, filter_sigma = 1.5, k1 = 0.01, k2 = 0.03) # Compute SSIM over tf.float32 Tensors. im1 = tf.image.convert_image_dtype(im1, tf.float32) im2 = tf.image.convert_image_dtype(im2, tf.float32) - ssim2 = tf.image.ssim(im1, im2, max_val=1.0, filter_size = 11, filter_sigma = 1.5) + ssim2 = tf.image.ssim(im1, im2, max_val=1.0, filter_size = 11, filter_sigma = 1.5, k1 = 0.01, k2 = 0.03) # ssim1 and ssim2 both have type tf.float32 and are almost equal. ``` @@ -2976,6 +2988,12 @@ def ssim(img1, img2, max_val, filter_size = 11, filter_sigma = 1.5): img2: Second image batch. max_val: The dynamic range of the images (i.e., the difference between the maximum the and minimum allowed values). + filter_size: size of Gaussian filter. + filter_sigma: width of filter. + k1: Default value 0.01 + k2: Default value 0.03 (SSIM is less sensitivity to K2 for + lower values, so it would be better if we taken the valuesin range + of 0< K2 <0.4). Returns: A tensor containing an SSIM value for each image in batch. Returned SSIM @@ -2992,7 +3010,7 @@ def ssim(img1, img2, max_val, filter_size = 11, filter_sigma = 1.5): max_val = convert_image_dtype(max_val, dtypes.float32) img1 = convert_image_dtype(img1, dtypes.float32) img2 = convert_image_dtype(img2, dtypes.float32) - ssim_per_channel, _ = _ssim_per_channel(img1, img2, max_val, size = filter_size, sigma = filter_sigma) + ssim_per_channel, _ = _ssim_per_channel(img1, img2, max_val, size = filter_size, sigma = filter_sigma, SSIM_k1 = k1, SSIM_k2 = k2) # Compute average over color channels. return math_ops.reduce_mean(ssim_per_channel, [-1]) From 301b21e8846b79663c762312ca9805e92099429e Mon Sep 17 00:00:00 2001 From: gurpreet singh Date: Tue, 26 Mar 2019 16:42:43 +0530 Subject: [PATCH 03/15] removed k1 and k2 as default parameter --- tensorflow/python/ops/image_ops_impl.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tensorflow/python/ops/image_ops_impl.py b/tensorflow/python/ops/image_ops_impl.py index 6a5c32168eb915..850e9b07ba1692 100644 --- a/tensorflow/python/ops/image_ops_impl.py +++ b/tensorflow/python/ops/image_ops_impl.py @@ -2890,6 +2890,8 @@ def _ssim_per_channel(img1, img2, max_val=1.0, size = 11, sigma = 1.5): img2: Second image batch. max_val: The dynamic range of the images (i.e., the difference between the maximum the and minimum allowed values). + size: size of gaussian filter. + sigma: width of gaussian filter. Returns: A pair of tensors containing and channel-wise SSIM and contrast-structure @@ -2976,6 +2978,8 @@ def ssim(img1, img2, max_val, filter_size = 11, filter_sigma = 1.5): img2: Second image batch. max_val: The dynamic range of the images (i.e., the difference between the maximum the and minimum allowed values). + filter_size: size of gaussian filter. + filter_sigma: width of gaussian filter. Returns: A tensor containing an SSIM value for each image in batch. Returned SSIM From 1f3c5d317b25d5fb6a4d825198c743ceeaf63d42 Mon Sep 17 00:00:00 2001 From: gurpreet singh Date: Tue, 26 Mar 2019 16:49:14 +0530 Subject: [PATCH 04/15] removed k1 and k2 as default parameter --- tensorflow/python/ops/image_ops_impl.py | 52 +++++++------------------ 1 file changed, 14 insertions(+), 38 deletions(-) diff --git a/tensorflow/python/ops/image_ops_impl.py b/tensorflow/python/ops/image_ops_impl.py index c5b1ccc67b7805..850e9b07ba1692 100644 --- a/tensorflow/python/ops/image_ops_impl.py +++ b/tensorflow/python/ops/image_ops_impl.py @@ -2798,14 +2798,12 @@ def psnr(a, b, max_val, name=None): with ops.control_dependencies(checks): return array_ops.identity(psnr_val) -_SSIM_k1 = 0.01 -_SSIM_k2 = 0.03 -_SSIM_filter_size = 11 -_SSIM_sigma = 1.5 +_SSIM_K1 = 0.01 +_SSIM_K2 = 0.03 -def _ssim_helper(x, y, reducer, max_val, compensation = 1.0, SSIM_k1 = _SSIM_k1, SSIM_k2 = _SSIM_k2): - """Helper function for computing SSIM. +def _ssim_helper(x, y, reducer, max_val, compensation=1.0): + r"""Helper function for computing SSIM. SSIM estimates covariances with weighted sums. The default parameters use a biased estimate of the covariance: @@ -2829,16 +2827,12 @@ def _ssim_helper(x, y, reducer, max_val, compensation = 1.0, SSIM_k1 = _SSIM_k1, max_val: The dynamic range (i.e., the difference between the maximum possible allowed value and the minimum allowed value). compensation: Compensation factor. See above. - SSIM_k1: Default value 0.01 - SSIM_k2: Default value 0.03 (SSIM is less sensitivity to K2 for - lower values, so it would be better if we taken the valuesin range - of 0< K2 <0.4). Returns: A pair containing the luminance measure, and the contrast-structure measure. """ - c1 = (SSIM_k1 * max_val) ** 2 - c2 = (SSIM_k2 * max_val) ** 2 + c1 = (_SSIM_K1 * max_val) ** 2 + c2 = (_SSIM_K2 * max_val) ** 2 # SSIM luminance measure is # (2 * mu_x * mu_y + c1) / (mu_x ** 2 + mu_y ** 2 + c1). @@ -2879,7 +2873,7 @@ def _fspecial_gauss(size, sigma): return array_ops.reshape(g, shape=[size, size, 1, 1]) -def _ssim_per_channel(img1, img2, max_val=1.0, size = _SSIM_filter_size, sigma = _SSIM_sigma, SSIM_k1 = _SSIM_k1, SSIM_k2 = _SSIM_k2): +def _ssim_per_channel(img1, img2, max_val=1.0, size = 11, sigma = 1.5): """Computes SSIM index between img1 and img2 per color channel. This function matches the standard SSIM implementation from: @@ -2896,17 +2890,8 @@ def _ssim_per_channel(img1, img2, max_val=1.0, size = _SSIM_filter_size, sigma = img2: Second image batch. max_val: The dynamic range of the images (i.e., the difference between the maximum the and minimum allowed values). -<<<<<<< HEAD size: size of gaussian filter. sigma: width of gaussian filter. -======= - size: size of Gaussian filter. - sigma: width of filter. - SSIM_k1: Default value 0.01 - SSIM_k2: Default value 0.03 (SSIM is less sensitivity to K2 for - lower values, so it would be better if we taken the valuesin range - of 0< K2 <0.4). ->>>>>>> 7363c885f14dbad5c758bd00bb86b82280d9953b Returns: A pair of tensors containing and channel-wise SSIM and contrast-structure @@ -2944,7 +2929,7 @@ def reducer(x): return array_ops.reshape(y, array_ops.concat([shape[:-3], array_ops.shape(y)[1:]], 0)) - luminance, cs = _ssim_helper(img1, img2, reducer, max_val, compensation, SSIM_k1 = SSIM_k1, SSIM_k2 = SSIM_k2) + luminance, cs = _ssim_helper(img1, img2, reducer, max_val, compensation) # Average over the second and the third from the last: height, width. axes = constant_op.constant([-3, -2], dtype=dtypes.int32) @@ -2954,7 +2939,7 @@ def reducer(x): @tf_export('image.ssim') -def ssim(img1, img2, max_val, filter_size = _SSIM_filter_size, filter_sigma = _SSIM_sigma, k1 = _SSIM_k1, k2 = _SSIM_k2): +def ssim(img1, img2, max_val, filter_size = 11, filter_sigma = 1.5): """Computes SSIM index between img1 and img2. This function is based on the standard SSIM implementation from: @@ -2976,15 +2961,15 @@ def ssim(img1, img2, max_val, filter_size = _SSIM_filter_size, filter_sigma = _S ```python # Read images from file. - im1 = tf.image.decode_png('path/to/im1.png') - im2 = tf.image.decode_png('path/to/im2.png') + im1 = tf.decode_png('path/to/im1.png') + im2 = tf.decode_png('path/to/im2.png') # Compute SSIM over tf.uint8 Tensors. - ssim1 = tf.image.ssim(im1, im2, max_val=255, filter_size = 11, filter_sigma = 1.5, k1 = 0.01, k2 = 0.03) + ssim1 = tf.image.ssim(im1, im2, max_val=255, filter_size = 11, filter_sigma = 1.5) # Compute SSIM over tf.float32 Tensors. im1 = tf.image.convert_image_dtype(im1, tf.float32) im2 = tf.image.convert_image_dtype(im2, tf.float32) - ssim2 = tf.image.ssim(im1, im2, max_val=1.0, filter_size = 11, filter_sigma = 1.5, k1 = 0.01, k2 = 0.03) + ssim2 = tf.image.ssim(im1, im2, max_val=1.0, filter_size = 11, filter_sigma = 1.5) # ssim1 and ssim2 both have type tf.float32 and are almost equal. ``` @@ -2993,17 +2978,8 @@ def ssim(img1, img2, max_val, filter_size = _SSIM_filter_size, filter_sigma = _S img2: Second image batch. max_val: The dynamic range of the images (i.e., the difference between the maximum the and minimum allowed values). -<<<<<<< HEAD filter_size: size of gaussian filter. filter_sigma: width of gaussian filter. -======= - filter_size: size of Gaussian filter. - filter_sigma: width of filter. - k1: Default value 0.01 - k2: Default value 0.03 (SSIM is less sensitivity to K2 for - lower values, so it would be better if we taken the valuesin range - of 0< K2 <0.4). ->>>>>>> 7363c885f14dbad5c758bd00bb86b82280d9953b Returns: A tensor containing an SSIM value for each image in batch. Returned SSIM @@ -3020,7 +2996,7 @@ def ssim(img1, img2, max_val, filter_size = _SSIM_filter_size, filter_sigma = _S max_val = convert_image_dtype(max_val, dtypes.float32) img1 = convert_image_dtype(img1, dtypes.float32) img2 = convert_image_dtype(img2, dtypes.float32) - ssim_per_channel, _ = _ssim_per_channel(img1, img2, max_val, size = filter_size, sigma = filter_sigma, SSIM_k1 = k1, SSIM_k2 = k2) + ssim_per_channel, _ = _ssim_per_channel(img1, img2, max_val, size = filter_size, sigma = filter_sigma) # Compute average over color channels. return math_ops.reduce_mean(ssim_per_channel, [-1]) From 31ce89633cd87be9ad81c3e0bdebd6a2ea9f0f58 Mon Sep 17 00:00:00 2001 From: gurpreet singh Date: Tue, 26 Mar 2019 17:24:19 +0530 Subject: [PATCH 05/15] added parameter to test case --- tensorflow/python/ops/image_ops_test.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tensorflow/python/ops/image_ops_test.py b/tensorflow/python/ops/image_ops_test.py index 71e310edc8569f..c037a69fdecd07 100644 --- a/tensorflow/python/ops/image_ops_test.py +++ b/tensorflow/python/ops/image_ops_test.py @@ -4637,7 +4637,7 @@ def testAgainstMatlab(self): expected = self._ssim[np.triu_indices(3)] ph = [array_ops.placeholder(dtype=dtypes.float32) for _ in range(2)] - ssim = image_ops.ssim(*ph, max_val=1.0) + ssim = image_ops.ssim(*ph, max_val=1.0, filter_size=11, filter_sigma=1.5) with self.cached_session(use_gpu=True): scores = [ssim.eval(dict(zip(ph, t))) for t in itertools.combinations_with_replacement(img, 2)] @@ -4652,7 +4652,7 @@ def testBatch(self): img2 = np.concatenate(img2) ssim = image_ops.ssim(constant_op.constant(img1), - constant_op.constant(img2), 1.0) + constant_op.constant(img2), 1.0, filter_size=11,filter_sigma=1.5) with self.cached_session(use_gpu=True): self.assertAllClose(expected, self.evaluate(ssim), atol=1e-4) @@ -4664,7 +4664,7 @@ def testBroadcast(self): img1 = array_ops.expand_dims(img, axis=0) # batch dims: 1, 2. img2 = array_ops.expand_dims(img, axis=1) # batch dims: 2, 1. - ssim = image_ops.ssim(img1, img2, 1.0) + ssim = image_ops.ssim(img1, img2, 1.0, 11, 1.5) with self.cached_session(use_gpu=True): self.assertAllClose(expected, self.evaluate(ssim), atol=1e-4) @@ -4679,7 +4679,7 @@ def testNegative(self): img2 = img2.reshape((1, 16, 16, 1)) ssim = image_ops.ssim(constant_op.constant(img1), - constant_op.constant(img2), 255) + constant_op.constant(img2), 255, 11, 1.5) with self.cached_session(use_gpu=True): self.assertLess(ssim.eval(), 0) @@ -4689,10 +4689,10 @@ def testInt(self): img2 = self._RandomImage((1, 16, 16, 3), 255) img1 = constant_op.constant(img1, dtypes.uint8) img2 = constant_op.constant(img2, dtypes.uint8) - ssim_uint8 = image_ops.ssim(img1, img2, 255) + ssim_uint8 = image_ops.ssim(img1, img2, 255, 11, 1.5) img1 = image_ops.convert_image_dtype(img1, dtypes.float32) img2 = image_ops.convert_image_dtype(img2, dtypes.float32) - ssim_float32 = image_ops.ssim(img1, img2, 1.0) + ssim_float32 = image_ops.ssim(img1, img2, 1.0, 11, 1.5) with self.cached_session(use_gpu=True): self.assertAllClose( ssim_uint8.eval(), self.evaluate(ssim_float32), atol=0.001) From ea89b5257b4b013c344faac0e93177262b339359 Mon Sep 17 00:00:00 2001 From: gurpreet singh Date: Tue, 26 Mar 2019 20:47:24 +0530 Subject: [PATCH 06/15] added kwargs in multiscale --- tensorflow/python/ops/image_ops_impl.py | 73 ++++++++++++++++++++----- tensorflow/python/ops/image_ops_test.py | 45 ++++++++++----- 2 files changed, 90 insertions(+), 28 deletions(-) diff --git a/tensorflow/python/ops/image_ops_impl.py b/tensorflow/python/ops/image_ops_impl.py index 850e9b07ba1692..3d6a7e83482123 100644 --- a/tensorflow/python/ops/image_ops_impl.py +++ b/tensorflow/python/ops/image_ops_impl.py @@ -2800,9 +2800,11 @@ def psnr(a, b, max_val, name=None): _SSIM_K1 = 0.01 _SSIM_K2 = 0.03 +_SSIM_FILTER_SIZE = 11 +_SSIM_SIGMA = 1.5 -def _ssim_helper(x, y, reducer, max_val, compensation=1.0): +def _ssim_helper(x, y, reducer, max_val, compensation=1.0, k1=_SSIM_K1, k2=_SSIM_K2): r"""Helper function for computing SSIM. SSIM estimates covariances with weighted sums. The default parameters @@ -2827,12 +2829,23 @@ def _ssim_helper(x, y, reducer, max_val, compensation=1.0): max_val: The dynamic range (i.e., the difference between the maximum possible allowed value and the minimum allowed value). compensation: Compensation factor. See above. + k1: Default value 0.01 + k2: Default value 0.03 (SSIM is less sensitivity to K2 for + lower values, so it would be better if we taken the valuesin range + of 0< K2 <0.4). Returns: A pair containing the luminance measure, and the contrast-structure measure. """ - c1 = (_SSIM_K1 * max_val) ** 2 - c2 = (_SSIM_K2 * max_val) ** 2 + + if k1 is None: + c1 = (_SSIM_K1 * max_val) ** 2 + else: + c1 = (k1 * max_val) ** 2 + if k2 is None: + c2 = (_SSIM_K2 * max_val) ** 2 + else: + c2 = (k2 * max_val) ** 2 # SSIM luminance measure is # (2 * mu_x * mu_y + c1) / (mu_x ** 2 + mu_y ** 2 + c1). @@ -2873,7 +2886,7 @@ def _fspecial_gauss(size, sigma): return array_ops.reshape(g, shape=[size, size, 1, 1]) -def _ssim_per_channel(img1, img2, max_val=1.0, size = 11, sigma = 1.5): +def _ssim_per_channel(img1, img2, max_val=1.0, **kwargs): """Computes SSIM index between img1 and img2 per color channel. This function matches the standard SSIM implementation from: @@ -2893,13 +2906,28 @@ def _ssim_per_channel(img1, img2, max_val=1.0, size = 11, sigma = 1.5): size: size of gaussian filter. sigma: width of gaussian filter. + Kwargs: + filter_size: size of gaussian filter. + filter_sigma: width of gaussian filter. + k1: Default value 0.01 + k2: Default value 0.03 (SSIM is less sensitivity to K2 for + lower values, so it would be better if we taken the valuesin range + of 0< K2 <0.4). + Returns: A pair of tensors containing and channel-wise SSIM and contrast-structure values. The shape is [..., channels]. """ - filter_size = constant_op.constant(size, dtype=dtypes.int32) - filter_sigma = constant_op.constant(sigma, dtype=img1.dtype) - + if kwargs.get('filter_size') is None: + filter_size = constant_op.constant(_SSIM_FILTER_SIZE, dtype=dtypes.int32) + else: + filter_size = constant_op.constant(kwargs.get('filter_size'), + dtype=dtypes.int32) + if kwargs.get('filter_sigma') is None: + filter_sigma = constant_op.constant(_SSIM_FILTER_SIGMA, dtype=img1.dtype) + else: + filter_sigma = constant_op.constant(kwargs.get('filter_sigma'), + dtype=img1.dtype) shape1, shape2 = array_ops.shape_n([img1, img2]) checks = [ control_flow_ops.Assert(math_ops.reduce_all(math_ops.greater_equal( @@ -2929,7 +2957,8 @@ def reducer(x): return array_ops.reshape(y, array_ops.concat([shape[:-3], array_ops.shape(y)[1:]], 0)) - luminance, cs = _ssim_helper(img1, img2, reducer, max_val, compensation) + luminance, cs = _ssim_helper(img1, img2, reducer, max_val, compensation, + kwargs.get('k1'), kwargs.get('k2')) # Average over the second and the third from the last: height, width. axes = constant_op.constant([-3, -2], dtype=dtypes.int32) @@ -2939,7 +2968,7 @@ def reducer(x): @tf_export('image.ssim') -def ssim(img1, img2, max_val, filter_size = 11, filter_sigma = 1.5): +def ssim(img1, img2, max_val, **kwargs): """Computes SSIM index between img1 and img2. This function is based on the standard SSIM implementation from: @@ -2964,12 +2993,14 @@ def ssim(img1, img2, max_val, filter_size = 11, filter_sigma = 1.5): im1 = tf.decode_png('path/to/im1.png') im2 = tf.decode_png('path/to/im2.png') # Compute SSIM over tf.uint8 Tensors. - ssim1 = tf.image.ssim(im1, im2, max_val=255, filter_size = 11, filter_sigma = 1.5) + ssim1 = tf.image.ssim(im1, im2, max_val=255, filter_size = 11, + filter_sigma = 1.5, k1 = 0.01, k2 = 0.03) # Compute SSIM over tf.float32 Tensors. im1 = tf.image.convert_image_dtype(im1, tf.float32) im2 = tf.image.convert_image_dtype(im2, tf.float32) - ssim2 = tf.image.ssim(im1, im2, max_val=1.0, filter_size = 11, filter_sigma = 1.5) + ssim2 = tf.image.ssim(im1, im2, max_val=1.0, filter_size = 11, + filter_sigma = 1.5, k1 = 0.01, k2 = 0.03) # ssim1 and ssim2 both have type tf.float32 and are almost equal. ``` @@ -2978,8 +3009,14 @@ def ssim(img1, img2, max_val, filter_size = 11, filter_sigma = 1.5): img2: Second image batch. max_val: The dynamic range of the images (i.e., the difference between the maximum the and minimum allowed values). + + Kwargs: filter_size: size of gaussian filter. filter_sigma: width of gaussian filter. + k1: Default value 0.01 + k2: Default value 0.03 (SSIM is less sensitivity to K2 for + lower values, so it would be better if we taken the valuesin range + of 0< K2 <0.4). Returns: A tensor containing an SSIM value for each image in batch. Returned SSIM @@ -2996,7 +3033,7 @@ def ssim(img1, img2, max_val, filter_size = 11, filter_sigma = 1.5): max_val = convert_image_dtype(max_val, dtypes.float32) img1 = convert_image_dtype(img1, dtypes.float32) img2 = convert_image_dtype(img2, dtypes.float32) - ssim_per_channel, _ = _ssim_per_channel(img1, img2, max_val, size = filter_size, sigma = filter_sigma) + ssim_per_channel, _ = _ssim_per_channel(img1, img2, max_val, **kwargs) # Compute average over color channels. return math_ops.reduce_mean(ssim_per_channel, [-1]) @@ -3006,7 +3043,7 @@ def ssim(img1, img2, max_val, filter_size = 11, filter_sigma = 1.5): @tf_export('image.ssim_multiscale') -def ssim_multiscale(img1, img2, max_val, power_factors=_MSSSIM_WEIGHTS): +def ssim_multiscale(img1, img2, max_val, power_factors=_MSSSIM_WEIGHTS, **kwargs): """Computes the MS-SSIM between img1 and img2. This function assumes that `img1` and `img2` are image batches, i.e. the last @@ -3031,6 +3068,14 @@ def ssim_multiscale(img1, img2, max_val, power_factors=_MSSSIM_WEIGHTS): being downsampled by 2. Defaults to (0.0448, 0.2856, 0.3001, 0.2363, 0.1333), which are the values obtained in the original paper. + Kwargs: + filter_size: size of gaussian filter. + filter_sigma: width of gaussian filter. + k1: Default value 0.01 + k2: Default value 0.03 (SSIM is less sensitivity to K2 for + lower values, so it would be better if we taken the valuesin range + of 0< K2 <0.4). + Returns: A tensor containing an MS-SSIM value for each image in batch. The values are in range [0, 1]. Returns a tensor with shape: @@ -3098,7 +3143,7 @@ def do_pad(images, remainder): ] # Overwrite previous ssim value since we only need the last one. - ssim_per_channel, cs = _ssim_per_channel(*imgs, max_val=max_val) + ssim_per_channel, cs = _ssim_per_channel(*imgs, max_val=max_val,**kwargs) mcs.append(nn_ops.relu(cs)) # Remove the cs score for the last scale. In the MS-SSIM calculation, diff --git a/tensorflow/python/ops/image_ops_test.py b/tensorflow/python/ops/image_ops_test.py index c037a69fdecd07..74afe76f83d92e 100644 --- a/tensorflow/python/ops/image_ops_test.py +++ b/tensorflow/python/ops/image_ops_test.py @@ -4637,7 +4637,8 @@ def testAgainstMatlab(self): expected = self._ssim[np.triu_indices(3)] ph = [array_ops.placeholder(dtype=dtypes.float32) for _ in range(2)] - ssim = image_ops.ssim(*ph, max_val=1.0, filter_size=11, filter_sigma=1.5) + ssim = image_ops.ssim(*ph, max_val=1.0, filter_size=11, filter_sigma=1.5, + k1 = 0.01, k2 = 0.03) with self.cached_session(use_gpu=True): scores = [ssim.eval(dict(zip(ph, t))) for t in itertools.combinations_with_replacement(img, 2)] @@ -4652,7 +4653,8 @@ def testBatch(self): img2 = np.concatenate(img2) ssim = image_ops.ssim(constant_op.constant(img1), - constant_op.constant(img2), 1.0, filter_size=11,filter_sigma=1.5) + constant_op.constant(img2), 1.0, filter_size=11, + filter_sigma=1.5, k1 = 0.01, k2 = 0.03) with self.cached_session(use_gpu=True): self.assertAllClose(expected, self.evaluate(ssim), atol=1e-4) @@ -4664,7 +4666,8 @@ def testBroadcast(self): img1 = array_ops.expand_dims(img, axis=0) # batch dims: 1, 2. img2 = array_ops.expand_dims(img, axis=1) # batch dims: 2, 1. - ssim = image_ops.ssim(img1, img2, 1.0, 11, 1.5) + ssim = image_ops.ssim(img1, img2, 1.0, filter_size=11, filter_sigma=1.5, + k1 = 0.01, k2 = 0.03) with self.cached_session(use_gpu=True): self.assertAllClose(expected, self.evaluate(ssim), atol=1e-4) @@ -4678,8 +4681,8 @@ def testNegative(self): img1 = img1.reshape((1, 16, 16, 1)) img2 = img2.reshape((1, 16, 16, 1)) - ssim = image_ops.ssim(constant_op.constant(img1), - constant_op.constant(img2), 255, 11, 1.5) + ssim = image_ops.ssim(constant_op.constant(img1),constant_op.constant(img2), + 255, filter_size=11, filter_sigma=1.5, k1=0.01, k2=0.03) with self.cached_session(use_gpu=True): self.assertLess(ssim.eval(), 0) @@ -4689,10 +4692,12 @@ def testInt(self): img2 = self._RandomImage((1, 16, 16, 3), 255) img1 = constant_op.constant(img1, dtypes.uint8) img2 = constant_op.constant(img2, dtypes.uint8) - ssim_uint8 = image_ops.ssim(img1, img2, 255, 11, 1.5) + ssim_uint8 = image_ops.ssim(img1, img2, 255, filter_size=11, filter_sigma=1.5, + k1 = 0.01, k2 = 0.03) img1 = image_ops.convert_image_dtype(img1, dtypes.float32) img2 = image_ops.convert_image_dtype(img2, dtypes.float32) - ssim_float32 = image_ops.ssim(img1, img2, 1.0, 11, 1.5) + ssim_float32 = image_ops.ssim(img1, img2, 1.0, filter_size=11, filter_sigma=1.5, + k1 = 0.01, k2 = 0.03) with self.cached_session(use_gpu=True): self.assertAllClose( ssim_uint8.eval(), self.evaluate(ssim_float32), atol=0.001) @@ -4735,7 +4740,8 @@ def testAgainstMatlab(self): expected = self._msssim[np.triu_indices(3)] ph = [array_ops.placeholder(dtype=dtypes.float32) for _ in range(2)] - msssim = image_ops.ssim_multiscale(*ph, max_val=1.0) + msssim = image_ops.ssim_multiscale(*ph, max_val=1.0,filter_size=11, + filter_sigma=1.5,k1 = 0.01, k2 = 0.03) with self.cached_session(use_gpu=True): scores = [msssim.eval(dict(zip(ph, t))) for t in itertools.combinations_with_replacement(img, 2)] @@ -4749,7 +4755,9 @@ def testUnweightedIsDifferentiable(self): scalar = constant_op.constant(1.0, dtype=dtypes.float32) scaled_ph = [x * scalar for x in ph] msssim = image_ops.ssim_multiscale(*scaled_ph, max_val=1.0, - power_factors=(1, 1, 1, 1, 1)) + power_factors=(1, 1, 1, 1, 1), + filter_size=11, filter_sigma=1.5, + k1 = 0.01, k2 = 0.03) grads = gradients.gradients(msssim, scalar) with self.cached_session(use_gpu=True) as sess: np_grads = sess.run(grads, feed_dict={ph[0]: img[0], ph[1]: img[1]}) @@ -4765,7 +4773,9 @@ def testBatch(self): img2 = np.concatenate(img2) msssim = image_ops.ssim_multiscale(constant_op.constant(img1), - constant_op.constant(img2), 1.0) + constant_op.constant(img2), 1.0, + filter_size=11, filter_sigma=1.5, + k1 = 0.01, k2 = 0.03) with self.cached_session(use_gpu=True): self.assertAllClose(expected, self.evaluate(msssim), 1e-4) @@ -4778,7 +4788,9 @@ def testBroadcast(self): img1 = array_ops.expand_dims(img, axis=0) # batch dims: 1, 2. img2 = array_ops.expand_dims(img, axis=1) # batch dims: 2, 1. - score_tensor = image_ops.ssim_multiscale(img1, img2, 1.0) + score_tensor = image_ops.ssim_multiscale(img1, img2, 1.0, filter_size=11, + filter_sigma=1.5, k1 = 0.01, + k2 = 0.03) with self.cached_session(use_gpu=True): self.assertAllClose(expected, self.evaluate(score_tensor), 1e-4) @@ -4796,7 +4808,9 @@ def testRange(self): np.full_like(img1, fill_value=255)] images = [ops.convert_to_tensor(x, dtype=dtypes.float32) for x in images] - msssim_ops = [image_ops.ssim_multiscale(x, y, 1.0) + msssim_ops = [image_ops.ssim_multiscale(x, y, 1.0, filter_size=11, + filter_sigma=1.5, k1=0.01, + k2=0.03) for x, y in itertools.combinations(images, 2)] msssim = self.evaluate(msssim_ops) msssim = np.squeeze(msssim) @@ -4810,10 +4824,13 @@ def testInt(self): img2 = self._RandomImage((1, 180, 240, 3), 255) img1 = constant_op.constant(img1, dtypes.uint8) img2 = constant_op.constant(img2, dtypes.uint8) - ssim_uint8 = image_ops.ssim_multiscale(img1, img2, 255) + ssim_uint8 = image_ops.ssim_multiscale(img1, img2, 255, filter_size=11, + filter_sigma=1.5, k1 = 0.01, + k2 = 0.03) img1 = image_ops.convert_image_dtype(img1, dtypes.float32) img2 = image_ops.convert_image_dtype(img2, dtypes.float32) - ssim_float32 = image_ops.ssim_multiscale(img1, img2, 1.0) + ssim_float32 = image_ops.ssim_multiscale(img1, img2, 1.0, filter_size=11, + filter_sigma=1.5, k1=0.01, k2=0.03) with self.cached_session(use_gpu=True): self.assertAllClose( ssim_uint8.eval(), self.evaluate(ssim_float32), atol=0.001) From d21adc0e8f41fb9108950a5cbf72f57d25c69579 Mon Sep 17 00:00:00 2001 From: gurpreet singh Date: Thu, 28 Mar 2019 22:11:03 +0530 Subject: [PATCH 07/15] added args --- tensorflow/python/ops/image_ops_impl.py | 38 +++++++++++-------------- tensorflow/python/ops/image_ops_test.py | 20 ++++++------- 2 files changed, 26 insertions(+), 32 deletions(-) diff --git a/tensorflow/python/ops/image_ops_impl.py b/tensorflow/python/ops/image_ops_impl.py index 3d6a7e83482123..36f3c2a01cdde0 100644 --- a/tensorflow/python/ops/image_ops_impl.py +++ b/tensorflow/python/ops/image_ops_impl.py @@ -2886,7 +2886,8 @@ def _fspecial_gauss(size, sigma): return array_ops.reshape(g, shape=[size, size, 1, 1]) -def _ssim_per_channel(img1, img2, max_val=1.0, **kwargs): +def _ssim_per_channel(img1, img2, max_val=1.0, filter_size = _SSIM_FILTER_SIZE, + filter_sigma = _SSIM_SIGMA, k1 = _SSIM_K1, k2 = _SSIM_K2): """Computes SSIM index between img1 and img2 per color channel. This function matches the standard SSIM implementation from: @@ -2905,8 +2906,6 @@ def _ssim_per_channel(img1, img2, max_val=1.0, **kwargs): maximum the and minimum allowed values). size: size of gaussian filter. sigma: width of gaussian filter. - - Kwargs: filter_size: size of gaussian filter. filter_sigma: width of gaussian filter. k1: Default value 0.01 @@ -2918,16 +2917,9 @@ def _ssim_per_channel(img1, img2, max_val=1.0, **kwargs): A pair of tensors containing and channel-wise SSIM and contrast-structure values. The shape is [..., channels]. """ - if kwargs.get('filter_size') is None: - filter_size = constant_op.constant(_SSIM_FILTER_SIZE, dtype=dtypes.int32) - else: - filter_size = constant_op.constant(kwargs.get('filter_size'), - dtype=dtypes.int32) - if kwargs.get('filter_sigma') is None: - filter_sigma = constant_op.constant(_SSIM_FILTER_SIGMA, dtype=img1.dtype) - else: - filter_sigma = constant_op.constant(kwargs.get('filter_sigma'), - dtype=img1.dtype) + filter_size = constant_op.constant(filter_size, dtype=dtypes.int32) + filter_sigma = constant_op.constant(filter_sigma, dtype=img1.dtype) + shape1, shape2 = array_ops.shape_n([img1, img2]) checks = [ control_flow_ops.Assert(math_ops.reduce_all(math_ops.greater_equal( @@ -2958,7 +2950,7 @@ def reducer(x): array_ops.shape(y)[1:]], 0)) luminance, cs = _ssim_helper(img1, img2, reducer, max_val, compensation, - kwargs.get('k1'), kwargs.get('k2')) + k1, k2) # Average over the second and the third from the last: height, width. axes = constant_op.constant([-3, -2], dtype=dtypes.int32) @@ -2968,7 +2960,8 @@ def reducer(x): @tf_export('image.ssim') -def ssim(img1, img2, max_val, **kwargs): +def ssim(img1, img2, max_val, filter_size = _SSIM_FILTER_SIZE, + filter_sigma = _SSIM_SIGMA, k1 = _SSIM_K1, k2 = _SSIM_K2): """Computes SSIM index between img1 and img2. This function is based on the standard SSIM implementation from: @@ -3009,8 +3002,6 @@ def ssim(img1, img2, max_val, **kwargs): img2: Second image batch. max_val: The dynamic range of the images (i.e., the difference between the maximum the and minimum allowed values). - - Kwargs: filter_size: size of gaussian filter. filter_sigma: width of gaussian filter. k1: Default value 0.01 @@ -3033,7 +3024,8 @@ def ssim(img1, img2, max_val, **kwargs): max_val = convert_image_dtype(max_val, dtypes.float32) img1 = convert_image_dtype(img1, dtypes.float32) img2 = convert_image_dtype(img2, dtypes.float32) - ssim_per_channel, _ = _ssim_per_channel(img1, img2, max_val, **kwargs) + ssim_per_channel, _ = _ssim_per_channel(img1, img2, max_val, filter_size, + filter_sigma, k1, k2 ) # Compute average over color channels. return math_ops.reduce_mean(ssim_per_channel, [-1]) @@ -3043,7 +3035,9 @@ def ssim(img1, img2, max_val, **kwargs): @tf_export('image.ssim_multiscale') -def ssim_multiscale(img1, img2, max_val, power_factors=_MSSSIM_WEIGHTS, **kwargs): +def ssim_multiscale(img1, img2, max_val, power_factors=_MSSSIM_WEIGHTS, + filter_size = _SSIM_FILTER_SIZE, filter_sigma = _SSIM_SIGMA, + k1 = _SSIM_K1, k2 = _SSIM_K2): """Computes the MS-SSIM between img1 and img2. This function assumes that `img1` and `img2` are image batches, i.e. the last @@ -3067,8 +3061,6 @@ def ssim_multiscale(img1, img2, max_val, power_factors=_MSSSIM_WEIGHTS, **kwargs resolution's weight and each increasing scale corresponds to the image being downsampled by 2. Defaults to (0.0448, 0.2856, 0.3001, 0.2363, 0.1333), which are the values obtained in the original paper. - - Kwargs: filter_size: size of gaussian filter. filter_sigma: width of gaussian filter. k1: Default value 0.01 @@ -3143,7 +3135,9 @@ def do_pad(images, remainder): ] # Overwrite previous ssim value since we only need the last one. - ssim_per_channel, cs = _ssim_per_channel(*imgs, max_val=max_val,**kwargs) + ssim_per_channel, cs = _ssim_per_channel(*imgs, max_val=max_val, + filter_size = filter_size, + filter_sigma = filter_sigma, k1 = k1, k2 = k2) mcs.append(nn_ops.relu(cs)) # Remove the cs score for the last scale. In the MS-SSIM calculation, diff --git a/tensorflow/python/ops/image_ops_test.py b/tensorflow/python/ops/image_ops_test.py index 74afe76f83d92e..ad65d6edea9f47 100644 --- a/tensorflow/python/ops/image_ops_test.py +++ b/tensorflow/python/ops/image_ops_test.py @@ -4638,7 +4638,7 @@ def testAgainstMatlab(self): ph = [array_ops.placeholder(dtype=dtypes.float32) for _ in range(2)] ssim = image_ops.ssim(*ph, max_val=1.0, filter_size=11, filter_sigma=1.5, - k1 = 0.01, k2 = 0.03) + k1=0.01, k2=0.03) with self.cached_session(use_gpu=True): scores = [ssim.eval(dict(zip(ph, t))) for t in itertools.combinations_with_replacement(img, 2)] @@ -4654,7 +4654,7 @@ def testBatch(self): ssim = image_ops.ssim(constant_op.constant(img1), constant_op.constant(img2), 1.0, filter_size=11, - filter_sigma=1.5, k1 = 0.01, k2 = 0.03) + filter_sigma=1.5, k1=0.01, k2=0.03) with self.cached_session(use_gpu=True): self.assertAllClose(expected, self.evaluate(ssim), atol=1e-4) @@ -4667,7 +4667,7 @@ def testBroadcast(self): img2 = array_ops.expand_dims(img, axis=1) # batch dims: 2, 1. ssim = image_ops.ssim(img1, img2, 1.0, filter_size=11, filter_sigma=1.5, - k1 = 0.01, k2 = 0.03) + k1=0.01, k2=0.03) with self.cached_session(use_gpu=True): self.assertAllClose(expected, self.evaluate(ssim), atol=1e-4) @@ -4741,7 +4741,7 @@ def testAgainstMatlab(self): ph = [array_ops.placeholder(dtype=dtypes.float32) for _ in range(2)] msssim = image_ops.ssim_multiscale(*ph, max_val=1.0,filter_size=11, - filter_sigma=1.5,k1 = 0.01, k2 = 0.03) + filter_sigma=1.5, k1=0.01, k2=0.03) with self.cached_session(use_gpu=True): scores = [msssim.eval(dict(zip(ph, t))) for t in itertools.combinations_with_replacement(img, 2)] @@ -4757,7 +4757,7 @@ def testUnweightedIsDifferentiable(self): msssim = image_ops.ssim_multiscale(*scaled_ph, max_val=1.0, power_factors=(1, 1, 1, 1, 1), filter_size=11, filter_sigma=1.5, - k1 = 0.01, k2 = 0.03) + k1=0.01, k2=0.03) grads = gradients.gradients(msssim, scalar) with self.cached_session(use_gpu=True) as sess: np_grads = sess.run(grads, feed_dict={ph[0]: img[0], ph[1]: img[1]}) @@ -4775,7 +4775,7 @@ def testBatch(self): msssim = image_ops.ssim_multiscale(constant_op.constant(img1), constant_op.constant(img2), 1.0, filter_size=11, filter_sigma=1.5, - k1 = 0.01, k2 = 0.03) + k1=0.01, k2 =0.03) with self.cached_session(use_gpu=True): self.assertAllClose(expected, self.evaluate(msssim), 1e-4) @@ -4789,8 +4789,8 @@ def testBroadcast(self): img2 = array_ops.expand_dims(img, axis=1) # batch dims: 2, 1. score_tensor = image_ops.ssim_multiscale(img1, img2, 1.0, filter_size=11, - filter_sigma=1.5, k1 = 0.01, - k2 = 0.03) + filter_sigma=1.5, k1=0.01, + k2=0.03) with self.cached_session(use_gpu=True): self.assertAllClose(expected, self.evaluate(score_tensor), 1e-4) @@ -4825,8 +4825,8 @@ def testInt(self): img1 = constant_op.constant(img1, dtypes.uint8) img2 = constant_op.constant(img2, dtypes.uint8) ssim_uint8 = image_ops.ssim_multiscale(img1, img2, 255, filter_size=11, - filter_sigma=1.5, k1 = 0.01, - k2 = 0.03) + filter_sigma=1.5, k1=0.01, + k2=0.03) img1 = image_ops.convert_image_dtype(img1, dtypes.float32) img2 = image_ops.convert_image_dtype(img2, dtypes.float32) ssim_float32 = image_ops.ssim_multiscale(img1, img2, 1.0, filter_size=11, From 862d821b8ad4d8a51f4fea2ad2bcc2045e2e11b3 Mon Sep 17 00:00:00 2001 From: gurpreet singh Date: Thu, 28 Mar 2019 22:17:36 +0530 Subject: [PATCH 08/15] removed redundent code --- tensorflow/python/ops/image_ops_impl.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/tensorflow/python/ops/image_ops_impl.py b/tensorflow/python/ops/image_ops_impl.py index 36f3c2a01cdde0..bd6b5b25deaa27 100644 --- a/tensorflow/python/ops/image_ops_impl.py +++ b/tensorflow/python/ops/image_ops_impl.py @@ -2838,14 +2838,8 @@ def _ssim_helper(x, y, reducer, max_val, compensation=1.0, k1=_SSIM_K1, k2=_SSIM A pair containing the luminance measure, and the contrast-structure measure. """ - if k1 is None: - c1 = (_SSIM_K1 * max_val) ** 2 - else: - c1 = (k1 * max_val) ** 2 - if k2 is None: - c2 = (_SSIM_K2 * max_val) ** 2 - else: - c2 = (k2 * max_val) ** 2 + c1 = (k1 * max_val) ** 2 + c2 = (k2 * max_val) ** 2 # SSIM luminance measure is # (2 * mu_x * mu_y + c1) / (mu_x ** 2 + mu_y ** 2 + c1). From acf4cb811bb9d67efc65b61b2e1c99c005f313b1 Mon Sep 17 00:00:00 2001 From: Gurpreet singh Date: Sat, 30 Mar 2019 14:51:52 +0530 Subject: [PATCH 09/15] indentation --- tensorflow/python/ops/image_ops_impl.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tensorflow/python/ops/image_ops_impl.py b/tensorflow/python/ops/image_ops_impl.py index bd6b5b25deaa27..9c097fd4b9a985 100644 --- a/tensorflow/python/ops/image_ops_impl.py +++ b/tensorflow/python/ops/image_ops_impl.py @@ -2981,13 +2981,13 @@ def ssim(img1, img2, max_val, filter_size = _SSIM_FILTER_SIZE, im2 = tf.decode_png('path/to/im2.png') # Compute SSIM over tf.uint8 Tensors. ssim1 = tf.image.ssim(im1, im2, max_val=255, filter_size = 11, - filter_sigma = 1.5, k1 = 0.01, k2 = 0.03) + filter_sigma = 1.5, k1 = 0.01, k2 = 0.03) # Compute SSIM over tf.float32 Tensors. im1 = tf.image.convert_image_dtype(im1, tf.float32) im2 = tf.image.convert_image_dtype(im2, tf.float32) ssim2 = tf.image.ssim(im1, im2, max_val=1.0, filter_size = 11, - filter_sigma = 1.5, k1 = 0.01, k2 = 0.03) + filter_sigma = 1.5, k1 = 0.01, k2 = 0.03) # ssim1 and ssim2 both have type tf.float32 and are almost equal. ``` From e617cd9b5ff0727b4cd9bd363d2dd11d6b653ef7 Mon Sep 17 00:00:00 2001 From: gurpreetsingh9465 Date: Thu, 4 Apr 2019 23:13:40 +0530 Subject: [PATCH 10/15] api compatability test --- tensorflow/python/ops/image_ops_impl.py | 2 +- tensorflow/tools/api/golden/v1/tensorflow.image.pbtxt | 4 ++-- tensorflow/tools/api/golden/v2/tensorflow.image.pbtxt | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tensorflow/python/ops/image_ops_impl.py b/tensorflow/python/ops/image_ops_impl.py index 9c097fd4b9a985..af7bbbaeb6bd6a 100644 --- a/tensorflow/python/ops/image_ops_impl.py +++ b/tensorflow/python/ops/image_ops_impl.py @@ -2831,7 +2831,7 @@ def _ssim_helper(x, y, reducer, max_val, compensation=1.0, k1=_SSIM_K1, k2=_SSIM compensation: Compensation factor. See above. k1: Default value 0.01 k2: Default value 0.03 (SSIM is less sensitivity to K2 for - lower values, so it would be better if we taken the valuesin range + lower values, so it would be better if we taken the values in range of 0< K2 <0.4). Returns: diff --git a/tensorflow/tools/api/golden/v1/tensorflow.image.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.image.pbtxt index 131ec939838cb3..3fcb1bd0b5a251 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.image.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.image.pbtxt @@ -238,11 +238,11 @@ tf_module { } member_method { name: "ssim" - argspec: "args=[\'img1\', \'img2\', \'max_val\'], varargs=None, keywords=None, defaults=None" + argspec: "args=[\'img1\', \'img2\', \'max_val\', \'filter_size\', \'filter_sigma\', \'k1\', \'k2\'], varargs=None, keywords=None, defaults=[\'11\', \'1.5\', \'0.01\', \'0.03\'], " } member_method { name: "ssim_multiscale" - argspec: "args=[\'img1\', \'img2\', \'max_val\', \'power_factors\'], varargs=None, keywords=None, defaults=[\'(0.0448, 0.2856, 0.3001, 0.2363, 0.1333)\'], " + argspec: "args=[\'img1\', \'img2\', \'max_val\', \'power_factors\', \'filter_size\', \'filter_sigma\', \'k1\', \'k2\'], varargs=None, keywords=None, defaults=[\'(0.0448, 0.2856, 0.3001, 0.2363, 0.1333)\', \'11\', \'1.5\', \'0.01\', \'0.03\'], " } member_method { name: "total_variation" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.image.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.image.pbtxt index 741b5b772cffa5..a35004a60ff2ab 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.image.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.image.pbtxt @@ -218,11 +218,11 @@ tf_module { } member_method { name: "ssim" - argspec: "args=[\'img1\', \'img2\', \'max_val\'], varargs=None, keywords=None, defaults=None" + argspec: "args=[\'img1\', \'img2\', \'max_val\', \'filter_size\', \'filter_sigma\', \'k1\', \'k2\'], varargs=None, keywords=None, defaults=[\'11\', \'1.5\', \'0.01\', \'0.03\'], " } member_method { name: "ssim_multiscale" - argspec: "args=[\'img1\', \'img2\', \'max_val\', \'power_factors\'], varargs=None, keywords=None, defaults=[\'(0.0448, 0.2856, 0.3001, 0.2363, 0.1333)\'], " + argspec: "args=[\'img1\', \'img2\', \'max_val\', \'power_factors\', \'filter_size\', \'filter_sigma\', \'k1\', \'k2\'], varargs=None, keywords=None, defaults=[\'(0.0448, 0.2856, 0.3001, 0.2363, 0.1333)\', \'11\', \'1.5\', \'0.01\', \'0.03\'], " } member_method { name: "total_variation" From d362b1fb698cbce1a2b47d756b019c88ab98c02c Mon Sep 17 00:00:00 2001 From: gurpreetsingh9465 Date: Fri, 19 Apr 2019 15:47:11 +0530 Subject: [PATCH 11/15] fix pylint error --- tensorflow/python/ops/image_ops_impl.py | 56 +++++++++++++++++-------- tensorflow/python/ops/image_ops_test.py | 16 +++---- 2 files changed, 47 insertions(+), 25 deletions(-) diff --git a/tensorflow/python/ops/image_ops_impl.py b/tensorflow/python/ops/image_ops_impl.py index af7bbbaeb6bd6a..04bfe940598dff 100644 --- a/tensorflow/python/ops/image_ops_impl.py +++ b/tensorflow/python/ops/image_ops_impl.py @@ -2804,7 +2804,13 @@ def psnr(a, b, max_val, name=None): _SSIM_SIGMA = 1.5 -def _ssim_helper(x, y, reducer, max_val, compensation=1.0, k1=_SSIM_K1, k2=_SSIM_K2): +def _ssim_helper(x, + y, + reducer, + max_val, + compensation=1.0, + k1=_SSIM_K1, + k2=_SSIM_K2): r"""Helper function for computing SSIM. SSIM estimates covariances with weighted sums. The default parameters @@ -2880,8 +2886,13 @@ def _fspecial_gauss(size, sigma): return array_ops.reshape(g, shape=[size, size, 1, 1]) -def _ssim_per_channel(img1, img2, max_val=1.0, filter_size = _SSIM_FILTER_SIZE, - filter_sigma = _SSIM_SIGMA, k1 = _SSIM_K1, k2 = _SSIM_K2): +def _ssim_per_channel(img1, + img2, + max_val=1.0, + filter_size=_SSIM_FILTER_SIZE, + filter_sigma=_SSIM_SIGMA, + k1=_SSIM_K1, + k2=_SSIM_K2): """Computes SSIM index between img1 and img2 per color channel. This function matches the standard SSIM implementation from: @@ -2944,7 +2955,7 @@ def reducer(x): array_ops.shape(y)[1:]], 0)) luminance, cs = _ssim_helper(img1, img2, reducer, max_val, compensation, - k1, k2) + k1, k2) # Average over the second and the third from the last: height, width. axes = constant_op.constant([-3, -2], dtype=dtypes.int32) @@ -2954,8 +2965,13 @@ def reducer(x): @tf_export('image.ssim') -def ssim(img1, img2, max_val, filter_size = _SSIM_FILTER_SIZE, - filter_sigma = _SSIM_SIGMA, k1 = _SSIM_K1, k2 = _SSIM_K2): +def ssim(img1, + img2, + max_val, + filter_size=_SSIM_FILTER_SIZE, + filter_sigma=_SSIM_SIGMA, + k1=_SSIM_K1, + k2=_SSIM_K2): """Computes SSIM index between img1 and img2. This function is based on the standard SSIM implementation from: @@ -2980,14 +2996,14 @@ def ssim(img1, img2, max_val, filter_size = _SSIM_FILTER_SIZE, im1 = tf.decode_png('path/to/im1.png') im2 = tf.decode_png('path/to/im2.png') # Compute SSIM over tf.uint8 Tensors. - ssim1 = tf.image.ssim(im1, im2, max_val=255, filter_size = 11, - filter_sigma = 1.5, k1 = 0.01, k2 = 0.03) + ssim1 = tf.image.ssim(im1, im2, max_val=255, filter_size=11, + filter_sigma=1.5, k1=0.01, k2=0.03) # Compute SSIM over tf.float32 Tensors. im1 = tf.image.convert_image_dtype(im1, tf.float32) im2 = tf.image.convert_image_dtype(im2, tf.float32) - ssim2 = tf.image.ssim(im1, im2, max_val=1.0, filter_size = 11, - filter_sigma = 1.5, k1 = 0.01, k2 = 0.03) + ssim2 = tf.image.ssim(im1, im2, max_val=1.0, filter_size=11, + filter_sigma=1.5, k1=0.01, k2=0.03) # ssim1 and ssim2 both have type tf.float32 and are almost equal. ``` @@ -3019,7 +3035,7 @@ def ssim(img1, img2, max_val, filter_size = _SSIM_FILTER_SIZE, img1 = convert_image_dtype(img1, dtypes.float32) img2 = convert_image_dtype(img2, dtypes.float32) ssim_per_channel, _ = _ssim_per_channel(img1, img2, max_val, filter_size, - filter_sigma, k1, k2 ) + filter_sigma, k1, k2) # Compute average over color channels. return math_ops.reduce_mean(ssim_per_channel, [-1]) @@ -3029,9 +3045,14 @@ def ssim(img1, img2, max_val, filter_size = _SSIM_FILTER_SIZE, @tf_export('image.ssim_multiscale') -def ssim_multiscale(img1, img2, max_val, power_factors=_MSSSIM_WEIGHTS, - filter_size = _SSIM_FILTER_SIZE, filter_sigma = _SSIM_SIGMA, - k1 = _SSIM_K1, k2 = _SSIM_K2): +def ssim_multiscale(img1, + img2, + max_val, + power_factors=_MSSSIM_WEIGHTS, + filter_size=_SSIM_FILTER_SIZE, + filter_sigma=_SSIM_SIGMA, + k1=_SSIM_K1, + k2=_SSIM_K2): """Computes the MS-SSIM between img1 and img2. This function assumes that `img1` and `img2` are image batches, i.e. the last @@ -3059,7 +3080,7 @@ def ssim_multiscale(img1, img2, max_val, power_factors=_MSSSIM_WEIGHTS, filter_sigma: width of gaussian filter. k1: Default value 0.01 k2: Default value 0.03 (SSIM is less sensitivity to K2 for - lower values, so it would be better if we taken the valuesin range + lower values, so it would be better if we taken the values in range of 0< K2 <0.4). Returns: @@ -3130,8 +3151,9 @@ def do_pad(images, remainder): # Overwrite previous ssim value since we only need the last one. ssim_per_channel, cs = _ssim_per_channel(*imgs, max_val=max_val, - filter_size = filter_size, - filter_sigma = filter_sigma, k1 = k1, k2 = k2) + filter_size=filter_size, + filter_sigma=filter_sigma, + k1=k1, k2=k2) mcs.append(nn_ops.relu(cs)) # Remove the cs score for the last scale. In the MS-SSIM calculation, diff --git a/tensorflow/python/ops/image_ops_test.py b/tensorflow/python/ops/image_ops_test.py index ad65d6edea9f47..81bcace5d6e9ff 100644 --- a/tensorflow/python/ops/image_ops_test.py +++ b/tensorflow/python/ops/image_ops_test.py @@ -4652,9 +4652,9 @@ def testBatch(self): img1 = np.concatenate(img1) img2 = np.concatenate(img2) - ssim = image_ops.ssim(constant_op.constant(img1), - constant_op.constant(img2), 1.0, filter_size=11, - filter_sigma=1.5, k1=0.01, k2=0.03) + ssim = image_ops.ssim(constant_op.constant(img1),constant_op.constant(img2), + 1.0, filter_size=11, filter_sigma=1.5, k1=0.01, + k2=0.03) with self.cached_session(use_gpu=True): self.assertAllClose(expected, self.evaluate(ssim), atol=1e-4) @@ -4682,7 +4682,8 @@ def testNegative(self): img2 = img2.reshape((1, 16, 16, 1)) ssim = image_ops.ssim(constant_op.constant(img1),constant_op.constant(img2), - 255, filter_size=11, filter_sigma=1.5, k1=0.01, k2=0.03) + 255, filter_size=11, filter_sigma=1.5, k1=0.01, + k2=0.03) with self.cached_session(use_gpu=True): self.assertLess(ssim.eval(), 0) @@ -4696,8 +4697,8 @@ def testInt(self): k1 = 0.01, k2 = 0.03) img1 = image_ops.convert_image_dtype(img1, dtypes.float32) img2 = image_ops.convert_image_dtype(img2, dtypes.float32) - ssim_float32 = image_ops.ssim(img1, img2, 1.0, filter_size=11, filter_sigma=1.5, - k1 = 0.01, k2 = 0.03) + ssim_float32 = image_ops.ssim(img1, img2, 1.0, filter_size=11, + filter_sigma=1.5, k1 = 0.01, k2 = 0.03) with self.cached_session(use_gpu=True): self.assertAllClose( ssim_uint8.eval(), self.evaluate(ssim_float32), atol=0.001) @@ -4825,8 +4826,7 @@ def testInt(self): img1 = constant_op.constant(img1, dtypes.uint8) img2 = constant_op.constant(img2, dtypes.uint8) ssim_uint8 = image_ops.ssim_multiscale(img1, img2, 255, filter_size=11, - filter_sigma=1.5, k1=0.01, - k2=0.03) + filter_sigma=1.5, k1=0.01, k2=0.03) img1 = image_ops.convert_image_dtype(img1, dtypes.float32) img2 = image_ops.convert_image_dtype(img2, dtypes.float32) ssim_float32 = image_ops.ssim_multiscale(img1, img2, 1.0, filter_size=11, From 423fb4811844df3a82d70b8a5638aecc196e528f Mon Sep 17 00:00:00 2001 From: gurpreetsingh9465 Date: Fri, 19 Apr 2019 15:54:05 +0530 Subject: [PATCH 12/15] docs string lint fix --- tensorflow/python/ops/image_ops_impl.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tensorflow/python/ops/image_ops_impl.py b/tensorflow/python/ops/image_ops_impl.py index 04bfe940598dff..bee0545339b683 100644 --- a/tensorflow/python/ops/image_ops_impl.py +++ b/tensorflow/python/ops/image_ops_impl.py @@ -2915,7 +2915,7 @@ def _ssim_per_channel(img1, filter_sigma: width of gaussian filter. k1: Default value 0.01 k2: Default value 0.03 (SSIM is less sensitivity to K2 for - lower values, so it would be better if we taken the valuesin range + lower values, so it would be better if we taken the values in range of 0< K2 <0.4). Returns: @@ -3016,7 +3016,7 @@ def ssim(img1, filter_sigma: width of gaussian filter. k1: Default value 0.01 k2: Default value 0.03 (SSIM is less sensitivity to K2 for - lower values, so it would be better if we taken the valuesin range + lower values, so it would be better if we taken the values in range of 0< K2 <0.4). Returns: From 55fe7bd6d1c96132a0f5dd0701b0407697f07bd9 Mon Sep 17 00:00:00 2001 From: gurpreetsingh9465 Date: Sat, 20 Apr 2019 12:45:56 +0530 Subject: [PATCH 13/15] added constants --- tensorflow/python/ops/image_ops_impl.py | 38 +++++++++++-------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/tensorflow/python/ops/image_ops_impl.py b/tensorflow/python/ops/image_ops_impl.py index bee0545339b683..7245da8599704e 100644 --- a/tensorflow/python/ops/image_ops_impl.py +++ b/tensorflow/python/ops/image_ops_impl.py @@ -2798,19 +2798,13 @@ def psnr(a, b, max_val, name=None): with ops.control_dependencies(checks): return array_ops.identity(psnr_val) -_SSIM_K1 = 0.01 -_SSIM_K2 = 0.03 -_SSIM_FILTER_SIZE = 11 -_SSIM_SIGMA = 1.5 - - def _ssim_helper(x, y, reducer, max_val, compensation=1.0, - k1=_SSIM_K1, - k2=_SSIM_K2): + k1=0.01, + k2=0.03): r"""Helper function for computing SSIM. SSIM estimates covariances with weighted sums. The default parameters @@ -2889,10 +2883,10 @@ def _fspecial_gauss(size, sigma): def _ssim_per_channel(img1, img2, max_val=1.0, - filter_size=_SSIM_FILTER_SIZE, - filter_sigma=_SSIM_SIGMA, - k1=_SSIM_K1, - k2=_SSIM_K2): + filter_size=11, + filter_sigma=1.5, + k1=0.01, + k2=0.03): """Computes SSIM index between img1 and img2 per color channel. This function matches the standard SSIM implementation from: @@ -2968,10 +2962,10 @@ def reducer(x): def ssim(img1, img2, max_val, - filter_size=_SSIM_FILTER_SIZE, - filter_sigma=_SSIM_SIGMA, - k1=_SSIM_K1, - k2=_SSIM_K2): + filter_size=11, + filter_sigma=1.5, + k1=0.01, + k2=0.03): """Computes SSIM index between img1 and img2. This function is based on the standard SSIM implementation from: @@ -3012,8 +3006,8 @@ def ssim(img1, img2: Second image batch. max_val: The dynamic range of the images (i.e., the difference between the maximum the and minimum allowed values). - filter_size: size of gaussian filter. - filter_sigma: width of gaussian filter. + filter_size: Default value 11 (size of gaussian filter). + filter_sigma: Default value 1.5 (width of gaussian filter). k1: Default value 0.01 k2: Default value 0.03 (SSIM is less sensitivity to K2 for lower values, so it would be better if we taken the values in range @@ -3049,10 +3043,10 @@ def ssim_multiscale(img1, img2, max_val, power_factors=_MSSSIM_WEIGHTS, - filter_size=_SSIM_FILTER_SIZE, - filter_sigma=_SSIM_SIGMA, - k1=_SSIM_K1, - k2=_SSIM_K2): + filter_size=11, + filter_sigma=1.5, + k1=0.01, + k2=0.03): """Computes the MS-SSIM between img1 and img2. This function assumes that `img1` and `img2` are image batches, i.e. the last From cf7b2887dda3959eb5a72b7d42052dcb84f8b609 Mon Sep 17 00:00:00 2001 From: gurpreetsingh9465 Date: Sat, 20 Apr 2019 12:55:15 +0530 Subject: [PATCH 14/15] docs changes --- tensorflow/python/ops/image_ops_impl.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tensorflow/python/ops/image_ops_impl.py b/tensorflow/python/ops/image_ops_impl.py index 4ee4be07ea55c4..c655fc363b4af1 100644 --- a/tensorflow/python/ops/image_ops_impl.py +++ b/tensorflow/python/ops/image_ops_impl.py @@ -2925,8 +2925,8 @@ def _ssim_per_channel(img1, maximum the and minimum allowed values). size: size of gaussian filter. sigma: width of gaussian filter. - filter_size: size of gaussian filter. - filter_sigma: width of gaussian filter. + filter_size: Default value 11 (size of gaussian filter). + filter_sigma: Default value 1.5 (width of gaussian filter). k1: Default value 0.01 k2: Default value 0.03 (SSIM is less sensitivity to K2 for lower values, so it would be better if we taken the values in range @@ -3097,8 +3097,8 @@ def ssim_multiscale(img1, resolution's weight and each increasing scale corresponds to the image being downsampled by 2. Defaults to (0.0448, 0.2856, 0.3001, 0.2363, 0.1333), which are the values obtained in the original paper. - filter_size: size of gaussian filter. - filter_sigma: width of gaussian filter. + filter_size: Default value 11 (size of gaussian filter). + filter_sigma: Default value 1.5 (width of gaussian filter). k1: Default value 0.01 k2: Default value 0.03 (SSIM is less sensitivity to K2 for lower values, so it would be better if we taken the values in range From 9010b5a76a61301beebb53bcf6444ea072a72891 Mon Sep 17 00:00:00 2001 From: gurpreetsingh9465 Date: Sat, 20 Apr 2019 12:59:39 +0530 Subject: [PATCH 15/15] docs changes --- tensorflow/python/ops/image_ops_impl.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tensorflow/python/ops/image_ops_impl.py b/tensorflow/python/ops/image_ops_impl.py index c655fc363b4af1..ad6b8069182c01 100644 --- a/tensorflow/python/ops/image_ops_impl.py +++ b/tensorflow/python/ops/image_ops_impl.py @@ -2923,8 +2923,6 @@ def _ssim_per_channel(img1, img2: Second image batch. max_val: The dynamic range of the images (i.e., the difference between the maximum the and minimum allowed values). - size: size of gaussian filter. - sigma: width of gaussian filter. filter_size: Default value 11 (size of gaussian filter). filter_sigma: Default value 1.5 (width of gaussian filter). k1: Default value 0.01