import numpy as np 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. Parameters ---------- s1, s2 : numpy arrays s1 and s2 are label fields of the same shape. Returns ------- j : numpy array The join segmentation of s1 and s2. Examples -------- >>> import numpy as np >>> from skimage.segmentation import join_segmentations >>> s1 = np.array([[0, 0, 1, 1], ... [0, 2, 1, 1], ... [2, 2, 2, 1]]) >>> s2 = np.array([[0, 1, 1, 0], ... [0, 1, 1, 0], ... [0, 1, 1, 1]]) >>> join_segmentations(s1, s2) array([[0, 1, 3, 2], [0, 5, 3, 2], [4, 5, 5, 3]]) """ 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] j = (s2.max() + 1) * s1 + s2 j = relabel_from_one(j)[0] return j def relabel_from_one(label_field): """Convert labels in an arbitrary label field to {1, ... 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). Parameters ---------- label_field : numpy ndarray (integer type) Returns ------- relabeled : numpy array of same shape as ar forward_map : 1d numpy array of length np.unique(ar) + 1 inverse_map : 1d numpy array of length len(np.unique(ar)) The length is len(np.unique(ar)) + 1 if 0 is not in np.unique(ar) Examples -------- >>> import numpy as np >>> 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 array([1, 1, 2, 2, 3, 5, 4]) >>> fw array([0, 1, 0, 0, 0, 2, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5]) >>> inv array([ 0, 1, 5, 8, 42, 99]) >>> (fw[label_field] == relab).all() True >>> (inv[relab] == label_field).all() True """ labels = np.unique(label_field) labels0 = labels[labels != 0] m = labels.max() 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) if not (labels == 0).any(): labels = np.concatenate(([0], labels)) inverse_map = labels return forward_map[label_field], forward_map, inverse_map