def load_and_run_detector(model_file, image_file_names, output_dir, render_confidence_threshold=TFDetector.DEFAULT_RENDERING_CONFIDENCE_THRESHOLD, crop_images=False): """Load and run detector on target images, and visualize the results.""" if len(image_file_names) == 0: print('Warning: no files available') return start_time = time.time() tf_detector = TFDetector(model_file) elapsed = time.time() - start_time print('Loaded model in {}'.format(humanfriendly.format_timespan(elapsed))) detection_results = [] time_load = [] time_infer = [] # Dictionary mapping output file names to a collision-avoidance count. # # Since we'll be writing a bunch of files to the same folder, we rename # as necessary to avoid collisions. output_filename_collision_counts = {} def input_file_to_detection_file(fn, crop_index=-1): """Creates unique file names for output files. This function does 3 things: 1) If the --crop flag is used, then each input image may produce several output crops. For example, if foo.jpg has 3 detections, then this function should get called 3 times, with crop_index taking on 0, 1, then 2. Each time, this function appends crop_index to the filename, resulting in foo_crop00_detections.jpg foo_crop01_detections.jpg foo_crop02_detections.jpg 2) If the --recursive flag is used, then the same file (base)name may appear multiple times. However, we output into a single flat folder. To avoid filename collisions, we prepend an integer prefix to duplicate filenames: foo_crop00_detections.jpg 0000_foo_crop00_detections.jpg 0001_foo_crop00_detections.jpg 3) Prepends the output directory: out_dir/foo_crop00_detections.jpg Args: fn: str, filename crop_index: int, crop number Returns: output file path """ fn = os.path.basename(fn).lower() name, ext = os.path.splitext(fn) if crop_index >= 0: name += '_crop{:0>2d}'.format(crop_index) fn = '{}{}{}'.format(name, ImagePathUtils.DETECTION_FILENAME_INSERT, '.jpg') if fn in output_filename_collision_counts: n_collisions = output_filename_collision_counts[fn] fn = '{:0>4d}'.format(n_collisions) + '_' + fn output_filename_collision_counts[fn] += 1 else: output_filename_collision_counts[fn] = 0 fn = os.path.join(output_dir, fn) return fn for im_file in tqdm(image_file_names): try: start_time = time.time() image = viz_utils.load_image(im_file) elapsed = time.time() - start_time time_load.append(elapsed) except Exception as e: print('Image {} cannot be loaded. Exception: {}'.format(im_file, e)) result = { 'file': im_file, 'failure': TFDetector.FAILURE_IMAGE_OPEN } detection_results.append(result) continue try: start_time = time.time() result = tf_detector.generate_detections_one_image(image, im_file) detection_results.append(result) elapsed = time.time() - start_time time_infer.append(elapsed) except Exception as e: print('An error occurred while running the detector on image {}. Exception: {}'.format(im_file, e)) continue try: if crop_images: images_cropped = viz_utils.crop_image(result['detections'], image) for i_crop, cropped_image in enumerate(images_cropped): output_full_path = input_file_to_detection_file(im_file, i_crop) cropped_image.save(output_full_path) else: # image is modified in place viz_utils.render_detection_bounding_boxes(result['detections'], image, label_map=TFDetector.DEFAULT_DETECTOR_LABEL_MAP, confidence_threshold=render_confidence_threshold) output_full_path = input_file_to_detection_file(im_file) image.save(output_full_path) except Exception as e: print('Visualizing results on the image {} failed. Exception: {}'.format(im_file, e)) continue # ...for each image ave_time_load = statistics.mean(time_load) ave_time_infer = statistics.mean(time_infer) if len(time_load) > 1 and len(time_infer) > 1: std_dev_time_load = humanfriendly.format_timespan(statistics.stdev(time_load)) std_dev_time_infer = humanfriendly.format_timespan(statistics.stdev(time_infer)) else: std_dev_time_load = 'not available' std_dev_time_infer = 'not available' print('On average, for each image,') print('- loading took {}, std dev is {}'.format(humanfriendly.format_timespan(ave_time_load), std_dev_time_load)) print('- inference took {}, std dev is {}'.format(humanfriendly.format_timespan(ave_time_infer), std_dev_time_infer))
def load_and_run_detector(model_file, image_file_names, output_dir, render_confidence_threshold=TFDetector. DEFAULT_RENDERING_CONFIDENCE_THRESHOLD, crop_images=False): if len(image_file_names) == 0: print('Warning: no files available') return # load and run detector on target images, and visualize the results start_time = time.time() tf_detector = TFDetector(model_file) elapsed = time.time() - start_time print('Loaded model in {}'.format(humanfriendly.format_timespan(elapsed))) detection_results = [] time_load = [] time_infer = [] # Dictionary mapping output file names to a collision-avoidance count. # # Since we'll be writing a bunch of files to the same folder, we rename # as necessary to avoid collisions. output_filename_collision_counts = {} def input_file_to_detection_file(fn, crop_index=-1): """ Append "_detctions" to fn, prepend the output folder. Because we may be mapping many directories to one, we can have filename collisions. Resolve by adding integer suffixes for duplicate filenames. """ fn = os.path.basename(fn).lower() name, ext = os.path.splitext(fn) if crop_index >= 0: name += '_crop{:0>2d}'.format(crop_index) fn = '{}{}{}'.format(name, ImagePathUtils.DETECTION_FILENAME_INSERT, '.jpg') if fn in output_filename_collision_counts: n_collisions = output_filename_collision_counts[fn] fn = '{:0>4d}'.format(n_collisions) + '_' + fn output_filename_collision_counts[fn] = n_collisions + 1 else: output_filename_collision_counts[fn] = 0 fn = os.path.join(output_dir, fn) return fn for im_file in tqdm(image_file_names): try: start_time = time.time() image = viz_utils.load_image(im_file) elapsed = time.time() - start_time time_load.append(elapsed) except Exception as e: print('Image {} cannot be loaded. Exception: {}'.format( im_file, e)) result = { 'file': im_file, 'failure': TFDetector.FAILURE_IMAGE_OPEN } detection_results.append(result) continue try: start_time = time.time() result = tf_detector.generate_detections_one_image(image, im_file) detection_results.append(result) elapsed = time.time() - start_time time_infer.append(elapsed) except Exception as e: print( 'An error occurred while running the detector on image {}. Exception: {}' .format(im_file, e)) continue try: if crop_images: images_cropped = viz_utils.crop_image(result['detections'], image) for i_crop, cropped_image in enumerate(images_cropped): output_full_path = input_file_to_detection_file( im_file, i_crop) cropped_image.save(output_full_path) else: # image is modified in place viz_utils.render_detection_bounding_boxes( result['detections'], image, label_map=TFDetector.DEFAULT_DETECTOR_LABEL_MAP, confidence_threshold=render_confidence_threshold) output_full_path = input_file_to_detection_file(im_file) image.save(output_full_path) except Exception as e: print('Visualizing results on the image {} failed. Exception: {}'. format(im_file, e)) continue # ...for each image ave_time_load = statistics.mean(time_load) ave_time_infer = statistics.mean(time_infer) if len(time_load) > 1 and len(time_infer) > 1: std_dev_time_load = humanfriendly.format_timespan( statistics.stdev(time_load)) std_dev_time_infer = humanfriendly.format_timespan( statistics.stdev(time_infer)) else: std_dev_time_load = 'not available' std_dev_time_infer = 'not available' print('On average, for each image,') print('- loading took {}, std dev is {}'.format( humanfriendly.format_timespan(ave_time_load), std_dev_time_load)) print('- inference took {}, std dev is {}'.format( humanfriendly.format_timespan(ave_time_infer), std_dev_time_infer))