From a61562364301446ce546478a673cc5f82ac4b149 Mon Sep 17 00:00:00 2001 From: emmanuelle Date: Fri, 1 May 2015 19:28:56 +0200 Subject: [PATCH 1/6] Added function to generate binary image with rounded (blob-like) objects. --- skimage/data/__init__.py | 2 +- skimage/data/_binary_blobs.py | 49 +++++++++++++++++++++++++++++++++ skimage/data/tests/test_data.py | 8 ++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 skimage/data/_binary_blobs.py diff --git a/skimage/data/__init__.py b/skimage/data/__init__.py index 2be829ac..1711185c 100644 --- a/skimage/data/__init__.py +++ b/skimage/data/__init__.py @@ -10,7 +10,7 @@ import os as _os from .. import data_dir from ..io import imread, use_plugin - +from ._binary_blobs import binary_blobs __all__ = ['load', 'camera', diff --git a/skimage/data/_binary_blobs.py b/skimage/data/_binary_blobs.py new file mode 100644 index 00000000..38977071 --- /dev/null +++ b/skimage/data/_binary_blobs.py @@ -0,0 +1,49 @@ +import numpy as np +from ..filters import gaussian_filter + + +def binary_blobs(length=512, blob_size_fraction=0.1, n_dim=2, + volume_fraction=0.5, seed=None): + """ + Generate synthetic binary image with several blob-like rounded objects. + + Parameters + ---------- + length : int, default 512 + Linear size of output image. + blob_size_fraction : float, default 0.1 + Typical linear size of blob, as a fraction of ``length``, should be + smaller than 1. + n_dim : int, default 2 + Number of dimensions of output image. + volume_fraction : float, default 0.5 + Fraction of image pixels covered by the blobs (where the output is 1). + Should be in [0, 1]. + seed : int, default 0 + Seed to initialize the random number generator. + + Returns + ------- + blobs : ndarray of bools + Output binary image + + Examples + -------- + >>> blobs = binary_blobs(length=256, blob_size_fraction=0.1) + >>> # Finer structures + >>> blobs = binary_blobs(length=256, blob_size_fraction=0.05) + >>> # Blobs cover a smaller volume fraction of the image + >>> blobs = binary_blobs(length=256, volume_fraction=0.3) + """ + if seed is None: + seed = 0 + # Fix the seed for reproducible results + rs = np.random.RandomState(seed) + shape = tuple([length] * n_dim) + mask = np.zeros(shape) + n_pts = max(int(1. / blob_size_fraction) ** n_dim, 1) + points = (length * rs.rand(n_dim, n_pts)).astype(np.int) + mask[[indices for indices in points]] = 1 + mask = gaussian_filter(mask, sigma=0.25 * length * blob_size_fraction) + threshold = np.percentile(mask, 100 * (1 - volume_fraction)) + return np.logical_not(mask < threshold) diff --git a/skimage/data/tests/test_data.py b/skimage/data/tests/test_data.py index bfcdc571..139f1ddb 100644 --- a/skimage/data/tests/test_data.py +++ b/skimage/data/tests/test_data.py @@ -54,6 +54,14 @@ def test_coffee(): data.coffee() +def test_binary_blobs(): + blobs = data.binary_blobs(length=128) + assert blobs.mean() == 0.5 + blobs = data.binary_blobs(length=128, volume_fraction=0.25) + assert blobs.mean() == 0.25 + blobs = data.binary_blobs(length=32, volume_fraction=0.25, n_dim=3) + assert blobs.mean() == 0.25 + if __name__ == "__main__": from numpy.testing import run_module_suite run_module_suite() From 1c3af75dd355e28c6337ec7cfc3569624a832da8 Mon Sep 17 00:00:00 2001 From: emmanuelle Date: Sat, 9 May 2015 10:23:49 +0200 Subject: [PATCH 2/6] Addressed a few minor issues raised by Juan and Stefan. --- skimage/data/_binary_blobs.py | 19 +++++++++++-------- skimage/data/tests/test_data.py | 6 ++++++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/skimage/data/_binary_blobs.py b/skimage/data/_binary_blobs.py index 38977071..ce173024 100644 --- a/skimage/data/_binary_blobs.py +++ b/skimage/data/_binary_blobs.py @@ -5,21 +5,21 @@ from ..filters import gaussian_filter def binary_blobs(length=512, blob_size_fraction=0.1, n_dim=2, volume_fraction=0.5, seed=None): """ - Generate synthetic binary image with several blob-like rounded objects. + Generate synthetic binary image with several rounded blob-like objects. Parameters ---------- - length : int, default 512 + length : int, optional Linear size of output image. - blob_size_fraction : float, default 0.1 + blob_size_fraction : float, optional Typical linear size of blob, as a fraction of ``length``, should be smaller than 1. - n_dim : int, default 2 + n_dim : int, optional Number of dimensions of output image. volume_fraction : float, default 0.5 Fraction of image pixels covered by the blobs (where the output is 1). Should be in [0, 1]. - seed : int, default 0 + seed : int, optional Seed to initialize the random number generator. Returns @@ -29,15 +29,18 @@ def binary_blobs(length=512, blob_size_fraction=0.1, n_dim=2, Examples -------- + >>> data.binary_blobs(length=5, blob_size_fraction=0.2, seed=1) + array([[ True, False, True, True, True], + [ True, True, True, False, True], + [False, True, False, True, True], + [ True, False, False, True, True], + [ True, False, False, False, True]], dtype=bool) >>> blobs = binary_blobs(length=256, blob_size_fraction=0.1) >>> # Finer structures >>> blobs = binary_blobs(length=256, blob_size_fraction=0.05) >>> # Blobs cover a smaller volume fraction of the image >>> blobs = binary_blobs(length=256, volume_fraction=0.3) """ - if seed is None: - seed = 0 - # Fix the seed for reproducible results rs = np.random.RandomState(seed) shape = tuple([length] * n_dim) mask = np.zeros(shape) diff --git a/skimage/data/tests/test_data.py b/skimage/data/tests/test_data.py index 139f1ddb..a4afb056 100644 --- a/skimage/data/tests/test_data.py +++ b/skimage/data/tests/test_data.py @@ -1,3 +1,4 @@ +import numpy as np import skimage.data as data from numpy.testing import assert_equal @@ -7,6 +8,7 @@ def test_lena(): lena = data.lena() assert_equal(lena.shape, (512, 512, 3)) + def test_astronaut(): """ Test that "astronaut" image can be loaded. """ astronaut = data.astronaut() @@ -61,6 +63,10 @@ def test_binary_blobs(): assert blobs.mean() == 0.25 blobs = data.binary_blobs(length=32, volume_fraction=0.25, n_dim=3) assert blobs.mean() == 0.25 + other_realization = data.binary_blobs(length=32, volume_fraction=0.25, + n_dim=3) + assert not np.all(blobs == other_realization) + if __name__ == "__main__": from numpy.testing import run_module_suite From a8a39ebf35130f865e3a9829708cdf73e19643e2 Mon Sep 17 00:00:00 2001 From: emmanuelle Date: Sat, 9 May 2015 12:08:21 +0200 Subject: [PATCH 3/6] Used new function to generate binary blobs in existing gallery example --- .../plot_random_walker_segmentation.py | 25 +++---------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/doc/examples/plot_random_walker_segmentation.py b/doc/examples/plot_random_walker_segmentation.py index fa70e503..0c494de5 100644 --- a/doc/examples/plot_random_walker_segmentation.py +++ b/doc/examples/plot_random_walker_segmentation.py @@ -25,30 +25,11 @@ from scipy import ndimage import matplotlib.pyplot as plt from skimage.segmentation import random_walker - - -def microstructure(l=256): - """ - Synthetic binary data: binary microstructure with blobs. - - Parameters - ---------- - - l: int, optional - linear size of the returned image - """ - n = 5 - x, y = np.ogrid[0:l, 0:l] - mask = np.zeros((l, l)) - generator = np.random.RandomState(1) - points = l * generator.rand(2, n ** 2) - mask[(points[0]).astype(np.int), (points[1]).astype(np.int)] = 1 - mask = ndimage.gaussian_filter(mask, sigma=l / (4. * n)) - return (mask > mask.mean()).astype(np.float) - +from skimage.data import binary_blobs +import skimage # Generate noisy synthetic data -data = microstructure(l=128) +data = skimage.img_as_float(binary_blobs(length=128, seed=1)) data += 0.35 * np.random.randn(*data.shape) markers = np.zeros(data.shape, dtype=np.uint) markers[data < -0.3] = 1 From 073c9735dc92d20faf07be0b36ec49e798c1e7ec Mon Sep 17 00:00:00 2001 From: emmanuelle Date: Sat, 9 May 2015 14:51:41 +0200 Subject: [PATCH 4/6] Fixed example in doctest. --- skimage/data/_binary_blobs.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/skimage/data/_binary_blobs.py b/skimage/data/_binary_blobs.py index ce173024..f441fce2 100644 --- a/skimage/data/_binary_blobs.py +++ b/skimage/data/_binary_blobs.py @@ -29,17 +29,18 @@ def binary_blobs(length=512, blob_size_fraction=0.1, n_dim=2, Examples -------- + >>> from skimage import data >>> data.binary_blobs(length=5, blob_size_fraction=0.2, seed=1) array([[ True, False, True, True, True], [ True, True, True, False, True], [False, True, False, True, True], [ True, False, False, True, True], [ True, False, False, False, True]], dtype=bool) - >>> blobs = binary_blobs(length=256, blob_size_fraction=0.1) + >>> blobs = data.binary_blobs(length=256, blob_size_fraction=0.1) >>> # Finer structures - >>> blobs = binary_blobs(length=256, blob_size_fraction=0.05) + >>> blobs = data.binary_blobs(length=256, blob_size_fraction=0.05) >>> # Blobs cover a smaller volume fraction of the image - >>> blobs = binary_blobs(length=256, volume_fraction=0.3) + >>> blobs = data.binary_blobs(length=256, volume_fraction=0.3) """ rs = np.random.RandomState(seed) shape = tuple([length] * n_dim) From e751d245f372cf8a69ef155f45cffb6557fb8efb Mon Sep 17 00:00:00 2001 From: emmanuelle Date: Sun, 10 May 2015 23:29:54 +0200 Subject: [PATCH 5/6] Modified test with a less stringent condition on numerical value for the mean value of blobs image. --- skimage/data/tests/test_data.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/skimage/data/tests/test_data.py b/skimage/data/tests/test_data.py index a4afb056..ce9b5879 100644 --- a/skimage/data/tests/test_data.py +++ b/skimage/data/tests/test_data.py @@ -1,6 +1,6 @@ import numpy as np import skimage.data as data -from numpy.testing import assert_equal +from numpy.testing import assert_equal, assert_almost_equal def test_lena(): @@ -58,11 +58,11 @@ def test_coffee(): def test_binary_blobs(): blobs = data.binary_blobs(length=128) - assert blobs.mean() == 0.5 + assert_almost_equal(blobs.mean(), 0.5, decimal=4) blobs = data.binary_blobs(length=128, volume_fraction=0.25) - assert blobs.mean() == 0.25 + assert_almost_equal(blobs.mean(), 0.25, decimal=4) blobs = data.binary_blobs(length=32, volume_fraction=0.25, n_dim=3) - assert blobs.mean() == 0.25 + assert_almost_equal(blobs.mean(), 0.25, decimal=4) other_realization = data.binary_blobs(length=32, volume_fraction=0.25, n_dim=3) assert not np.all(blobs == other_realization) From 1ef90468e0820f7f621bd02357f67ef237f7c982 Mon Sep 17 00:00:00 2001 From: emmanuelle Date: Mon, 11 May 2015 22:58:16 +0200 Subject: [PATCH 6/6] Modified (again) test accuracy. --- skimage/data/tests/test_data.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/skimage/data/tests/test_data.py b/skimage/data/tests/test_data.py index ce9b5879..38e4543a 100644 --- a/skimage/data/tests/test_data.py +++ b/skimage/data/tests/test_data.py @@ -58,11 +58,11 @@ def test_coffee(): def test_binary_blobs(): blobs = data.binary_blobs(length=128) - assert_almost_equal(blobs.mean(), 0.5, decimal=4) + assert_almost_equal(blobs.mean(), 0.5, decimal=1) blobs = data.binary_blobs(length=128, volume_fraction=0.25) - assert_almost_equal(blobs.mean(), 0.25, decimal=4) + assert_almost_equal(blobs.mean(), 0.25, decimal=1) blobs = data.binary_blobs(length=32, volume_fraction=0.25, n_dim=3) - assert_almost_equal(blobs.mean(), 0.25, decimal=4) + assert_almost_equal(blobs.mean(), 0.25, decimal=1) other_realization = data.binary_blobs(length=32, volume_fraction=0.25, n_dim=3) assert not np.all(blobs == other_realization)