We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
denoise_bilateral works separately on channels, but no warning raised for 3-D images
The implementation of `restoration.denoise_bilateral` is 2-D only, with the last dimension considered to be for channels. However, this is not documented in the docstring, and no warning is raised if a 3-D image (with last dimension > 3) is passed. 

I used `denoise_bilateral` in the past on 3-D images thinking that the implementation was 3-D. We could consider making the code 3-D or nD in the future, but for now fixing the docstring + warning looks like a reasonable goal for 0.12.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `skimage/restoration/_denoise.py`
Content:
```
1 # coding: utf-8
2 import numpy as np
3 from .. import img_as_float
4 from ..restoration._denoise_cy import _denoise_bilateral, _denoise_tv_bregman
5 from .._shared.utils import _mode_deprecations
6 
7 
8 def denoise_bilateral(image, win_size=5, sigma_range=None, sigma_spatial=1,
9                       bins=10000, mode='constant', cval=0):
10     """Denoise image using bilateral filter.
11 
12     This is an edge-preserving and noise reducing denoising filter. It averages
13     pixels based on their spatial closeness and radiometric similarity.
14 
15     Spatial closeness is measured by the gaussian function of the euclidian
16     distance between two pixels and a certain standard deviation
17     (`sigma_spatial`).
18 
19     Radiometric similarity is measured by the gaussian function of the euclidian
20     distance between two color values and a certain standard deviation
21     (`sigma_range`).
22 
23     Parameters
24     ----------
25     image : ndarray, shape (M, N[, 3])
26         Input image, 2D grayscale or RGB.
27     win_size : int
28         Window size for filtering.
29     sigma_range : float
30         Standard deviation for grayvalue/color distance (radiometric
31         similarity). A larger value results in averaging of pixels with larger
32         radiometric differences. Note, that the image will be converted using
33         the `img_as_float` function and thus the standard deviation is in
34         respect to the range ``[0, 1]``. If the value is ``None`` the standard
35         deviation of the ``image`` will be used.
36     sigma_spatial : float
37         Standard deviation for range distance. A larger value results in
38         averaging of pixels with larger spatial differences.
39     bins : int
40         Number of discrete values for gaussian weights of color filtering.
41         A larger value results in improved accuracy.
42     mode : {'constant', 'edge', 'symmetric', 'reflect', 'wrap'}
43         How to handle values outside the image borders. See
44         `numpy.pad` for detail.
45     cval : string
46         Used in conjunction with mode 'constant', the value outside
47         the image boundaries.
48 
49     Returns
50     -------
51     denoised : ndarray
52         Denoised image.
53 
54     References
55     ----------
56     .. [1] http://users.soe.ucsc.edu/~manduchi/Papers/ICCV98.pdf
57 
58     Examples
59     --------
60     >>> from skimage import data, img_as_float
61     >>> astro = img_as_float(data.astronaut())
62     >>> astro = astro[220:300, 220:320]
63     >>> noisy = astro + 0.6 * astro.std() * np.random.random(astro.shape)
64     >>> noisy = np.clip(noisy, 0, 1)
65     >>> denoised = denoise_bilateral(noisy, sigma_range=0.05, sigma_spatial=15)
66     """
67     mode = _mode_deprecations(mode)
68     return _denoise_bilateral(image, win_size, sigma_range, sigma_spatial,
69                               bins, mode, cval)
70 
71 
72 def denoise_tv_bregman(image, weight, max_iter=100, eps=1e-3, isotropic=True):
73     """Perform total-variation denoising using split-Bregman optimization.
74 
75     Total-variation denoising (also know as total-variation regularization)
76     tries to find an image with less total-variation under the constraint
77     of being similar to the input image, which is controlled by the
78     regularization parameter.
79 
80     Parameters
81     ----------
82     image : ndarray
83         Input data to be denoised (converted using img_as_float`).
84     weight : float
85         Denoising weight. The smaller the `weight`, the more denoising (at
86         the expense of less similarity to the `input`). The regularization
87         parameter `lambda` is chosen as `2 * weight`.
88     eps : float, optional
89         Relative difference of the value of the cost function that determines
90         the stop criterion. The algorithm stops when::
91 
92             SUM((u(n) - u(n-1))**2) < eps
93 
94     max_iter : int, optional
95         Maximal number of iterations used for the optimization.
96     isotropic : boolean, optional
97         Switch between isotropic and anisotropic TV denoising.
98 
99     Returns
100     -------
101     u : ndarray
102         Denoised image.
103 
104     References
105     ----------
106     .. [1] http://en.wikipedia.org/wiki/Total_variation_denoising
107     .. [2] Tom Goldstein and Stanley Osher, "The Split Bregman Method For L1
108            Regularized Problems",
109            ftp://ftp.math.ucla.edu/pub/camreport/cam08-29.pdf
110     .. [3] Pascal Getreuer, "Rudin–Osher–Fatemi Total Variation Denoising
111            using Split Bregman" in Image Processing On Line on 2012–05–19,
112            http://www.ipol.im/pub/art/2012/g-tvd/article_lr.pdf
113     .. [4] http://www.math.ucsb.edu/~cgarcia/UGProjects/BregmanAlgorithms_JacquelineBush.pdf
114 
115     """
116     return _denoise_tv_bregman(image, weight, max_iter, eps, isotropic)
117 
118 
119 def _denoise_tv_chambolle_nd(im, weight=0.1, eps=2.e-4, n_iter_max=200):
120     """Perform total-variation denoising on n-dimensional images.
121 
122     Parameters
123     ----------
124     im : ndarray
125         n-D input data to be denoised.
126     weight : float, optional
127         Denoising weight. The greater `weight`, the more denoising (at
128         the expense of fidelity to `input`).
129     eps : float, optional
130         Relative difference of the value of the cost function that determines
131         the stop criterion. The algorithm stops when:
132 
133             (E_(n-1) - E_n) < eps * E_0
134 
135     n_iter_max : int, optional
136         Maximal number of iterations used for the optimization.
137 
138     Returns
139     -------
140     out : ndarray
141         Denoised array of floats.
142 
143     Notes
144     -----
145     Rudin, Osher and Fatemi algorithm.
146 
147     """
148 
149     ndim = im.ndim
150     p = np.zeros((im.ndim, ) + im.shape, dtype=im.dtype)
151     g = np.zeros_like(p)
152     d = np.zeros_like(im)
153     i = 0
154     while i < n_iter_max:
155         if i > 0:
156             # d will be the (negative) divergence of p
157             d = -p.sum(0)
158             slices_d = [slice(None), ] * ndim
159             slices_p = [slice(None), ] * (ndim + 1)
160             for ax in range(ndim):
161                 slices_d[ax] = slice(1, None)
162                 slices_p[ax+1] = slice(0, -1)
163                 slices_p[0] = ax
164                 d[slices_d] += p[slices_p]
165                 slices_d[ax] = slice(None)
166                 slices_p[ax+1] = slice(None)
167             out = im + d
168         else:
169             out = im
170         E = (d ** 2).sum()
171 
172         # g stores the gradients of out along each axis
173         # e.g. g[0] is the first order finite difference along axis 0
174         slices_g = [slice(None), ] * (ndim + 1)
175         for ax in range(ndim):
176             slices_g[ax+1] = slice(0, -1)
177             slices_g[0] = ax
178             g[slices_g] = np.diff(out, axis=ax)
179             slices_g[ax+1] = slice(None)
180 
181         norm = np.sqrt((g ** 2).sum(axis=0))[np.newaxis, ...]
182         E += weight * norm.sum()
183         tau = 1. / (2.*ndim)
184         norm *= tau / weight
185         norm += 1.
186         p -= tau * g
187         p /= norm
188         E /= float(im.size)
189         if i == 0:
190             E_init = E
191             E_previous = E
192         else:
193             if np.abs(E_previous - E) < eps * E_init:
194                 break
195             else:
196                 E_previous = E
197         i += 1
198     return out
199 
200 
201 def denoise_tv_chambolle(im, weight=0.1, eps=2.e-4, n_iter_max=200,
202                          multichannel=False):
203     """Perform total-variation denoising on n-dimensional images.
204 
205     Parameters
206     ----------
207     im : ndarray of ints, uints or floats
208         Input data to be denoised. `im` can be of any numeric type,
209         but it is cast into an ndarray of floats for the computation
210         of the denoised image.
211     weight : float, optional
212         Denoising weight. The greater `weight`, the more denoising (at
213         the expense of fidelity to `input`).
214     eps : float, optional
215         Relative difference of the value of the cost function that
216         determines the stop criterion. The algorithm stops when:
217 
218             (E_(n-1) - E_n) < eps * E_0
219 
220     n_iter_max : int, optional
221         Maximal number of iterations used for the optimization.
222     multichannel : bool, optional
223         Apply total-variation denoising separately for each channel. This
224         option should be true for color images, otherwise the denoising is
225         also applied in the channels dimension.
226 
227     Returns
228     -------
229     out : ndarray
230         Denoised image.
231 
232     Notes
233     -----
234     Make sure to set the multichannel parameter appropriately for color images.
235 
236     The principle of total variation denoising is explained in
237     http://en.wikipedia.org/wiki/Total_variation_denoising
238 
239     The principle of total variation denoising is to minimize the
240     total variation of the image, which can be roughly described as
241     the integral of the norm of the image gradient. Total variation
242     denoising tends to produce "cartoon-like" images, that is,
243     piecewise-constant images.
244 
245     This code is an implementation of the algorithm of Rudin, Fatemi and Osher
246     that was proposed by Chambolle in [1]_.
247 
248     References
249     ----------
250     .. [1] A. Chambolle, An algorithm for total variation minimization and
251            applications, Journal of Mathematical Imaging and Vision,
252            Springer, 2004, 20, 89-97.
253 
254     Examples
255     --------
256     2D example on astronaut image:
257 
258     >>> from skimage import color, data
259     >>> img = color.rgb2gray(data.astronaut())[:50, :50]
260     >>> img += 0.5 * img.std() * np.random.randn(*img.shape)
261     >>> denoised_img = denoise_tv_chambolle(img, weight=60)
262 
263     3D example on synthetic data:
264 
265     >>> x, y, z = np.ogrid[0:20, 0:20, 0:20]
266     >>> mask = (x - 22)**2 + (y - 20)**2 + (z - 17)**2 < 8**2
267     >>> mask = mask.astype(np.float)
268     >>> mask += 0.2*np.random.randn(*mask.shape)
269     >>> res = denoise_tv_chambolle(mask, weight=100)
270 
271     """
272 
273     im_type = im.dtype
274     if not im_type.kind == 'f':
275         im = img_as_float(im)
276 
277     if multichannel:
278         out = np.zeros_like(im)
279         for c in range(im.shape[-1]):
280             out[..., c] = _denoise_tv_chambolle_nd(im[..., c], weight, eps,
281                                                    n_iter_max)
282     else:
283         out = _denoise_tv_chambolle_nd(im, weight, eps, n_iter_max)
284     return out
285
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/skimage/restoration/_denoise.py b/skimage/restoration/_denoise.py
--- a/skimage/restoration/_denoise.py
+++ b/skimage/restoration/_denoise.py
@@ -3,10 +3,11 @@
 from .. import img_as_float
 from ..restoration._denoise_cy import _denoise_bilateral, _denoise_tv_bregman
 from .._shared.utils import _mode_deprecations
+import warnings
 
 
 def denoise_bilateral(image, win_size=5, sigma_range=None, sigma_spatial=1,
-                      bins=10000, mode='constant', cval=0):
+                      bins=10000, mode='constant', cval=0, multichannel=True):
     """Denoise image using bilateral filter.
 
     This is an edge-preserving and noise reducing denoising filter. It averages
