From c6e5c7095350e931709acd894a54b32c42375822 Mon Sep 17 00:00:00 2001 From: Scott Sievert Date: Sat, 23 Jul 2016 15:09:12 -0500 Subject: [PATCH] makes PyWavelets required --- optional_requirements.txt | 1 - requirements.txt | 1 + skimage/restoration/_denoise.py | 25 ++++++++--------------- skimage/restoration/tests/test_denoise.py | 6 +++--- 4 files changed, 13 insertions(+), 20 deletions(-) diff --git a/optional_requirements.txt b/optional_requirements.txt index 6f923675..8bc53bb0 100644 --- a/optional_requirements.txt +++ b/optional_requirements.txt @@ -4,4 +4,3 @@ SimpleITK; python_version != '3.4' and python_version != '3.5' astropy tifffile imageio -PyWavelets diff --git a/requirements.txt b/requirements.txt index 1e6921be..b05402dc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,3 +5,4 @@ six>=1.7.3 networkx>=1.8 pillow>=2.1.0 dask[array]>=0.5.0 +PyWavelets>=0.4.0 diff --git a/skimage/restoration/_denoise.py b/skimage/restoration/_denoise.py index 33fac776..94a11608 100644 --- a/skimage/restoration/_denoise.py +++ b/skimage/restoration/_denoise.py @@ -5,6 +5,7 @@ from .. import img_as_float from ..restoration._denoise_cy import _denoise_bilateral, _denoise_tv_bregman from .._shared.utils import skimage_deprecation, warn import warnings +import pywt def denoise_bilateral(image, win_size=None, sigma_color=None, sigma_spatial=1, @@ -336,6 +337,7 @@ def denoise_tv_chambolle(im, weight=0.1, eps=2.e-4, n_iter_max=200, def _wavelet_threshold(img, wavelet, threshold=None, sigma=None, mode='soft'): """Performs wavelet denoising. + Parameters ---------- img : ndarray (2d or 3d) of ints, uints or floats @@ -372,8 +374,8 @@ def _wavelet_threshold(img, wavelet, threshold=None, sigma=None, mode='soft'): .. [2] D. L. Donoho and I. M. Johnstone. "Ideal spatial adaptation by wavelet shrinkage." Biometrika 81.3 (1994): 425-455. DOI: 10.1093/biomet/81.3.425 + """ - import pywt coeffs = pywt.wavedecn(img, wavelet=wavelet) detail_coeffs = coeffs[-1]['d' * img.ndim] @@ -393,7 +395,8 @@ def _wavelet_threshold(img, wavelet, threshold=None, sigma=None, mode='soft'): def denoise_wavelet(img, sigma=None, wavelet='db1', mode='soft'): - r"""Performs wavelet denoising on an image. + """Performs wavelet denoising on an image. + Parameters ---------- img : ndarray (greater than 2d) of ints, uints or floats @@ -406,7 +409,7 @@ def denoise_wavelet(img, sigma=None, wavelet='db1', mode='soft'): standard deviation is estimated via the method in [2]_. wavelet : string, optional The type of wavelet to perform and can be any of the options - [pywt.wavelist]_ outputs. The default is `'db1'`. For example, + ``pywt.wavelist`` outputs. The default is `'db1'`. For example, ``wavelet`` can be any of ``{'db2', 'haar', 'sym9'}`` and many more. mode : {'soft', 'hard'}, optional An optional argument to choose the type of denoising performed. It @@ -424,15 +427,6 @@ def denoise_wavelet(img, sigma=None, wavelet='db1', mode='soft'): wavelet domain. Correspondingly, many pixel values of an image are 0 after taking the wavelet transform. - By wavelet denoising, we are enforcing that many of the wavelet - coefficients are 0 while keeping the error small. When we use soft - thresholding, our estimate is - - .. math:: \widehat{x} = \arg \min_x ||z - x||_2^2 + \lambda ||x||_1 - - where :math:`z` is the input image wavelet coefficients and :math:`\lambda` - is the threshold. - This function performs wavelet denoising on each color plane separately. The output is clipped between 0 and 1. @@ -451,11 +445,10 @@ def denoise_wavelet(img, sigma=None, wavelet='db1', mode='soft'): >>> from skimage import color, data >>> img = img_as_float(data.astronaut()) >>> img = color.rgb2gray(img) - >>> img += 0.5 * img.std() * np.random.randn(*img.shape) + >>> img += 0.1 * np.random.randn(*img.shape) >>> img = np.clip(img, 0, 1) - >>> denoised_img = denoise_wavelet(img) - >>> assert denoised_img.min() >= 0.0 - >>> assert denoised_img.max() <= 1.0 + >>> denoised_img = denoise_wavelet(img, sigma=0.1) + """ if not img.dtype.kind == 'f': diff --git a/skimage/restoration/tests/test_denoise.py b/skimage/restoration/tests/test_denoise.py index 664f89a3..206f1923 100644 --- a/skimage/restoration/tests/test_denoise.py +++ b/skimage/restoration/tests/test_denoise.py @@ -313,11 +313,11 @@ def test_wavelet_denoising(): img = img.copy() + 0.1 * np.random.randn(*(img.shape)) img = np.clip(img, 0, 1) # less energy in signal - assert restoration.denoise_wavelet(img).sum() <= img.sum() + assert restoration.denoise_wavelet(img, sigma=0.3).sum() <= img.sum() # test changing noise_std (higher threshold, so less energy in signal) - assert (restoration.denoise_wavelet(img, noise_stdev=0.2).sum() <= - restoration.denoise_wavelet(img, noise_stdev=0.1).sum()) + assert (restoration.denoise_wavelet(img, sigma=0.2).sum() <= + restoration.denoise_wavelet(img, sigma=0.1).sum()) # This works for this particular image assert (np.sum(restoration.denoise_wavelet(img, wavelet='db2')) <