From 18438299179cb6598745a13ace1ceaa52a677d41 Mon Sep 17 00:00:00 2001 From: Juan Nunez-Iglesias Date: Thu, 3 Oct 2013 16:08:29 +1000 Subject: [PATCH 1/5] Add relabel_sequential, deprecate relabel_from_one --- skimage/segmentation/_join.py | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/skimage/segmentation/_join.py b/skimage/segmentation/_join.py index 1eda9176..ce440b23 100644 --- a/skimage/segmentation/_join.py +++ b/skimage/segmentation/_join.py @@ -1,4 +1,5 @@ import numpy as np +from skimage._shared.utils import deprecated def join_segmentations(s1, s2): @@ -42,9 +43,18 @@ def join_segmentations(s1, s2): return j +@deprecated('relabel_sequential') def relabel_from_one(label_field): """Convert labels in an arbitrary label field to {1, ... number_of_labels}. + This function is deprecated, see ``relabel_sequential`` for more. + """ + return relabel_sequential(label_field, offset=1) + + +def relabel_sequential(label_field, offset=1): + """Relabel arbitrary labels to {`offset`, ... `offset` + number_of_labels}. + This function also returns the forward map (mapping the original labels to the reduced labels) and the inverse map (mapping the reduced labels back to the original ones). @@ -52,6 +62,10 @@ def relabel_from_one(label_field): Parameters ---------- label_field : numpy array of int, arbitrary shape + An array of labels. + offset : int, optional + The return labels will start at `offset`, which should be + strictly positive. Returns ------- @@ -62,13 +76,15 @@ def relabel_from_one(label_field): The map from the original label space to the returned label space. Can be used to re-apply the same mapping. See examples for usage. - inverse_map : numpy array of int, shape ``(len(np.unique(label_field)),)`` + inverse_map : 1D numpy array of int, of length offset + number of labels The map from the new label space to the original space. This can be used to reconstruct the original label field from the relabeled one. Notes ----- + The label 0 is assumed to denote the background and is never remapped. + The forward map can be extremely big for some inputs, since its length is given by the maximum of the label field. However, in most situations, ``label_field.max()`` is much smaller than @@ -79,7 +95,7 @@ def relabel_from_one(label_field): -------- >>> from skimage.segmentation import relabel_from_one >>> label_field = array([1, 1, 5, 5, 8, 99, 42]) - >>> relab, fw, inv = relabel_from_one(label_field) + >>> relab, fw, inv = relabel_sequential(label_field) >>> relab array([1, 1, 2, 2, 3, 5, 4]) >>> fw @@ -94,6 +110,9 @@ def relabel_from_one(label_field): True >>> (inv[relab] == label_field).all() True + >>> relab, fw, inv = relabel_sequential(label_field, offset=5) + >>> relab + array([5, 5, 6, 6, 7, 9, 8]) """ labels = np.unique(label_field) labels0 = labels[labels != 0] @@ -101,9 +120,11 @@ def relabel_from_one(label_field): if m == len(labels0): # nothing to do, already 1...n labels return label_field, labels, labels forward_map = np.zeros(m+1, int) - forward_map[labels0] = np.arange(1, len(labels0) + 1) + forward_map[labels0] = np.arange(offset, offset + len(labels0) + 1) if not (labels == 0).any(): labels = np.concatenate(([0], labels)) - inverse_map = labels - return forward_map[label_field], forward_map, inverse_map + inverse_map = np.zeros(offset - 1 + len(labels), dtype=np.intp) + inverse_map[(offset - 1):] = labels + relabeled = forward_map[label_field] + return relabeled, forward_map, inverse_map From 37f66f769b748d8f78838accf5033ede4dba4a83 Mon Sep 17 00:00:00 2001 From: Juan Nunez-Iglesias Date: Thu, 3 Oct 2013 16:09:27 +1000 Subject: [PATCH 2/5] Add relabel_sequential to __init__ import --- skimage/segmentation/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/skimage/segmentation/__init__.py b/skimage/segmentation/__init__.py index 107111bd..aea6c70f 100644 --- a/skimage/segmentation/__init__.py +++ b/skimage/segmentation/__init__.py @@ -4,7 +4,7 @@ from .slic_superpixels import slic from ._quickshift import quickshift from .boundaries import find_boundaries, visualize_boundaries, mark_boundaries from ._clear_border import clear_border -from ._join import join_segmentations, relabel_from_one +from ._join import join_segmentations, relabel_from_one, relabel_sequential __all__ = ['random_walker', @@ -16,4 +16,5 @@ __all__ = ['random_walker', 'mark_boundaries', 'clear_border', 'join_segmentations', - 'relabel_from_one'] + 'relabel_from_one', + 'relabel_sequential'] From bfab4931337fd09d6780244c000bf42285de4fb5 Mon Sep 17 00:00:00 2001 From: Juan Nunez-Iglesias Date: Thu, 3 Oct 2013 16:11:52 +1000 Subject: [PATCH 3/5] Add new tests for relabel_sequential --- skimage/segmentation/tests/test_join.py | 31 ++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/skimage/segmentation/tests/test_join.py b/skimage/segmentation/tests/test_join.py index f03244e9..548fcc8d 100644 --- a/skimage/segmentation/tests/test_join.py +++ b/skimage/segmentation/tests/test_join.py @@ -1,6 +1,6 @@ import numpy as np from numpy.testing import assert_array_equal, assert_raises -from skimage.segmentation import join_segmentations, relabel_from_one +from skimage.segmentation import join_segmentations, relabel_sequential def test_join_segmentations(): s1 = np.array([[0, 0, 1, 1], @@ -24,9 +24,10 @@ def test_join_segmentations(): s3 = np.array([[0, 0, 1, 1], [0, 2, 2, 1]]) assert_raises(ValueError, join_segmentations, s1, s3) -def test_relabel_from_one(): + +def test_relabel_sequential_offset1(): ar = np.array([1, 1, 5, 5, 8, 99, 42]) - ar_relab, fw, inv = relabel_from_one(ar) + ar_relab, fw, inv = relabel_sequential(ar) ar_relab_ref = np.array([1, 1, 2, 2, 3, 5, 4]) assert_array_equal(ar_relab, ar_relab_ref) fw_ref = np.zeros(100, int) @@ -36,5 +37,29 @@ def test_relabel_from_one(): assert_array_equal(inv, inv_ref) +def test_relabel_sequential_offset5(): + ar = np.array([1, 1, 5, 5, 8, 99, 42]) + ar_relab, fw, inv = relabel_sequential(ar, offset=5) + ar_relab_ref = np.array([5, 5, 6, 6, 7, 9, 8]) + assert_array_equal(ar_relab, ar_relab_ref) + fw_ref = np.zeros(100, int) + fw_ref[1] = 5; fw_ref[5] = 6; fw_ref[8] = 7; fw_ref[42] = 8; fw_ref[99] = 9 + assert_array_equal(fw, fw_ref) + inv_ref = np.array([0, 0, 0, 0, 0, 1, 5, 8, 42, 99]) + assert_array_equal(inv, inv_ref) + + +def test_relabel_sequential_offset5_with0(): + ar = np.array([1, 1, 5, 5, 8, 99, 42, 0]) + ar_relab, fw, inv = relabel_sequential(ar, offset=5) + ar_relab_ref = np.array([5, 5, 6, 6, 7, 9, 8, 0]) + assert_array_equal(ar_relab, ar_relab_ref) + fw_ref = np.zeros(100, int) + fw_ref[1] = 5; fw_ref[5] = 6; fw_ref[8] = 7; fw_ref[42] = 8; fw_ref[99] = 9 + assert_array_equal(fw, fw_ref) + inv_ref = np.array([0, 0, 0, 0, 0, 1, 5, 8, 42, 99]) + assert_array_equal(inv, inv_ref) + + if __name__ == "__main__": np.testing.run_module_suite() From a8488bfecd4c80b33b67bdb792f15954bb983795 Mon Sep 17 00:00:00 2001 From: Juan Nunez-Iglesias Date: Thu, 3 Oct 2013 16:14:30 +1000 Subject: [PATCH 4/5] Remove deprecated use of relabel_from_one --- skimage/segmentation/_join.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/skimage/segmentation/_join.py b/skimage/segmentation/_join.py index ce440b23..bb2268b3 100644 --- a/skimage/segmentation/_join.py +++ b/skimage/segmentation/_join.py @@ -5,9 +5,9 @@ from skimage._shared.utils import deprecated def join_segmentations(s1, s2): """Return the join of the two input segmentations. - The join J of S1 and S2 is defined as the segmentation in which two voxels - are in the same segment in J if and only if they are in the same segment - in *both* S1 and S2. + The join J of S1 and S2 is defined as the segmentation in which two + voxels are in the same segment if and only if they are in the same + segment in *both* S1 and S2. Parameters ---------- @@ -36,10 +36,10 @@ def join_segmentations(s1, s2): if s1.shape != s2.shape: raise ValueError("Cannot join segmentations of different shape. " + "s1.shape: %s, s2.shape: %s" % (s1.shape, s2.shape)) - s1 = relabel_from_one(s1)[0] - s2 = relabel_from_one(s2)[0] + s1 = relabel_sequential(s1)[0] + s2 = relabel_sequential(s2)[0] j = (s2.max() + 1) * s1 + s2 - j = relabel_from_one(j)[0] + j = relabel_sequential(j)[0] return j From a9afb241cc915b3b06da77898a2b4bfcf7554c45 Mon Sep 17 00:00:00 2001 From: Juan Nunez-Iglesias Date: Thu, 3 Oct 2013 16:23:30 +1000 Subject: [PATCH 5/5] Rename deprecated relabel_from_one in docstring example --- skimage/segmentation/_join.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skimage/segmentation/_join.py b/skimage/segmentation/_join.py index bb2268b3..462bb18f 100644 --- a/skimage/segmentation/_join.py +++ b/skimage/segmentation/_join.py @@ -93,7 +93,7 @@ def relabel_sequential(label_field, offset=1): Examples -------- - >>> from skimage.segmentation import relabel_from_one + >>> from skimage.segmentation import relabel_sequential >>> label_field = array([1, 1, 5, 5, 8, 99, 42]) >>> relab, fw, inv = relabel_sequential(label_field) >>> relab