def test_with_ax(fake_points_of_interest): fig, ax = plt.subplots(figsize=(20, 5)) points_interest, true_results_pix, true_results_mm = fake_points_of_interest axes = [ax] + [None] * 6 dist_pix, dist_mm = measurement.main(points_interest, 2) assert dist_pix == true_results_pix assert dist_mm == true_results_mm
def test_t_space_unchanged(fake_points_of_interest): # tests with simple t_space = 1 that everything remains the same. points_interest, true_results_pix, true_results_mm = fake_points_of_interest dist_pix, dist_mm = measurement.main(points_interest, 1) assert dist_pix == true_results_pix assert dist_mm == true_results_pix
def test_different_t_space(fake_points_of_interest): points_interest, true_results_pix, true_results_mm = fake_points_of_interest dist_pix, dist_mm = measurement.main(points_interest, 2) assert dist_pix == true_results_pix assert dist_mm == true_results_mm
def main(): # Assign description to the help doc parser = argparse.ArgumentParser( description='This is mothra, a software to automate different\ measurements on images of Lepidopterae.') # Add arguments # Plotting parser.add_argument('-p', '--plot', action='store_true', help='If entered images are plotted to the output\ folder') parser.add_argument('-pp', '--detailed_plot', action='store_true', help='If entered detailed images are plotted to the\ output folder') # Input path parser.add_argument('-i', '--input', type=str, help='Input path for single image, folder or text\ file (extension txt) containing paths', required=False, default='input_images') # Output path parser.add_argument('-o', '--output_folder', type=str, help='Output path for raw image', required=False, default='outputs') # Stage parser.add_argument('-s', '--stage', type=str, help="Stage name: 'binarization', 'ruler_detection',\ 'measurements'", required=False, default='measurements') # Dots per inch parser.add_argument('-dpi', type=int, help='Dots per inch of the saved figures', default=300) # CSV output path parser.add_argument('-csv', '--path_csv', type=str, help='Path of the resulting csv file', default='outputs/results.csv') # Disable cache parser.add_argument( '--cache', action='store_true', help='Enable computation cache (useful when developing algorithms)') args = parser.parse_args() # Initialization if os.path.exists(args.output_folder): oldList = os.listdir(args.output_folder) for oldFile in oldList: os.remove(args.output_folder + "/" + oldFile) else: os.mkdir(args.output_folder) stages = ['ruler_detection', 'binarization', 'measurements'] if args.stage not in stages: print((f"* mothra expects stage to be 'ruler_detection', " f"binarization', or 'measurements'. Received '{args.stage}'")) return None plot_level = 0 if args.plot: plot_level = 1 if args.detailed_plot: plot_level = 2 # initializing the csv file. if args.stage == 'measurements': initialize_csv_file(csv_fname=args.path_csv) stage_idx = stages.index(args.stage) pipeline_process = stages[:stage_idx + 1] # reading and processing input path. input_name = args.input image_paths = _process_paths_in_input(input_name) number_of_images = len(image_paths) # Set up caching and import motha modules if args.cache: from mothra import cache import joblib cache.memory = joblib.Memory('./cachedir', verbose=0) from mothra import (ruler_detection, tracing, measurement, binarization, identification) for i, image_path in enumerate(image_paths): try: # creating axes layout for plotting. axes = create_layout(len(pipeline_process), plot_level) image_name = os.path.basename(image_path) print(f'Image {i+1}/{number_of_images} : {image_name}') image_rgb = imread(image_path) # check image orientation and untilt it, if necessary. angle = read_orientation(image_path) if angle not in (None, 0): # angle == 0 does not need untilting image_rgb = img_as_ubyte( rotate(image_rgb, angle=angle, resize=True)) for step in pipeline_process: # first, binarize the input image and return its components. _, ruler_bin, lepidop_bin = binarization.main(image_rgb, axes) if step == 'ruler_detection': T_space, top_ruler = ruler_detection.main( image_rgb, ruler_bin, axes) elif step == 'binarization': # already binarized in the beginning. Moving on... pass elif step == 'measurements': points_interest = tracing.main(lepidop_bin, axes) _, dist_mm = measurement.main(points_interest, T_space, axes) # measuring position and gender position, gender = identification.main(image_rgb) with open(args.path_csv, 'a') as csv_file: _write_csv_data(csv_file, image_name, dist_mm, position, gender) if plot_level > 0: output_path = os.path.normpath( os.path.join(args.output_folder, image_name)) dpi = args.dpi if plot_level == 2: dpi = int(1.5 * args.dpi) plt.savefig(output_path, dpi=dpi) plt.close() except Exception as exc: print( f"* Sorry, could not process {image_path}. More details:\n {exc}" ) continue