def membrane_image_segmentation(img, gaussian_sigma=0.75, h_min=None, segmentation_gaussian_sigma=0.5, volume_threshold=None): voxelsize = np.array(img.voxelsize) if h_min is None: h_min = 2 if img.dtype==np.uint8 else 1000 smooth_image = nd.gaussian_filter(img, sigma=gaussian_sigma / voxelsize).astype(img.dtype) smooth_img = SpatialImage(smooth_image, voxelsize=voxelsize) ext_img = h_transform(smooth_img, h=h_min, method='min') seed_img = region_labeling(ext_img, low_threshold=1, high_threshold=h_min, method='connected_components') seg_smooth_image = nd.gaussian_filter(img, sigma=segmentation_gaussian_sigma / voxelsize).astype(img.dtype) seg_smooth_img = SpatialImage(seg_smooth_image, voxelsize=voxelsize) seg_img = segmentation(seg_smooth_img, seed_img, control='first', method='seeded_watershed') if volume_threshold is not None: seg_volumes = dict(zip(np.arange(seg_img.max()) + 1, nd.sum(np.prod(voxelsize) * np.ones_like(seg_img), seg_img, index=np.arange(seg_img.max()) + 1))) labels_to_remove = np.array(list(seg_volumes.keys()))[np.array(list(seg_volumes.values())) > volume_threshold] print("--> Removing too large labels :", labels_to_remove) for l in labels_to_remove: seg_img[seg_img == l] = 1 return seg_img
def test_plugin(): im = imread(data_path('segmentation_src.inr')) im_ref = imread(data_path('segmentation_seeded_watershed.inr')) smooth_img = linear_filtering(im, std_dev=2.0, method='gaussian_smoothing') regext_img = h_transform(smooth_img, h=5, method='h_transform_min') conn_img = region_labeling(regext_img, low_threshold=1, high_threshold=3, method='connected_components') wat_img = segmentation(smooth_img, conn_img, control='first', method='seeded_watershed') np.testing.assert_array_equal(wat_img, im_ref)
# ext_img = h_transform(asf_img, h=h_min, method='h_transform_min') smooth_img = linear_filtering(img2seg, std_dev=std_dev, method='gaussian_smoothing') ext_img = h_transform(smooth_img, h=h_min, method='h_transform_min') seed_img = region_labeling(ext_img, low_threshold=1, high_threshold=h_min, method='connected_components') print "Detected {} seeds!".format(len(np.unique(seed_img))) print "\n - Performing seeded watershed segmentation..." from timagetk.plugins import segmentation std_dev = 1.0 # smooth_img = linear_filtering(img2seg, std_dev=std_dev, method='gaussian_smoothing') seg_im = segmentation(smooth_img, seed_img, method='seeded_watershed') seg_im[seg_im == 0] = back_id # world.add(seg_im, 'seg', colormap='glasbey', alphamap='constant') from timagetk.io import imsave imsave(seg_img_fname, seg_im) else: from timagetk.io import imread seg_im = imread(seg_img_fname) ############################################################################### # -- MAYAVI VISU: ############################################################################### # from mayavi import mlab # from os.path import splitext # import numpy as np
method='h_transform_min') print " --> Components labelling..." con_img = region_labeling(ext_img, low_threshold=1, high_threshold=h_min, method='connected_components') nb_connectec_comp = len(np.unique(con_img.get_array())) print nb_connectec_comp, "seeds detected!" if nb_connectec_comp <= 3: print "Not enough seeds, aborting!" continue # world.add(con_img, 'labelled_seeds', voxelsize=vxs) del ext_img print " --> Seeded watershed..." seg_im = segmentation(img, con_img, method='seeded_watershed') # - Performs topomesh creation from detected seeds: print " --> Analysing segmented image...", img_graph = graph_from_image( seg_im, background=1, spatio_temporal_properties=['barycenter', 'L1'], ignore_cells_at_stack_margins=False) print img_graph.nb_vertices( ), "seeds extracted by 'graph_from_image'!" # -- Create a topomesh from 'seed_positions': print " --> Topomesh creation..." seed_positions = { v: img_graph.vertex_property('barycenter')[v] * microscope_orientation
largest_component = (np.arange(n_components) + 1)[np.argmax(components_area)] background_img = ( connected_background_components == largest_component).astype(np.uint16) # ---- Finaly add the background and make a SpatialImage: seed_img[background_img == 1] = 1 del smooth_img_bck, background_img seed_img = SpatialImage(seed_img, voxelsize=voxelsize) # world.add(seed_img,"seed_image", colormap="glasbey", alphamap="constant",voxelsize=microscope_orientation*voxelsize, bg_id=0) # -- Performs automatic seeded watershed using previously created seed image: print "\n# - Seeded watershed using seed EXPERT seed positions..." smooth_img = linear_filtering(img, std_dev=std_dev, method='gaussian_smoothing') seg_im = segmentation(smooth_img, seed_img) # Use largest bounding box to determine background value: background = get_background_value(seg_im, microscope_orientation) print "Detected background value:", background # world.add(seg_im,"seg_image", colormap="glasbey", alphamap="constant",voxelsize=microscope_orientation*voxelsize, bg_id=background) # -- Create a vertex_topomesh from detected cell positions: print "\n# - Extracting 'barycenter' & 'L1' properties from segmented image..." # --- Compute 'L1' and 'barycenter' properties using 'graph_from_image' img_graph = graph_from_image( seg_im, background=background, spatio_temporal_properties=['L1', 'barycenter'], ignore_cells_at_stack_margins=True) print img_graph.nb_vertices(), " cells detected" print "\n# - Creating a vertex_topomesh..."
components_area = nd.sum(np.ones_like(connected_background_components), connected_background_components, index=np.arange(n_components) + 1) largest_component = (np.arange(n_components) + 1)[np.argmax(components_area)] background_img = (connected_background_components == largest_component).astype( np.uint16) con_img[background_img == 1] = 1 del smooth_img_bck, background_img con_img = SpatialImage(con_img, voxelsize=voxelsize) # world.add(con_img,"seed_image", colormap="glasbey", alphamap="constant",voxelsize=microscope_orientation*voxelsize, bg_id=0) # -- Performs automatic seeded watershed using previously created seed image: smooth_img = linear_filtering(img, std_dev=std_dev, method='gaussian_smoothing') seg_im = segmentation(smooth_img, con_img) # world.add(seg_im,"seg_image", colormap="glasbey", alphamap="constant",voxelsize=microscope_orientation*voxelsize) # -- Create a vertex_topomesh from detected cell positions: # --- Get cell barycenters positions: img_graph = graph_from_image(seg_im, background=1, spatio_temporal_properties=['L1', 'barycenter'], ignore_cells_at_stack_margins=True) print img_graph.nb_vertices(), " cells detected" vtx = list(img_graph.vertices()) labels = img_graph.vertex_property('labels') margin_expert_cells = [ c for c in expert_topomesh.wisps(0) if not c in [labels[v] for v in vtx] ] for c in margin_expert_cells:
from timagetk.plugins import labels_post_processing except ImportError: raise ImportError('Import Error') out_path = './results/' # to save results # we consider an input image # SpatialImage instance input_img = imread(data_path('input.tif')) # optional denoising block smooth_img = linear_filtering(input_img, std_dev=2.0, method='gaussian_smoothing') asf_img = morphology(smooth_img, max_radius=3, method='co_alternate_sequential_filter') ext_img = h_transform(asf_img, h=150, method='h_transform_min') con_img = region_labeling(ext_img, low_threshold=1, high_threshold=150, method='connected_components') seg_img = segmentation(smooth_img, con_img, control='first', method='seeded_watershed') # optional post processig block pp_img = labels_post_processing(seg_img, radius=1, iterations=1, method='labels_erosion') res_name = 'example_segmentation.tif' imsave(out_path+res_name, pp_img)
def seg_pipe(img2seg, h_min, img2sub=None, iso=True, equalize=True, stretch=False, std_dev=0.8, min_cell_volume=20., back_id=1, to_8bits=False): """Define the sementation pipeline Parameters ---------- img2seg : str image to segment. h_min : int h-minima used with the h-transform function img2sub : str, optional image to subtract to the image to segment. iso : bool, optional if True (default), isometric resampling is performed after h-minima detection and before watershed segmentation equalize : bool, optional if True (default), intensity adaptative equalization is performed before h-minima detection stretch : bool, optional if True (default, False), intensity histogram stretching is performed before h-minima detection std_dev : float, optional real unit standard deviation used for Gaussian smoothing of the image to segment min_cell_volume : float, optional minimal volume accepted in the segmented image back_id : int, optional the background label to_8bits : bool, optional transform the image to segment as an unsigned 8 bits image for the h-transform and seed-labelleing steps Returns ------- seg_im : SpatialImage the labelled image obtained by seeded-watershed Notes ----- * Both 'equalize' & 'stretch' can not be True at the same time since they work on the intensity of the pixels; * Signal subtraction is performed after intensity rescaling (if any); * Linear filtering (Gaussian smoothing) is performed before h-minima transform for local minima detection; * Gaussian smoothing should be performed on isometric images, if the provided image is not isometric, we resample it before smoothing, then go back to original voxelsize; * In any case H-Transfrom is performed on the image with its native resolution to speed upd seed detection; * Same goes for connexe components detection (seed labelling); * Segmentation will be performed on the isometric images if iso is True, in such case we resample the image of detected seeds and use the isometric smoothed intensity image; """ t_start = time.time() # - Check we have only one intensity rescaling method called: try: assert equalize + stretch < 2 except AssertionError: raise ValueError( "Both 'equalize' & 'stretch' can not be True at once!") # - Check the standard deviation value for Gaussian smoothing is valid: try: assert std_dev <= 1. except AssertionError: raise ValueError( "Standard deviation for Gaussian smoothing should be superior or equal to 1!" ) ori_vxs = img2seg.voxelsize ori_shape = img2seg.shape if img2sub is not None: print "\n - Performing signal substraction..." img2seg = signal_subtraction(img2seg, img2sub) if equalize: print "\n - Performing z-slices adaptative histogram equalisation on the intensity image to segment..." img2seg = z_slice_equalize_adapthist(img2seg) if stretch: print "\n - Performing z-slices histogram contrast stretching on the intensity image to segment..." img2seg = z_slice_contrast_stretch(img2seg) print "\n - Automatic seed detection...".format(h_min) # morpho_radius = 1.0 # asf_img = morphology(img2seg, max_radius=morpho_radius, method='co_alternate_sequential_filter') # ext_img = h_transform(asf_img, h=h_min, method='h_transform_min') min_vxs = min(img2seg.voxelsize) if std_dev < min_vxs: print " -- Isometric resampling prior to Gaussian smoothing...".format( std_dev) img2seg = isometric_resampling(img2seg) print " -- Gaussian smoothing with std_dev={}...".format(std_dev) iso_smooth_img = linear_filtering(img2seg, std_dev=std_dev, method='gaussian_smoothing', real=True) if std_dev < min_vxs: print " -- Down-sampling a copy back to original voxelsize (to use with `h-transform`)..." smooth_img = resample(iso_smooth_img, ori_vxs) if not np.allclose(ori_shape, smooth_img.shape): print "WARNING: shape missmatch after down-sampling from isometric image:" print " -- original image shape: {}".format(ori_shape) print " -- down-sampled image shape: {}".format(smooth_img.shape) else: print " -- Copying original image (to use with `h-transform`)..." smooth_img = iso_smooth_img if not iso: del iso_smooth_img # no need to keep this image after this step! print " -- H-minima transform with h-min={}...".format(h_min) if to_8bits: ext_img = h_transform(smooth_img.to_8bits(), h=h_min, method='h_transform_min') else: ext_img = h_transform(smooth_img, h=h_min, method='h_transform_min') if iso: smooth_img = iso_smooth_img # no need to keep both images after this step! print " -- Region labelling: connexe components detection..." seed_img = region_labeling(ext_img, low_threshold=1, high_threshold=h_min, method='connected_components') print "Detected {} seeds!".format(len(np.unique(seed_img)) - 1) # '0' is in the list! del ext_img # no need to keep this image after this step! print "\n - Performing seeded watershed segmentation..." if iso: seed_img = isometric_resampling(seed_img, option='label') if to_8bits: seg_im = segmentation(smooth_img.to_8bits(), seed_img, method='seeded_watershed') else: seg_im = segmentation(smooth_img, seed_img, method='seeded_watershed') # seg_im[seg_im == 0] = back_id print "Detected {} labels!".format(len(np.unique(seg_im))) if min_cell_volume > 0.: from vplants.tissue_analysis.spatial_image_analysis import SpatialImageAnalysis print "\n - Performing cell volume filtering..." spia = SpatialImageAnalysis(seg_im, background=None) vol = spia.volume() too_small_labels = [ k for k, v in vol.items() if v < min_cell_volume and k != 0 ] if too_small_labels != []: print "Detected {} labels with a volume < {}µm2".format( len(too_small_labels), min_cell_volume) print " -- Removing seeds leading to small cells..." spia = SpatialImageAnalysis(seed_img, background=None) seed_img = spia.get_image_without_labels(too_small_labels) print " -- Performing final seeded watershed segmentation..." seg_im = segmentation(smooth_img, seed_img, method='seeded_watershed') # seg_im[seg_im == 0] = back_id print "Detected {} labels!".format(len(np.unique(seg_im))) print "\nDone in {}s".format(round(time.time() - t_start, 3)) return seg_im