mirror of
https://github.com/wassname/scikit-image.git
synced 2026-06-29 03:21:19 +08:00
ENH: Improve random_noise with better param names & docfixes
This commit is contained in:
+33
-23
@@ -24,18 +24,20 @@ def random_noise(image, mode='gaussian', seed=None, **kwargs):
|
||||
'speckle' Multiplicative noise using out = image + n*image, where
|
||||
n is uniform noise with specified mean & variance.
|
||||
seed : int
|
||||
If provided, this will set the random seed before generating noise.
|
||||
m : float
|
||||
If provided, this will set the random seed before generating noise,
|
||||
for valid pseudo-random comparisons.
|
||||
mean : float
|
||||
Mean of random distribution. Used in 'gaussian' and 'speckle'.
|
||||
v : float
|
||||
Default : 0.
|
||||
var : float
|
||||
Variance of random distribution. Used in 'gaussian' and 'speckle'.
|
||||
Note: variance = (standard deviation) ** 2
|
||||
d : float
|
||||
Note: variance = (standard deviation) ** 2. Default : 0.01
|
||||
prop_replace : float
|
||||
Proportion of image pixels to replace with noise on range [0, 1].
|
||||
Used in 'salt', 'pepper', and 'salt & pepper'.
|
||||
p : float
|
||||
Used in 'salt', 'pepper', and 'salt & pepper'. Default : 0.05
|
||||
prop_salt : float
|
||||
Proportion of salt vs. pepper noise for 's&p' on range [0, 1].
|
||||
Higher values represent more salt.
|
||||
Higher values represent more salt. Default : 0.5 (equal amounts)
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -57,15 +59,15 @@ def random_noise(image, mode='gaussian', seed=None, **kwargs):
|
||||
'speckle': 'gaussian_values'}
|
||||
|
||||
kwdefaults = {
|
||||
'm': 0.,
|
||||
'v': 0.01,
|
||||
'd': 0.05,
|
||||
'p': 0.5}
|
||||
'mean': 0.,
|
||||
'var': 0.01,
|
||||
'prop_replace': 0.05,
|
||||
'prop_salt': 0.5}
|
||||
|
||||
allowedkwargs = {
|
||||
'gaussian_values': ['m', 'v'],
|
||||
'sp_values': ['d'],
|
||||
's&p_values': ['d', 'p']}
|
||||
'gaussian_values': ['mean', 'var'],
|
||||
'sp_values': ['prop_replace'],
|
||||
's&p_values': ['prop_replace', 'prop_salt']}
|
||||
|
||||
for key in kwargs:
|
||||
if key not in allowedkwargs[allowedtypes[mode]]:
|
||||
@@ -77,7 +79,8 @@ def random_noise(image, mode='gaussian', seed=None, **kwargs):
|
||||
kwargs.setdefault(kw, kwdefaults[kw])
|
||||
|
||||
if mode == 'gaussian':
|
||||
noise = np.random.normal(kwargs['m'], kwargs['v'] ** 0.5, image.shape)
|
||||
noise = np.random.normal(kwargs['mean'], kwargs['var'] ** 0.5,
|
||||
image.shape)
|
||||
out = np.clip(image + noise, 0., 1.)
|
||||
|
||||
elif mode == 'poisson':
|
||||
@@ -91,29 +94,36 @@ def random_noise(image, mode='gaussian', seed=None, **kwargs):
|
||||
|
||||
elif mode == 'salt':
|
||||
# Re-call function with mode='s&p' and p=1 (all salt noise)
|
||||
out = random_noise(image, mode='s&p', seed=seed, d=kwargs['d'], p=1)
|
||||
out = random_noise(image, mode='s&p', seed=seed,
|
||||
prop_replace=kwargs['prop_replace'], prop_salt=1.)
|
||||
|
||||
elif mode == 'pepper':
|
||||
# Re-call function with mode='s&p' and p=1 (all pepper noise)
|
||||
out = random_noise(image, mode='s&p', seed=seed, d=kwargs['d'], p=0)
|
||||
out = random_noise(image, mode='s&p', seed=seed,
|
||||
prop_replace=kwargs['prop_replace'], prop_salt=0.)
|
||||
|
||||
elif mode == 's&p':
|
||||
# This mode makes no effort to avoid repeat sampling. Thus, the
|
||||
# exact number of replaced pixels is only approximate.
|
||||
out = image.copy()
|
||||
|
||||
# Salt mode
|
||||
num_salt = np.ceil(kwargs['d'] * image.size * kwargs['p'])
|
||||
coords = [np.random.randint(0, i - 1, num_salt)
|
||||
num_salt = np.ceil(
|
||||
kwargs['prop_replace'] * image.size * kwargs['prop_salt'])
|
||||
coords = [np.random.randint(0, i - 1, int(num_salt))
|
||||
for i in image.shape]
|
||||
out[coords] = 1
|
||||
|
||||
# Pepper mode
|
||||
num_pepper = np.ceil(kwargs['d'] * image.size * (1. - kwargs['p']))
|
||||
coords = [np.random.randint(0, i - 1, num_pepper)
|
||||
num_pepper = np.ceil(
|
||||
kwargs['prop_replace'] * image.size * (1. - kwargs['prop_salt']))
|
||||
coords = [np.random.randint(0, i - 1, int(num_pepper))
|
||||
for i in image.shape]
|
||||
out[coords] = 0
|
||||
|
||||
elif mode == 'speckle':
|
||||
noise = np.random.normal(kwargs['m'], kwargs['v'] ** 0.5, image.shape)
|
||||
noise = np.random.normal(kwargs['mean'], kwargs['var'] ** 0.5,
|
||||
image.shape)
|
||||
out = np.clip(image + image * noise, 0., 1.)
|
||||
|
||||
return out
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from numpy.testing import assert_array_equal, assert_allclose
|
||||
from numpy.testing import assert_array_equal, assert_allclose, assert_raises
|
||||
|
||||
import numpy as np
|
||||
from skimage.data import camera
|
||||
@@ -15,7 +15,7 @@ def test_set_seed():
|
||||
def test_salt():
|
||||
seed = 42
|
||||
cam = img_as_float(camera())
|
||||
cam_noisy = random_noise(cam, seed=seed, mode='salt', d=0.15)
|
||||
cam_noisy = random_noise(cam, seed=seed, mode='salt', prop_replace=0.15)
|
||||
saltmask = cam != cam_noisy
|
||||
|
||||
# Ensure all changes are to 1.0
|
||||
@@ -29,7 +29,7 @@ def test_salt():
|
||||
def test_pepper():
|
||||
seed = 42
|
||||
cam = img_as_float(camera())
|
||||
cam_noisy = random_noise(cam, seed=seed, mode='pepper', d=0.15)
|
||||
cam_noisy = random_noise(cam, seed=seed, mode='pepper', prop_replace=0.15)
|
||||
peppermask = cam != cam_noisy
|
||||
|
||||
# Ensure all changes are to 1.0
|
||||
@@ -43,7 +43,8 @@ def test_pepper():
|
||||
def test_salt_and_pepper():
|
||||
seed = 42
|
||||
cam = img_as_float(camera())
|
||||
cam_noisy = random_noise(cam, seed=seed, mode='s&p', d=0.15, p=0.25)
|
||||
cam_noisy = random_noise(cam, seed=seed, mode='s&p', prop_replace=0.15,
|
||||
prop_salt=0.25)
|
||||
saltmask = np.logical_and(cam != cam_noisy, cam_noisy == 1.)
|
||||
peppermask = np.logical_and(cam != cam_noisy, cam_noisy == 0.)
|
||||
|
||||
@@ -63,10 +64,10 @@ def test_salt_and_pepper():
|
||||
def test_gaussian():
|
||||
seed = 42
|
||||
data = np.zeros((128, 128)) + 0.5
|
||||
data_gaussian = random_noise(data, seed=seed, v=0.01)
|
||||
data_gaussian = random_noise(data, seed=seed, var=0.01)
|
||||
assert 0.008 < data_gaussian.var() < 0.012
|
||||
|
||||
data_gaussian = random_noise(data, seed=seed, m=0.3, v=0.015)
|
||||
data_gaussian = random_noise(data, seed=seed, mean=0.3, var=0.015)
|
||||
assert 0.28 < data_gaussian.mean() - 0.5 < 0.32
|
||||
assert 0.012 < data_gaussian.var() < 0.018
|
||||
|
||||
@@ -78,10 +79,15 @@ def test_speckle():
|
||||
noise = np.random.normal(0.1, 0.02 ** 0.5, (128, 128))
|
||||
expected = np.clip(data + data * noise, 0, 1)
|
||||
|
||||
data_speckle = random_noise(data, mode='speckle', seed=seed, m=0.1,
|
||||
v=0.02)
|
||||
data_speckle = random_noise(data, mode='speckle', seed=seed, mean=0.1,
|
||||
var=0.02)
|
||||
assert_allclose(expected, data_speckle)
|
||||
|
||||
|
||||
def test_bad_mode():
|
||||
data = np.zeros((64, 64))
|
||||
assert_raises(KeyError, random_noise, data, 'perlin')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
np.testing.run_module_suite()
|
||||
|
||||
Reference in New Issue
Block a user