@@ -45,6 +46,9 @@
     cval : string
         Used in conjunction with mode 'constant', the value outside
         the image boundaries.
+    multichannel : bool
+        Whether the last axis of the image is to be interpreted as multiple
+        channels or another spatial dimension.
 
     Returns
     -------
@@ -64,6 +68,38 @@
     >>> noisy = np.clip(noisy, 0, 1)
     >>> denoised = denoise_bilateral(noisy, sigma_range=0.05, sigma_spatial=15)
     """
+    if multichannel:
+        if image.ndim != 3:
+            if image.ndim == 2:
+                raise ValueError("Use ``multichannel=False`` for 2D grayscale "
+                                 "images. The last axis of the input image "
+                                 "must be multiple color channels not another "
+                                 "spatial dimension.")
+            else:
+                raise ValueError("Bilateral filter is only implemented for "
+                                 "2D grayscale images (image.ndim == 2) and "
+                                 "2D multichannel (image.ndim == 3) images, "
+                                 "but the input image has {0} dimensions. "
+                                 "".format(image.ndim))
+        elif image.shape[2] not in (3, 4):
+            if image.shape[2] > 4:
+                warnings.warn("The last axis of the input image is interpreted "
+                              "as channels. Input image with shape {0} has {1} "
+                              "channels in last axis. ``denoise_bilateral`` is "
+                              "implemented for 2D grayscale and color images "
+                              "only.".format(image.shape, image.shape[2]))
+            else:
+                msg = "Input image must be grayscale, RGB, or RGBA; but has shape {0}."
+                warnings.warn(msg.format(image.shape))
+    else:
+        if image.ndim > 2:
+            raise ValueError("Bilateral filter is not implemented for "
+                             "grayscale images of 3 or more dimensions, "
+                             "but input image has {0} dimension. Use "
+                             "``multichannel=True`` for 2-D RGB "
+                             "images.".format(image.shape))
+
+
     mode = _mode_deprecations(mode)
     return _denoise_bilateral(image, win_size, sigma_range, sigma_spatial,
                               bins, mode, cval)

{"golden_diff": "diff --git a/skimage/restoration/_denoise.py b/skimage/restoration/_denoise.py\n--- a/skimage/restoration/_denoise.py\n+++ b/skimage/restoration/_denoise.py\n@@ -3,10 +3,11 @@\n from .. import img_as_float\n from ..restoration._denoise_cy import _denoise_bilateral, _denoise_tv_bregman\n from .._shared.utils import _mode_deprecations\n+import warnings\n \n \n def denoise_bilateral(image, win_size=5, sigma_range=None, sigma_spatial=1,\n-                      bins=10000, mode='constant', cval=0):\n+                      bins=10000, mode='constant', cval=0, multichannel=True):\n     \"\"\"Denoise image using bilateral filter.\n \n     This is an edge-preserving and noise reducing denoising filter. It averages\n@@ -45,6 +46,9 @@\n     cval : string\n         Used in conjunction with mode 'constant', the value outside\n         the image boundaries.\n+    multichannel : bool\n+        Whether the last axis of the image is to be interpreted as multiple\n+        channels or another spatial dimension.\n \n     Returns\n     -------\n@@ -64,6 +68,38 @@\n     >>> noisy = np.clip(noisy, 0, 1)\n     >>> denoised = denoise_bilateral(noisy, sigma_range=0.05, sigma_spatial=15)\n     \"\"\"\n+    if multichannel:\n+        if image.ndim != 3:\n+            if image.ndim == 2:\n+                raise ValueError(\"Use ``multichannel=False`` for 2D grayscale \"\n+                                 \"images. The last axis of the input image \"\n+                                 \"must be multiple color channels not another \"\n+                                 \"spatial dimension.\")\n+            else:\n+                raise ValueError(\"Bilateral filter is only implemented for \"\n+                                 \"2D grayscale images (image.ndim == 2) and \"\n+                                 \"2D multichannel (image.ndim == 3) images, \"\n+                                 \"but the input image has {0} dimensions. \"\n+                                 \"\".format(image.ndim))\n+        elif image.shape[2] not in (3, 4):\n+            if image.shape[2] > 4:\n+                warnings.warn(\"The last axis of the input image is interpreted \"\n+                              \"as channels. Input image with shape {0} has {1} \"\n+                              \"channels in last axis. ``denoise_bilateral`` is \"\n+                              \"implemented for 2D grayscale and color images \"\n+                              \"only.\".format(image.shape, image.shape[2]))\n+            else:\n+                msg = \"Input image must be grayscale, RGB, or RGBA; but has shape {0}.\"\n+                warnings.warn(msg.format(image.shape))\n+    else:\n+        if image.ndim > 2:\n+            raise ValueError(\"Bilateral filter is not implemented for \"\n+                             \"grayscale images of 3 or more dimensions, \"\n+                             \"but input image has {0} dimension. Use \"\n+                             \"``multichannel=True`` for 2-D RGB \"\n+                             \"images.\".format(image.shape))\n+\n+\n     mode = _mode_deprecations(mode)\n     return _denoise_bilateral(image, win_size, sigma_range, sigma_spatial,\n                               bins, mode, cval)\n", "issue": "denoise_bilateral works separately on channels, but no warning raised for 3-D images\nThe implementation of `restoration.denoise_bilateral` is 2-D only, with the last dimension considered to be for channels. However, this is not documented in the docstring, and no warning is raised if a 3-D image (with last dimension > 3) is passed. \n\nI used `denoise_bilateral` in the past on 3-D images thinking that the implementation was 3-D. We could consider making the code 3-D or nD in the future, but for now fixing the docstring + warning looks like a reasonable goal for 0.12.\n\n", "before_files": [{"content": "# coding: utf-8\nimport numpy as np\nfrom .. import img_as_float\nfrom ..restoration._denoise_cy import _denoise_bilateral, _denoise_tv_bregman\nfrom .._shared.utils import _mode_deprecations\n\n\ndef denoise_bilateral(image, win_size=5, sigma_range=None, sigma_spatial=1,\n                      bins=10000, mode='constant', cval=0):\n    \"\"\"Denoise image using bilateral filter.\n\n    This is an edge-preserving and noise reducing denoising filter. It averages\n    pixels based on their spatial closeness and radiometric similarity.\n\n    Spatial closeness is measured by the gaussian function of the euclidian\n    distance between two pixels and a certain standard deviation\n    (`sigma_spatial`).\n\n    Radiometric similarity is measured by the gaussian function of the euclidian\n    distance between two color values and a certain standard deviation\n    (`sigma_range`).\n\n    Parameters\n    ----------\n    image : ndarray, shape (M, N[, 3])\n        Input image, 2D grayscale or RGB.\n    win_size : int\n        Window size for filtering.\n    sigma_range : float\n        Standard deviation for grayvalue/color distance (radiometric\n        similarity). A larger value results in averaging of pixels with larger\n        radiometric differences. Note, that the image will be converted using\n        the `img_as_float` function and thus the standard deviation is in\n        respect to the range ``[0, 1]``. If the value is ``None`` the standard\n        deviation of the ``image`` will be used.\n    sigma_spatial : float\n        Standard deviation for range distance. A larger value results in\n        averaging of pixels with larger spatial differences.\n    bins : int\n        Number of discrete values for gaussian weights of color filtering.\n        A larger value results in improved accuracy.\n    mode : {'constant', 'edge', 'symmetric', 'reflect', 'wrap'}\n        How to handle values outside the image borders. See\n        `numpy.pad` for detail.\n    cval : string\n        Used in conjunction with mode 'constant', the value outside\n        the image boundaries.\n\n    Returns\n    -------\n    denoised : ndarray\n        Denoised image.\n\n    References\n    ----------\n    .. [1] http://users.soe.ucsc.edu/~manduchi/Papers/ICCV98.pdf\n\n    Examples\n    --------\n    >>> from skimage import data, img_as_float\n    >>> astro = img_as_float(data.astronaut())\n    >>> astro = astro[220:300, 220:320]\n    >>> noisy = astro + 0.6 * astro.std() * np.random.random(astro.shape)\n    >>> noisy = np.clip(noisy, 0, 1)\n    >>> denoised = denoise_bilateral(noisy, sigma_range=0.05, sigma_spatial=15)\n    \"\"\"\n    mode = _mode_deprecations(mode)\n    return _denoise_bilateral(image, win_size, sigma_range, sigma_spatial,\n                              bins, mode, cval)\n\n\ndef denoise_tv_bregman(image, weight, max_iter=100, eps=1e-3, isotropic=True):\n    \"\"\"Perform total-variation denoising using split-Bregman optimization.\n\n    Total-variation denoising (also know as total-variation regularization)\n    tries to find an image with less total-variation under the constraint\n    of being similar to the input image, which is controlled by the\n    regularization parameter.\n\n    Parameters\n    ----------\n    image : ndarray\n        Input data to be denoised (converted using img_as_float`).\n    weight : float\n        Denoising weight. The smaller the `weight`, the more denoising (at\n        the expense of less similarity to the `input`). The regularization\n        parameter `lambda` is chosen as `2 * weight`.\n    eps : float, optional\n        Relative difference of the value of the cost function that determines\n        the stop criterion. The algorithm stops when::\n\n            SUM((u(n) - u(n-1))**2) < eps\n\n    max_iter : int, optional\n        Maximal number of iterations used for the optimization.\n    isotropic : boolean, optional\n        Switch between isotropic and anisotropic TV denoising.\n\n    Returns\n    -------\n    u : ndarray\n        Denoised image.\n\n    References\n    ----------\n    .. [1] http://en.wikipedia.org/wiki/Total_variation_denoising\n    .. [2] Tom Goldstein and Stanley Osher, \"The Split Bregman Method For L1\n           Regularized Problems\",\n           ftp://ftp.math.ucla.edu/pub/camreport/cam08-29.pdf\n    .. [3] Pascal Getreuer, \"Rudin\u2013Osher\u2013Fatemi Total Variation Denoising\n           using Split Bregman\" in Image Processing On Line on 2012\u201305\u201319,\n           http://www.ipol.im/pub/art/2012/g-tvd/article_lr.pdf\n    .. [4] http://www.math.ucsb.edu/~cgarcia/UGProjects/BregmanAlgorithms_JacquelineBush.pdf\n\n    \"\"\"\n    return _denoise_tv_bregman(image, weight, max_iter, eps, isotropic)\n\n\ndef _denoise_tv_chambolle_nd(im, weight=0.1, eps=2.e-4, n_iter_max=200):\n    \"\"\"Perform total-variation denoising on n-dimensional images.\n\n    Parameters\n    ----------\n    im : ndarray\n        n-D input data to be denoised.\n    weight : float, optional\n        Denoising weight. The greater `weight`, the more denoising (at\n        the expense of fidelity to `input`).\n    eps : float, optional\n        Relative difference of the value of the cost function that determines\n        the stop criterion. The algorithm stops when:\n\n            (E_(n-1) - E_n) < eps * E_0\n\n    n_iter_max : int, optional\n        Maximal number of iterations used for the optimization.\n\n    Returns\n    -------\n    out : ndarray\n        Denoised array of floats.\n\n    Notes\n    -----\n    Rudin, Osher and Fatemi algorithm.\n\n    \"\"\"\n\n    ndim = im.ndim\n    p = np.zeros((im.ndim, ) + im.shape, dtype=im.dtype)\n    g = np.zeros_like(p)\n    d = np.zeros_like(im)\n    i = 0\n    while i < n_iter_max:\n        if i > 0:\n            # d will be the (negative) divergence of p\n            d = -p.sum(0)\n            slices_d = [slice(None), ] * ndim\n            slices_p = [slice(None), ] * (ndim + 1)\n            for ax in range(ndim):\n                slices_d[ax] = slice(1, None)\n                slices_p[ax+1] = slice(0, -1)\n                slices_p[0] = ax\n                d[slices_d] += p[slices_p]\n                slices_d[ax] = slice(None)\n                slices_p[ax+1] = slice(None)\n            out = im + d\n        else:\n            out = im\n        E = (d ** 2).sum()\n\n        # g stores the gradients of out along each axis\n        # e.g. g[0] is the first order finite difference along axis 0\n        slices_g = [slice(None), ] * (ndim + 1)\n        for ax in range(ndim):\n            slices_g[ax+1] = slice(0, -1)\n            slices_g[0] = ax\n            g[slices_g] = np.diff(out, axis=ax)\n            slices_g[ax+1] = slice(None)\n\n        norm = np.sqrt((g ** 2).sum(axis=0))[np.newaxis, ...]\n        E += weight * norm.sum()\n        tau = 1. / (2.*ndim)\n        norm *= tau / weight\n        norm += 1.\n        p -= tau * g\n        p /= norm\n        E /= float(im.size)\n        if i == 0:\n            E_init = E\n            E_previous = E\n        else:\n            if np.abs(E_previous - E) < eps * E_init:\n                break\n            else:\n                E_previous = E\n        i += 1\n    return out\n\n\ndef denoise_tv_chambolle(im, weight=0.1, eps=2.e-4, n_iter_max=200,\n                         multichannel=False):\n    \"\"\"Perform total-variation denoising on n-dimensional images.\n\n    Parameters\n    ----------\n    im : ndarray of ints, uints or floats\n        Input data to be denoised. `im` can be of any numeric type,\n        but it is cast into an ndarray of floats for the computation\n        of the denoised image.\n    weight : float, optional\n        Denoising weight. The greater `weight`, the more denoising (at\n        the expense of fidelity to `input`).\n    eps : float, optional\n        Relative difference of the value of the cost function that\n        determines the stop criterion. The algorithm stops when:\n\n            (E_(n-1) - E_n) < eps * E_0\n\n    n_iter_max : int, optional\n        Maximal number of iterations used for the optimization.\n    multichannel : bool, optional\n        Apply total-variation denoising separately for each channel. This\n        option should be true for color images, otherwise the denoising is\n        also applied in the channels dimension.\n\n    Returns\n    -------\n    out : ndarray\n        Denoised image.\n\n    Notes\n    -----\n    Make sure to set the multichannel parameter appropriately for color images.\n\n    The principle of total variation denoising is explained in\n    http://en.wikipedia.org/wiki/Total_variation_denoising\n\n    The principle of total variation denoising is to minimize the\n    total variation of the image, which can be roughly described as\n    the integral of the norm of the image gradient. Total variation\n    denoising tends to produce \"cartoon-like\" images, that is,\n    piecewise-constant images.\n\n    This code is an implementation of the algorithm of Rudin, Fatemi and Osher\n    that was proposed by Chambolle in [1]_.\n\n    References\n    ----------\n    .. [1] A. Chambolle, An algorithm for total variation minimization and\n           applications, Journal of Mathematical Imaging and Vision,\n           Springer, 2004, 20, 89-97.\n\n    Examples\n    --------\n    2D example on astronaut image:\n\n    >>> from skimage import color, data\n    >>> img = color.rgb2gray(data.astronaut())[:50, :50]\n    >>> img += 0.5 * img.std() * np.random.randn(*img.shape)\n    >>> denoised_img = denoise_tv_chambolle(img, weight=60)\n\n    3D example on synthetic data:\n\n    >>> x, y, z = np.ogrid[0:20, 0:20, 0:20]\n    >>> mask = (x - 22)**2 + (y - 20)**2 + (z - 17)**2 < 8**2\n    >>> mask = mask.astype(np.float)\n    >>> mask += 0.2*np.random.randn(*mask.shape)\n    >>> res = denoise_tv_chambolle(mask, weight=100)\n\n    \"\"\"\n\n    im_type = im.dtype\n    if not im_type.kind == 'f':\n        im = img_as_float(im)\n\n    if multichannel:\n        out = np.zeros_like(im)\n        for c in range(im.shape[-1]):\n            out[..., c] = _denoise_tv_chambolle_nd(im[..., c], weight, eps,\n                                                   n_iter_max)\n    else:\n        out = _denoise_tv_chambolle_nd(im, weight, eps, n_iter_max)\n    return out\n", "path": "skimage/restoration/_denoise.py"}], "after_files": [{"content": "# coding: utf-8\nimport numpy as np\nfrom .. import img_as_float\nfrom ..restoration._denoise_cy import _denoise_bilateral, _denoise_tv_bregman\nfrom .._shared.utils import _mode_deprecations\nimport warnings\n\n\ndef denoise_bilateral(image, win_size=5, sigma_range=None, sigma_spatial=1,\n                      bins=10000, mode='constant', cval=0, multichannel=True):\n    \"\"\"Denoise image using bilateral filter.\n\n    This is an edge-preserving and noise reducing denoising filter. It averages\n    pixels based on their spatial closeness and radiometric similarity.\n\n    Spatial closeness is measured by the gaussian function of the euclidian\n    distance between two pixels and a certain standard deviation\n    (`sigma_spatial`).\n\n    Radiometric similarity is measured by the gaussian function of the euclidian\n    distance between two color values and a certain standard deviation\n    (`sigma_range`).\n\n    Parameters\n    ----------\n    image : ndarray, shape (M, N[, 3])\n        Input image, 2D grayscale or RGB.\n    win_size : int\n        Window size for filtering.\n    sigma_range : float\n        Standard deviation for grayvalue/color distance (radiometric\n        similarity). A larger value results in averaging of pixels with larger\n        radiometric differences. Note, that the image will be converted using\n        the `img_as_float` function and thus the standard deviation is in\n        respect to the range ``[0, 1]``. If the value is ``None`` the standard\n        deviation of the ``image`` will be used.\n    sigma_spatial : float\n        Standard deviation for range distance. A larger value results in\n        averaging of pixels with larger spatial differences.\n    bins : int\n        Number of discrete values for gaussian weights of color filtering.\n        A larger value results in improved accuracy.\n    mode : {'constant', 'edge', 'symmetric', 'reflect', 'wrap'}\n        How to handle values outside the image borders. See\n        `numpy.pad` for detail.\n    cval : string\n        Used in conjunction with mode 'constant', the value outside\n        the image boundaries.\n    multichannel : bool\n        Whether the last axis of the image is to be interpreted as multiple\n        channels or another spatial dimension.\n\n    Returns\n    -------\n    denoised : ndarray\n        Denoised image.\n\n    References\n    ----------\n    .. [1] http://users.soe.ucsc.edu/~manduchi/Papers/ICCV98.pdf\n\n    Example\n    -------\n    >>> from skimage import data, img_as_float\n    >>> astro = img_as_float(data.astronaut())\n    >>> astro = astro[220:300, 220:320]\n    >>> noisy = astro + 0.6 * astro.std() * np.random.random(astro.shape)\n    >>> noisy = np.clip(noisy, 0, 1)\n    >>> denoised = denoise_bilateral(noisy, sigma_range=0.05, sigma_spatial=15)\n    \"\"\"\n    if multichannel:\n        if image.ndim != 3:\n            if image.ndim == 2:\n                raise ValueError(\"Use ``multichannel=False`` for 2D grayscale \"\n                                 \"images. The last axis of the input image \"\n                                 \"must be multiple color channels not another \"\n                                 \"spatial dimension.\")\n            else:\n                raise ValueError(\"Bilateral filter is only implemented for \"\n                                 \"2D grayscale images (image.ndim == 2) and \"\n                                 \"2D multichannel (image.ndim == 3) images, \"\n                                 \"but the input image has {0} dimensions. \"\n                                 \"\".format(image.ndim))\n        elif image.shape[2] not in (3, 4):\n            if image.shape[2] > 4:\n                warnings.warn(\"The last axis of the input image is interpreted \"\n                              \"as channels. Input image with shape {0} has {1} \"\n                              \"channels in last axis. ``denoise_bilateral`` is \"\n                              \"implemented for 2D grayscale and color images \"\n                              \"only.\".format(image.shape, image.shape[2]))\n            else:\n                msg = \"Input image must be grayscale, RGB, or RGBA; but has shape {0}.\"\n                warnings.warn(msg.format(image.shape))\n    else:\n        if image.ndim > 2:\n            raise ValueError(\"Bilateral filter is not implemented for \"\n                             \"grayscale images of 3 or more dimensions, \"\n                             \"but input image has {0} dimension. Use \"\n                             \"``multichannel=True`` for 2-D RGB \"\n                             \"images.\".format(image.shape))\n\n\n    mode = _mode_deprecations(mode)\n    return _denoise_bilateral(image, win_size, sigma_range, sigma_spatial,\n                              bins, mode, cval)\n\n\ndef denoise_tv_bregman(image, weight, max_iter=100, eps=1e-3, isotropic=True):\n    \"\"\"Perform total-variation denoising using split-Bregman optimization.\n\n    Total-variation denoising (also know as total-variation regularization)\n    tries to find an image with less total-variation under the constraint\n    of being similar to the input image, which is controlled by the\n    regularization parameter.\n\n    Parameters\n    ----------\n    image : ndarray\n        Input data to be denoised (converted using img_as_float`).\n    weight : float\n        Denoising weight. The smaller the `weight`, the more denoising (at\n        the expense of less similarity to the `input`). The regularization\n        parameter `lambda` is chosen as `2 * weight`.\n    eps : float, optional\n        Relative difference of the value of the cost function that determines\n        the stop criterion. The algorithm stops when::\n\n            SUM((u(n) - u(n-1))**2) < eps\n\n    max_iter : int, optional\n        Maximal number of iterations used for the optimization.\n    isotropic : boolean, optional\n        Switch between isotropic and anisotropic TV denoising.\n\n    Returns\n    -------\n    u : ndarray\n        Denoised image.\n\n    References\n    ----------\n    .. [1] http://en.wikipedia.org/wiki/Total_variation_denoising\n    .. [2] Tom Goldstein and Stanley Osher, \"The Split Bregman Method For L1\n           Regularized Problems\",\n           ftp://ftp.math.ucla.edu/pub/camreport/cam08-29.pdf\n    .. [3] Pascal Getreuer, \"Rudin\u2013Osher\u2013Fatemi Total Variation Denoising\n           using Split Bregman\" in Image Processing On Line on 2012\u201305\u201319,\n           http://www.ipol.im/pub/art/2012/g-tvd/article_lr.pdf\n    .. [4] http://www.math.ucsb.edu/~cgarcia/UGProjects/BregmanAlgorithms_JacquelineBush.pdf\n\n    \"\"\"\n    return _denoise_tv_bregman(image, weight, max_iter, eps, isotropic)\n\n\ndef _denoise_tv_chambolle_nd(im, weight=0.1, eps=2.e-4, n_iter_max=200):\n    \"\"\"Perform total-variation denoising on n-dimensional images.\n\n    Parameters\n    ----------\n    im : ndarray\n        n-D input data to be denoised.\n    weight : float, optional\n        Denoising weight. The greater `weight`, the more denoising (at\n        the expense of fidelity to `input`).\n    eps : float, optional\n        Relative difference of the value of the cost function that determines\n        the stop criterion. The algorithm stops when:\n\n            (E_(n-1) - E_n) < eps * E_0\n\n    n_iter_max : int, optional\n        Maximal number of iterations used for the optimization.\n\n    Returns\n    -------\n    out : ndarray\n        Denoised array of floats.\n\n    Notes\n    -----\n    Rudin, Osher and Fatemi algorithm.\n\n    \"\"\"\n\n    ndim = im.ndim\n    p = np.zeros((im.ndim, ) + im.shape, dtype=im.dtype)\n    g = np.zeros_like(p)\n    d = np.zeros_like(im)\n    i = 0\n    while i < n_iter_max:\n        if i > 0:\n            # d will be the (negative) divergence of p\n            d = -p.sum(0)\n            slices_d = [slice(None), ] * ndim\n            slices_p = [slice(None), ] * (ndim + 1)\n            for ax in range(ndim):\n                slices_d[ax] = slice(1, None)\n                slices_p[ax+1] = slice(0, -1)\n                slices_p[0] = ax\n                d[slices_d] += p[slices_p]\n                slices_d[ax] = slice(None)\n                slices_p[ax+1] = slice(None)\n            out = im + d\n        else:\n            out = im\n        E = (d ** 2).sum()\n\n        # g stores the gradients of out along each axis\n        # e.g. g[0] is the first order finite difference along axis 0\n        slices_g = [slice(None), ] * (ndim + 1)\n        for ax in range(ndim):\n            slices_g[ax+1] = slice(0, -1)\n            slices_g[0] = ax\n            g[slices_g] = np.diff(out, axis=ax)\n            slices_g[ax+1] = slice(None)\n\n        norm = np.sqrt((g ** 2).sum(axis=0))[np.newaxis, ...]\n        E += weight * norm.sum()\n        tau = 1. / (2.*ndim)\n        norm *= tau / weight\n        norm += 1.\n        p -= tau * g\n        p /= norm\n        E /= float(im.size)\n        if i == 0:\n            E_init = E\n            E_previous = E\n        else:\n            if np.abs(E_previous - E) < eps * E_init:\n                break\n            else:\n                E_previous = E\n        i += 1\n    return out\n\n\ndef denoise_tv_chambolle(im, weight=0.1, eps=2.e-4, n_iter_max=200,\n                         multichannel=False):\n    \"\"\"Perform total-variation denoising on n-dimensional images.\n\n    Parameters\n    ----------\n    im : ndarray of ints, uints or floats\n        Input data to be denoised. `im` can be of any numeric type,\n        but it is cast into an ndarray of floats for the computation\n        of the denoised image.\n    weight : float, optional\n        Denoising weight. The greater `weight`, the more denoising (at\n        the expense of fidelity to `input`).\n    eps : float, optional\n        Relative difference of the value of the cost function that\n        determines the stop criterion. The algorithm stops when:\n\n            (E_(n-1) - E_n) < eps * E_0\n\n    n_iter_max : int, optional\n        Maximal number of iterations used for the optimization.\n    multichannel : bool, optional\n        Apply total-variation denoising separately for each channel. This\n        option should be true for color images, otherwise the denoising is\n        also applied in the channels dimension.\n\n    Returns\n    -------\n    out : ndarray\n        Denoised image.\n\n    Notes\n    -----\n    Make sure to set the multichannel parameter appropriately for color images.\n\n    The principle of total variation denoising is explained in\n    http://en.wikipedia.org/wiki/Total_variation_denoising\n\n    The principle of total variation denoising is to minimize the\n    total variation of the image, which can be roughly described as\n    the integral of the norm of the image gradient. Total variation\n    denoising tends to produce \"cartoon-like\" images, that is,\n    piecewise-constant images.\n\n    This code is an implementation of the algorithm of Rudin, Fatemi and Osher\n    that was proposed by Chambolle in [1]_.\n\n    References\n    ----------\n    .. [1] A. Chambolle, An algorithm for total variation minimization and\n           applications, Journal of Mathematical Imaging and Vision,\n           Springer, 2004, 20, 89-97.\n\n    Examples\n    --------\n    2D example on astronaut image:\n\n    >>> from skimage import color, data\n    >>> img = color.rgb2gray(data.astronaut())[:50, :50]\n    >>> img += 0.5 * img.std() * np.random.randn(*img.shape)\n    >>> denoised_img = denoise_tv_chambolle(img, weight=60)\n\n    3D example on synthetic data:\n\n    >>> x, y, z = np.ogrid[0:20, 0:20, 0:20]\n    >>> mask = (x - 22)**2 + (y - 20)**2 + (z - 17)**2 < 8**2\n    >>> mask = mask.astype(np.float)\n    >>> mask += 0.2*np.random.randn(*mask.shape)\n    >>> res = denoise_tv_chambolle(mask, weight=100)\n\n    \"\"\"\n\n    im_type = im.dtype\n    if not im_type.kind == 'f':\n        im = img_as_float(im)\n\n    if multichannel:\n        out = np.zeros_like(im)\n        for c in range(im.shape[-1]):\n            out[..., c] = _denoise_tv_chambolle_nd(im[..., c], weight, eps,\n                                                   n_iter_max)\n    else:\n        out = _denoise_tv_chambolle_nd(im, weight, eps, n_iter_max)\n    return out\n", "path": "skimage/restoration/_denoise.py"}]}