Merge pull request #924 from ahojnnes/restoration

Move functions to restoration submodule
This commit is contained in:
Stefan van der Walt
2014-03-14 23:03:01 +02:00
22 changed files with 212 additions and 153 deletions
+1
View File
@@ -8,6 +8,7 @@ Version 0.11
`skimage.transform.ProjectiveTransform._matrix`,
`skimage.transform.PolynomialTransform._params`,
`skimage.transform.PiecewiseAffineTransform.affines_*` attributes
* Remove deprecated functions `skimage.filter.denoise_*`
Version 0.10
------------
+11 -10
View File
@@ -35,7 +35,8 @@ Library:
skimage, skimage.color, skimage.data, skimage.draw, skimage.exposure,
skimage.feature, skimage.filter, skimage.graph, skimage.io,
skimage.io._plugins, skimage.measure, skimage.morphology,
skimage.scripts, skimage.segmentation, skimage.transform, skimage.util
skimage.scripts, skimage.restoration, skimage.segmentation,
skimage.transform, skimage.util
Extension: skimage.morphology._pnpoly
Sources:
skimage/morphology/_pnpoly.pyx
@@ -63,9 +64,6 @@ Library:
Extension: skimage.filter._ctmf
Sources:
skimage/filter/_ctmf.pyx
Extension: skimage.filter._denoise_cy
Sources:
skimage/filter/_denoise_cy.pyx
Extension: skimage.morphology.ccomp
Sources:
skimage/morphology/ccomp.pyx
@@ -141,15 +139,18 @@ Library:
Extension: skimage.filter.rank.bilateral_cy
Sources:
skimage/filter/rank/bilateral_cy.pyx
Extension: skimage.exposure._unwrap_3d
Extension: skimage.restoration._unwrap_1d
Sources:
skimage/exposure/_unwrap_3d.pyx, skimage/exposure/unwrap_3d_ljmu.c
Extension: skimage.exposure._unwrap_2d
skimage/restoration/_unwrap_1d.pyx
Extension: skimage.restoration._unwrap_2d
Sources:
skimage/exposure/_unwrap_2d.pyx, skimage/exposure/unwrap_2d_ljmu.c
Extension: skimage.exposure._unwrap_1d
skimage/restoration/_unwrap_2d.pyx skimage/exposure/unwrap_2d_ljmu.c
Extension: skimage.restoration._unwrap_3d
Sources:
skimage/exposure/_unwrap_1d.pyx
skimage/restoration/_unwrap_3d.pyx skimage/exposure/unwrap_3d_ljmu.c
Extension: skimage.restoration._denoise_cy
Sources:
skimage/restoration/_denoise_cy.pyx
Executable: skivi
Module: skimage.scripts.skivi
+1 -1
View File
@@ -29,7 +29,7 @@ import numpy as np
import matplotlib.pyplot as plt
from skimage import data, img_as_float
from skimage.filter import denoise_tv_chambolle, denoise_bilateral
from skimage.restoration import denoise_tv_chambolle, denoise_bilateral
lena = img_as_float(data.lena())
+1 -1
View File
@@ -14,7 +14,7 @@ skimage. Here we will demonstrate phase unwrapping in the two dimensional case.
import numpy as np
from matplotlib import pyplot as plt
from skimage import data, img_as_float, color, exposure
from skimage.exposure import unwrap_phase
from skimage.restoration import unwrap_phase
# Load an image as a floating-point grayscale
+1 -1
View File
@@ -30,7 +30,7 @@ measure
morphology
Morphological operations, e.g. opening or skeletonization.
restoration
Deconvolution algorithms.
Restoration algorithms.
segmentation
Splitting an image into self-similar regions.
transform
+2 -3
View File
@@ -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']
-13
View File
@@ -13,19 +13,6 @@ def configuration(parent_package='', top_path=None):
config = Configuration('exposure', 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)
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()])
return config
if __name__ == '__main__':
+10 -2
View File
@@ -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',
+1 -1
View File
@@ -59,7 +59,7 @@ __all__ = ['autolevel',
'tophat',
'noise_filter',
'entropy',
'otsu'
'otsu',
'percentile',
# Deprecated
'percentile_autolevel',
-3
View File
@@ -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'],
+10 -2
View File
@@ -19,7 +19,15 @@ 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"]
'unsupervised_wiener',
'richardson_lucy',
'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, "RudinOsherFatemi Total Variation Denoising
using Split Bregman" in Image Processing On Line on 20120519,
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, "RudinOsherFatemi Total Variation Denoising
using Split Bregman" in Image Processing On Line on 20120519,
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:
+43
View File
@@ -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):