def create_byn_mask(img_eq, parameters, img_name, to_byn_folder, _save=False): # opencv k-means clustering segmentation K = int(parameters['K_cluster']) img_k4, center, label = opencv_th_k_means_th(img=img_eq, K=K) # choice label for segmentation k_true_by_param = int(parameters['K_true']) unique, counts = np.unique(img_k4, return_counts=True) # check cluster dimension if counts[1] > counts[0]: k_true = k_true_by_param - 1 # 2th cluster is too big -> 1th and 2th are mapped to black else: k_true = k_true_by_param # 2th cluster is ok -> only 1th cluster is mapped to black # create binary mask from segmented images cells_mask = make_cells_mask(center, label, img_eq.shape, K=K, true=k_true) # pixels are ZERO or ONE # prepare defintive mask t_ratio_holes = parameters['t_ratio_holes'] BW_cells_mask = widens_mask_deconv(cells_mask, t_ratio_holes) if _save: save_tiff(img=BW_cells_mask, img_name=img_name, comment='bin', folder_path=to_byn_folder) return BW_cells_mask, np.count_nonzero(BW_cells_mask)
def create_and_save_segmented_images(bw_cells_mask, img_eq, img_name, to_seg_folder, _save=False): final = img_eq * bw_cells_mask.astype(bool) if _save: save_tiff(img=final, img_name=img_name, comment='seg', folder_path=to_seg_folder)
def clahe(img, parameters, img_name, to_folder, _save=False): ksize = parameters['clahe_ksize'] clip = parameters['clip_clahe'] img = normalize( exposure.equalize_adapthist(img, clip_limit=clip, kernel_size=ksize)) if _save: save_tiff(img=img, img_name=img_name, comment='eq', folder_path=to_folder) return img
def save_contours(img_name, contours, img_shape, countours_folder): # empty black image black = np.zeros(img_shape) # draw contours cv2.drawContours(black, contours, -1, 255, 1) # save singular images save_tiff(img=black, img_name=img_name, comment='only_cont', folder_path=countours_folder)
def segment_by_masks(parsers): print('START') args = parser.parse_args() if args.source_file_list == None or args.mask_file_list == None: print('You should select the Path of Source Images and masks Images.') parser.print_help() source_data = make_dataset(args.source_file_list) print('source_file_list ', args.source_file_list) print('source_data.len() = ', len(source_data)) mask_data = make_dataset(args.mask_file_list) print('mask_file_list ', args.mask_file_list) print('mask_data.len() = ', len(mask_data)) dest_folder = args.output print('dest_folder ', dest_folder) imgs = create_stack(source_data) print('imgs.shape[2] = ', imgs.shape[2]) masks = create_stack(mask_data) print('imgs.shape[2] = ', imgs.shape[2]) if imgs is not None and masks is not None: if imgs.shape[2] != masks.shape[2]: print('Warning! Dimension of Images and masks mismatch.') else: # todo script print('write in {} \n'.format(dest_folder)) segmented = np.zeros(imgs.shape) print('\n segmented shape: ', segmented.shape) print('imgs shape: ', imgs.shape) print('masks shape: ', masks.shape) for z in range(imgs.shape[2]): img = normalize(imgs[:, :, z]) img_eq = exposure.equalize_adapthist(img, clip_limit=0.03) segmented[:, :, z] = img_eq * masks[:, :, z] save_tiff(img=segmented[:, :, z], img_name=str(z), prefix='s', comment='dec_seg', folder_path=dest_folder) print('img n° {}'.format(z)) print(' \n ** Proces Finished \n')
def create_surrounded_images(BW_mask, img_eq, img_name, to_countourned_folder, _save=False): # plot contour mak over original image contours = (cv2.findContours(BW_mask.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE))[1] # prepare image img_eq_with_contour = normalize(img_eq.copy()) # draw contour cv2.drawContours(img_eq_with_contour, contours, -1, 255, 1) if _save: save_tiff(img=img_eq_with_contour, img_name=img_name, comment='cont', folder_path=to_countourned_folder) return contours
def main(parser): # read args from console args = parser.parse_args() # read source path (path of binary segmentation images) source_path = manage_path_argument(args.source_folder) # take base path and stack name base_path = os.path.dirname(os.path.dirname(source_path)) stack_name = os.path.basename(source_path) # create path and folder where save section images sections_path = os.path.join(base_path, 'xz_sections', stack_name) filled_sections_path = os.path.join(base_path, 'xz_filled_sections', stack_name) for path in [sections_path, filled_sections_path]: if not os.path.exists(path): os.makedirs(path) # portion of y axes for section estimation y_start = np.uint16(args.y_start[0]) y_stop = np.uint16(args.y_stop[0]) # preference for fill or not the holes _fill_holes = args.fill_holes print('\n\n\n _fill_holes : ', _fill_holes) # Def .txt filepath txt_parameters_path = os.path.join(base_path, 'parameters.txt') if _fill_holes: txt_results_path = os.path.join(base_path, 'Measure_analysis_filled.txt') else: txt_results_path = os.path.join(base_path, 'Measure_analysis.txt') # SCRIPT ---------------------------------------------------------------------- # print to video and write in results.txt init message init_message = [ ' **** Script for Estimation of Section Area and Volume **** \n \n' ' Source from path : {}'.format(base_path), ' Stack : {}'.format(stack_name), '\n\n *** Start processing... \n' ] error_message = '\n *** ERROR *** : stack in this path is None' with open(txt_results_path, 'w') as f: for line in init_message: print(line) f.write(line + '\n') # reads parameters parameters = extract_parameters(txt_parameters_path) # measure units x_step = parameters['res_xy'] # micron y_step = parameters['res_xy'] # micron z_step = parameters['res_z'] # micron pixel_xy_in_micron2 = x_step * y_step # micron^2 pixel_xz_in_micron2 = x_step * z_step # micron^2 voxel_in_micron3 = x_step * y_step * z_step # micron^3 # preferences _save_binary_sections = bool(parameters['save_binary_sections']) # create images stack from source path print(' *** Start to load the Stack...') # old version: # masks, mess = load_stack_into_numpy_ndarray([source_path]) # print(mess) #new version: masks = load_tif_data(source_path) if len(masks.shape) == 2: masks = np.expand_dims(masks, axis=2) # add the zeta axis # count selected sections total_sections = masks.shape[0] # row -> y -> number of sections print('\n Volume shape:', masks.shape) print('Number of total sections: ', total_sections) print('\n') # set y portion if y_stop < y_start: y_start = np.uint16(total_sections / 4) y_stop = np.uint16(total_sections * 3 / 4) print( ' *** ATTENTION : y portion selected by DEFAULT: {} -> {}'.format( y_start, y_stop)) # Every Section(y) is XZ projection of mask. Estimated Area is the sum of the Non_Zero pixel selected_sections = np.uint16(y_stop - y_start) sections_micron2 = np.zeros(selected_sections) print('Number of selected sections: ', y_stop - y_start) # Initializing to zero the Volume counter effective_myocites_volume = 0 # real estimated volume of myocites (sum of area of real cells) t_start = time.time() analyzed_section = 0 # counter, only for control the for loop (remove) with open(txt_results_path, 'a') as f: pre_info = list() pre_info.append('\nPortion of y selected: [{} -> {}]'.format( y_start, y_stop)) pre_info.append('Option for fill the holes: {}'.format(_fill_holes)) pre_info.append('\n') for l in pre_info: print(l) f.write(l + '\n') if masks is not None: # *** 1 *** - Mean Section Estimation print('\n... Estimation of mean section...') for y in range(y_start, y_stop): # extract section section = masks[y, :, :] sec_name = create_img_name_from_index(total_sections - y - 1) # img_name.tif # filled the section holes and set comment for tiff filenames if _fill_holes: section = ndimage.morphology.binary_fill_holes(section) comment = 'filled_section' dest_path = filled_sections_path else: comment = 'section' dest_path = sections_path # count cell pixel pixels_with_cell = np.count_nonzero(section.astype(bool)) if pixels_with_cell > 0: area_in_micron2 = pixels_with_cell * pixel_xz_in_micron2 sections_micron2[y - y_start] = area_in_micron2 measure = ' - {} ----> {} um^2'.format( sec_name, area_in_micron2) if _save_binary_sections: # transform point of view section = np.rot90(m=np.flipud(section), k=1, axes=(0, 1)) # save section in correct path save_tiff(img=section, img_name=sec_name, comment=comment, folder_path=dest_path) else: measure = ' - {} is empty'.format(sec_name) analyzed_section += 1 print(measure) # f.write(measure+'\n') # *** 2 *** - Volume Estimation print('\n\n ...Estimation of Volume...\n') for z in range(masks.shape[2]): # check fill option if _fill_holes: print('... filling {} xy frame'.format(z)) z_frame = ndimage.morphology.binary_fill_holes(masks[:, :, z]) else: z_frame = masks[:, :, z] # add pixels_of_real_cells of current z-slice to the counter effective_myocites_volume += np.count_nonzero(z_frame) # execution time (h, m, s) = seconds_to_min_sec(time.time() - t_start) # volumes in micron^3 effective_volume_in_micron3 = effective_myocites_volume * voxel_in_micron3 # count empty sections sections_with_cell = np.count_nonzero(sections_micron2) empties = selected_sections - sections_with_cell # Mean sections: mean_section = np.sum( sections_micron2) / sections_with_cell # (original images) # create results string result_message = list() result_message.append( '\n *** Process successfully completed, time of execution: {0:2d}h {1:2d}m {2:2d}s \n' .format(int(h), int(m), int(s))) result_message.append(' Total number of frames: {}'.format( masks.shape[2])) result_message.append(' Total sections: {}'.format(total_sections)) result_message.append( ' Selected sections: {}'.format(selected_sections)) result_message.append( ' Effective analyzed sections: {}'.format(analyzed_section)) result_message.append( ' Number of empty section: {}'.format(empties)) result_message.append( ' Number of section with cells: {}'.format(sections_with_cell)) result_message.append('\n') result_message.append( ' Mean sections: {0:.3f} um^2'.format(mean_section)) result_message.append( ' Effective miocytes tissue volume : {0:.6f} mm^3'.format( effective_volume_in_micron3 / 10**9)) result_message.append('\n') result_message.append(' \n OUTPUT SAVED IN: \n') result_message.append(txt_results_path) # write and print results for l in result_message: print(l) f.write(l + '\n') else: print(error_message) f.write(error_message) print(' \n \n \n ')