def test_mismatched_array_markers(): S = np.zeros((10, 12), np.uint8) markers = np.zeros((8, 12), np.uint8) markers[2, 2] = 1 markers[6, 2] = 2 with pytest.raises(ValueError): mahotas.cwatershed(S, markers)
def test_float_input(): "[watershed]: Compare floating point input with integer input" f = np.random.random((128, 64)) f = mh.gaussian_filter(f, 8.) f = mh.gaussian_filter(f, 8.) markers, _ = mh.label(mh.regmin(f)) f = np.round(f * 2**30) wf = mh.cwatershed(f / 2**30., markers) w32 = mh.cwatershed(f.astype(np.int32), markers) assert (wf == w32).mean() > .999
def test_float_input(): "[watershed]: Compare floating point input with integer input" f = np.random.random((128,64)) f = mh.gaussian_filter(f, 8.) f = mh.gaussian_filter(f, 8.) markers,_ = mh.label(mh.regmin(f)) f = np.round(f * 2**30) wf = mh.cwatershed(f / 2**30., markers) w32 = mh.cwatershed(f.astype(np.int32), markers) assert (wf == w32).mean() > .999
def _mahotas_ws(self, NEED_WL): if NEED_WL: labels, wl = cwatershed(self.dist, self.markers, Bc=ndimage.generate_binary_structure(3, 3), return_lines=NEED_WL) else: labels = cwatershed(self.dist, self.markers, Bc=ndimage.generate_binary_structure(3, 3), return_lines=NEED_WL) return labels
def chromatids_elements(TopHatedChromosome): '''Take a High pass filtered (or top hat) image of a chromosome and label the chromatids elements ''' threshed = TopHatedChromosome > 0 #threshed = mh.open(threshed) labthres, _ = mh.label(threshed) labsz = mh.labeled.labeled_size(labthres) mh.labeled.remove_regions_where(labthres, labsz < 2, inplace=True) threshed = labthres > 0 skel2 = mh.thin(threshed) bp2 = branchedPoints(skel2, showSE=False) > 0 rem = np.logical_and(skel2, np.logical_not(bp2)) labskel, _ = mh.labeled.label(rem) #print labskel.dtype size_sk = mh.labeled.labeled_size(labskel) #print size_sk skelem = mh.labeled.remove_regions_where(labskel, size_sk < 4) distances = mh.stretch(mh.distance(threshed)) surface = (distances.max() - distances) chr_label = mh.cwatershed(surface, skelem) #print chr_label.dtype, type(chr_label) chr_label *= threshed #This convertion is important !! chr_label = chr_label.astype(np.intc) #------------------------------- mh.labeled.relabel(chr_label, inplace=True) labsize2 = mh.labeled.labeled_size(chr_label) cleaned = mh.labeled.remove_regions_where(chr_label, labsize2 < 8) mh.labeled.relabel(cleaned, inplace=True) return cleaned
def test_watershed2(): S = np.zeros((100,10), np.uint8) markers = np.zeros_like(S) markers[20,2] = 1 markers[80,2] = 2 W = mahotas.cwatershed(S, markers) assert np.all( (W == 1) | (W == 2) )
def test_run_distance(image, module, image_set, workspace): module.use_advanced.value = False module.operation.value = "Distance" module.x_name.value = "binary" module.y_name.value = "watershed" module.footprint.value = 3 data = image.pixel_data if image.multichannel: data = skimage.color.rgb2gray(data) threshold = skimage.filters.threshold_otsu(data) binary = data > threshold image_set.add( "binary", cellprofiler_core.image.Image( image=binary, convert=False, dimensions=image.dimensions ), ) module.run(workspace) original_shape = binary.shape distance = scipy.ndimage.distance_transform_edt(binary) distance = mahotas.stretch(distance) surface = distance.max() - distance if image.volumetric: footprint = numpy.ones((3, 3, 3)) else: footprint = numpy.ones((3, 3)) peaks = mahotas.regmax(distance, footprint) if image.volumetric: markers, _ = mahotas.label(peaks, numpy.ones((16, 16, 16))) else: markers, _ = mahotas.label(peaks, numpy.ones((16, 16))) expected = mahotas.cwatershed(surface, markers) expected = expected * binary expected = skimage.measure.label(expected) actual = workspace.get_objects("watershed") actual = actual.segmented numpy.testing.assert_array_equal(expected, actual)
def watershed(self, Ta=0): """ Identification of particles through inverted slope comparisons Parameters ----------- Ta : int Threshold value in which the particles will be identified by """ self.Ta = Ta dist = mh.distance(self.image > 0.05 * self.Ta) dist1 = dist dist = dist.max() - dist dist -= dist.min() # inverting color dist = dist / float(dist.ptp()) * 255 dist = dist.astype(np.uint8) self.dist = mh.stretch(dist, 0, 255) self.labels, self.n_particles = mh.label(self.image > 0.7 * self.Ta) thr = np.median(dist) # not accurate to particles detected(?) # but matches dist graph well thresh = (dist < thr) areas = 0.9 * mh.cwatershed(dist, self.labels) self.areas = areas * thresh return
def test_run_distance(image, module, image_set, workspace): module.operation.value = "Distance" module.x_name.value = "binary" module.y_name.value = "watershed" module.connectivity.value = 3 data = image.pixel_data if image.multichannel: data = skimage.color.rgb2gray(data) threshold = skimage.filters.threshold_otsu(data) binary = data > threshold image_set.add( "binary", cellprofiler.image.Image( image=binary, convert=False, dimensions=image.dimensions ) ) module.run(workspace) original_shape = binary.shape distance = scipy.ndimage.distance_transform_edt(binary) distance = mahotas.stretch(distance) surface = distance.max() - distance if image.volumetric: footprint = numpy.ones((3, 3, 3)) else: footprint = numpy.ones((3, 3)) peaks = mahotas.regmax(distance, footprint) if image.volumetric: markers, _ = mahotas.label(peaks, numpy.ones((16, 16, 16))) else: markers, _ = mahotas.label(peaks, numpy.ones((16, 16))) expected = mahotas.cwatershed(surface, markers) expected = expected * binary expected = skimage.measure.label(expected) actual = workspace.get_objects("watershed") actual = actual.segmented numpy.testing.assert_array_equal(expected, actual)
def roysam_watershed(dna,thresh=None,blur_factor=3): ''' Run watershed on mixed gradient & intensity image as suggested by Lin et al. -Input dna: DNA image thresh: Gray value threshold (default: computed using Murphy's RC) blur_factor: Blur factor (default: 3) REFERENCE Gang Lin, Umesh Adiga, Kathy Olson, John F. Guzowski, Carol A. Barnes, and Badrinath Roysam "A Hybrid 3-D Watershed Algorithm Incorporating Gradient Cues & Object Models for Automatic Segmentation of Nuclei in Confocal Image Stacks" Vol. 56A, No. 1, pp. 23-36 Cytometry Part A, November 2003. ''' if thresh is None: thresh = 'murphy_rc' M = (ndimage.gaussian_filter(dna,4) > thresholding.threshold(dna,thresh)) G = pymorph.gradm(dna) D = ndimage.distance_transform_edt(M) D *= np.exp(1-G/float(G.max())) T = ndimage.gaussian_filter(D.max() - D,blur_factor) if T.max() < 256: T = pymorph.to_uint8(T) else: T = pymorph.to_uint8(T*(256.0/T.max())) T *= M R = pymorph.regmin(T) R *= M R,N = ndimage.label(R) R[(R==0)&(M==0)] = N+1 W,WL = mahotas.cwatershed(T,R,return_lines=True) W *= M return W,WL
def test_watershed2(): S = np.zeros((100, 10), np.uint8) markers = np.zeros_like(S) markers[20, 2] = 1 markers[80, 2] = 2 W = mahotas.cwatershed(S, markers) assert np.all((W == 1) | (W == 2))
def watershed_adjusted_membranes(img_file_name, img_membrane_file_name): print 'reading image ' + img_file_name img = mahotas.imread(img_file_name) label_img = mahotas.imread(img_membrane_file_name) blur_img = scipy.ndimage.gaussian_filter(img, 1) #put boundaries as either extracellular/unlabeled space or gradient between two labeled regions into one image boundaries = label_img==0 boundaries[0:-1,:] = np.logical_or(boundaries[0:-1,:], np.diff(label_img, axis=0)!=0) boundaries[:,0:-1] = np.logical_or(boundaries[:,0:-1], np.diff(label_img, axis=1)!=0) #erode to be sure we include at least one membrane shrink_radius=4 y,x = np.ogrid[-shrink_radius:shrink_radius+1, -shrink_radius:shrink_radius+1] shrink_disc = x*x + y*y <= (shrink_radius ** 2) inside = mahotas.dilate(boundaries ==0, shrink_disc) #use watersheds to find the actual membranes (sort of) seeds = label_img.copy() seeds[np.nonzero(inside==0)] = 0 seeds,_ = mahotas.label(seeds == 0) wsImage = 255-np.uint8(scale_to_unit_interval(blur_img)*255) grow = mahotas.cwatershed(wsImage, seeds) membrane = np.zeros(img.shape, dtype=np.uint8) membrane[0:-1,:] = np.diff(grow, axis=0) != 0 membrane[:,0:-1] = np.logical_or(membrane[:,0:-1], np.diff(grow,axis=1) != 0) return np.uint8(membrane*255)
def ws_funkey(pmap, seed_method='grid', seed_distance=10, threshold=.5, use_affinities=False): """ """ if use_affinities: assert pmap.ndim == 4 aff_dim = np.argmin(pmap.shape)[0] assert aff_dim in (0, 3) # TODO is this ok ? pmap = pmap.copy() if aff_dim == 0: pmap = 1. - .5 * ( pmap[1] + pmap[2] ) # this assumes that the affinities are in the front channel else: pmap = 1. - .5 * ( pmap[..., 1] + pmap[..., 2] ) # this assumes that the affinities are in the front channel else: assert pmap.ndim == 3 fragments = np.zeros_like(pmap, dtype='uint32') start_id = 0 for z in xrange(depth): seeds, n_seeds = get_seeds(pmap[z], seed_method, seed_distance, threshold, start_id) fragments[z] = mahotas.cwatershed(pmap, seeds) start_id += n_seeds return fragments, n_seeds
def watershed(sample, surface, markers, fg, its=1): # compute watershed ws = mahotas.cwatershed(surface, markers) # write watershed directly logger.debug("%s: watershed output: %s %s %f %f", sample, ws.shape, ws.dtype, ws.max(), ws.min()) wsUI = ws.astype(np.uint16) # overlay fg and write wsFG = ws * fg logger.debug("%s: watershed (foreground only): %s %s %f %f", sample, wsFG.shape, wsFG.dtype, wsFG.max(), wsFG.min()) wsFGUI = wsFG.astype(np.uint16) wsFGUIdil = np.copy(wsFGUI) if its == 0: return wsUI, wsFGUI, wsFGUIdil for lbl in np.unique(wsFGUIdil): if lbl == 0: continue label_mask = wsFGUIdil == lbl dilated_label_mask = scipy.ndimage.binary_dilation(label_mask, iterations=its) wsFGUIdil[dilated_label_mask] = lbl return wsUI, wsFGUI, wsFGUIdil
def test_watershed_labeled(): import mahotas as mh S = np.array([[0, 0, 0, 0], [0, 1, 2, 1], [1, 1, 1, 1], [0, 0, 1, 0], [1, 1, 1, 1], [1, 2, 2, 1], [1, 1, 2, 2]]) M = np.array([[0, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 2, 0, 0], [0, 0, 0, 0]]) labeled = mh.cwatershed(S, M) sizes = mh.labeled.labeled_sum(S, labeled) assert len(sizes) == labeled.max() + 1
def watershed(probs, radius): if probs.ndim == 3: shed = np.zeros(probs.shape) for n in xrange(probs.shape[0]): sel = disk(radius) minima = mh.regmin(probs[n], Bc=sel) markers, nr_markers = mh.label(minima) shed[n] = mh.cwatershed(probs[n], markers) else: sel = disk(radius) minima = mh.regmin(probs, Bc=sel) markers, nr_markers = mh.label(minima) shed = mh.cwatershed(probs, markers) return shed
def watershed(stg, labeled): dna = Image.open(stg) dna = dna.convert('L') dna = np.array(dna) labeled = mh.cwatershed(dna.max() - dna, labeled) plt.imshow(labeled) plt.show() return
def test_mix_types(): f = np.zeros((64, 64), np.uint16) f += (np.indices(f.shape)[1]**2).astype(np.uint16) f += ((np.indices(f.shape)[0] - 23)**2).astype(np.uint16) markers = np.zeros((64, 64), np.int64) markers[32, 32] = 1 # Below used to force a crash (at least in debug mode) a, b = mahotas.cwatershed(f, markers, return_lines=1)
def _segment(histone): markers = np.zeros_like(histone) markers[16::32, 16::32] = 1 markers, _ = mh.label(markers) regions = mh.cwatershed(histone.max() - mh.gaussian_filter(histone, 1.2).astype(int), markers) sizes = mh.labeled.labeled_size(regions.astype(np.intc)) invalid, = np.where(sizes < 512) return mh.labeled.relabel(mh.labeled.remove_regions(regions.astype(np.intc), invalid))
def segment(img, T): binimg = (img > T) binimg = ndimage.median_filter(binimg, size=5) dist = mahotas.distance(binimg) dist = dist.astype(np.int32) maxima = pymorph.regmax(dist) maxima,_ = ndimage.label(maxima) return mahotas.cwatershed(dist.max() - dist, maxima)
def cast_test(dtype): St = S.astype(dtype) Mt = M.astype(int) W = mahotas.cwatershed(2 - St, Mt) assert sys.getrefcount(W) == 2 assert np.all(W == np.array([[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [2, 2, 1, 1], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2]]))
def cast_test(M, S, dtype): M = M.astype(dtype) S = S.astype(dtype) W = mahotas.cwatershed(2 - S, M) assert sys.getrefcount(W) == 2 assert np.all(W == np.array([[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [2, 2, 1, 1], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2]]))
def segmentCones(self): """Function to take regional maxima and segment the cones from them""" dist = mh.distance(self.orgImage > self.params['threshold']) dist = dist.max() - dist dist = dist = dist - dist.min() dist = dist/float(dist.ptp()) * 255 dist = dist.astype(np.uint8) self.params['cones'] = mh.cwatershed(dist, self.ConeCounts.Seeds)
def test_mix_types(): f = np.zeros((64,64), np.uint16) f += (np.indices(f.shape)[1]**2).astype(np.uint16) f += ((np.indices(f.shape)[0]-23)**2).astype(np.uint16) markers = np.zeros((64,64), np.int64) markers[32,32] = 1 # Below used to force a crash (at least in debug mode) a,b = mahotas.cwatershed(f, markers, return_lines=1)
def test_mix_types(): "[watershed regression]: Mixing types of surface and marker arrays used to cause crash" f = np.zeros((64, 64), np.uint16) f += (np.indices(f.shape)[1]**2).astype(np.uint16) f += ((np.indices(f.shape)[0] - 23)**2).astype(np.uint16) markers = np.zeros((64, 64), np.int64) markers[32, 32] = 1 # Below used to force a crash (at least in debug mode) a, b = mahotas.cwatershed(f, markers, return_lines=1)
def WatershedFillDoubleSizedOutlineArray(arr): '''Take an image array similar to the "Outlines" (but with lines=0, cells=1 instead) and turn it into a (double-sized) fully segmented image''' arrEdit = ndimage.measurements.label(arr)[0] arrDouble = shape_multiply(arrEdit,[2,2]).astype(np.uint16) arrInvDouble = (1-shape_multiply(arr,[2,2])).astype(np.uint16) waterArr = mahotas.cwatershed(arrInvDouble,arrDouble) return waterArr
def test_mix_types(): "[watershed regression]: Mixing types of surface and marker arrays used to cause crash" f = np.zeros((64,64), np.uint16) f += (np.indices(f.shape)[1]**2).astype(np.uint16) f += ((np.indices(f.shape)[0]-23)**2).astype(np.uint16) markers = np.zeros((64,64), np.int64) markers[32,32] = 1 # Below used to force a crash (at least in debug mode) a,b = mahotas.cwatershed(f, markers, return_lines=1)
def test_watershed(dtype): St = S.astype(dtype) Mt = M.astype(int) W = mahotas.cwatershed(2 - St, Mt) if hasattr(sys, 'getrefcount'): assert sys.getrefcount(W) == 2 assert np.all( W == np.array([[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [2, 2, 1, 1], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2]]))
def _segment(histone): markers = np.zeros_like(histone) markers[16::32, 16::32] = 1 markers, _ = mh.label(markers) regions = mh.cwatershed( histone.max() - mh.gaussian_filter(histone, 1.2).astype(int), markers) sizes = mh.labeled.labeled_size(regions.astype(np.intc)) invalid, = np.where(sizes < 512) return mh.labeled.relabel( mh.labeled.remove_regions(regions.astype(np.intc), invalid))
def create_random_segmentation(seed): np.random.seed(seed) peaks = np.random.random(size).astype(np.float32) peaks = gaussian_filter(peaks, sigma=5.0) max_filtered = maximum_filter(peaks, 10) maxima = max_filtered == peaks seeds, n = mahotas.label(maxima) print("Creating segmentation with %d segments" % n) return mahotas.cwatershed(1.0 - peaks, seeds).astype(np.uint64)
def provide(self, request): voxel_size = self.spec[self.raw].voxel_size shape = gp.Coordinate((1, ) + request[self.raw].roi.get_shape()) noise = np.abs(np.random.randn(*shape)) smoothed_noise = gaussian_filter(noise, sigma=self.smoothness) seeds = np.zeros(shape, dtype=int) for i in range(self.n_objects): if i == 0: num_points = 100 else: num_points = self.points_per_skeleton points = np.stack( [ np.random.randint(0, shape[dim], num_points) for dim in range(3) ], axis=1, ) tree = skelerator.Tree(points) skeleton = skelerator.Skeleton(tree, [1, 1, 1], "linear", generate_graph=False) seeds = skeleton.draw(seeds, np.array([0, 0, 0]), i + 1) seeds[maximum_filter(seeds, size=4) != seeds] = 0 seeds_dt = distance_transform_edt(seeds == 0) + 5.0 * smoothed_noise gt_data = cwatershed(seeds_dt, seeds).astype(np.uint64)[0] - 1 labels = np.unique(gt_data) raw_data = np.zeros_like(gt_data, dtype=np.uint8) value = 0 for label in labels: raw_data[gt_data == label] = value value += 255.0 / self.n_objects spec = request[self.raw].copy() spec.voxel_size = (1, 1) raw = gp.Array(raw_data, spec) spec = request[self.gt].copy() spec.voxel_size = (1, 1) gt_crop = (request[self.gt].roi - request[self.raw].roi.get_begin()) / voxel_size gt_crop = gt_crop.to_slices() gt = gp.Array(gt_data[gt_crop], spec) batch = gp.Batch() batch[self.raw] = raw batch[self.gt] = gt return batch
def cast_test(M, S, dtype): M = M.astype(dtype) S = S.astype(dtype) W = mahotas.cwatershed(2 - S, M) assert sys.getrefcount(W) == 2 assert np.all( W == np.array( [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [2, 2, 1, 1], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2]] ) )
def get_watershed(dn): # otsu1 = otsu(dn, 1) thr = adaptive_thr(dn, 63, -10) cmp = np.array(get_network_component(thr), np.uint8) cmp = cv2.morphologyEx(cmp, cv2.MORPH_CLOSE, kernel=k5x5, iterations=2) markers, n_markers = get_markers(1 - cmp) n_cells = remove_small_components(markers, n_markers) W = mh.cwatershed(dn, markers) return W - 1, n_cells + 1
def sobel_segment(img): vsobel = np.array([ [1,2,1], [0,0,0], [-1,-2,-1]]) sobel = ndimage.convolve(img.astype(float),vsobel)**2 hsobel = vsobel.T sobel += ndimage.convolve(img.astype(float), hsobel)**2 imgf = ndimage.gaussian_filter(img,2) maxima,nmaxima = ndimage.label(pymorph.regmax(imgf)) overseg = mahotas.cwatershed(sobel.astype(np.uint32), maxima) return overseg
def compute_vertex_areas(input_map, adj_list): '''Computes the image map containing pixel-vertex relation''' surface = numpy.ones(input_map.shape, dtype=numpy.uint32) markers = numpy.zeros(input_map.shape, dtype=numpy.uint32) vertex_list = [] for index, (x, y) in enumerate(adj_list.iterkeys()): markers[x, y] = index + 1 vertex_list.append((x, y)) return mahotas.cwatershed(surface, markers), vertex_list
def cast_test(dtype): St = S.astype(dtype) Mt = M.astype(int) W = mahotas.cwatershed(2-St,Mt) assert sys.getrefcount(W) == 2 assert np.all(W == np.array([[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [2, 2, 1, 1], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2]]))
def watershedSegment(image, diskSize=20): gradmag = gradientMagnitudue(image) ## compute foreground markers # open image to create flat regions at cell centers se_disk = pymorph.sedisk(diskSize) image_opened = mahotas.open(image, se_disk); # define foreground markers as regional maxes of cells # this step is slow! foreground_markers = mahotas.regmax(image_opened) ## compute background markers # Threshold the image, cast it to the right datatype, and then calculate the distance image image_black_white = image_opened > mahotas.otsu(image_opened) image_black_white = image_black_white.astype('uint16') # note the inversion here- a key difference from the matlab algorithm # matlab distance is to nearest non-zero pixel # python distance is to nearest 0 pixel image_distance = pymorph.to_uint16(nd.distance_transform_edt(np.logical_not(image_black_white))) eight_conn = pymorph.sebox() distance_markers = mahotas.label(mahotas.regmin(image_distance, eight_conn))[0] image_dist_wshed, image_dist_wshed_lines =mahotas.cwatershed(image_distance, distance_markers, eight_conn, return_lines=True) background_markers = image_distance_watershed_lines - image_black_white all_markers = np.logical_or(foreground_markers, background_markers) # impose a min on the gradient image. assumes int64 gradmag2 = imimposemin(gradmag.astype(int), all_markers, eight_conn) # call watershed segmented_cells, segmented_cell_lines = mahotas.cwatershed(gradmag2, mahotas.label(all_markers)[0], eight_conn, return_lines=True) # seperate watershed regions segmented_cells[gradientMagnitudue(segmented_cells) > 0] = 0 return segmented_cells > 0, segmented_cells
def split(image, array, label): ''' ''' large_label = Util.threshold(array, label) label_bbox = mh.bbox(large_label) label = large_label[label_bbox[0]:label_bbox[1], label_bbox[2]:label_bbox[3]] image = image[label_bbox[0]:label_bbox[1], label_bbox[2]:label_bbox[3]] # # smooth the image # image = mh.gaussian_filter(image, 3.5) grad_x = np.gradient(image)[0] grad_y = np.gradient(image)[1] grad = np.add(np.abs(grad_x), np.abs(grad_y)) #grad = np.add(np.abs(grad_x), np.abs(grad_y)) grad -= grad.min() grad /= grad.max() grad *= 255 grad = grad.astype(np.uint8) #imshow(grad) # we need 4 labels as output max_label = 0 #while max_label!=3: coords = zip(*np.where(label == 1)) seed1 = random.choice(coords) seed2 = random.choice(coords) seeds = np.zeros(label.shape, dtype=np.uint64) seeds[seed1] = 1 seeds[seed2] = 2 # imshow(seeds) for i in range(10): seeds = mh.dilate(seeds) ws = mh.cwatershed(grad, seeds) ws[label == 0] = 0 ws_relabeled = skimage.measure.label(ws.astype(np.uint64)) max_label = ws_relabeled.max() #print max_label large_label = np.zeros(large_label.shape, dtype=np.uint64) large_label[label_bbox[0]:label_bbox[1], label_bbox[2]:label_bbox[3]] = ws return large_label
def watershed_single_channel(np_array, threshold=10, blur_factor=9, max_bb_size=13000, min_bb_size=1000, footprint=10): # INPUT: # np_array: numpy image of single channel # threshold: minimum value to be analysed # blur_factor: gaussian blur. some blur is good. too much is bad. too little is bad too. # max_bb_size: set maximum size for a bounding box. # min_bb_size: set minimum size for a bounding box. # footprint: box of size footprint x footprint used to find regions of maximum intensity. # OUTPUT: # return: array of bounding boxes for the channel image given # NOTE: input values should be tuned. this alg is useless if input arguments are not optimized... right now its by hand. otherwise just leave them # nuclear is a blured version of origional image nuclear = mh.gaussian_filter(np_array, blur_factor) # calculate a minimum threshold using otsu method otsu_thresh = threshold_otsu(nuclear) # determine minimum threshold from otsu and input argument. if little/no signal in image; otsu value can be way too low set_thresh = None if threshold>otsu_thresh: set_thresh = threshold else: set_thresh = otsu_thresh # set values lower than set_thresh to zero index_otsu = nuclear < set_thresh nuclear[index_otsu] = 0 # determine areas of maximum intensity and the distance between them thresh = (nuclear > nuclear.mean()) dist = mh.stretch(mh.distance(thresh)) Bc = np.ones((footprint, footprint)) # the code the generate region_props from watersheding alg. maxima = mh.morph.regmax(dist, Bc=Bc) spots, n_spots = mh.label(maxima, Bc=Bc) sizes = mh.labeled.labeled_size(spots) too_big = np.where(sizes > max_bb_size) spots = mh.labeled.remove_regions(spots, too_big) spots = mh.labeled.remove_bordering(spots) spots, n_left = mh.labeled.relabel(spots) surface = (dist.max() - dist) areas = mh.cwatershed(surface, spots) areas *= thresh # get list of region properties from watershed. allot of information in region_props. allot of which is inaccurate. NEVER TRUST REGIONPROPS! region_props=regionprops(areas,intensity_image=nuclear) # generate array of bounding boxes from measured region properties. call bbs_from_rprops() watershed_bb_array = bbs_from_rprops(region_props, max_bb_size, min_bb_size) return(watershed_bb_array)
def nuclei_regions(comp_map): """ NUCLEI_REGIONS: extract "support regions" for nuclei. This function expects as input a "tissue components map" (as returned, for example, by segm.tissue_components) where values of 1 indicate pixels having a color corresponding to nuclei. It returns a set of compact support regions corresponding to the nuclei. :param comp_map: numpy.ndarray A mask identifying different tissue components, as obtained by classification in RGB space. The value 0 See segm.tissue.tissue_components() :return: """ # Deprecated:... # img_hem, _ = rgb2he(img0, normalize=True) # img_hem = denoise_tv_bregman(img_hem, HE_OPTS['bregm']) # Get a mask of nuclei regions by unsupervised clustering: # Vector Quantization: background, mid-intensity Hem and high intensity Hem # -train the quantizer for 3 levels # vq = KMeans(n_clusters=3) # vq.fit(img_hem.reshape((-1,1))) # -the level of interest is the brightest: # k = np.argsort(vq.cluster_centers_.squeeze())[2] # mask_hem = (vq.labels_ == k).reshape(img_hem.shape) # ...end deprecated # Final mask: mask = (comp_map == 1) # use the components classified by color # mask = morph.closing(mask, selem=HE_OPTS['strel1']) # mask = morph.opening(mask, selem=HE_OPTS['strel1']) # morph.remove_small_objects(mask, in_place=True) # mask = (mask > 0) mask = mahotas.close_holes(mask) morph.remove_small_objects(mask, in_place=True) dst = mahotas.stretch(mahotas.distance(mask)) Bc=np.ones((9,9)) lmax = mahotas.regmax(dst, Bc=Bc) spots, _ = mahotas.label(lmax, Bc=Bc) regions = mahotas.cwatershed(lmax.max() - lmax, spots) * mask return regions # end NUCLEI_REGIONS
def Watershed_MRF(Iin, I_MM): # ------------------------------------------------------------------------------------ # # # # This algorithm is implemented by Oren Kraus on July 2013 # # # # ------------------------------------------------------------------------------------ # Fgm = (I_MM > 0) SdsLab = mh.label(I_MM == 2)[0] SdsSizes = mh.labeled.labeled_size(SdsLab) too_small_Sds = np.where(SdsSizes < 30) SdsLab = mh.labeled.remove_regions(SdsLab, too_small_Sds) Sds = SdsLab > 0 se2 = nd.generate_binary_structure(2, 2).astype(np.int) dilatedNuc = nd.binary_dilation(Sds, se2) Fgm = (dilatedNuc.astype(np.int) + Fgm.astype(np.int)) > 0 FgmLab = mh.label(Fgm)[0] FgmSizes = mh.labeled.labeled_size(FgmLab) too_small_Fgm = np.where(FgmSizes < 30) FgmLab = mh.labeled.remove_regions(FgmLab, too_small_Fgm) Fgm = FgmLab > 0 se3 = nd.generate_binary_structure(2, 1).astype(np.int) Fgm = nd.binary_erosion(Fgm, structure=se3) Fgm_Lab, Fgm_num = nd.measurements.label(Fgm) Nuc_Loc_1d = np.where(np.ravel(Sds == 1))[0] for Lab in range(Fgm_num): Fgm_Loc_1d = np.where(np.ravel(Fgm_Lab == Lab))[0] if not bool((np.intersect1d(Fgm_Loc_1d, Nuc_Loc_1d)).any()): Fgm[Fgm_Lab == Lab] = 0 Im_ad = (np.double(Iin) * 2 ** 16 / Iin.max()).round() Im_ad = nd.filters.gaussian_filter(Im_ad, .5, mode='constant') Im_ad_comp = np.ones(Im_ad.shape) Im_ad_comp = Im_ad_comp * Im_ad.max() Im_ad_comp = Im_ad_comp - Im_ad mask = ((Sds == 1).astype(np.int) + (Fgm == 0).astype(np.int)) mask = nd.label(mask)[0] LabWater = mh.cwatershed(np.uint16(Im_ad_comp), mask) back_loc_1d = np.where(np.ravel(Fgm == 0))[0] for Lab in range(2, LabWater.max()): cell_Loc_1d = np.where(np.ravel(LabWater == Lab))[0] if bool((np.intersect1d(cell_Loc_1d, back_loc_1d)).any()): LabWater[LabWater == Lab] = 1 return LabWater
def GradBasedSegmentation(im): blur=nd.gaussian_filter(im, 16) rmax = pymorph.regmax(blur) T = mahotas.thresholding.otsu(blur) bImg0=im>T #bImg01=nd.binary_closing(bImg0,iterations=2) bImg01=pymorph.close(bImg0, pymorph.sedisk(3)) bImg=pymorph.open(bImg01, pymorph.sedisk(4)) #bImg=nd.binary_opening(bImg01,iterations=3) b=pymorph.edgeoff(bImg) d=distanceTranform(b) seeds,nr_nuclei = nd.label(rmax) lab=mahotas.cwatershed(d,seeds) return lab
def GradBasedSegmentation(im): blur = nd.gaussian_filter(im, 16) rmax = pymorph.regmax(blur) T = mahotas.thresholding.otsu(blur) bImg0 = im > T # bImg01=nd.binary_closing(bImg0,iterations=2) bImg01 = pymorph.close(bImg0, pymorph.sedisk(3)) bImg = pymorph.open(bImg01, pymorph.sedisk(4)) # bImg=nd.binary_opening(bImg01,iterations=3) b = pymorph.edgeoff(bImg) d = distanceTranform(b) seeds, nr_nuclei = nd.label(rmax) lab = mahotas.cwatershed(d, seeds) return lab
def random_watershed(array, speed_image, border_seeds=False, erode=False): ''' ''' copy_array = np.array(array, dtype=np.bool) if erode: for i in range(10): copy_array = mh.erode(copy_array) seed_array = np.array(copy_array) if border_seeds: seed_array = mh.labeled.border(copy_array, 1, 0, Bc=mh.disk(7)) coords = zip(*np.where(seed_array==1)) if len(coords) == 0: # print 'err' return np.zeros(array.shape) seed1_ = None seed2_ = None max_distance = -np.inf for i in range(10): seed1 = random.choice(coords) seed2 = random.choice(coords) d = distance.euclidean(seed1, seed2) if max_distance < d: max_distance = d seed1_ = seed1 seed2_ = seed2 seeds = np.zeros(array.shape, dtype=np.uint8) seeds[seed1_[0], seed1_[1]] = 1 seeds[seed2_[0], seed2_[1]] = 2 for i in range(8): seeds = mh.dilate(seeds) # Util.view(seeds,large=True) # print speed_image.shape, seeds.shape ws = mh.cwatershed(speed_image, seeds) ws[array == 0] = 0 return ws
def watershed(surface, markers, fg): # compute watershed ws = mahotas.cwatershed(surface, markers) # write watershed directly logger.debug("watershed output: %s %s %f %f", ws.shape, ws.dtype, ws.max(), ws.min()) # overlay fg and write wsFG = ws * fg logger.debug("watershed (foreground only): %s %s %f %f", wsFG.shape, wsFG.dtype, wsFG.max(), wsFG.min()) wsFGUI = wsFG.astype(np.uint16) return wsFGUI
def ConvertOutlinesToWatershed(origArr,outlines,useDilate=False,structure=[[0,1,0],[1,1,1],[0,1,0]]): if useDilate: outlines=ndimage.morphology.binary_dilation(origArr,structure=structure) labels = ndimage.label(1-outlines)[0] wh=np.where(labels==0) labels[wh]=-1 labels+=1 labels = labels.astype(np.uint16) labels[0]=1 labels[-1]=1 labels[:,0]=1 labels[:,-1]=1 water = mahotas.cwatershed(origArr,labels) return water
def watershed(affs, seed_method, boundary_thres=0.5, label_nb=None, seg_bg=True): fragments = np.zeros_like(affs[0]).astype(np.uint64) depth = fragments.shape[0] next_id = 0 for z in range(depth): affs_xy = 1.0 - 0.5 * (affs[1, z] + affs[2, z]) seeds, num_seeds = get_seeds(affs_xy, next_id=next_id, method=seed_method, \ boundary_thres=boundary_thres, label_nb = label_nb) fragments[z] = mahotas.cwatershed(affs_xy, seeds) next_id += num_seeds return fragments
def test_watershed_labeled(): import mahotas as mh S = np.array([[0, 0, 0, 0], [0, 1, 2, 1], [1, 1, 1, 1], [0, 0, 1, 0], [1, 1, 1, 1], [1, 2, 2, 1], [1, 1, 2, 2]]) M = np.array([ [0, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 2, 0, 0], [0, 0, 0, 0], ]) labeled = mh.cwatershed(S, M) sizes = mh.labeled.labeled_sum(S, labeled) assert len(sizes) == labeled.max() + 1
def watershed_segment(img, mode='direct', thresholding=None, min_obj_size=None, **kwargs): ''' segment_watershed(img, mode='direct', thresholding=None, min_obj_size=None, **kwargs) Segment using traditional watershed Parameters ---------- * img: a pyslic.Image. The algorithm operates on the dna channel. * mode: 'direct' or 'gradient': whether to use the image or the gradient of the image * thresholding: how to threshold the smoothed image (default: None, no thresholding) * min_obj_size: minimum object size. This is slightly different than post-filtering for minimum object size as it fill those holes with a second watershed pass as opposed to having an image with holes * smoothing: whether to smooth (default: True) * smooth_gamma: Size of Gaussian for blurring, in pixels (default: 12) ''' assert mode in ('direct','gradient'), "segment_watershed: mode '%s' not understood" % mode with loadedimage(img): dna = img.get('dna') if kwargs.get('smoothing',True): dnaf = ndimage.gaussian_filter(dna, kwargs.get('smooth_gamma',12)) else: dnaf = dna rmax = pymorph.regmax(dnaf) rmax_L,_ = ndimage.label(rmax) if mode == 'direct': watershed_img = dna.max()-dna elif mode == 'gradient': dnag = pymorph.gradm(dna) watershed_img = dnag.max()-dnag water = mahotas.cwatershed(watershed_img,rmax_L) if thresholding is not None: T = threshold(dnaf,thresholding) water *= (dnaf >= T) if min_obj_size is not None: oid = 1 while oid <= water.max(): if (water == oid).sum() < min_obj_size: water[water == oid] =0 water[water > oid] -= 1 else: oid += 1 return water
def _segment(cell): # takes a numpy array of a microscopy # segments it based on filtering the image then applying a distance transform and # a watershed method to get the proper segmentation import mahotas as mh filt_cell = mh.gaussian_filter(cell, 2) T = mh.thresholding.otsu((np.rint(filt_cell).astype('uint8'))) dist = mh.stretch(mh.distance(filt_cell > T)) Bc = np.ones((3,3)) rmax = mh.regmin((dist)) rmax = np.invert(rmax) labels, num_cells = mh.label(rmax, Bc) surface = (dist.max() - dist) areas = mh.cwatershed(dist, labels) areas *= T return areas
def segment(fname): dna = mh.imread(fname) dna = dna[:,:,0] sigma = 12. dnaf = mh.gaussian_filter(dna, sigma) T_mean = dnaf.mean() bin_image = dnaf > T_mean labeled, nr_objects = mh.label(bin_image) maxima = mh.regmax(mh.stretch(dnaf)) maxima = mh.dilate(maxima, np.ones((5,5))) maxima,_ = mh.label(maxima) dist = mh.distance(bin_image) dist = 255 - mh.stretch(dist) watershed = mh.cwatershed(dist, maxima) watershed *= bin_image return watershed
def create_segmentation_from_seeds( input_image, seed_image ): """Create a Seedwater style segmentation from a bunch of seeds in an image. Parameters ---------- input_image : nd_array image that should be segmented seed_image : nd_array image that contains the seeds Returns ------- segmentation : nd_array segmented image represented as 16bit integer image """ segmented_image = mahotas.cwatershed( input_image, seed_image ) segmented_image_as_16_bit = np.array( segmented_image, dtype = 'uint16' ) return segmented_image_as_16_bit
def test_overflow(): '''Test whether we can force an overflow in the output of cwatershed This was reported as issue #41 on github: https://github.com/luispedro/mahotas/issues/41 ''' f = np.random.random((128,64)) f *= 255 f = f.astype(np.uint8) for max_n in [127, 240, 280]: markers = np.zeros(f.shape, np.int) for i in range(max_n): while True: a = np.random.randint(f.shape[0]) b = np.random.randint(f.shape[1]) if markers[a,b] == 0: markers[a,b] = i + 1 break r = mh.cwatershed(f, markers) assert markers.max() == max_n assert r.max() == max_n
boundaries = label_img==0; boundaries[0:-1,:] = np.logical_or(boundaries[0:-1,:], diff(label_img, axis=0)!=0); boundaries[:,0:-1] = np.logical_or(boundaries[:,0:-1], diff(label_img, axis=1)!=0); # erode to be sure we include at least one membrane inside = mahotas.erode(boundaries == 0, shrink_disc) #display = input_img.copy() #display[np.nonzero(inside)] = 0 #figure(figsize=(20,20)) #imshow(display, cmap=cm.gray) seeds = label_img.copy() seeds[np.nonzero(inside==0)] = 0 grow = mahotas.cwatershed(255-blur_img, seeds) membrane = np.zeros(input_img.shape, dtype=uint8) membrane[0:-1,:] = diff(grow, axis=0) != 0; membrane[:,0:-1] = np.logical_or(membrane[:,0:-1], diff(grow, axis=1) != 0); #display[np.nonzero(membrane)] = 2 #figure(figsize=(20,20)) #imshow(display, cmap=cm.gray) # erode again to avoid all membrane non_membrane = mahotas.erode(inside, shrink_disc) if mask is None: mask = ones(input_img.shape, dtype=uint8) mask[:min_border,:] = 0;
valid_ids = np.nonzero(compressed_id_map)[0] compressed_id_map[valid_ids] = np.arange(1, len(valid_ids) + 1, dtype=np.uint32) print "Compressing {0} ids down to {1}.".format(compressed_id_map.shape[0], len(valid_ids)) for file in files: original_input_ids_name = file original_ids = load_id_image(original_input_ids_name) ## Grow regions until there are no boundaries ## Method 4 - watershed original_ids = mahotas.cwatershed( np.zeros(original_ids.shape, dtype=np.uint32), original_ids, return_lines=False ) if compress_ids: original_ids = compressed_id_map[original_ids] # boundaries = original_ids == 0 # boundary_indices = np.nonzero(boundaries) # grow_count = 0 # while len(boundary_indices[0]) > 0: # ## Method 1 - dilate (slow) # #original_ids[boundary_indices] = mahotas.dilate(original_ids)[boundary_indices] - 1 # ## Method 2 - conditional dilate (doesn't work) # #original_ids[boundary_indices] = mahotas.cdilate(original_ids, boundaries==0)[boundary_indices] - 1
with timer.Timer("maxflow"): print "Flow is {0}".format(flow_graph.maxflow()) labels = flow_graph.what_segment_vectorized() labels = labels.reshape(imshape) with timer.Timer("close/open"): labels = mahotas.morph.close(labels.astype(np.bool), disc) labels = mahotas.morph.open(labels.astype(np.bool), disc) ## Use blurred probabilities and watershed instead of region growing with timer.Timer("label2"): seeds,_ = mahotas.label(labels==1) with timer.Timer("watershed"): ws = mahotas.cwatershed(blur_prob, seeds) with timer.Timer("gradient2"): dx, dy = np.gradient(ws) ws_boundary = np.logical_or(dx!=0, dy!=0) ## Identify possible extra-cellular space - distance method #extra_cellular = np.logical_and(mahotas.distance(labels==0) > 100, seeds == np.min(seeds)) #extra_cellular = mahotas.morph.close(extra_cellular.astype(np.bool), disc) #extra_cellular = mahotas.morph.open(extra_cellular.astype(np.bool), disc) #extra_cellular_indices = np.nonzero(extra_cellular) ## Identify possible extra-cellular space - minima method with timer.Timer("extra_cellular"): with timer.Timer(" (sub)min"): rmin = mahotas.regmin(blur_prob, min_disc)
nlabels = nlabels + 1 if nlabels <= 1: print "Cleanup only found {0} segment - nothing to do.".format(nlabels) clean_vol = label_vol else: packed_vol = np.reshape(packed_vol, label_vol.shape) print "Cleanup starting with {0} segments.".format(nlabels) # Grow labels so there are no boundary pixels if has_boundaries: for image_i in range(packed_vol.shape[2]): label_image = packed_vol[:,:,image_i] packed_vol[:,:,image_i] = mahotas.cwatershed(np.zeros(label_image.shape, dtype=np.uint32), label_image, return_lines=False) if Debug: from libtiff import TIFF for image_i in range(packed_vol.shape[2]): tif = TIFF.open('preclean_z{0:04}.tif'.format(image_i), mode='w') tif.write_image(np.uint8(packed_vol[:, :, image_i] * 13 % 251)) # Determine label adjicency and sizes borders = np.zeros(packed_vol.shape, dtype=np.bool) # Code currently only supports a 3d volume assert(packed_vol.ndim == 3) with timer.Timer("adjicency matrix construction"):
def test_mismatched_array_markers(): S = np.zeros((10,12), np.uint8) markers = np.zeros((8,12), np.uint8) markers[2,2] = 1 markers[6,2] = 2 mahotas.cwatershed(S, markers)