ENH: Improve random_noise with better param names & docfixes

This commit is contained in:
Josh Warner (Mac)
2013-07-03 23:54:26 -05:00
parent 647aacb316
commit 32f39eecbb
2 changed files with 47 additions and 31 deletions
+33 -23
View File
@@ -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
+14 -8
View File
@@ -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()