mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-14 11:18:06 +08:00
Move denoise functions to restoration submodule
This commit is contained in:
@@ -3,7 +3,7 @@ from .exposure import histogram, equalize, equalize_hist, \
|
||||
adjust_gamma, adjust_sigmoid, adjust_log
|
||||
|
||||
from ._adapthist import equalize_adapthist
|
||||
from .unwrap import unwrap_phase
|
||||
|
||||
|
||||
__all__ = ['histogram',
|
||||
'equalize',
|
||||
@@ -13,5 +13,4 @@ __all__ = ['histogram',
|
||||
'cumulative_distribution',
|
||||
'adjust_gamma',
|
||||
'adjust_sigmoid',
|
||||
'adjust_log',
|
||||
'unwrap_phase']
|
||||
'adjust_log']
|
||||
|
||||
@@ -5,8 +5,6 @@ from ._canny import canny
|
||||
from .edges import (sobel, hsobel, vsobel, scharr, hscharr, vscharr, prewitt,
|
||||
hprewitt, vprewitt, roberts, roberts_positive_diagonal,
|
||||
roberts_negative_diagonal)
|
||||
from ._denoise import denoise_tv_chambolle
|
||||
from ._denoise_cy import denoise_bilateral, denoise_tv_bregman
|
||||
from ._rank_order import rank_order
|
||||
from ._gabor import gabor_kernel, gabor_filter
|
||||
from .thresholding import (threshold_adaptive, threshold_otsu, threshold_yen,
|
||||
@@ -14,6 +12,16 @@ from .thresholding import (threshold_adaptive, threshold_otsu, threshold_yen,
|
||||
from . import rank
|
||||
|
||||
|
||||
from skimage._shared.utils import deprecated
|
||||
from skimage import restoration
|
||||
denoise_bilateral = deprecated('skimage.restoration.denoise_bilateral')\
|
||||
(restoration.denoise_bilateral)
|
||||
denoise_tv_bregman = deprecated('skimage.restoration.denoise_tv_bregman')\
|
||||
(restoration.denoise_tv_bregman)
|
||||
denoise_tv_chambolle = deprecated('skimage.restoration.denoise_tv_chambolle')\
|
||||
(restoration.denoise_tv_chambolle)
|
||||
|
||||
|
||||
__all__ = ['inverse',
|
||||
'wiener',
|
||||
'LPIFilter2D',
|
||||
|
||||
@@ -59,7 +59,7 @@ __all__ = ['autolevel',
|
||||
'tophat',
|
||||
'noise_filter',
|
||||
'entropy',
|
||||
'otsu'
|
||||
'otsu',
|
||||
'percentile',
|
||||
# Deprecated
|
||||
'percentile_autolevel',
|
||||
|
||||
@@ -14,7 +14,6 @@ def configuration(parent_package='', top_path=None):
|
||||
config.add_data_dir('rank/tests')
|
||||
|
||||
cython(['_ctmf.pyx'], working_path=base_path)
|
||||
cython(['_denoise_cy.pyx'], working_path=base_path)
|
||||
cython(['rank/core_cy.pyx'], working_path=base_path)
|
||||
cython(['rank/generic_cy.pyx'], working_path=base_path)
|
||||
cython(['rank/percentile_cy.pyx'], working_path=base_path)
|
||||
@@ -22,8 +21,6 @@ def configuration(parent_package='', top_path=None):
|
||||
|
||||
config.add_extension('_ctmf', sources=['_ctmf.c'],
|
||||
include_dirs=[get_numpy_include_dirs()])
|
||||
config.add_extension('_denoise_cy', sources=['_denoise_cy.c'],
|
||||
include_dirs=[get_numpy_include_dirs(), '../_shared'])
|
||||
config.add_extension('rank.core_cy', sources=['rank/core_cy.c'],
|
||||
include_dirs=[get_numpy_include_dirs()])
|
||||
config.add_extension('rank.generic_cy', sources=['rank/generic_cy.c'],
|
||||
|
||||
@@ -20,8 +20,14 @@ References
|
||||
|
||||
from .deconvolution import wiener, unsupervised_wiener, richardson_lucy
|
||||
from .unwrap import unwrap_phase
|
||||
from ._denoise import denoise_tv_chambolle, denoise_tv_bregman, \
|
||||
denoise_bilateral
|
||||
|
||||
|
||||
__all__ = ['wiener',
|
||||
'unsupervised_wiener',
|
||||
'richardson_lucy',
|
||||
'unwrap_phase']
|
||||
'unwrap_phase',
|
||||
'denoise_tv_bregman',
|
||||
'denoise_tv_chambolle',
|
||||
'denoise_bilateral']
|
||||
|
||||
@@ -1,5 +1,109 @@
|
||||
# coding: utf-8
|
||||
import numpy as np
|
||||
from skimage import img_as_float
|
||||
from skimage.restoration._denoise_cy import _denoise_bilateral, \
|
||||
_denoise_tv_bregman
|
||||
|
||||
|
||||
def denoise_bilateral(image, win_size=5, sigma_range=None, sigma_spatial=1,
|
||||
bins=10000, mode='constant', cval=0):
|
||||
"""Denoise image using bilateral filter.
|
||||
|
||||
This is an edge-preserving and noise reducing denoising filter. It averages
|
||||
pixels based on their spatial closeness and radiometric similarity.
|
||||
|
||||
Spatial closeness is measured by the gaussian function of the euclidian
|
||||
distance between two pixels and a certain standard deviation
|
||||
(`sigma_spatial`).
|
||||
|
||||
Radiometric similarity is measured by the gaussian function of the euclidian
|
||||
distance between two color values and a certain standard deviation
|
||||
(`sigma_range`).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : ndarray
|
||||
Input image.
|
||||
win_size : int
|
||||
Window size for filtering.
|
||||
sigma_range : float
|
||||
Standard deviation for grayvalue/color distance (radiometric
|
||||
similarity). A larger value results in averaging of pixels with larger
|
||||
radiometric differences. Note, that the image will be converted using
|
||||
the `img_as_float` function and thus the standard deviation is in
|
||||
respect to the range `[0, 1]`.
|
||||
sigma_spatial : float
|
||||
Standard deviation for range distance. A larger value results in
|
||||
averaging of pixels with larger spatial differences.
|
||||
bins : int
|
||||
Number of discrete values for gaussian weights of color filtering.
|
||||
A larger value results in improved accuracy.
|
||||
mode : string
|
||||
How to handle values outside the image borders. See
|
||||
`scipy.ndimage.map_coordinates` for detail.
|
||||
cval : string
|
||||
Used in conjunction with mode 'constant', the value outside
|
||||
the image boundaries.
|
||||
|
||||
Returns
|
||||
-------
|
||||
denoised : ndarray
|
||||
Denoised image.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] http://users.soe.ucsc.edu/~manduchi/Papers/ICCV98.pdf
|
||||
|
||||
"""
|
||||
return _denoise_bilateral(image, win_size, sigma_range, sigma_spatial,
|
||||
bins, mode, cval)
|
||||
|
||||
|
||||
def denoise_tv_bregman(image, weight, max_iter=100, eps=1e-3, isotropic=True):
|
||||
"""Perform total-variation denoising using split-Bregman optimization.
|
||||
|
||||
Total-variation denoising (also know as total-variation regularization)
|
||||
tries to find an image with less total-variation under the constraint
|
||||
of being similar to the input image, which is controlled by the
|
||||
regularization parameter.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : ndarray
|
||||
Input data to be denoised (converted using img_as_float`).
|
||||
weight : float, optional
|
||||
Denoising weight. The smaller the `weight`, the more denoising (at
|
||||
the expense of less similarity to the `input`). The regularization
|
||||
parameter `lambda` is chosen as `2 * weight`.
|
||||
eps : float, optional
|
||||
Relative difference of the value of the cost function that determines
|
||||
the stop criterion. The algorithm stops when::
|
||||
|
||||
SUM((u(n) - u(n-1))**2) < eps
|
||||
|
||||
max_iter : int, optional
|
||||
Maximal number of iterations used for the optimization.
|
||||
isotropic : boolean, optional
|
||||
Switch between isotropic and anisotropic TV denoising.
|
||||
|
||||
Returns
|
||||
-------
|
||||
u : ndarray
|
||||
Denoised image.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] http://en.wikipedia.org/wiki/Total_variation_denoising
|
||||
.. [2] Tom Goldstein and Stanley Osher, "The Split Bregman Method For L1
|
||||
Regularized Problems",
|
||||
ftp://ftp.math.ucla.edu/pub/camreport/cam08-29.pdf
|
||||
.. [3] Pascal Getreuer, "Rudin–Osher–Fatemi Total Variation Denoising
|
||||
using Split Bregman" in Image Processing On Line on 2012–05–19,
|
||||
http://www.ipol.im/pub/art/2012/g-tvd/article_lr.pdf
|
||||
.. [4] http://www.math.ucsb.edu/~cgarcia/UGProjects/BregmanAlgorithms_JacquelineBush.pdf
|
||||
|
||||
"""
|
||||
return _denoise_tv_bregman(image, weight, max_iter, eps, isotropic)
|
||||
|
||||
|
||||
def _denoise_tv_chambolle_3d(im, weight=100, eps=2.e-4, n_iter_max=200):
|
||||
@@ -10,7 +10,6 @@ from libc.stdlib cimport malloc, free
|
||||
from libc.float cimport DBL_MAX
|
||||
from skimage._shared.interpolation cimport get_pixel3d
|
||||
from skimage.util import img_as_float
|
||||
from skimage._shared.utils import deprecated
|
||||
|
||||
|
||||
cdef inline double _gaussian_weight(double sigma, double value):
|
||||
@@ -45,58 +44,9 @@ cdef double* _compute_range_lut(Py_ssize_t win_size, double sigma):
|
||||
return range_lut
|
||||
|
||||
|
||||
def denoise_bilateral(image, Py_ssize_t win_size=5, sigma_range=None,
|
||||
double sigma_spatial=1, Py_ssize_t bins=10000,
|
||||
mode='constant', double cval=0):
|
||||
"""Denoise image using bilateral filter.
|
||||
|
||||
This is an edge-preserving and noise reducing denoising filter. It averages
|
||||
pixels based on their spatial closeness and radiometric similarity.
|
||||
|
||||
Spatial closeness is measured by the gaussian function of the euclidian
|
||||
distance between two pixels and a certain standard deviation
|
||||
(`sigma_spatial`).
|
||||
|
||||
Radiometric similarity is measured by the gaussian function of the euclidian
|
||||
distance between two color values and a certain standard deviation
|
||||
(`sigma_range`).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : ndarray
|
||||
Input image.
|
||||
win_size : int
|
||||
Window size for filtering.
|
||||
sigma_range : float
|
||||
Standard deviation for grayvalue/color distance (radiometric
|
||||
similarity). A larger value results in averaging of pixels with larger
|
||||
radiometric differences. Note, that the image will be converted using
|
||||
the `img_as_float` function and thus the standard deviation is in
|
||||
respect to the range `[0, 1]`.
|
||||
sigma_spatial : float
|
||||
Standard deviation for range distance. A larger value results in
|
||||
averaging of pixels with larger spatial differences.
|
||||
bins : int
|
||||
Number of discrete values for gaussian weights of color filtering.
|
||||
A larger value results in improved accuracy.
|
||||
mode : string
|
||||
How to handle values outside the image borders. See
|
||||
`scipy.ndimage.map_coordinates` for detail.
|
||||
cval : string
|
||||
Used in conjunction with mode 'constant', the value outside
|
||||
the image boundaries.
|
||||
|
||||
Returns
|
||||
-------
|
||||
denoised : ndarray
|
||||
Denoised image.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] http://users.soe.ucsc.edu/~manduchi/Papers/ICCV98.pdf
|
||||
|
||||
"""
|
||||
|
||||
def _denoise_bilateral(image, Py_ssize_t win_size, sigma_range,
|
||||
double sigma_spatial, Py_ssize_t bins,
|
||||
mode, double cval):
|
||||
image = np.atleast_3d(img_as_float(image))
|
||||
|
||||
# if image.max() is 0, then dist_scale can have an unverified value
|
||||
@@ -194,52 +144,8 @@ def denoise_bilateral(image, Py_ssize_t win_size=5, sigma_range=None,
|
||||
return np.squeeze(np.asarray(out))
|
||||
|
||||
|
||||
def denoise_tv_bregman(image, double weight, int max_iter=100, double eps=1e-3,
|
||||
char isotropic=True):
|
||||
"""Perform total-variation denoising using split-Bregman optimization.
|
||||
|
||||
Total-variation denoising (also know as total-variation regularization)
|
||||
tries to find an image with less total-variation under the constraint
|
||||
of being similar to the input image, which is controlled by the
|
||||
regularization parameter.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
image : ndarray
|
||||
Input data to be denoised (converted using img_as_float`).
|
||||
weight : float, optional
|
||||
Denoising weight. The smaller the `weight`, the more denoising (at
|
||||
the expense of less similarity to the `input`). The regularization
|
||||
parameter `lambda` is chosen as `2 * weight`.
|
||||
eps : float, optional
|
||||
Relative difference of the value of the cost function that determines
|
||||
the stop criterion. The algorithm stops when::
|
||||
|
||||
SUM((u(n) - u(n-1))**2) < eps
|
||||
|
||||
max_iter : int, optional
|
||||
Maximal number of iterations used for the optimization.
|
||||
isotropic : boolean, optional
|
||||
Switch between isotropic and anisotropic TV denoising.
|
||||
|
||||
Returns
|
||||
-------
|
||||
u : ndarray
|
||||
Denoised image.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] http://en.wikipedia.org/wiki/Total_variation_denoising
|
||||
.. [2] Tom Goldstein and Stanley Osher, "The Split Bregman Method For L1
|
||||
Regularized Problems",
|
||||
ftp://ftp.math.ucla.edu/pub/camreport/cam08-29.pdf
|
||||
.. [3] Pascal Getreuer, "Rudin–Osher–Fatemi Total Variation Denoising
|
||||
using Split Bregman" in Image Processing On Line on 2012–05–19,
|
||||
http://www.ipol.im/pub/art/2012/g-tvd/article_lr.pdf
|
||||
.. [4] http://www.math.ucsb.edu/~cgarcia/UGProjects/BregmanAlgorithms_JacquelineBush.pdf
|
||||
|
||||
"""
|
||||
|
||||
def _denoise_tv_bregman(image, double weight, int max_iter, double eps,
|
||||
char isotropic):
|
||||
image = np.atleast_3d(img_as_float(image))
|
||||
|
||||
cdef:
|
||||
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
|
||||
from skimage._build import cython
|
||||
|
||||
base_path = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
|
||||
def configuration(parent_package='', top_path=None):
|
||||
from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs
|
||||
|
||||
config = Configuration('restoration', parent_package, top_path)
|
||||
config.add_data_dir('tests')
|
||||
|
||||
cython(['_unwrap_1d.pyx'], working_path=base_path)
|
||||
cython(['_unwrap_2d.pyx'], working_path=base_path)
|
||||
cython(['_unwrap_3d.pyx'], working_path=base_path)
|
||||
cython(['_denoise_cy.pyx'], working_path=base_path)
|
||||
|
||||
config.add_extension('_unwrap_1d', sources=['_unwrap_1d.c'],
|
||||
include_dirs=[get_numpy_include_dirs()])
|
||||
unwrap_sources_2d = ['_unwrap_2d.c', 'unwrap_2d_ljmu.c']
|
||||
config.add_extension('_unwrap_2d', sources=unwrap_sources_2d,
|
||||
include_dirs=[get_numpy_include_dirs()])
|
||||
unwrap_sources_3d = ['_unwrap_3d.c', 'unwrap_3d_ljmu.c']
|
||||
config.add_extension('_unwrap_3d', sources=unwrap_sources_3d,
|
||||
include_dirs=[get_numpy_include_dirs()])
|
||||
config.add_extension('_denoise_cy', sources=['_denoise_cy.c'],
|
||||
include_dirs=[get_numpy_include_dirs(), '../_shared'])
|
||||
|
||||
return config
|
||||
|
||||
if __name__ == '__main__':
|
||||
from numpy.distutils.core import setup
|
||||
setup(maintainer='scikit-image Developers',
|
||||
author='scikit-image Developers',
|
||||
maintainer_email='scikit-image@googlegroups.com',
|
||||
description='Restoration',
|
||||
url='https://github.com/scikit-image/scikit-image',
|
||||
license='SciPy License (BSD Style)',
|
||||
**(configuration(top_path='').todict())
|
||||
)
|
||||
@@ -1,7 +1,7 @@
|
||||
import numpy as np
|
||||
from numpy.testing import run_module_suite, assert_raises, assert_equal
|
||||
|
||||
from skimage import filter, data, color, img_as_float
|
||||
from skimage import restoration, data, color, img_as_float
|
||||
|
||||
|
||||
np.random.seed(1234)
|
||||
@@ -19,7 +19,7 @@ def test_denoise_tv_chambolle_2d():
|
||||
# clip noise so that it does not exceed allowed range for float images.
|
||||
img = np.clip(img, 0, 1)
|
||||
# denoise
|
||||
denoised_lena = filter.denoise_tv_chambolle(img, weight=60.0)
|
||||
denoised_lena = restoration.denoise_tv_chambolle(img, weight=60.0)
|
||||
# which dtype?
|
||||
assert denoised_lena.dtype in [np.float, np.float32, np.float64]
|
||||
from scipy import ndimage
|
||||
@@ -33,8 +33,9 @@ def test_denoise_tv_chambolle_2d():
|
||||
|
||||
|
||||
def test_denoise_tv_chambolle_multichannel():
|
||||
denoised0 = filter.denoise_tv_chambolle(lena[..., 0], weight=60.0)
|
||||
denoised = filter.denoise_tv_chambolle(lena, weight=60.0, multichannel=True)
|
||||
denoised0 = restoration.denoise_tv_chambolle(lena[..., 0], weight=60.0)
|
||||
denoised = restoration.denoise_tv_chambolle(lena, weight=60.0,
|
||||
multichannel=True)
|
||||
assert_equal(denoised[..., 0], denoised0)
|
||||
|
||||
|
||||
@@ -43,7 +44,7 @@ def test_denoise_tv_chambolle_float_result_range():
|
||||
img = lena_gray
|
||||
int_lena = np.multiply(img, 255).astype(np.uint8)
|
||||
assert np.max(int_lena) > 1
|
||||
denoised_int_lena = filter.denoise_tv_chambolle(int_lena, weight=60.0)
|
||||
denoised_int_lena = restoration.denoise_tv_chambolle(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
|
||||
@@ -59,12 +60,12 @@ def test_denoise_tv_chambolle_3d():
|
||||
mask += 20 * np.random.random(mask.shape)
|
||||
mask[mask < 0] = 0
|
||||
mask[mask > 255] = 255
|
||||
res = filter.denoise_tv_chambolle(mask.astype(np.uint8), weight=100)
|
||||
res = restoration.denoise_tv_chambolle(mask.astype(np.uint8), weight=100)
|
||||
assert res.dtype == np.float
|
||||
assert res.std() * 255 < mask.std()
|
||||
|
||||
# test wrong number of dimensions
|
||||
assert_raises(ValueError, filter.denoise_tv_chambolle,
|
||||
assert_raises(ValueError, restoration.denoise_tv_chambolle,
|
||||
np.random.random((8, 8, 8, 8)))
|
||||
|
||||
|
||||
@@ -74,8 +75,8 @@ def test_denoise_tv_bregman_2d():
|
||||
img += 0.5 * img.std() * np.random.random(img.shape)
|
||||
img = np.clip(img, 0, 1)
|
||||
|
||||
out1 = filter.denoise_tv_bregman(img, weight=10)
|
||||
out2 = filter.denoise_tv_bregman(img, weight=5)
|
||||
out1 = restoration.denoise_tv_bregman(img, weight=10)
|
||||
out2 = restoration.denoise_tv_bregman(img, weight=5)
|
||||
|
||||
# make sure noise is reduced
|
||||
assert img.std() > out1.std()
|
||||
@@ -87,7 +88,7 @@ def test_denoise_tv_bregman_float_result_range():
|
||||
img = lena_gray
|
||||
int_lena = np.multiply(img, 255).astype(np.uint8)
|
||||
assert np.max(int_lena) > 1
|
||||
denoised_int_lena = filter.denoise_tv_bregman(int_lena, weight=60.0)
|
||||
denoised_int_lena = restoration.denoise_tv_bregman(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
|
||||
@@ -100,8 +101,8 @@ def test_denoise_tv_bregman_3d():
|
||||
img += 0.5 * img.std() * np.random.random(img.shape)
|
||||
img = np.clip(img, 0, 1)
|
||||
|
||||
out1 = filter.denoise_tv_bregman(img, weight=10)
|
||||
out2 = filter.denoise_tv_bregman(img, weight=5)
|
||||
out1 = restoration.denoise_tv_bregman(img, weight=10)
|
||||
out2 = restoration.denoise_tv_bregman(img, weight=5)
|
||||
|
||||
# make sure noise is reduced
|
||||
assert img.std() > out1.std()
|
||||
@@ -114,8 +115,10 @@ def test_denoise_bilateral_2d():
|
||||
img += 0.5 * img.std() * np.random.random(img.shape)
|
||||
img = np.clip(img, 0, 1)
|
||||
|
||||
out1 = filter.denoise_bilateral(img, sigma_range=0.1, sigma_spatial=20)
|
||||
out2 = filter.denoise_bilateral(img, sigma_range=0.2, sigma_spatial=30)
|
||||
out1 = restoration.denoise_bilateral(img, sigma_range=0.1,
|
||||
sigma_spatial=20)
|
||||
out2 = restoration.denoise_bilateral(img, sigma_range=0.2,
|
||||
sigma_spatial=30)
|
||||
|
||||
# make sure noise is reduced
|
||||
assert img.std() > out1.std()
|
||||
@@ -128,8 +131,10 @@ def test_denoise_bilateral_3d():
|
||||
img += 0.5 * img.std() * np.random.random(img.shape)
|
||||
img = np.clip(img, 0, 1)
|
||||
|
||||
out1 = filter.denoise_bilateral(img, sigma_range=0.1, sigma_spatial=20)
|
||||
out2 = filter.denoise_bilateral(img, sigma_range=0.2, sigma_spatial=30)
|
||||
out1 = restoration.denoise_bilateral(img, sigma_range=0.1,
|
||||
sigma_spatial=20)
|
||||
out2 = restoration.denoise_bilateral(img, sigma_range=0.2,
|
||||
sigma_spatial=30)
|
||||
|
||||
# make sure noise is reduced
|
||||
assert img.std() > out1.std()
|
||||
@@ -6,7 +6,7 @@ from numpy.testing import (run_module_suite, assert_array_almost_equal,
|
||||
assert_raises)
|
||||
import warnings
|
||||
|
||||
from skimage.exposure import unwrap_phase
|
||||
from skimage.restoration import unwrap_phase
|
||||
|
||||
|
||||
def assert_phase_almost_equal(a, b, *args, **kwargs):
|
||||
|
||||
Reference in New Issue
Block a user