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 read_tiff_sequence(path, detectors=25, channels=1): """ Construct ArrayDetectorData from a series of TIF images on disk. The images should be named in a way that the detector channels are in a correct order ((det_0, channel_0), (det_0, channel_1), (det_1, channel_0), (det_1, channel_1)) after a simple sort. :param path: the directory that contains the images :param detectors: number of pixels in the array detectors :param channels: number of channels. Can denote photodetectors (pixel time split), color channels, time-points etc. :return: the ArrayDetectorData object that cotnains the imported data """ files = sorted(filter(lambda x: x.endswith(".tif"), os.listdir(path))) if len(files) != detectors * channels: raise RuntimeError( "The number of images does not match the data definition.") data = ArrayDetectorData(detectors, channels) steps = itertools.product(range(channels), range(detectors)) for idx, (channel, detector) in enumerate(steps): image = imread.get_image(os.path.join(path, files[idx]), bioformats=False) data[detector, channel] = image return data
def batch_evaluate_frc(path, options): """ Batch calculate FRC resolution for files placed in a directory :param options: options for the FRC :parame path: directory that contains the images to be analyzed """ assert os.path.isdir(path) measures = FourierCorrelationDataCollection() image_names = [] for idx, image_name in enumerate(sorted(os.listdir(path))): real_path = os.path.join(path, image_name) # Only process images. The bioformats reader can actually do many more file formats # but I was a little lazy here, as we usually have tiffs. if not os.path.isfile(real_path) or not real_path.endswith( (".tiff", ".tif")): continue # ImageJ files have particular TIFF tags that can be processed correctly # with the options.imagej switch image = imread.get_image(real_path) # Only grayscale images are processed. If the input is an RGB image, # a channel can be chosen for processing. measures[idx] = calculate_single_image_frc(image, options) image_names.append(image_name) return measures, image_names
def main(): path = sys.argv[1] assert os.path.isdir(path), path # Create output directory output_dir = os.path.join(path, "Subtracted") if not os.path.exists(output_dir): os.makedirs(output_dir) for image_name in os.listdir(path): real_path = os.path.join(path, image_name) if not os.path.isfile(real_path) or not real_path.endswith(".jpg"): continue image_red = read.get_image(real_path, channel=0) image_green = read.get_image(real_path, channel=1) image_sub = image_green - image_red save_name = "sub_" + image_name save_path = os.path.join(path, output_dir) save_path = os.path.join(save_path, save_name) write.image(image_sub, save_path) print("Saved %s to %s" % (save_name, save_path))
def main(): options = miplib_entry_point_options.get_power_script_options(sys.argv[1:]) path = options.working_directory assert os.path.isdir(path) # Create output directory output_dir = datetime.datetime.now().strftime("%Y-%m-%d") + '_PyIQ_output' output_dir = os.path.join(options.working_directory, output_dir) if not os.path.exists(output_dir): os.makedirs(output_dir) # Create output file date_now = datetime.datetime.now().strftime("%H-%M-%S") file_name = date_now + '_PyIQ_power_spectra' + '.csv' file_path = os.path.join(output_dir, file_name) csv_data = pandas.DataFrame() # Scan through images for image_in in os.listdir(path): if not image_in.endswith((".jpg", ".tif", ".tiff", ".png")): continue path_in = os.path.join(path, image_in) # Get image image = read.get_image(path_in, channel=options.rgb_channel) image = improc.crop_to_rectangle(image) for dim in image.shape: if dim != options.image_size: image = improc.resize(image, options.image_size) break task = filters.FrequencyQuality(image, options) task.calculate_power_spectrum() task.calculate_summed_power() power_spectrum = task.get_power_spectrum() csv_data[image_in] = power_spectrum[1] csv_data.insert(0, "Power", numpy.linspace(0, 1, num=len(csv_data))) csv_data.to_csv(file_path, index=False)
def main(): path = sys.argv[1] assert os.path.isdir(path), path channel = sys.argv[2] # Create output directory output_dir = os.path.join(path, "Extracted") if not os.path.exists(output_dir): os.makedirs(output_dir) for image_name in os.listdir(path): real_path = os.path.join(path, image_name) if not os.path.isfile(real_path): continue image = read.get_image(real_path, channel=channel) save_name = "channel_" + channel + "_" + image_name save_path = os.path.join(path, output_dir) save_path = os.path.join(save_path, save_name) write.image(image, save_path) print("Saved %s to %s" % (save_name, save_path))
def main(): args = options.get_deconvolve_script_options(sys.argv[1:]) # Load image image_name = args.image dir = args.working_directory image_path = os.path.join(dir, image_name) # Figure out an image type and use the correct loader. if image_path.endswith('.tif'): image = imread.get_image(image_path) elif image_path.endswith('.mat'): image = imread.get_image(image_path)[args.carma_gate_idx, args.carma_det_idx] else: raise AttributeError("Unknown image type %s" % image_path.split('.')[-1]) # Load/Generate PSF if args.psf == "estimate": psf = psfgen.PSF(psftype=args.psf_type, shape=args.psf_shape, dims=args.psf_size, ex_wavelen=args.ex_wl, em_wavelen=args.em_wl, num_aperture=args.na, refr_index=args.refractive_index, magnification=args.magnification, pinhole_radius=args.pinhole_radius) if args.sted_psf: psf.sted_correction(args.sted_phi, args.sted_sigma) psf_image = psf.volume() psf_spacing = psf.dims['um'][0] / psf.shape[0] if image.get_dimensions()[0] == 1: psf_image = psf_image[psf_image.shape / 2] psf = image.Image(psf_image, psf_spacing) else: psf = image.Image.get_image_from_imagej_tiff(args.psf_path) # Start deconvolution if cuda_compatible(): print("Found a compatible GPU. The image deconvolution will be run with " \ "hardware acceleration.") task = deconvolve_cuda.DeconvolutionRLCuda(image, psf, args) else: task = deconvolve.DeconvolutionRL(image, psf, args) begin = time.time() task.execute() end = time.time() result = task.get_result() print("Deconvolution complete.") print("The deconvolution process with %i iterations " \ "took %s (H:M:S) to complete." % (args.max_nof_iterations, ops_output.format_time_string( end - begin))) if uiutils.get_user_input("Do you want to save the result to TIFF? "): file_path = os.path.join(args.working_directory, "fusion_result.tif") result.save_to_tiff(file_path)
def main(): options = miplib_entry_point_options.get_import_script_options(sys.argv[1:]) directory = options.data_dir_path # Create a new HDF5 file. If a file exists, new data will be appended. file_name = input("Give a name for the HDF5 file: ") file_name += ".hdf5" data_path = os.path.join(directory, file_name) data = image_data.ImageData(data_path) # Add image files that have been named according to the correct format for image_name in os.listdir(directory): full_path = os.path.join(directory, image_name) if full_path.endswith((".tiff", ".tif", ".mhd", ".mha")): images = read.get_image(full_path) spacing = images.spacing else: continue if options.normalize_inputs: images = (images * (255.0/images.max())).astype(numpy.uint8) if not all(x in image_name for x in params_c) or not any(x in image_name for x in image_types_c): print("Unrecognized image name %s. Skipping it." % image_name) continue image_type = image_name.split("_scale")[0] scale = image_name.split("scale_")[-1].split("_index")[0] index = image_name.split("index_")[-1].split("_channel")[0] channel = image_name.split("channel_")[-1].split("_angle")[0] angle = image_name.split("angle_")[-1].split(".")[0] assert all(x.isdigit() for x in (scale, index, channel, angle)) # data, angle, spacing, index, scale, channel, chunk_size=None if image_type == "original": data.add_original_image(images, scale, index, channel, angle, spacing) elif image_type == "registered": data.add_registered_image(images, scale, index, channel, angle, spacing) elif image_type == "psf": data.add_psf(images, scale, index, channel, angle, spacing) # Calculate resampled images if options.scales is not None: for scale in options.scales: print("Creating %s percent downsampled versions of the original images" % scale) data.create_rescaled_images("original", scale) # Add transforms for registered images. for transform_name in os.listdir(directory): if not transform_name.endswith(".txt"): continue if not all(x in transform_name for x in params_c) or not "transform" in transform_name: print("Unrecognized transform name %s. Skipping it." % transform_name) continue scale = transform_name.split("scale_")[-1].split("_index")[0] index = transform_name.split("index_")[-1].split("_channel")[0] channel = transform_name.split("channel_")[-1].split("_angle")[0] angle = transform_name.split("angle_")[-1].split(".")[0] full_path = os.path.join(directory, transform_name) # First calculate registered image if not in the data structure if not data.check_if_exists("registered", index, channel, scale): print("Resampling registered image for image nr. ", index) data.set_active_image(0, channel, scale, "original") reference = data.get_itk_image() data.set_active_image(index, channel, scale, "original") moving = data.get_itk_image() transform = read.__itk_transform(full_path, return_itk=True) registered = itkutils.resample_image(moving, transform, reference=reference) registered = itkutils.convert_from_itk_image(registered) spacing = registered.spacing data.add_registered_image(registered, scale, index, channel, angle, spacing) # The add it's transform transform_type, params, fixed_params = read.__itk_transform(full_path) data.add_transform(scale, index, channel, params, fixed_params, transform_type) # Calculate missing PSFs if options.calculate_psfs: data.calculate_missing_psfs() if options.copy_registration_result != -1: from_scale = options.copy_registration_result[0] to_scale = options.copy_registration_result[1] data.copy_registration_result(from_scale, to_scale) data.close()
def main(): options = supertomo_options.get_transform_script_options(sys.argv[1:]) fixed_image = None moving_image = None transform = None if options.hdf: raise NotImplementedError("Only single image files are supported " "currently") else: # CHECK FILES # Check that the fixed image exists fixed_image_path = os.path.join( options.working_directory, options.fixed_image ) if not os.path.isfile(fixed_image_path): raise ValueError('No such file: %s' % options.fixed_image) # Check that the EM image exists moving_image_path = os.path.join( options.working_directory, options.moving_image) if not os.path.isfile(moving_image_path): raise ValueError('No such file: %s' % options.moving_image) transform_path = os.path.join( options.working_directory, options.transform) if not os.path.isfile(transform_path): raise ValueError('No such file: %s' % options.transform) # READ FILES fixed_image = ioutils.get_image(fixed_image_path, return_itk=True) moving_image = ioutils.get_image(moving_image_path, return_itk=True) transform = ioutils.__itk_transform(transform_path, return_itk=True) transformed_image = itkutils.resample_image(moving_image, transform, fixed_image) # OUTPUT ########################################################################## output_dir = datetime.datetime.now().strftime("%Y-%m-%d") + '_supertomo_out' output_dir = os.path.join(options.working_directory, output_dir) if not os.path.exists(output_dir): os.makedirs(output_dir) # Files are named according to current time (the date will be # in the folder name) date_now = datetime.datetime.now().strftime("%H-%M-%S") file_name = date_now + '_transformed.mha' rgb_image = itkutils.make_composite_rgb_image(fixed_image, transformed_image) image_path = os.path.join(output_dir, file_name) sitk.WriteImage(rgb_image, image_path)
def main(): """ The Main program of the PyImageQualityRanking software. """ options = miplib_entry_point_options.get_quality_script_options( sys.argv[1:]) path = options.working_directory file_path = None csv_data = None print("Mode option is %s" % options.mode) if "file" in options.mode: # In "file" mode a single file is analyzed and the various parameter # values are printed on screen. This functionality is provided mainly # for debugging purposes. assert options.file is not None, "You have to specify a file with a " \ "--file option" path = os.path.join(path, options.file) assert os.path.isfile(path) image = read.get_image(path, channel=options.rgb_channel) print("The shape is %s" % str(image.shape)) task = filters.LocalImageQuality(image, options) task.set_smoothing_kernel_size(100) entropy = task.calculate_image_quality() task2 = filters.FrequencyQuality(image, options) finfo = task2.analyze_power_spectrum() print("SPATIAL MEASURES:") print("The entropy value of %s is %f" % (path, entropy)) print("ANALYSIS OF THE POWER SPECTRUM TAIL") print("The mean is: %e" % finfo[0]) print("The std is: %e" % finfo[1]) print("The entropy is %e" % finfo[2]) print("The threshold frequency is %f Hz" % finfo[3]) print("Power at high frequencies %e" % finfo[4]) print("The skewness is %f" % finfo[5]) print("The kurtosis is %f" % finfo[6]) if "directory" in options.mode: # In directory mode every image in a given directory is analyzed in a # single run. The analysis results are saved into a csv file. assert os.path.isdir(path), path # Create output directory output_dir = datetime.datetime.now().strftime( "%Y-%m-%d") + '_PyIQ_output' output_dir = os.path.join(options.working_directory, output_dir) if not os.path.exists(output_dir): os.makedirs(output_dir) # Create output file date_now = datetime.datetime.now().strftime("%H-%M-%S") file_name = date_now + '_PyIQ_out' + '.csv' file_path = os.path.join(output_dir, file_name) output_file = open(file_path, 'wt') output_writer = csv.writer(output_file, quoting=csv.QUOTE_NONNUMERIC, delimiter=",") output_writer.writerow( ("Filename", "tEntropy", "tBrenner", "fMoments", "fMean", "fSTD", "fEntropy", "fTh", "fMaxPw", "Skew", "Kurtosis", "MeanBin")) for image_name in 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", ".png")): continue # ImageJ files have particular TIFF tags that can be processed correctly # with the options.imagej switch image = read.get_image(path, channel=options.rgb_channel) # Only grayscale images are processed. If the input is an RGB image, # a channel can be chosen for processing. # Time series sometimes contain images of very different content: the start # of the series may show nearly empty (black) images, whereas at the end # of the series the whole field-of-view may be full of cells. Ranking such # dataset in a single piece may be challenging. Therefore the beginning of # the dataset can be separated from the end, by selecting a minimum value # for average grayscale pixel value here. if options.average_filter > 0 and image.average( ) < options.average_filter: continue # Run spatial domain analysis task = filters.LocalImageQuality(image, options) task.set_smoothing_kernel_size(100) entropy = task.calculate_image_quality() # Run frequency domain analysis task2 = filters.FrequencyQuality(image, options) results = task2.analyze_power_spectrum() task3 = filters.SpectralMoments(image, options) moments = task3.calculate_spectral_moments() task4 = filters.BrennerImageQuality(image, options) brenner = task4.calculate_brenner_quality() # Save results results.insert(0, moments) results.insert(0, brenner) results.insert(0, entropy) results.insert(0, os.path.join(path, image_name)) output_writer.writerow(results) print("Done analyzing %s" % image_name) output_file.close() print("The results were saved to %s" % file_path) if "analyze" in options.mode: # In analyze mode the previously created quality ranking variables are # normalized to the highest value of every given variable. In addition # some new parameters are calculated. The results are saved into a new # csv file. if file_path is None: assert options.file is not None, "You have to specify a data file" \ "with the --file option" path = os.path.join(options.working_directory, options.file) print(path) file_path = path assert os.path.isfile(path), "Not a valid file %s" % path assert path.endswith( ".csv"), "Unknown suffix %s" % path.split(".")[-1] csv_data = pandas.read_csv(file_path) csv_data["cv"] = csv_data.fSTD / csv_data.fMean csv_data["SpatEntNorm"] = csv_data.tEntropy / csv_data.tEntropy.max() csv_data["SpectMean"] = csv_data.fMean / csv_data.fMean.max() csv_data["SpectSTDNorm"] = csv_data.fSTD / csv_data.fSTD.max() csv_data["InvSpectSTDNorm"] = 1 - csv_data.SpectSTDNorm csv_data["SpectEntNorm"] = csv_data.fEntropy / csv_data.fEntropy.max() csv_data["SkewNorm"] = 1 - abs(csv_data.Skew) / abs( csv_data.Skew).max() csv_data["KurtosisNorm"] = abs(csv_data.Kurtosis) / abs( csv_data.Kurtosis).max() csv_data["SpectHighPowerNorm"] = csv_data.fMaxPw / csv_data.fMaxPw.max( ) csv_data["MeanBinNorm"] = csv_data.MeanBin / csv_data.MeanBin.max() csv_data["BrennerNorm"] = csv_data.tBrenner / csv_data.tBrenner.max() csv_data[ "SpectMomentsNorm"] = csv_data.fMoments / csv_data.fMoments.max() # Create output directory output_dir = datetime.datetime.now().strftime( "%Y-%m-%d") + '_PyIQ_output' output_dir = os.path.join(options.working_directory, output_dir) if not os.path.exists(output_dir): os.makedirs(output_dir) date_now = datetime.datetime.now().strftime("%H-%M-%S") file_name = date_now + '_PyIQ_analyze_out' + '.csv' file_path = os.path.join(output_dir, file_name) csv_data.to_csv(file_path) print("The results were saved to %s" % file_path) if "plot" in options.mode: # With the plot option the dataset is sorted according to the desired ranking variable. # The changes are saved to the original csv file. In addition a plot is created to show # a subset of highest and lowest ranked images (the amount of images to show is # controlled by the options.npics parameter if csv_data is None: file_path = os.path.join(options.working_directory, options.file) assert os.path.isfile(file_path), "Not a valid file %s" % path assert path.endswith( ".csv"), "Unknown suffix %s" % path.split(".")[-1] csv_data = pandas.read_csv(file_path) if options.result == "average": csv_data["Average"] = csv_data[["InvSpectSTDNorm", "SpatEntNorm"]].mean(axis=1) csv_data.sort(columns="Average", ascending=False, inplace=True) elif options.result == "fskew": csv_data.sort(columns="SkewNorm", ascending=False, inplace=True) elif options.result == "fentropy": csv_data.sort(columns="SpectEntNorm", ascending=False, inplace=True) elif options.result == "ientropy": csv_data.sort(columns="SpatEntNorm", ascending=False, inplace=True) elif options.result == "icv": csv_data.sort(columns="SpatEntNorm", ascending=False, inplace=True) elif options.result == "fstd": csv_data.sort(columns="SpectSTDNorm", ascending=False, inplace=True) elif options.result == "fkurtosis": csv_data.sort(columns="KurtosisNorm", ascending=False, inplace=True) elif options.result == "fpw": csv_data.sort(columns="SpectHighPowerNorm", ascending=False, inplace=True) elif options.result == "fmean": csv_data.sort(columns="SpectHighPowerNorm", ascending=False, inplace=True) elif options.result == "meanbin": csv_data.sort(columns="MeanBinNorm", ascending=False, inplace=True) else: print("Unknown results sorting method %s" % options.result) sys.exit() best_pics = csv_data["Filename"].head(options.npics).as_matrix() worst_pics = csv_data["Filename"].tail(options.npics).as_matrix() show_pics_from_disk(best_pics, title="BEST PICS") show_pics_from_disk(worst_pics, title="WORST PICS") csv_data.to_csv(file_path, index=False)
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)