def save_thick_fibers(read_path, save_path, thickness, write_images=True): """ Takes the images in the read path together with the ground truth labels. Produces and saves new images with thicker ground truth label saved in the save path. :param read_path: The path were the original ground truths are :param save_path: The path were the new thicker ground truths will be saved :param thickness: The thickness for the new ground truth images :param load_type: The type of the original images saved :param write_images: This flag determines if the original images will be also copied into the path (the input data) :return: None """ # Get the image names in the read path names = name_list(read_path) if not (exists(save_path)): makedirs( save_path) # Creates the folder if the save path doesn't exist # For each of the images produce a new image with the thicker ground truth for name in names: print('Converting image %s...\n' % name) _, label = load_image_label(read_path, name) thick_label = create_thick_fibers(label, thickness) cv2.imwrite( join( save_path, name.replace(get_file_extension(name), '_FIB' + get_file_extension(name))), thick_label) if write_images: copyfile(join(read_path, name), join(save_path, name))
def convolutional_selection(self,save_path, size, img, label, name): # Obtain the left top corner for the hard example window chip_names = [] # Convolve the label to find the relevant spots __, label = cv2.threshold(label, 127, 255, cv2.THRESH_BINARY_INV) convolved1 = convolve2d(label[:,:,0], self.gaussian_kernel((np.min(self.size))), mode='valid') convolved2 = convolve2d(label[:,:,1], self.gaussian_kernel((np.min(self.size))), mode='valid') __, label = cv2.threshold(label, 127, 255, cv2.THRESH_BINARY_INV) while np.sum(convolved1) != 0: index1, index2 = np.unravel_index(convolved1.argmax(), convolved1.shape) chip_image = img[index1:(index1 + size[0]), index2:(index2 + size[1])] # Get the hard example window chip_label = label[index1:(index1 + size[0]), index2:(index2 + size[1]),0] # Get the hard example label window chip_label2 = label[index1:(index1 + size[0]), index2:(index2 + size[1]),1] # Get the hard example label window # Remove a certain search area for the convolution index1_rmv_conv_start = max([index1 - int(size[0] / 4) + 1, 0]) index2_rmv_conv_start = max([index2 - int(size[1] / 4) + 1, 0]) index1_rmv_conv_end = min([index1_rmv_conv_start + (size[0] - 2), img.shape[0]]) index2_rmv_conv_end = min([index2_rmv_conv_start + (size[1] - 2), img.shape[1]]) convolved1[index1_rmv_conv_start:index1_rmv_conv_end, index2_rmv_conv_start:index2_rmv_conv_end] = 0 convolved2[index1_rmv_conv_start:index1_rmv_conv_end, index2_rmv_conv_start:index2_rmv_conv_end] = 0 save_name = name.replace(get_file_extension(name), '_H_' + str(index1) + '_' + str(index2) + get_file_extension(name)) cv2.imwrite(join(save_path, save_name), chip_image) cv2.imwrite(join(save_path, save_name.replace(get_file_extension(save_name), '_FIB' + get_file_extension(save_name))), chip_label) cv2.imwrite(join(save_path, save_name.replace(get_file_extension(save_name), '_FIB2' + get_file_extension(save_name))), chip_label2) # while np.sum(convolved2) != 0: # index1, index2 = np.unravel_index(convolved2.argmax(), convolved2.shape) # chip_image = img[index1:(index1 + size[0]), # index2:(index2 + size[1])] # Get the hard example window # chip_label = label[index1:(index1 + size[0]), # index2:(index2 + size[1]),0] # Get the hard example label window # chip_label2 = label[index1:(index1 + size[0]), # index2:(index2 + size[1]),1] # Get the hard example label window # # Remove a certain search area for the convolution # index1_rmv_conv_start = max([index1 - int(size[0] / 4) + 1, 0]) # index2_rmv_conv_start = max([index2 - int(size[1] / 4) + 1, 0]) # index1_rmv_conv_end = min([index1_rmv_conv_start + (size[0] - 2), img.shape[0]]) # index2_rmv_conv_end = min([index2_rmv_conv_start + (size[1] - 2), img.shape[1]]) # convolved1[index1_rmv_conv_start:index1_rmv_conv_end, index2_rmv_conv_start:index2_rmv_conv_end] = 0 # convolved2[index1_rmv_conv_start:index1_rmv_conv_end, index2_rmv_conv_start:index2_rmv_conv_end] = 0 # save_name = name.replace(get_file_extension(name), # '_H_' + str(index1) + '_' + str(index2) + get_file_extension(name)) # cv2.imwrite(join(save_path, save_name), chip_image) # cv2.imwrite(join(save_path, # save_name.replace(get_file_extension(save_name), '_FIB' + get_file_extension(save_name))), # chip_label) # cv2.imwrite(join(save_path, # save_name.replace(get_file_extension(save_name), '_FIB2' + get_file_extension(save_name))), # chip_label2) return chip_names
def produce_prediction_files(self, name, model, threshold, threshold_folder): """ This function takes an image with certain name and makes a prediction with the specified model. The prediction is then thresholded to obtain a boolean mask which is used to produce prediction files which are then stored in the threshold folder :param name: Name of the input image :param model: Model used to produce the prediction :param threshold: Threshold to produce the boolean mask from the prediction :param threshold_folder: Where the prediction files will be stored :return: Saves the predictions in the corresponding folder. The predictions are: _FIB: The original ground truth file _PROB: The raw prediction obtained from the model each pixel represents the probability of predicting a fiber _PRED: The boolean mask prediction _MASKED: The original image with a mask that represents TP,FP,FN _STAT_MASK: The mask with the TP,FP,FN """ img, label = load_image_label(self.path_data, name) sizex = img.shape[0] sizey = img.shape[1] colored_image = np.concatenate((img.reshape(sizex, sizey, 1), ) * 3, axis=2) # Reshape the image so it can be fed to the model img = img.reshape(1, sizex, sizey, 1) # Make the prediction and reshape it prediction = model.predict(img).reshape(sizex, sizey) prediction_bool = (prediction >= threshold) prediction = prediction * 255 __, __, __, colored_mask = prediction_masks(prediction_bool, label) # Write the created images in the corresponding folder cv2.imwrite( threshold_folder + '/' + name.replace(get_file_extension(name), '_FIB' + '.tiff'), label) cv2.imwrite( threshold_folder + '/' + name.replace(get_file_extension(name), '_PROB' + '.tiff'), prediction.astype(np.uint8)) cv2.imwrite( threshold_folder + '/' + name.replace(get_file_extension(name), '_PRED' + '.tiff'), prediction_bool * 255) cv2.imwrite( threshold_folder + '/' + name.replace(get_file_extension(name), '_MASKED' + '.tiff'), np.multiply(colored_mask, colored_image)) cv2.imwrite( threshold_folder + '/' + name.replace(get_file_extension(name), '_STATMASK' + '.tiff'), colored_mask * 255)
def separate_hard_example_name(self, name): extension = get_file_extension(name) root_name = name.split('_H_')[0] indexes = name.split('_H_')[-1].split('.')[0] index1 = int(indexes.split('_')[0]) index2 = int(indexes.split('_')[1]) return root_name, index1, index2, extension
def summary_image(self, threshold_folder): """ Produces an image with the summary of the data obtained previously :param threshold_folder: Where the image is going to be stored :return: Saves in the threshold_folder an image with the corresponding produced table """ print("Saving the image summary table") try: object_precision = self.found_fibers / ( self.found_fibers + self.false_positive_objects) except ZeroDivisionError: object_precision = None try: object_recall = self.found_fibers / (self.total_fibers) except ZeroDivisionError: object_recall = None filename_fiber_detailed = self.name.replace( get_file_extension(self.name), '') + '_FD.txt' ffd = open(join(threshold_folder, filename_fiber_detailed), 'w+') for fiber in range(len(self.image_percentages)): ffd.write( 'Fiber {} Predicted_Pixels {} GTPixels {} Percentage {} \n' .format(fiber + 1, self.image_intersection_pixels[fiber], self.image_fiber_pixels[fiber], self.image_percentages[fiber])) ffd.close() filename_image_summary = self.name.replace( get_file_extension(self.name), '') + '_FIS.txt' fis = open(join(threshold_folder, filename_image_summary), 'w+') fis.write( 'Total_fibers {} Found_fibers {} False_Positive_Objects {} \n' .format(self.total_fibers, self.found_fibers, self.false_positive_objects)) fis.write( 'Object_precision {} Object_recall {} Pixel_precision {} Pixel_recall {} \n' .format(object_precision, object_recall, self.precision, self.recall)) fis.close() return self.precision, self.recall, self.found_fibers, self.total_fibers, self.image_percentages, self.false_positive_objects
def convolutional_selection(self, comparison, img, label, name, HE_per_image): # Obtain the left top corner for the hard example window hard_example_names = [] convolved = convolve2d(comparison, np.ones((self.data.size[1], self.data.size[0])), mode='valid') for num_example in range(HE_per_image): index1, index2 = np.unravel_index(convolved.argmax(), convolved.shape) hard_example = img[index1:(index1 + self.data.size[1]), index2:( index2 + self.data.size[0])] # Get the hard example window hard_example_label = label[index1:( index1 + self.data.size[1]), index2:( index2 + self.data.size[0])] # Get the hard example label window # Remove a certain search area for the convolution index1_rmv_conv_start = max( [index1 - int(self.data.size[1] / 4) + 1, 0]) index2_rmv_conv_start = max( [index2 - int(self.data.size[0] / 4) + 1, 0]) index1_rmv_conv_end = min([ index1_rmv_conv_start + (self.data.size[1] - 2), img.shape[0] ]) index2_rmv_conv_end = min([ index2_rmv_conv_start + (self.data.size[0] - 2), img.shape[1] ]) convolved[index1_rmv_conv_start:index1_rmv_conv_end, index2_rmv_conv_start:index2_rmv_conv_end] = 0 save_name = name.replace( get_file_extension(name), '_HEP_' + str(index1) + '_' + str(index2) + self.UNETnet.data_type) hard_example_names.append(save_name) cv2.imwrite(join(self.data.temp_train, save_name), hard_example) cv2.imwrite( join( self.data.temp_train, save_name.replace(get_file_extension(save_name), '_FIB' + get_file_extension(save_name))), hard_example_label) self.UNETnet.train_names.append(save_name) print("HE %d created \n" % num_example) return hard_example_names
def __init__(self, path_hard_example_files, path_image_files): self.path_hard_example_files = path_hard_example_files self.hard_example_texts = name_list(path_hard_example_files, extension='.txt') self.path_image_files = path_image_files self.image_names = name_list(path_image_files) self.image_extension = get_file_extension(self.image_names[-1]) self.sizes = self.size_hard_example() print("Existing hard example files are\n") print(self.hard_example_texts)
def hard_example_generator_convolution(self, HE_per_image=2): ''' This function reads the images in the read path and produces a prediction with the input model. The region of certain size with the most FP errors is identified. The crops are evaluated with the model and then HEpi crops with the worst score are then saved into the save_path ''' print("Hard example generation started...\n") # Read the image names in the read_path names = self.data.train_names_original hard_examples = [] for num_name, name in enumerate(names): print("Generating HE for image %d\n" % num_name) # Load the image with the corresponding labels print(self.data.path_name, name) img = cv2.imread(join(self.data.path_name, name)) label = cv2.imread( join( self.data.path_name, name.replace(get_file_extension(name), '_FIB' + get_file_extension(name))), 0) img = pad_image(self.num_layers, img) label = pad_image(self.num_layers, label) #img, label = load_image_label(self.data.path_name, name) label_thresh = (label == 255).astype(np.int) # Create the predictions from the original image prediction = self.UNETnet.model.predict(img[np.newaxis, :, :]) # Compare the prediction with the ground truth print('Shape prediction', prediction.shape, 'Label', label_thresh.shape) comparison = np.multiply((1 - prediction[0, :, :, 0]), label_thresh) print('Comparison', comparison.shape) # Make the convolution to find the left top corner for the hard example hard_example_names = self.convolutional_selection( comparison, img, label, name, HE_per_image) for name_hard in hard_example_names: hard_examples.append(name_hard) if not (exists('./' + self.data.data_name + '/Hard Examples')): makedirs('./' + self.data.data_name + '/Hard Examples') save_names(hard_examples, './' + self.data.data_name + '/Hard Examples/', self.UNETnet.model_name + " Iter " + str(self.iteration))
def save_images(self,name,image,threshold_folder,label,prediction_probability_mask,prediction_processed,colored_mask,colored_image,contours_prediction_processed): """ Saves the predictions in the corresponding folder. The predictions are: _FIB: The original ground truth file _PROB: The raw prediction obtained from the model each pixel represents the probability of predicting a fiber _PRED: The boolean mask prediction _MASKED: The original image with a mask that represents TP,FP,FN _STAT_MASK: The mask with the TP,FP,FN _OBJNUM: Numbered objects in the prediction :param name: Name of the image :param threshold_folder: Folder where it will be stored :param label: Label image :param prediction_probability_mask: Output of the model prediction to create an image with it :param prediction_processed: Prediction after removing small isolated pixels :param colored_mask: Colored mask with TP,FP,FN :param colored_image: Image for use together with colored mask :param contours_prediction_processed: Contours of the prediction after removing small isolated pixels :return: """ colored_image = np.concatenate((image.reshape(self.size, self.size, 1),) * 3, axis=2) cv2.imwrite(threshold_folder + '/' + name.replace(get_file_extension(name), '_FIB' + '.tiff'), label) cv2.imwrite(threshold_folder + '/' + name.replace(get_file_extension(name), '_PROB' + '.tiff'), prediction_probability_mask.astype(np.uint8)) cv2.imwrite(threshold_folder + '/' + name.replace(get_file_extension(name), '_PRED' + '.tiff'), prediction_processed) cv2.imwrite(threshold_folder + '/' + name.replace(get_file_extension(name), '_MASKED' + '.tiff'), np.multiply(colored_mask, colored_image)) cv2.imwrite(threshold_folder + '/' + name.replace(get_file_extension(name), '_STATMASK' + '.tiff'), colored_mask * 255) cv2.imwrite(threshold_folder + '/' + name.replace(get_file_extension(name), '_OBJNUM' + '.tiff'), self.numbered_fibers(np.multiply(colored_mask, colored_image), contours_prediction_processed))
def save_images(self, threshold_folder): """ Saves the predictions in the corresponding folder. The predictions are: _FIB: The original ground truth file _PROB: The raw prediction obtained from the model each pixel represents the probability of predicting a fiber _PRED: The boolean mask prediction _MASKED: The original image with a mask that represents TP,FP,FN _STAT_MASK: The mask with the TP,FP,FN _OBJNUM: Numbered objects in the prediction :param threshold_folder: Folder where it will be stored :return: """ print("Saving the prediction images \n") colored_image = np.concatenate( (self.image.reshape(self.size, self.size, 1), ) * 3, axis=2) cv2.imwrite( threshold_folder + '/' + self.name.replace( get_file_extension(self.name), '_FIB' + '.tiff'), self.label) cv2.imwrite( threshold_folder + '/' + self.name.replace( get_file_extension(self.name), '_PROB' + '.tiff'), self.prediction_prob_mask.astype(np.uint8)) cv2.imwrite( threshold_folder + '/' + self.name.replace( get_file_extension(self.name), '_PRED' + '.tiff'), self.prediction) cv2.imwrite( threshold_folder + '/' + self.name.replace( get_file_extension(self.name), '_PRED_UN' + '.tiff'), self.prediction_unprocessed) cv2.imwrite( threshold_folder + '/' + self.name.replace( get_file_extension(self.name), '_MASKED' + '.tiff'), np.multiply(self.colored_mask, colored_image)) cv2.imwrite( threshold_folder + '/' + self.name.replace( get_file_extension(self.name), '_STATMASK' + '.tiff'), self.colored_mask * 255) cv2.imwrite( threshold_folder + '/' + self.name.replace( get_file_extension(self.name), '_OBJNUM' + '.tiff'), self.numbered_fibers( np.multiply(self.colored_mask, colored_image), self.prediction_contours))
def get_chip_images(self, size): name_array = [ self.train_names_original, self.val_names_original, self.test_names_original ] folder_array = [self.temp_train, self.temp_val, self.temp_test] # Train data creation names = name_array[0] if not (exists(folder_array[0])): makedirs(folder_array[0]) for name in names: image = cv2.imread(join(self.path_name, name)) label = cv2.imread( join( self.path_name, name.replace(get_file_extension(name), '_FIB' + get_file_extension(name))), 0) self.convolutional_selection(folder_array[0], size, image, label, name) if self.augmentation: generate_complete_flipping(folder_array[0], folder_array[0], data_type=self.load_extension, y_flip=False, xy_flip=False) # Validation Test Data for num_folder in range(2): folder = folder_array[num_folder + 1] names = name_array[num_folder + 1] if not (exists(folder)): makedirs(folder) for name in names: image = cv2.imread(join(self.path_name, name)) label = cv2.imread( join( self.path_name, name.replace(get_file_extension(name), '_FIB' + get_file_extension(name))), 0) image = pad_image(image) label = pad_image(label) cv2.imwrite(join(folder, name), image) cv2.imwrite( join( folder, name.replace(get_file_extension(name), '_FIB' + get_file_extension(name))), label)
def get_information_image(self, percentage): final_precision = 0 final_recall = 0 final_total_list = [] final_found_list = [] final_total_fibers = 0 final_total_found = 0 for num_image, name in enumerate(self.names): texname = name.replace(get_file_extension(name), '.tex') pdfname = name.replace(get_file_extension(name), '.pdf') tablename = join(self.path, name.replace(get_file_extension(name), '.png')) image_percentages, total_fibers_image, found_fibers_image, image_fiber_pixels, image_intersection_pixels = self.fiber_discriminator_per_image( self.images_contours, num_image, percentage) final_total_fibers += total_fibers_image final_total_found += found_fibers_image final_total_list.append(total_fibers_image) final_found_list.append(found_fibers_image) precision, recall = self.get_statistics( self.statistics_names[num_image]) dict_information = { 'Fiber': range(1, len(image_percentages) + 1), 'Percentage %': image_percentages, 'GT Pixels': image_fiber_pixels, 'Predicted Pixels': image_intersection_pixels } dict_information2 = { 'Total Fibers': [total_fibers_image], 'Found Fibers': [found_fibers_image] } dict_information3 = {'Precision': [precision], 'Recall': [recall]} information1 = pd.DataFrame(dict_information, columns=[ 'Fiber', 'Predicted Pixels', 'GT Pixels', 'Percentage %' ]) information1.set_index('Fiber', inplace=True) information2 = pd.DataFrame( dict_information2, columns=['Found Fibers', 'Total Fibers']) #information2.set_index('Found Fibers', inplace=True) information3 = pd.DataFrame(dict_information3, columns=['Precision', 'Recall']) #information3.set_index('Precision', inplace=True) template = r'''\documentclass[preview]{{standalone}} \usepackage{{booktabs}} \begin{{document}} {} {} {} \end{{document}} ''' with open(texname, 'w') as f: f.write( template.format( information1.to_latex(column_format='|c|c|c|c|'), information2.to_latex(column_format='|c|c|c|'), information3.to_latex())) subprocess.call(['pdflatex', texname]) subprocess.call([ 'magick', 'convert', '-density', '300', pdfname, '-quality', '90', tablename ]) f.close() remove(texname) remove(pdfname) remove(texname.replace('.tex', '.log')) final_precision += precision final_recall += recall dict_information_final1 = { 'Image': self.names, 'Found Fibers': final_found_list, 'Total Fibers': final_total_list } information_final1 = pd.DataFrame( dict_information_final1, columns=['Image', 'Found Fibers', 'Total Fibers']) information_final1.set_index('Image', inplace=True) final_precision = final_precision / len(self.names) final_recall = final_recall / len(self.names) dict_information_final2 = { 'Summary': [], 'Overall Precision': [final_precision], 'Overall Recall': [final_recall], 'Total fibers found': [final_total_found], 'Total fibers': [final_total_fibers] } information_final2 = pd.DataFrame(dict_information_final2, columns=[ 'Summary', 'Overall Precision', 'Overall Recall', 'Total fibers found', 'Total fibers' ]) information_final2.set_index('Summary', inplace=True) template2 = r'''\documentclass[preview]{{standalone}} \usepackage{{booktabs}} \begin{{document}} {} {} \end{{document}} ''' texname = "Final_summary.tex" pdfname = "Final_summary.pdf" tablename = join(self.path, "Final_summary.png") with open(texname, 'w') as f: f.write( template2.format( information_final1.to_latex(column_format='|c|c|c|c|'), information_final2.to_latex(column_format='|c|c|c|c|c|'))) subprocess.call(['pdflatex', texname]) subprocess.call([ 'magick', 'convert', '-density', '300', pdfname, '-quality', '90', tablename ]) f.close() remove(texname) remove(pdfname) remove(texname.replace('.tex', '.log'))
def summary_image(self, threshold_folder): """ Produces an image with the summary of the data obtained previously :param threshold_folder: Where the image is going to be stored :return: Saves in the threshold_folder an image with the corresponding produced table """ print("Saving the image summary table") # Define the summary file names texname = self.name.replace(get_file_extension(self.name), '.tex') pdfname = self.name.replace(get_file_extension(self.name), '.pdf') tablename = join( threshold_folder, self.name.replace(get_file_extension(self.name), '.png')) # Create the dictionaries for the data frames dict_fiber_summary = { 'Fiber': range(1, len(self.image_percentages) + 1), 'Percentage %': self.image_percentages, 'GT Pixels': self.image_fiber_pixels, 'Predicted Pixels': self.image_intersection_pixels } dict_image_summary = { 'Total Fibers': [self.total_fibers], 'Found Fibers': [self.found_fibers], 'False Positive Objects': [self.false_positive_objects] } try: object_precision = self.found_fibers / ( self.found_fibers + self.false_positive_objects) except ZeroDivisionError: object_precision = None try: object_recall = self.found_fibers / (self.total_fibers) except ZeroDivisionError: object_recall = None dict_object_summary = { 'Object Precision': [object_precision], 'Object Recall': [object_recall] } dict_pixel_summary = { 'Pixel Precision': [self.precision], 'Pixel Recall': [self.recall] } df_fiber_summary = pd.DataFrame(dict_fiber_summary, columns=[ 'Fiber', 'Predicted Pixels', 'GT Pixels', 'Percentage %' ]) df_fiber_summary.set_index('Fiber', inplace=True) df_image_summary = pd.DataFrame(dict_image_summary, columns=[ 'Found Fibers', 'Total Fibers', 'False Positive Objects' ]) df_object_summary = pd.DataFrame( dict_object_summary, columns=['Object Precision', 'Object Recall']) df_pixel_summary = pd.DataFrame( dict_pixel_summary, columns=['Pixel Precision', 'Pixel Recall']) template = r'''\documentclass[preview]{{standalone}} \usepackage{{booktabs}} \begin{{document}} {} {} {} {} \end{{document}} ''' with open(texname, 'w') as f: f.write( template.format( df_fiber_summary.to_latex( column_format='|c|c|c|c|'), df_image_summary.to_latex( column_format='|c|c|c|c|'), df_object_summary.to_latex( column_format='|c|c|c|'), df_pixel_summary.to_latex( column_format='|c|c|c|'))) subprocess.call(['pdflatex', texname]) subprocess.call([ 'magick', 'convert', '-density', '300', pdfname, '-quality', '90', tablename ]) f.close() remove(texname) remove(pdfname) remove(texname.replace('.tex', '.aux')) remove(texname.replace('.tex', '.log')) return self.precision, self.recall, self.found_fibers, self.total_fibers, self.image_percentages, self.false_positive_objects