From 14d0923959e7509fd40f3f1b67e43989fa72a037 Mon Sep 17 00:00:00 2001 From: Andreas Wuerl Date: Mon, 27 Aug 2012 12:41:29 +0200 Subject: [PATCH 1/5] fixed data of tv_denoise result images with float datatype to be in default range [0.0:1.0] --- skimage/filter/_tv_denoise.py | 27 ++++++++++++++++++++++++- skimage/filter/tests/test_tv_denoise.py | 11 +++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/skimage/filter/_tv_denoise.py b/skimage/filter/_tv_denoise.py index e8736786..af8decfc 100644 --- a/skimage/filter/_tv_denoise.py +++ b/skimage/filter/_tv_denoise.py @@ -170,7 +170,30 @@ def _tv_denoise_2d(im, weight=50, eps=2.e-4, n_iter_max=200): i += 1 return out +def _renormalize_image(image, data_type): + """ + inplace renormalize image date to obey the float range [0.0:1.0] + Parameters + ---------- + immage: ndarray + input data to be renormalized + + data_type: type, + image data type before running tv_denoise + + Notes + ------- + the minimum and maximum values of the image data type define the range + which is mapped to the interval [0.0:1.0] + + """ + type_info = np.iinfo(data_type) + start = type_info.min + width = type_info.max - type_info.min + np.subtract(image, start, image) + np.divide(image, width, image) + def tv_denoise(im, weight=50, eps=2.e-4, keep_type=False, n_iter_max=200): """ Perform total-variation denoising on 2-d and 3-d images @@ -257,4 +280,6 @@ def tv_denoise(im, weight=50, eps=2.e-4, keep_type=False, n_iter_max=200): if keep_type: return out.astype(im_type) else: - return out + if not im_type.kind == 'f': + _renormalize_image(out, im_type) + return out diff --git a/skimage/filter/tests/test_tv_denoise.py b/skimage/filter/tests/test_tv_denoise.py index 4cc6adbb..47f53251 100644 --- a/skimage/filter/tests/test_tv_denoise.py +++ b/skimage/filter/tests/test_tv_denoise.py @@ -33,6 +33,16 @@ class TestTvDenoise(): weight=60.0, keep_type=True) assert denoised_lena_int.dtype is np.dtype('uint16') + def test_tv_denoise_float_result_range(self): + # lena image + lena = color.rgb2gray(data.lena())[:256, :256] + int_lena = np.multiply(lena, 255).astype(np.uint8) + assert np.max(int_lena) > 1 + denoised_int_lena = filter.tv_denoise(int_lena, weight=60.0) + # test if the value range of output float data is within [0.0:1.0] + assert np.max(denoised_int_lena) <= 1.0 + assert np.min(denoised_int_lena) >= 0.0 + def test_tv_denoise_3d(self): """ Apply the TV denoising algorithm on a 3D image representing @@ -59,6 +69,5 @@ class TestTvDenoise(): except ValueError: pass - if __name__ == "__main__": run_module_suite() From bcf45941700e3d1f7bde20c2070f237b45fcd1a3 Mon Sep 17 00:00:00 2001 From: Andreas Wuerl Date: Mon, 27 Aug 2012 15:18:03 +0200 Subject: [PATCH 2/5] use existing functionality for fix --- skimage/filter/_tv_denoise.py | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/skimage/filter/_tv_denoise.py b/skimage/filter/_tv_denoise.py index af8decfc..545f9e09 100644 --- a/skimage/filter/_tv_denoise.py +++ b/skimage/filter/_tv_denoise.py @@ -1,4 +1,5 @@ import numpy as np +from skimage.util import dtype def _tv_denoise_3d(im, weight=100, eps=2.e-4, n_iter_max=200): @@ -169,30 +170,6 @@ def _tv_denoise_2d(im, weight=50, eps=2.e-4, n_iter_max=200): E_previous = E i += 1 return out - -def _renormalize_image(image, data_type): - """ - inplace renormalize image date to obey the float range [0.0:1.0] - - Parameters - ---------- - immage: ndarray - input data to be renormalized - - data_type: type, - image data type before running tv_denoise - - Notes - ------- - the minimum and maximum values of the image data type define the range - which is mapped to the interval [0.0:1.0] - - """ - type_info = np.iinfo(data_type) - start = type_info.min - width = type_info.max - type_info.min - np.subtract(image, start, image) - np.divide(image, width, image) def tv_denoise(im, weight=50, eps=2.e-4, keep_type=False, n_iter_max=200): """ @@ -281,5 +258,5 @@ def tv_denoise(im, weight=50, eps=2.e-4, keep_type=False, n_iter_max=200): return out.astype(im_type) else: if not im_type.kind == 'f': - _renormalize_image(out, im_type) + out = dtype.convert(out.astype(im_type), np.float) return out From 42ae537a69247ffba90f06270bbbc48176293fc4 Mon Sep 17 00:00:00 2001 From: Andreas Wuerl Date: Mon, 27 Aug 2012 19:44:30 +0200 Subject: [PATCH 3/5] convert image to float before performing tv_denoise operation now removed keep_type argument from tv_denoise which becomes obsolete with the previos change adapted tests --- skimage/filter/_tv_denoise.py | 18 ++++-------------- skimage/filter/tests/test_tv_denoise.py | 14 +++++++------- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/skimage/filter/_tv_denoise.py b/skimage/filter/_tv_denoise.py index 545f9e09..76affb98 100644 --- a/skimage/filter/_tv_denoise.py +++ b/skimage/filter/_tv_denoise.py @@ -1,5 +1,5 @@ import numpy as np -from skimage.util import dtype +from skimage import img_as_float def _tv_denoise_3d(im, weight=100, eps=2.e-4, n_iter_max=200): @@ -171,7 +171,7 @@ def _tv_denoise_2d(im, weight=50, eps=2.e-4, n_iter_max=200): i += 1 return out -def tv_denoise(im, weight=50, eps=2.e-4, keep_type=False, n_iter_max=200): +def tv_denoise(im, weight=50, eps=2.e-4, n_iter_max=200): """ Perform total-variation denoising on 2-d and 3-d images @@ -192,11 +192,6 @@ def tv_denoise(im, weight=50, eps=2.e-4, keep_type=False, n_iter_max=200): (E_(n-1) - E_n) < eps * E_0 - keep_type: bool, optional (False) - whether the output has the same dtype as the input array. - keep_type is False by default, and the dtype of the output - is np.float - n_iter_max: int, optional maximal number of iterations used for the optimization. @@ -245,7 +240,7 @@ def tv_denoise(im, weight=50, eps=2.e-4, keep_type=False, n_iter_max=200): """ im_type = im.dtype if not im_type.kind == 'f': - im = im.astype(np.float) + im = img_as_float(im) if im.ndim == 2: out = _tv_denoise_2d(im, weight, eps, n_iter_max) @@ -254,9 +249,4 @@ def tv_denoise(im, weight=50, eps=2.e-4, keep_type=False, n_iter_max=200): else: raise ValueError('only 2-d and 3-d images may be denoised with this ' 'function') - if keep_type: - return out.astype(im_type) - else: - if not im_type.kind == 'f': - out = dtype.convert(out.astype(im_type), np.float) - return out + return out diff --git a/skimage/filter/tests/test_tv_denoise.py b/skimage/filter/tests/test_tv_denoise.py index 47f53251..afee6b02 100644 --- a/skimage/filter/tests/test_tv_denoise.py +++ b/skimage/filter/tests/test_tv_denoise.py @@ -2,7 +2,7 @@ import numpy as np from numpy.testing import run_module_suite from skimage import filter, data, color -from skimage import img_as_uint +from skimage import img_as_uint, img_as_ubyte class TestTvDenoise(): @@ -29,8 +29,8 @@ class TestTvDenoise(): # test if the total variation has decreased assert (np.sqrt((grad_denoised**2).sum()) < np.sqrt((grad**2).sum()) / 2) - denoised_lena_int = filter.tv_denoise(img_as_uint(lena), - weight=60.0, keep_type=True) + denoised_lena_int = img_as_uint(filter.tv_denoise(img_as_ubyte(lena), + weight=60.0)) assert denoised_lena_int.dtype is np.dtype('uint16') def test_tv_denoise_float_result_range(self): @@ -55,13 +55,13 @@ class TestTvDenoise(): mask += 20 * np.random.randn(*mask.shape) mask[mask < 0] = 0 mask[mask > 255] = 255 - res = filter.tv_denoise(mask.astype(np.uint8), - weight=100, keep_type=True) + res = img_as_ubyte(filter.tv_denoise(mask.astype(np.uint8), + weight=100)) assert res.std() < mask.std() assert res.dtype is np.dtype('uint8') - res = filter.tv_denoise(mask.astype(np.uint8), weight=100) + res = img_as_ubyte(filter.tv_denoise(mask.astype(np.uint8), weight=100)) assert res.std() < mask.std() - assert res.dtype is not np.dtype('uint8') + # test wrong number of dimensions a = np.random.random((8, 8, 8, 8)) try: From 12b8d8d051587006a8fee0a690df60c2c106fedf Mon Sep 17 00:00:00 2001 From: Andreas Wuerl Date: Sun, 2 Sep 2012 21:17:18 +0200 Subject: [PATCH 4/5] cleanup of tests hence all results of tv denoise operations are returned as float --- skimage/filter/tests/test_tv_denoise.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/skimage/filter/tests/test_tv_denoise.py b/skimage/filter/tests/test_tv_denoise.py index afee6b02..635dfdcd 100644 --- a/skimage/filter/tests/test_tv_denoise.py +++ b/skimage/filter/tests/test_tv_denoise.py @@ -27,11 +27,9 @@ class TestTvDenoise(): grad_denoised = ndimage.morphological_gradient( denoised_lena, size=((3, 3))) # test if the total variation has decreased + assert grad_denoised.dtype == np.float assert (np.sqrt((grad_denoised**2).sum()) < np.sqrt((grad**2).sum()) / 2) - denoised_lena_int = img_as_uint(filter.tv_denoise(img_as_ubyte(lena), - weight=60.0)) - assert denoised_lena_int.dtype is np.dtype('uint16') def test_tv_denoise_float_result_range(self): # lena image @@ -40,6 +38,7 @@ class TestTvDenoise(): assert np.max(int_lena) > 1 denoised_int_lena = filter.tv_denoise(int_lena, weight=60.0) # test if the value range of output float data is within [0.0:1.0] + assert denoised_int_lena.dtype == np.float assert np.max(denoised_int_lena) <= 1.0 assert np.min(denoised_int_lena) >= 0.0 @@ -55,12 +54,9 @@ class TestTvDenoise(): mask += 20 * np.random.randn(*mask.shape) mask[mask < 0] = 0 mask[mask > 255] = 255 - res = img_as_ubyte(filter.tv_denoise(mask.astype(np.uint8), - weight=100)) - assert res.std() < mask.std() - assert res.dtype is np.dtype('uint8') - res = img_as_ubyte(filter.tv_denoise(mask.astype(np.uint8), weight=100)) - assert res.std() < mask.std() + res = filter.tv_denoise(mask.astype(np.uint8), weight=100) + assert res.dtype == np.float + assert res.std() * 255 < mask.std() # test wrong number of dimensions a = np.random.random((8, 8, 8, 8)) @@ -69,5 +65,6 @@ class TestTvDenoise(): except ValueError: pass + if __name__ == "__main__": run_module_suite() From c85105308456d3d76e409566de5d84d4f6348e4b Mon Sep 17 00:00:00 2001 From: Andreas Wuerl Date: Sun, 2 Sep 2012 21:18:00 +0200 Subject: [PATCH 5/5] specified float array result in docstring --- skimage/filter/_tv_denoise.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/skimage/filter/_tv_denoise.py b/skimage/filter/_tv_denoise.py index 76affb98..4f663ae2 100644 --- a/skimage/filter/_tv_denoise.py +++ b/skimage/filter/_tv_denoise.py @@ -27,7 +27,7 @@ def _tv_denoise_3d(im, weight=100, eps=2.e-4, n_iter_max=200): Returns ------- out: ndarray - denoised array + denoised array of floats Notes ----- @@ -110,7 +110,7 @@ def _tv_denoise_2d(im, weight=50, eps=2.e-4, n_iter_max=200): Returns ------- out: ndarray - denoised array + denoised array of floats Notes ----- @@ -198,8 +198,7 @@ def tv_denoise(im, weight=50, eps=2.e-4, n_iter_max=200): Returns ------- out: ndarray - denoised array - + denoised array of floats Notes -----