mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-27 11:27:08 +08:00
Merge pull request #1895 from OrkoHunter/denoise_bilateral
Raise warning for 3D images in denoise_bilateral
This commit is contained in:
@@ -3,10 +3,11 @@ import numpy as np
|
||||
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 @@ def denoise_bilateral(image, win_size=5, sigma_range=None, sigma_spatial=1,
|
||||
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 @@ def denoise_bilateral(image, win_size=5, sigma_range=None, sigma_spatial=1,
|
||||
>>> 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)
|
||||
|
||||
@@ -2,6 +2,7 @@ import numpy as np
|
||||
from numpy.testing import run_module_suite, assert_raises, assert_equal
|
||||
|
||||
from skimage import restoration, data, color, img_as_float, measure
|
||||
from skimage._shared._warnings import expected_warnings
|
||||
|
||||
|
||||
np.random.seed(1234)
|
||||
@@ -159,34 +160,56 @@ def test_denoise_bilateral_2d():
|
||||
img = np.clip(img, 0, 1)
|
||||
|
||||
out1 = restoration.denoise_bilateral(img, sigma_range=0.1,
|
||||
sigma_spatial=20)
|
||||
sigma_spatial=20, multichannel=False)
|
||||
out2 = restoration.denoise_bilateral(img, sigma_range=0.2,
|
||||
sigma_spatial=30)
|
||||
sigma_spatial=30, multichannel=False)
|
||||
|
||||
# make sure noise is reduced in the checkerboard cells
|
||||
assert img[30:45, 5:15].std() > out1[30:45, 5:15].std()
|
||||
assert out1[30:45, 5:15].std() > out2[30:45, 5:15].std()
|
||||
|
||||
|
||||
def test_denoise_bilateral_3d():
|
||||
def test_denoise_bilateral_color():
|
||||
img = checkerboard.copy()
|
||||
# add some random noise
|
||||
img += 0.5 * img.std() * np.random.rand(*img.shape)
|
||||
img = np.clip(img, 0, 1)
|
||||
|
||||
out1 = restoration.denoise_bilateral(img, sigma_range=0.1,
|
||||
sigma_spatial=20)
|
||||
out2 = restoration.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 in the checkerboard cells
|
||||
assert img[30:45, 5:15].std() > out1[30:45, 5:15].std()
|
||||
assert out1[30:45, 5:15].std() > out2[30:45, 5:15].std()
|
||||
|
||||
|
||||
def test_denoise_bilateral_3d_grayscale():
|
||||
img = np.ones((50, 50, 3))
|
||||
assert_raises(ValueError, restoration.denoise_bilateral, img,
|
||||
multichannel=False)
|
||||
|
||||
|
||||
def test_denoise_bilateral_3d_multichannel():
|
||||
img = np.ones((50, 50, 50))
|
||||
with expected_warnings(["grayscale"]):
|
||||
result = restoration.denoise_bilateral(img)
|
||||
|
||||
expected = np.empty_like(img)
|
||||
expected.fill(np.nan)
|
||||
|
||||
assert_equal(result, expected)
|
||||
|
||||
|
||||
def test_denoise_bilateral_multidimensional():
|
||||
img = np.ones((10, 10, 10, 10))
|
||||
assert_raises(ValueError, restoration.denoise_bilateral, img)
|
||||
assert_raises(ValueError, restoration.denoise_bilateral, img,
|
||||
multichannel=True)
|
||||
|
||||
|
||||
def test_denoise_bilateral_nan():
|
||||
img = np.NaN + np.empty((50, 50))
|
||||
out = restoration.denoise_bilateral(img)
|
||||
out = restoration.denoise_bilateral(img, multichannel=False)
|
||||
assert_equal(img, out)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user