def batch_evaluate_image_quality(path, options): """ Batch calculate quality features for images in a directory :param options: options for the quality ranking scripts, as in miplib/ui/image_quality_options.py :parame path: directory that contains the images to be analyzed """ df = pd.DataFrame(columns=["Filename", "tEntropy", "tBrenner", "fMoments", "fMean", "fSTD", "fEntropy", "fTh", "fMaxPw", "Skew", "Kurtosis", "MeanBin", "Resolution"]) for idx, image_name in enumerate(os.listdir(path)): if options.file_filter is None or options.file_filter in image_name: real_path = os.path.join(path, image_name) # Only process images if not os.path.isfile(real_path) or not real_path.endswith((".jpg", ".tif", ".tiff", ".tif")): continue # ImageJ files have particular TIFF tags that can be processed correctly # with the options.imagej switch image = read.get_image(real_path, channel=options.rgb_channel) # Only grayscale images are processed. If the input is an RGB image, # a channel can be chosen for processing. results = evaluate_image_quality(image, options) results.insert(0, real_path) # Add resolution value to the end results.append(frc.calculate_single_image_frc(image, options).resolution["resolution"]) df.loc[idx] = results print ("Done analyzing {}".format(image_name)) return df
def generate_frc_based_psf(image, args): fwhm = [ frc.calculate_single_image_frc(image, args).resolution["resolution"], ] * 2 psf_generator = PsfFromFwhm(fwhm) if image.ndim == 2: return psf_generator.xy() else: return psf_generator.volume()
def __init__(self, image, psf, writer, options): """ :param image: a MyImage object :param options: command line options that control the behavior of the fusion algorithm """ assert isinstance(image, Image) assert isinstance(psf, Image) if options.save_intermediate_results: assert issubclass(writer.__class__, ImageWriterBase) self.image = image self.psf = psf self.options = options self.writer = writer self.image_size = numpy.array(self.image.shape) self.image_spacing = self.image.spacing self.psf_spacing = self.psf.spacing self.imdims = image.ndim self.__get_psfs() if options.verbose: print("The original image size is %s" % (self.image_size, )) self.iteration_count = 0 # Setup blocks self.num_blocks = options.num_blocks self.block_size, self.image_size = self.__calculate_block_and_image_size( ) self.memmap_directory = tempfile.mkdtemp() # Memmap the estimates to reduce memory requirements. This will slow # down the fusion process considerably.. if self.options.memmap_estimates: estimate_new_f = os.path.join(self.memmap_directory, "estimate_new.dat") self.estimate_new = Image( numpy.memmap(estimate_new_f, dtype='float32', mode='w+', shape=tuple(self.image_size)), self.image_spacing) estimate_f = os.path.join(self.memmap_directory, "estimate.dat") self.estimate = Image( numpy.memmap(estimate_f, dtype=numpy.float32, mode='w+', shape=tuple(self.image_size)), self.image_spacing) else: self.estimate = Image( numpy.zeros(tuple(self.image_size), dtype=numpy.float32), self.image_spacing) self.estimate_new = Image( numpy.zeros(tuple(self.image_size), dtype=numpy.float32), self.image_spacing) if not self.options.disable_tau1: prev_estimate_f = os.path.join(self.memmap_directory, "prev_estimate.dat") self.prev_estimate = Image( numpy.memmap(prev_estimate_f, dtype=numpy.float32, mode='w+', shape=tuple(self.image_size)), self.image_spacing) padded_block_size = tuple(i + 2 * self.options.block_pad for i in self.block_size) if options.verbose: print("The deconvolution will be run with %i blocks" % self.num_blocks) print("The internal block size is %s" % (padded_block_size, )) # Create temporary directory and data file. self.column_headers = ('t', 'tau1', 'leak', 'e', 's', 'u', 'n', 'uesu') self._progress_parameters = numpy.empty( (self.options.max_nof_iterations, len(self.column_headers)), dtype=numpy.float32) # Get initial resolution (in case you are using the FRC based stopping.) if self.options.rl_frc_stop > 0: self.resolution = frc.calculate_single_image_frc( self.image, self.options).resolution["resolution"] # Enable automatic background correction with --rl-auto-background if self.options.rl_auto_background: background_mask = masking.make_local_intensity_based_mask( image, threshold=30, kernel_size=60, invert=True) masked_image = Image(image * background_mask, image.spacing) self.options.rl_background = numpy.mean( masked_image[masked_image > 0])
def execute(self): """ This is the main fusion function """ save_intermediate_results = self.options.save_intermediate_results first_estimate = self.options.first_estimate if first_estimate == 'image': self.estimate[:] = self.image[:].astype(numpy.float32) elif first_estimate == 'blurred': self.estimate[:] = uniform_filter(self.image, 3).astype(numpy.float32) elif first_estimate == 'image_mean': self.estimate[:] = numpy.float32(numpy.mean(self.image[:])) elif first_estimate == 'constant': self.estimate[:] = numpy.float32(self.options.estimate_constant) else: raise NotImplementedError(repr(first_estimate)) self.iteration_count = 0 max_count = self.options.max_nof_iterations initial_photon_count = self.image[:].sum() bar = ops_output.ProgressBar(0, max_count, totalWidth=40, show_percentage=False) self._progress_parameters = numpy.zeros( (self.options.max_nof_iterations, len(self.column_headers)), dtype=numpy.float32) # duofrc_prev = 0 # The Fusion calculation starts here # ==================================================================== try: while True: if (self.options.update_blind_psf > 0 and self.iteration_count > 0 and (self.iteration_count + 1) % self.options.update_blind_psf == 0): self.psf = psfgen.generate_frc_based_psf( Image(self.estimate, self.image_spacing), self.options) self.__get_psfs() self.image = self.estimate.copy() info_map = {} ittime = time.time() self.prev_estimate[:] = self.estimate.copy() e, s, u, n = self.compute_estimate() self.iteration_count += 1 photon_leak = 1.0 - (e + s + u) / initial_photon_count u_esu = u / (e + s + u) tau1 = abs(self.estimate - self.prev_estimate).sum() / abs( self.prev_estimate).sum() info_map['TAU1=%s'] = tau1 t = time.time() - ittime leak = 100 * photon_leak if self.options.verbose: # Update UI info_map['E/S/U/N=%s/%s/%s/%s'] = int(e), int(s), int( u), int(n) info_map['LEAK=%s%%'] = leak info_map['U/ESU=%s'] = u_esu info_map['TIME=%ss'] = t bar.updateComment(' ' + ', '.join([ k % (ops_output.tostr(info_map[k])) for k in sorted(info_map) ])) bar(self.iteration_count) print() # Save parameters to file self._progress_parameters[self.iteration_count - 1] = (t, tau1, leak, e, s, u, n, u_esu) # Save intermediate image if save_intermediate_results: # self.temp_data.save_image( # self.estimate, # 'result_%s.tif' % self.iteration_count # ) self.writer.write(Image(self.estimate, self.image_spacing)) # Check if it's time to stop: if int(u) == 0 and int(n) == 0: stop_message = 'The number of non converging photons reached to zero.' break elif self.iteration_count >= max_count: stop_message = 'The number of iterations reached to maximal count: %s' % max_count break elif not self.options.disable_tau1 and tau1 <= self.options.stop_tau: stop_message = 'Desired tau-threshold achieved' break elif self.options.rl_frc_stop > 0: resolution_new = frc.calculate_single_image_frc( Image(self.estimate, self.image_spacing), self.options).resolution["resolution"] frc_diff = numpy.abs(self.resolution - resolution_new) if frc_diff <= self.options.rl_frc_stop: print('Desired FRC diff reached after {} iterations'. format(self.iteration_count)) break else: self.resolution = resolution_new # elif self.iteration_count >= 4 and abs(frc_diff) <= .0001: # stop_message = 'FRC stop condition reached' # break else: continue except KeyboardInterrupt: stop_message = 'Iteration was interrupted by user.' # if self.num_blocks > 1: # self.estimate = self.estimate[0:real_size[0], 0:real_size[1], 0:real_size[2]] if self.options.verbose: print() bar.updateComment(' ' + stop_message) bar(self.iteration_count) print()
def main(): # Get input arguments args = options.get_frc_script_options(sys.argv[1:]) path = args.directory # Create output directory output_dir = args.directory date_now = datetime.datetime.now().strftime("%H-%M-%S") filename = "{}_miplib_{}_frc_results.csv".format(date_now, args.frc_mode) filename = os.path.join(output_dir, filename) # Get image file names, sort in alphabetic order and complete. files_list = list(i for i in os.listdir(path) if i.endswith((".jpg", ".tif", ".tiff", ".png"))) files_list.sort() print('Number of images to analyze: {}'.format(len(files_list))) #df_main = pandas.DataFrame(0, index=np.arange(len(files_list)), columns=["Image", "Depth", "Kind", "Resolution"]) df_main = pandas.DataFrame(0, index=np.arange(len(files_list)), columns=["Image", "Resolution"]) if args.frc_mode == "two-image": def pairwise(iterable): a = iter(iterable) return zip(a, a) for idx, im1, im2 in enumerate(pairwise(files_list)): # Read images image1 = imread.get_image(os.path.join(path, im1)) image2 = imread.get_image(os.path.join(path, im2)) result = frc.calculate_two_image_frc(image1, image2, args) title = strutils.common_start(im1, im2) resolution = result.resolution['resolution'] df_main.iloc[idx] = title, resolution elif args.frc_mode == "one-image": for idx, im in enumerate(files_list): image = imread.get_image(os.path.join(path, im)) print("Analyzing image {}".format(im)) result = frc.calculate_single_image_frc(image, args) title = im.split('.')[0] # I left these snippets here to show how one can add additional info # to the dataframes in particular use cases. #depth = title.split('um_')[0].split("_")[-1] # kind = None # for x in ("apr_ism", "apr_ism_bplus", "closed", "open", "static_ism", "ism_sim"): # if x in title: # kind = x # if kind is None: # raise RuntimeError("Unknown image: {}".format(title)) resolution = result.resolution['resolution'] #df_main.iloc[idx] = title, depth, kind, resolution df_main.iloc[idx] = title, resolution else: raise NotImplementedError() df_main.index = list(range(len(df_main))) df_main.to_csv(filename)