def test_01_3D(self): x = numpy.zeros((5,5,5)) output = rank_order(x)[0] self.assertTrue(numpy.all(output==0)) self.assertEqual(x.ndim, 3) self.assertEqual(x.shape[0],5) self.assertEqual(x.shape[1],5) self.assertEqual(x.shape[2],5)
def test_01_3D(self): x = numpy.zeros((5, 5, 5)) output = rank_order(x)[0] self.assertTrue(numpy.all(output == 0)) self.assertEqual(x.ndim, 3) self.assertEqual(x.shape[0], 5) self.assertEqual(x.shape[1], 5) self.assertEqual(x.shape[2], 5)
def test_00_zeros(self): """Test rank_order on a matrix of all zeros""" x = numpy.zeros((5,5)) output = rank_order(x)[0] self.assertTrue(numpy.all(output==0)) self.assertTrue(output.dtype.type == numpy.uint32) self.assertEqual(x.ndim, 2) self.assertEqual(x.shape[0],5) self.assertEqual(x.shape[1],5)
def test_00_zeros(self): """Test rank_order on a matrix of all zeros""" x = numpy.zeros((5, 5)) output = rank_order(x)[0] self.assertTrue(numpy.all(output == 0)) self.assertTrue(output.dtype.type == numpy.uint32) self.assertEqual(x.ndim, 2) self.assertEqual(x.shape[0], 5) self.assertEqual(x.shape[1], 5)
def test_02_two_values(self): x = numpy.zeros((5,10)) x[3,5] = 2 x[4,7] = 2 output,orig = rank_order(x) self.assertEqual(output[3,5],1) self.assertEqual(output[4,7],1) self.assertEqual(len(orig),2) self.assertEqual(orig[0],0) self.assertEqual(orig[1],2) self.assertEqual(numpy.sum(output==0),48)
def test_02_two_values(self): x = numpy.zeros((5, 10)) x[3, 5] = 2 x[4, 7] = 2 output, orig = rank_order(x) self.assertEqual(output[3, 5], 1) self.assertEqual(output[4, 7], 1) self.assertEqual(len(orig), 2) self.assertEqual(orig[0], 0) self.assertEqual(orig[1], 2) self.assertEqual(numpy.sum(output == 0), 48)
def test_03_three_values(self): x = numpy.zeros((5,10)) x[3,5] = 4 x[4,7] = 4 x[0,9] = 3 output,orig = rank_order(x) self.assertEqual(output[0,9],1) self.assertEqual(output[3,5],2) self.assertEqual(output[4,7],2) self.assertEqual(len(orig),3) self.assertEqual(orig[0],0) self.assertEqual(orig[1],3) self.assertEqual(orig[2],4) self.assertEqual(numpy.sum(output==0),47)
def test_03_three_values(self): x = numpy.zeros((5, 10)) x[3, 5] = 4 x[4, 7] = 4 x[0, 9] = 3 output, orig = rank_order(x) self.assertEqual(output[0, 9], 1) self.assertEqual(output[3, 5], 2) self.assertEqual(output[4, 7], 2) self.assertEqual(len(orig), 3) self.assertEqual(orig[0], 0) self.assertEqual(orig[1], 3) self.assertEqual(orig[2], 4) self.assertEqual(numpy.sum(output == 0), 47)
def fast_watershed(image, markers, connectivity=None, offset=None, mask=None): """Return a matrix labeled using the watershed algorithm image - an array where the lowest value points are labeled first. markers - an array marking the basins with the values to be assigned in the label matrix. Zero means not a marker. This array should be of an integer type. connectivity - an array whose non-zero elements indicate neighbors for connection. Following the scipy convention, default is a one-connected array of the dimension of the image. offset - offset of the connectivity (one offset per dimension) mask - don't label points in the mask Returns a labeled matrix of the same type and shape as markers This implementation converts all arguments to specific, lowest common denominator types, then passes these to a C algorithm that operates as above. """ if connectivity == None: c_connectivity = scipy.ndimage.generate_binary_structure(image.ndim, 1) else: c_connectivity = numpy.array(connectivity, bool) if c_connectivity.ndim != image.ndim: raise ValueError, "Connectivity dimension must be same as image" if offset == None: if any([x % 2 == 0 for x in c_connectivity.shape]): raise ValueError, "Connectivity array must have an unambiguous center" # # offset to center of connectivity array # offset = numpy.array(c_connectivity.shape) / 2 # pad the image, markers, and mask so that we can use the mask to keep from running off the edges pads = offset def pad(im): new_im = numpy.zeros([i + 2 * p for i, p in zip(im.shape, pads)], im.dtype) new_im[[slice(p, -p, None) for p in pads]] = im return new_im if mask is not None: mask = pad(mask) else: mask = pad(numpy.ones(image.shape, bool)) image = pad(image) markers = pad(markers) c_image = rank_order(image)[0].astype(numpy.int32) c_markers = numpy.ascontiguousarray(markers, dtype=numpy.int32) if c_markers.ndim != c_image.ndim: raise ValueError, "markers (ndim=%d) must have same # of dimensions " "as image (ndim=%d)" % ( c_markers.ndim, c_image.ndim, ) if not all([x == y for x, y in zip(c_markers.shape, c_image.shape)]): raise ValueError("image and markers must have the same shape") if mask != None: c_mask = numpy.ascontiguousarray(mask, dtype=bool) if c_mask.ndim != c_markers.ndim: raise ValueError, "mask must have same # of dimensions as image" if not all([x == y for x, y in zip(c_markers.shape, c_mask.shape)]): raise ValueError, "mask must have same shape as image" c_markers[numpy.logical_not(mask)] = 0 else: c_mask = None c_output = c_markers.copy() # # We pass a connectivity array that pre-calculates the stride for each # neighbor. # # The result of this bit of code is an array with one row per # point to be considered. The first column is the pre-computed stride # and the second through last are the x,y...whatever offsets # (to do bounds checking). c = [] image_stride = __get_strides_for_shape(image.shape) for i in range(numpy.product(c_connectivity.shape)): multiplier = 1 offs = [] indexes = [] ignore = True for j in range(len(c_connectivity.shape)): elems = c_image.shape[j] idx = (i / multiplier) % c_connectivity.shape[j] off = idx - offset[j] if off: ignore = False offs.append(off) indexes.append(idx) multiplier *= c_connectivity.shape[j] if (not ignore) and c_connectivity.__getitem__(tuple(indexes)): stride = numpy.dot(image_stride, numpy.array(offs)) offs.insert(0, stride) c.append(offs) c = numpy.array(c, numpy.int32) pq, age = __heapify_markers(c_markers, c_image) pq = numpy.ascontiguousarray(pq, dtype=numpy.int32) if numpy.product(pq.shape) > 0: # If nothing is labeled, the output is empty and we don't have to # do anything c_output = c_output.flatten() if c_mask == None: c_mask = numpy.ones(c_image.shape, numpy.int8).flatten() else: c_mask = c_mask.astype(numpy.int8).flatten() _watershed.watershed( c_image.flatten(), pq, age, c, c_image.ndim, c_mask, numpy.array(c_image.shape, numpy.int32), c_output ) c_output = c_output.reshape(c_image.shape)[[slice(1, -1, None)] * image.ndim] try: return c_output.astype(markers.dtype) except: return c_output
def fast_watershed(image, markers, connectivity=None, offset=None, mask=None): """Return a matrix labeled using the watershed algorithm image - an array where the lowest value points are labeled first. markers - an array marking the basins with the values to be assigned in the label matrix. Zero means not a marker. This array should be of an integer type. connectivity - an array whose non-zero elements indicate neighbors for connection. Following the scipy convention, default is a one-connected array of the dimension of the image. offset - offset of the connectivity (one offset per dimension) mask - don't label points in the mask Returns a labeled matrix of the same type and shape as markers This implementation converts all arguments to specific, lowest common denominator types, then passes these to a C algorithm that operates as above. """ if connectivity == None: c_connectivity = scipy.ndimage.generate_binary_structure(image.ndim, 1) else: c_connectivity = numpy.array(connectivity, bool) if c_connectivity.ndim != image.ndim: raise ValueError, "Connectivity dimension must be same as image" if offset == None: if any([x % 2 == 0 for x in c_connectivity.shape]): raise ValueError, "Connectivity array must have an unambiguous center" # # offset to center of connectivity array # offset = numpy.array(c_connectivity.shape) / 2 # pad the image, markers, and mask so that we can use the mask to keep from running off the edges pads = offset def pad(im): new_im = numpy.zeros([i + 2 * p for i, p in zip(im.shape, pads)], im.dtype) new_im[[slice(p, -p, None) for p in pads]] = im return new_im if mask is not None: mask = pad(mask) else: mask = pad(numpy.ones(image.shape, bool)) image = pad(image) markers = pad(markers) c_image = rank_order(image)[0].astype(numpy.int32) c_markers = numpy.ascontiguousarray(markers, dtype=numpy.int32) if c_markers.ndim != c_image.ndim: raise ValueError,\ "markers (ndim=%d) must have same # of dimensions "\ "as image (ndim=%d)"%(c_markers.ndim, c_image.ndim) if not all([x == y for x, y in zip(c_markers.shape, c_image.shape)]): raise ValueError("image and markers must have the same shape") if mask != None: c_mask = numpy.ascontiguousarray(mask, dtype=bool) if c_mask.ndim != c_markers.ndim: raise ValueError, "mask must have same # of dimensions as image" if not all([x == y for x, y in zip(c_markers.shape, c_mask.shape)]): raise ValueError, "mask must have same shape as image" c_markers[numpy.logical_not(mask)] = 0 else: c_mask = None c_output = c_markers.copy() # # We pass a connectivity array that pre-calculates the stride for each # neighbor. # # The result of this bit of code is an array with one row per # point to be considered. The first column is the pre-computed stride # and the second through last are the x,y...whatever offsets # (to do bounds checking). c = [] image_stride = __get_strides_for_shape(image.shape) for i in range(numpy.product(c_connectivity.shape)): multiplier = 1 offs = [] indexes = [] ignore = True for j in range(len(c_connectivity.shape)): elems = c_image.shape[j] idx = (i / multiplier) % c_connectivity.shape[j] off = idx - offset[j] if off: ignore = False offs.append(off) indexes.append(idx) multiplier *= c_connectivity.shape[j] if (not ignore) and c_connectivity.__getitem__(tuple(indexes)): stride = numpy.dot(image_stride, numpy.array(offs)) offs.insert(0, stride) c.append(offs) c = numpy.array(c, numpy.int32) pq, age = __heapify_markers(c_markers, c_image) pq = numpy.ascontiguousarray(pq, dtype=numpy.int32) if numpy.product(pq.shape) > 0: # If nothing is labeled, the output is empty and we don't have to # do anything c_output = c_output.flatten() if c_mask == None: c_mask = numpy.ones(c_image.shape, numpy.int8).flatten() else: c_mask = c_mask.astype(numpy.int8).flatten() _watershed.watershed(c_image.flatten(), pq, age, c, c_image.ndim, c_mask, numpy.array(c_image.shape, numpy.int32), c_output) c_output = c_output.reshape(c_image.shape)[[slice(1, -1, None)] * image.ndim] try: return c_output.astype(markers.dtype) except: return c_output