mirror of
https://github.com/wassname/scikit-image.git
synced 2026-06-29 01:11:56 +08:00
348 lines
11 KiB
Python
348 lines
11 KiB
Python
# 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):
|
||
"""Perform total-variation denoising on 3D images.
|
||
|
||
Parameters
|
||
----------
|
||
im : ndarray
|
||
3-D input data to be denoised.
|
||
weight : float, optional
|
||
Denoising weight. The greater `weight`, the more denoising (at
|
||
the expense of fidelity to `input`).
|
||
eps : float, optional
|
||
Relative difference of the value of the cost function that determines
|
||
the stop criterion. The algorithm stops when:
|
||
|
||
(E_(n-1) - E_n) < eps * E_0
|
||
|
||
n_iter_max : int, optional
|
||
Maximal number of iterations used for the optimization.
|
||
|
||
Returns
|
||
-------
|
||
out : ndarray
|
||
Denoised array of floats.
|
||
|
||
Notes
|
||
-----
|
||
Rudin, Osher and Fatemi algorithm.
|
||
|
||
"""
|
||
|
||
px = np.zeros_like(im)
|
||
py = np.zeros_like(im)
|
||
pz = np.zeros_like(im)
|
||
gx = np.zeros_like(im)
|
||
gy = np.zeros_like(im)
|
||
gz = np.zeros_like(im)
|
||
d = np.zeros_like(im)
|
||
i = 0
|
||
while i < n_iter_max:
|
||
d = - px - py - pz
|
||
d[1:] += px[:-1]
|
||
d[:, 1:] += py[:, :-1]
|
||
d[:, :, 1:] += pz[:, :, :-1]
|
||
|
||
out = im + d
|
||
E = (d**2).sum()
|
||
|
||
gx[:-1] = np.diff(out, axis=0)
|
||
gy[:, :-1] = np.diff(out, axis=1)
|
||
gz[:, :, :-1] = np.diff(out, axis=2)
|
||
norm = np.sqrt(gx**2 + gy**2 + gz**2)
|
||
E += weight * norm.sum()
|
||
norm *= 0.5 / weight
|
||
norm += 1.
|
||
px -= 1. / 6. * gx
|
||
px /= norm
|
||
py -= 1. / 6. * gy
|
||
py /= norm
|
||
pz -= 1 / 6. * gz
|
||
pz /= norm
|
||
E /= float(im.size)
|
||
if i == 0:
|
||
E_init = E
|
||
E_previous = E
|
||
else:
|
||
if np.abs(E_previous - E) < eps * E_init:
|
||
break
|
||
else:
|
||
E_previous = E
|
||
i += 1
|
||
return out
|
||
|
||
|
||
def _denoise_tv_chambolle_2d(im, weight=50, eps=2.e-4, n_iter_max=200):
|
||
"""Perform total-variation denoising on 2D images.
|
||
|
||
Parameters
|
||
----------
|
||
im : ndarray
|
||
Input data to be denoised.
|
||
weight : float, optional
|
||
Denoising weight. The greater `weight`, the more denoising (at
|
||
the expense of fidelity to `input`)
|
||
eps : float, optional
|
||
Relative difference of the value of the cost function that determines
|
||
the stop criterion. The algorithm stops when:
|
||
|
||
(E_(n-1) - E_n) < eps * E_0
|
||
|
||
n_iter_max : int, optional
|
||
Maximal number of iterations used for the optimization.
|
||
|
||
Returns
|
||
-------
|
||
out : ndarray
|
||
Denoised array of floats.
|
||
|
||
Notes
|
||
-----
|
||
The principle of total variation denoising is explained in
|
||
http://en.wikipedia.org/wiki/Total_variation_denoising.
|
||
|
||
This code is an implementation of the algorithm of Rudin, Fatemi and Osher
|
||
that was proposed by Chambolle in [1]_.
|
||
|
||
References
|
||
----------
|
||
.. [1] A. Chambolle, An algorithm for total variation minimization and
|
||
applications, Journal of Mathematical Imaging and Vision,
|
||
Springer, 2004, 20, 89-97.
|
||
|
||
"""
|
||
|
||
px = np.zeros_like(im)
|
||
py = np.zeros_like(im)
|
||
gx = np.zeros_like(im)
|
||
gy = np.zeros_like(im)
|
||
d = np.zeros_like(im)
|
||
i = 0
|
||
while i < n_iter_max:
|
||
d = -px - py
|
||
d[1:] += px[:-1]
|
||
d[:, 1:] += py[:, :-1]
|
||
|
||
out = im + d
|
||
E = (d**2).sum()
|
||
gx[:-1] = np.diff(out, axis=0)
|
||
gy[:, :-1] = np.diff(out, axis=1)
|
||
norm = np.sqrt(gx**2 + gy**2)
|
||
E += weight * norm.sum()
|
||
norm *= 0.5 / weight
|
||
norm += 1
|
||
px -= 0.25 * gx
|
||
px /= norm
|
||
py -= 0.25 * gy
|
||
py /= norm
|
||
E /= float(im.size)
|
||
if i == 0:
|
||
E_init = E
|
||
E_previous = E
|
||
else:
|
||
if np.abs(E_previous - E) < eps * E_init:
|
||
break
|
||
else:
|
||
E_previous = E
|
||
i += 1
|
||
return out
|
||
|
||
|
||
def denoise_tv_chambolle(im, weight=50, eps=2.e-4, n_iter_max=200,
|
||
multichannel=False):
|
||
"""Perform total-variation denoising on 2D and 3D images.
|
||
|
||
Parameters
|
||
----------
|
||
im : ndarray (2d or 3d) of ints, uints or floats
|
||
Input data to be denoised. `im` can be of any numeric type,
|
||
but it is cast into an ndarray of floats for the computation
|
||
of the denoised image.
|
||
weight : float, optional
|
||
Denoising weight. The greater `weight`, the more denoising (at
|
||
the expense of fidelity to `input`).
|
||
eps : float, optional
|
||
Relative difference of the value of the cost function that
|
||
determines the stop criterion. The algorithm stops when:
|
||
|
||
(E_(n-1) - E_n) < eps * E_0
|
||
|
||
n_iter_max : int, optional
|
||
Maximal number of iterations used for the optimization.
|
||
multichannel : bool, optional
|
||
Apply total-variation denoising separately for each channel. This
|
||
option should be true for color images, otherwise the denoising is
|
||
also applied in the 3rd dimension.
|
||
|
||
Returns
|
||
-------
|
||
out : ndarray
|
||
Denoised image.
|
||
|
||
Notes
|
||
-----
|
||
Make sure to set the multichannel parameter appropriately for color images.
|
||
|
||
The principle of total variation denoising is explained in
|
||
http://en.wikipedia.org/wiki/Total_variation_denoising
|
||
|
||
The principle of total variation denoising is to minimize the
|
||
total variation of the image, which can be roughly described as
|
||
the integral of the norm of the image gradient. Total variation
|
||
denoising tends to produce "cartoon-like" images, that is,
|
||
piecewise-constant images.
|
||
|
||
This code is an implementation of the algorithm of Rudin, Fatemi and Osher
|
||
that was proposed by Chambolle in [1]_.
|
||
|
||
References
|
||
----------
|
||
.. [1] A. Chambolle, An algorithm for total variation minimization and
|
||
applications, Journal of Mathematical Imaging and Vision,
|
||
Springer, 2004, 20, 89-97.
|
||
|
||
Examples
|
||
--------
|
||
2D example on Lena image:
|
||
|
||
>>> from skimage import color, data
|
||
>>> lena = color.rgb2gray(data.lena())[:50, :50]
|
||
>>> lena += 0.5 * lena.std() * np.random.randn(*lena.shape)
|
||
>>> denoised_lena = denoise_tv_chambolle(lena, weight=60)
|
||
|
||
3D example on synthetic data:
|
||
|
||
>>> x, y, z = np.ogrid[0:20, 0:20, 0:20]
|
||
>>> mask = (x - 22)**2 + (y - 20)**2 + (z - 17)**2 < 8**2
|
||
>>> mask = mask.astype(np.float)
|
||
>>> mask += 0.2*np.random.randn(*mask.shape)
|
||
>>> res = denoise_tv_chambolle(mask, weight=100)
|
||
|
||
"""
|
||
|
||
im_type = im.dtype
|
||
if not im_type.kind == 'f':
|
||
im = img_as_float(im)
|
||
|
||
if im.ndim == 2:
|
||
out = _denoise_tv_chambolle_2d(im, weight, eps, n_iter_max)
|
||
elif im.ndim == 3:
|
||
if multichannel:
|
||
out = np.zeros_like(im)
|
||
for c in range(im.shape[2]):
|
||
out[..., c] = _denoise_tv_chambolle_2d(im[..., c], weight, eps,
|
||
n_iter_max)
|
||
else:
|
||
out = _denoise_tv_chambolle_3d(im, weight, eps, n_iter_max)
|
||
else:
|
||
raise ValueError('only 2-d and 3-d images may be denoised with this '
|
||
'function')
|
||
return out
|