def segment_images(inpDir, outDir, config_data): """ Workflow for curvilinear shapes such as: Sec61 beta, TOM20, lamin B1 (mitosis specific) Args: inpDir : path to the input directory outDir : path to the output directory config_data : path to the configuration file """ logging.basicConfig(format='%(asctime)s - %(name)-8s - %(levelname)-8s - %(message)s', datefmt='%d-%b-%y %H:%M:%S') logger = logging.getLogger("main") logger.setLevel(logging.INFO) inpDir_files = os.listdir(inpDir) for i,f in enumerate(inpDir_files): logger.info('Segmenting image : {}'.format(f)) # Load image br = BioReader(os.path.join(inpDir,f)) image = br.read_image() structure_channel = 0 struct_img0 = image[:,:,:,structure_channel,0] struct_img0 = struct_img0.transpose(2,0,1).astype(np.float32) # main algorithm intensity_scaling_param = config_data['intensity_scaling_param'] if intensity_scaling_param[1] == 0: struct_img = intensity_normalization(struct_img0, scaling_param=intensity_scaling_param[:1]) struct_img = intensity_normalization(struct_img0, scaling_param=intensity_scaling_param) gaussian_smoothing_sigma = config_data['gaussian_smoothing_sigma'] if config_data['preprocessing_function'] == 'image_smoothing_gaussian_3d': structure_img_smooth = image_smoothing_gaussian_3d(struct_img, sigma=gaussian_smoothing_sigma) elif config_data['preprocessing_function'] == 'edge_preserving_smoothing_3d': structure_img_smooth = edge_preserving_smoothing_3d(struct_img) f2_param = config_data['f2_param'] bw = filament_2d_wrapper(structure_img_smooth, f2_param) minArea = config_data['minArea'] seg = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) seg = seg >0 out_img=seg.astype(np.uint8) out_img[out_img>0]=255 # create output image out_img = out_img.transpose(1,2,0) out_img = out_img.reshape((out_img.shape[0], out_img.shape[1], out_img.shape[2], 1, 1)) # write image using BFIO bw = BioWriter(os.path.join(outDir,f)) bw.num_x(out_img.shape[1]) bw.num_y(out_img.shape[0]) bw.num_z(out_img.shape[2]) bw.num_c(out_img.shape[3]) bw.num_t(out_img.shape[4]) bw.pixel_type(dtype='uint8') bw.write_image(out_img) bw.close_image()
def nuc_seg(image, scale, sigma, f2, hol_min, hol_max, minA): img = intensity_normalization(image, scale) img_s = image_smoothing_gaussian_3d(img, sigma) bw = filament_2d_wrapper(img_s, f2) bw_2 = hole_filling(bw, hol_min, hol_max) seg = remove_small_objects(bw_2 > 0, min_size=minA, connectivity=1, in_place=False) seg2, n = label(seg, return_num=True) return (img_s, bw_2, seg2, n)
def segment_images(inpDir, outDir, config_data): """ Workflow for data with similar morphology as LAMP-1 Args: inpDir : path to the input directory outDir : path to the output directory config_data : path to the configuration file """ logging.basicConfig( format='%(asctime)s - %(name)-8s - %(levelname)-8s - %(message)s', datefmt='%d-%b-%y %H:%M:%S') logger = logging.getLogger("main") logger.setLevel(logging.INFO) inpDir_files = os.listdir(inpDir) for i, f in enumerate(inpDir_files): logger.info('Segmenting image : {}'.format(f)) # Load image br = BioReader(os.path.join(inpDir, f)) image = br.read_image() structure_channel = 0 struct_img0 = image[:, :, :, structure_channel, 0] struct_img0 = struct_img0.transpose(2, 0, 1).astype(np.float32) # main algorithm intensity_scaling_param = config_data['intensity_scaling_param'] struct_img = intensity_normalization( struct_img0, scaling_param=intensity_scaling_param) gaussian_smoothing_sigma = config_data['gaussian_smoothing_sigma'] structure_img_smooth = image_smoothing_gaussian_slice_by_slice( struct_img, sigma=gaussian_smoothing_sigma) s2_param = config_data['s2_param'] bw_spot = dot_2d_slice_by_slice_wrapper(structure_img_smooth, s2_param) f2_param = config_data['f2_param'] bw_filament = filament_2d_wrapper(structure_img_smooth, f2_param) bw = np.logical_or(bw_spot, bw_filament) fill_2d = config_data['fill_2d'] if fill_2d == 'True': fill_2d = True elif fill_2d == 'False': fill_2d = False fill_max_size = config_data['fill_max_size'] minArea = config_data['minArea'] bw_fill = hole_filling(bw, 0, fill_max_size, False) seg = remove_small_objects(bw_fill > 0, min_size=minArea, connectivity=1, in_place=False) seg = seg > 0 out_img = seg.astype(np.uint8) out_img[out_img > 0] = 255 # create output image out_img = out_img.transpose(1, 2, 0) out_img = out_img.reshape( (out_img.shape[0], out_img.shape[1], out_img.shape[2], 1, 1)) # write image using BFIO bw = BioWriter(os.path.join(outDir, f), metadata=br.read_metadata()) bw.num_x(out_img.shape[1]) bw.num_y(out_img.shape[0]) bw.num_z(out_img.shape[2]) bw.num_c(out_img.shape[3]) bw.num_t(out_img.shape[4]) bw.pixel_type(dtype='uint8') bw.write_image(out_img) bw.close_image()
def segment_images(inpDir, outDir, config_data): """ Workflow for data with shell like shapes such as lamin B1 (interphase-specific) Args: inpDir : path to the input directory outDir : path to the output directory config_data : path to the configuration file """ logging.basicConfig( format='%(asctime)s - %(name)-8s - %(levelname)-8s - %(message)s', datefmt='%d-%b-%y %H:%M:%S') logger = logging.getLogger("main") logger.setLevel(logging.INFO) inpDir_files = os.listdir(inpDir) for i, f in enumerate(inpDir_files): logger.info('Segmenting image : {}'.format(f)) # Load image br = BioReader(os.path.join(inpDir, f)) image = br.read_image() structure_channel = 0 struct_img0 = image[:, :, :, structure_channel, 0] struct_img0 = struct_img0.transpose(2, 0, 1).astype(np.float32) # main algorithm intensity_scaling_param = config_data['intensity_scaling_param'] struct_img = intensity_normalization( struct_img0, scaling_param=intensity_scaling_param) gaussian_smoothing_sigma = config_data['gaussian_smoothing_sigma'] structure_img_smooth = image_smoothing_gaussian_3d( struct_img, sigma=gaussian_smoothing_sigma) middle_frame_method = config_data['middle_frame_method'] mid_z = get_middle_frame(structure_img_smooth, method=middle_frame_method) f2_param = config_data['f2_param'] bw_mid_z = filament_2d_wrapper(structure_img_smooth[mid_z, :, :], f2_param) hole_max = config_data['hole_max'] hole_min = config_data['hole_min'] bw_fill_mid_z = hole_filling(bw_mid_z, hole_min, hole_max) seed = get_3dseed_from_mid_frame( np.logical_xor(bw_fill_mid_z, bw_mid_z), struct_img.shape, mid_z, hole_min) bw_filled = watershed( struct_img, seed.astype(int), watershed_line=True) > 0 seg = np.logical_xor(bw_filled, dilation(bw_filled, selem=ball(1))) seg = seg > 0 out_img = seg.astype(np.uint8) out_img[out_img > 0] = 255 # create output image out_img = out_img.transpose(1, 2, 0) out_img = out_img.reshape( (out_img.shape[0], out_img.shape[1], out_img.shape[2], 1, 1)) # write image using BFIO bw = BioWriter(os.path.join(outDir, f)) bw.num_x(out_img.shape[1]) bw.num_y(out_img.shape[0]) bw.num_z(out_img.shape[2]) bw.num_c(out_img.shape[3]) bw.num_t(out_img.shape[4]) bw.pixel_type(dtype='uint8') bw.write_image(out_img) bw.close_image()
def Workflow_lmnb1_mitotic(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [4000] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 f2_param = [[0.5, 0.01]] minArea = 5 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio > 0: struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8) / (struct_img.max() - struct_img.min() + 1e-8) # smoothing with boundary preserving smoothing structure_img_smooth = image_smoothing_gaussian_3d( struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### # 2d filament filter on the middle frame bw = filament_2d_wrapper(structure_img_smooth, f2_param) ################### # POST-PROCESSING ################### bw = remove_small_objects(bw > 0, min_size=minArea, connectivity=1, in_place=False) # output seg = bw > 0 seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append('bw_final') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'array': return seg elif output_type == 'array_with_contour': return (seg, generate_segmentation_contour(seg)) else: print('your can implement your output hook here, but not yet') quit()
def Workflow_lmnb1_mitotic( struct_img: np.ndarray, rescale_ratio: float = -1, output_type: str = "default", output_path: Union[str, Path] = None, fn: Union[str, Path] = None, output_func=None, ): """ classic segmentation workflow wrapper for structure LMNB1 mitotic Parameter: ----------- struct_img: np.ndarray the 3D image to be segmented rescale_ratio: float an optional parameter to allow rescale the image before running the segmentation functions, default is no rescaling output_type: str select how to handle output. Currently, four types are supported: 1. default: the result will be saved at output_path whose filename is original name without extention + "_struct_segmentaiton.tiff" 2. array: the segmentation result will be simply returned as a numpy array 3. array_with_contour: segmentation result will be returned together with the contour of the segmentation 4. customize: pass in an extra output_func to do a special save. All the intermediate results, names of these results, the output_path, and the original filename (without extension) will be passed in to output_func. """ ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [4000] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 f2_param = [[0.5, 0.01]] minArea = 5 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append("im_norm") # rescale if needed if rescale_ratio > 0: struct_img = zoom(struct_img, (1, rescale_ratio, rescale_ratio), order=2) struct_img = (struct_img - struct_img.min() + 1e-8) / (struct_img.max() - struct_img.min() + 1e-8) # smoothing with boundary preserving smoothing structure_img_smooth = image_smoothing_gaussian_3d( struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range, ) out_img_list.append(structure_img_smooth.copy()) out_name_list.append("im_smooth") ################### # core algorithm ################### # 2d filament filter on the middle frame bw = filament_2d_wrapper(structure_img_smooth, f2_param) ################### # POST-PROCESSING ################### bw = remove_small_objects(bw > 0, min_size=minArea, connectivity=1, in_place=False) # output seg = bw > 0 seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append("bw_final") if output_type == "default": # the default final output, simply save it to the output path save_segmentation(seg, False, Path(output_path), fn) elif output_type == "customize": # the hook for passing in a customized output function # use "out_img_list" and "out_name_list" in your hook to # customize your output functions output_func(out_img_list, out_name_list, Path(output_path), fn) elif output_type == "array": return seg elif output_type == "array_with_contour": return (seg, generate_segmentation_contour(seg)) else: raise NotImplementedError("invalid output type: {output_type}")
def Workflow_lmnb1_interphase(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [4000] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 f2_param = [[1, 0.01], [2, 0.01], [3, 0.01]] hole_max = 40000 hole_min = 400 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio > 0: struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8) / (struct_img.max() - struct_img.min() + 1e-8) # smoothing with boundary preserving smoothing structure_img_smooth = image_smoothing_gaussian_3d( struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### # get the mid frame mid_z = get_middle_frame(structure_img_smooth, method='intensity') # 2d filament filter on the middle frame bw_mid_z = filament_2d_wrapper(structure_img_smooth[mid_z, :, :], f2_param) # hole filling bw_fill_mid_z = hole_filling(bw_mid_z, hole_min, hole_max) seed = get_3dseed_from_mid_frame(np.logical_xor(bw_fill_mid_z, bw_mid_z), struct_img.shape, mid_z, hole_min, bg_seed=True) seg_filled = watershed( struct_img, seed.astype(int), watershed_line=True) > 1 # in watershed result, 1 is for background # get the actual shell seg = find_boundaries(seg_filled, connectivity=1, mode='thick') # output seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append('bw_final') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'array': return seg elif output_type == 'array_with_contour': return (seg, generate_segmentation_contour(seg)) else: print('your can implement your output hook here, but not yet') quit()
def Workflow_lmnb1_interphase( struct_img: np.ndarray, rescale_ratio: float = -1, output_type: str = "default", output_path: Union[str, Path] = None, fn: Union[str, Path] = None, output_func=None, ): """ classic segmentation workflow wrapper for structure LMNB1 interphase Parameter: ----------- struct_img: np.ndarray the 3D image to be segmented rescale_ratio: float an optional parameter to allow rescale the image before running the segmentation functions, default is no rescaling output_type: str select how to handle output. Currently, four types are supported: 1. default: the result will be saved at output_path whose filename is original name without extention + "_struct_segmentaiton.tiff" 2. array: the segmentation result will be simply returned as a numpy array 3. array_with_contour: segmentation result will be returned together with the contour of the segmentation 4. customize: pass in an extra output_func to do a special save. All the intermediate results, names of these results, the output_path, and the original filename (without extension) will be passed in to output_func. """ ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [4000] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 f2_param = [[1, 0.01], [2, 0.01], [3, 0.01]] hole_max = 40000 hole_min = 400 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append("im_norm") # rescale if needed if rescale_ratio > 0: struct_img = zoom(struct_img, (1, rescale_ratio, rescale_ratio), order=2) struct_img = (struct_img - struct_img.min() + 1e-8) / (struct_img.max() - struct_img.min() + 1e-8) # smoothing with boundary preserving smoothing structure_img_smooth = image_smoothing_gaussian_3d( struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range, ) out_img_list.append(structure_img_smooth.copy()) out_name_list.append("im_smooth") ################### # core algorithm ################### # get the mid frame mid_z = get_middle_frame(structure_img_smooth, method="intensity") # 2d filament filter on the middle frame bw_mid_z = filament_2d_wrapper(structure_img_smooth[mid_z, :, :], f2_param) # hole filling bw_fill_mid_z = hole_filling(bw_mid_z, hole_min, hole_max) seed = get_3dseed_from_mid_frame( np.logical_xor(bw_fill_mid_z, bw_mid_z), struct_img.shape, mid_z, hole_min, bg_seed=True, ) seg_filled = ( watershed(struct_img, seed.astype(int), watershed_line=True) > 1 ) # in watershed result, 1 is for background # get the actual shell seg = find_boundaries(seg_filled, connectivity=1, mode="thick") # output seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append("bw_final") if output_type == "default": # the default final output, simply save it to the output path save_segmentation(seg, False, Path(output_path), fn) elif output_type == "customize": # the hook for passing in a customized output function # use "out_img_list" and "out_name_list" in your hook to # customize your output functions output_func(out_img_list, out_name_list, Path(output_path), fn) elif output_type == "array": return seg elif output_type == "array_with_contour": return (seg, generate_segmentation_contour(seg)) else: raise NotImplementedError("invalid output type: {output_type}")