def segment_background(arguments): # parse segmentation method try: seg_method_enum = SegmentationMethods(arguments.method) TerminalColors.formatted_print("Segmentation method: " + seg_method_enum.name, TerminalColors.OKBLUE) except ValueError: raise ValueError("invalid segmentation method: " + arguments.method) # create segmentation object and perform segmentation if seg_method_enum == SegmentationMethods.BACKGROUND_SUBTRACTION: bg_segmentor = BackgroundSubtraction(arguments.data_directory, arguments.class_annotations) else: raise ValueError('unsupported segmentation method: ' + seg_method_enum.name) bg_segmentor.segment()
def collect_images(topic_name, image_dir, class_ann_file, sleep_time): TerminalColors.formatted_print('Image directory: ' + image_dir, TerminalColors.OKBLUE) if not os.path.isdir(image_dir): if prompt_for_yes_or_no( "'{}' does not exist, create it?".format(image_dir)): print('creating ' + image_dir) os.mkdir(image_dir) else: TerminalColors.formatted_print( "Not creating '{}'. Exiting program.".format(image_dir), TerminalColors.WARNING) return TerminalColors.formatted_print('class annotation file: ' + class_ann_file, TerminalColors.OKBLUE) if not os.path.exists(class_ann_file): raise RuntimeError("Class annotation file does not exist: " + class_ann_file) with open(class_ann_file, 'r') as infile: class_dict = yaml.load(infile, Loader=yaml.FullLoader) bridge = cv_bridge.CvBridge() for cls_id, cls_name in class_dict.items(): cls_img_dir = os.path.join(image_dir, cls_name) TerminalColors.formatted_print( "collecting images for class '{}' in '{}'".format( cls_name, cls_img_dir), TerminalColors.BOLD) if not os.path.isdir(cls_img_dir): print("creating '{}'".format(cls_img_dir)) os.mkdir(cls_img_dir) while True: num_image = int( prompt_for_float('please enter number of images to take')) if num_image < 1: TerminalColors.formatted_print( 'please input a positive integer for the number of images', TerminalColors.WARNING) continue collect_images_single_class(bridge, topic_name, cls_img_dir, cls_name, num_image, sleep_time) if not prompt_for_yes_or_no( "do you want to take more pictures for class '{}' (e.g. different pespective)?" .format(cls_name)): break
def __init__(self, class_id, obj_img_dir, obj_mask_dir): self.class_id = class_id # check directories if not os.path.isdir(obj_img_dir): raise RuntimeError( "image folder '{}' is not an existing directory".format( obj_img_dir)) if not os.path.isdir(obj_mask_dir): raise RuntimeError( "mask folder '{}' is not an existing directory".format( obj_mask_dir)) # glob object images obj_img_paths = glob_extensions_in_directory(obj_img_dir, ALLOWED_IMAGE_EXTENSIONS) if not obj_img_paths: raise RuntimeError( "found no image of supported types in '{}'".format( obj_img_dir)) # load images and masks print("found '{}' object images in '{}'".format( len(obj_img_paths), obj_img_dir)) self._segmented_objects = [] for img_path in obj_img_paths: # check expected path to mask mask_path = get_image_mask_path(img_path, obj_mask_dir) if not os.path.exists(mask_path): TerminalColors.formatted_print( "skipping image '{}': mask '{}' does not exist".format( img_path, mask_path), TerminalColors.WARNING) continue # add SegmentedObject instance for image-mask pair try: self._segmented_objects.append( SegmentedObject(img_path, mask_path)) except Exception as e: TerminalColors.formatted_print( "failed to process image '{}' and mask '{}': {}".format( img_path, mask_path, e), TerminalColors.FAIL) continue
def __init__(self, data_dir, class_annotation_file, confirmation=True): self._confirmation = confirmation # check data directory self._data_dir = data_dir TerminalColors.formatted_print("Data directory: " + data_dir, TerminalColors.OKBLUE) if not os.path.isdir(self._data_dir): raise RuntimeError("'{}' is not an existing directory".format(self._data_dir)) # check directory with green box images self._image_dir = os.path.join(data_dir, 'green_box_images') if not os.path.isdir(self._image_dir): raise RuntimeError("'{}' is not an existing directory".format(self._image_dir)) # check directory to store object masks self._mask_dir = os.path.join(data_dir, 'object_masks') TerminalColors.formatted_print("Will generate object masks to: " + self._mask_dir, TerminalColors.OKBLUE) if not os.path.exists(self._mask_dir): print("creating directory '{}'".format(self._mask_dir)) os.mkdir(self._mask_dir) elif os.listdir(self._mask_dir) and self._confirmation: if not prompt_for_yes_or_no("Mask directory '{}' not empty, overwrite?".format(self._mask_dir)): raise RuntimeError("directory '{}' not empty, not overwriting".format(self._mask_dir)) # load class annotation file if not os.path.exists(class_annotation_file): raise RuntimeError("class annotation YAML does not exist: " + class_annotation_file) with open(class_annotation_file, 'r') as infile: self._class_dict = yaml.load(infile, Loader=yaml.FullLoader) TerminalColors.formatted_print("Found '{}' classes in annotation file '{}'" .format(len(self._class_dict), class_annotation_file), TerminalColors.OKBLUE)
def generate_masks_and_annotations(data_dir, class_annotation_file, output_dir, output_annotation_dir, display_boxes): augmenter = ImageAugmenter(data_dir, class_annotation_file) if not output_dir: output_dir = os.path.join(data_dir, 'synthetic_images') if not output_annotation_dir: output_annotation_dir = os.path.join(data_dir, 'annotations') TerminalColors.formatted_print("begin generating images under '{}' and annotation files under '{}'" .format(output_dir, output_annotation_dir), TerminalColors.OKBLUE) if not os.path.isdir(output_dir): print("creating directory: " + output_dir) os.mkdir(output_dir) if not os.path.isdir(output_annotation_dir): print("creating directory: " + output_annotation_dir) os.mkdir(output_annotation_dir) while True: # ask user for split name, number of images to generate per background, and maximum # number of objects per background split_name = None while not split_name: split_name = input("please enter split name (e.g. 'go2019_train'): ") num_image_per_bg = -1 while num_image_per_bg < 0: num_image_per_bg = int(prompt_for_float("please enter the number of images to be generated" " for each background")) max_obj_num_per_bg = -1 max_obj_num_per_bg = int(prompt_for_float("please enter the maximum number of objects to be projected" " onto each background")) # generate images augmenter.generate_detection_data(split_name, output_dir, output_annotation_dir, num_image_per_bg, max_obj_num_per_bg, display_boxes=display_boxes) if not prompt_for_yes_or_no("do you want to generate images for another dataset split?"): break
def segment(self): for class_name in self._class_dict.values(): # check directory containing object images class_img_dir = os.path.join(self._image_dir, class_name) if not os.path.isdir(class_img_dir): TerminalColors.formatted_print("skipping class '{}': '{}' is not an existing directory" .format(class_name, class_img_dir), TerminalColors.WARNING) continue # glob all supported image files & warn if no image found image_paths = glob_extensions_in_directory(class_img_dir, ALLOWED_IMAGE_EXTENSIONS) if not image_paths: TerminalColors.formatted_print( "skipping class '{}': directory '{}' does not contain any supported images" .format(class_name, class_img_dir), TerminalColors.WARNING) continue # Handle algorithm-specific segmentation TerminalColors.formatted_print("Generating masks for class '{}' from '{}' images" .format(class_name, len(image_paths)), TerminalColors.BOLD) self._segment_class(class_name, image_paths)
break if __name__ == '__main__': parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter, description="Script to generate training images and annotations for bounding box based object detection." " This is done by randomly projecting segemented object pixels onto backgrounds, then" " calculating the corresponding bounding boxes.") parser.add_argument('--data-directory', '-d', required=True, help='directory where the script will look for images, backgrounds and saved object masks') parser.add_argument('--class-annotations', '-c', required=True, help='file containing mappings from class ID to class name') parser.add_argument('--output-dir', '-o', default=None, help='(optional) directory to store generated images') parser.add_argument('--output-annotation-dir', '-a', default=None, help='(optional) directory to store the generated YAML annotations') parser.add_argument('--display-boxes', '-b', action='store_true', help='(optional) whether to display the synthetic images with visualized bounding boxes') args = parser.parse_args() try: generate_masks_and_annotations(args.data_directory, args.class_annotations, args.output_dir, args.output_annotation_dir, args.display_boxes) TerminalColors.formatted_print('image and annotation generation complete', TerminalColors.OKGREEN) except KeyboardInterrupt: TerminalColors.formatted_print('\nscript interrupted', TerminalColors.WARNING) except Exception as e: TerminalColors.formatted_print(e, TerminalColors.FAIL) raise
def create_tf_record(image_annotation_path, class_annotation_path, output_path, image_dir, num_shards): if tfrecords_exist(output_path) \ and not prompt_for_yes_or_no("shards for '{}' exists, overwrite?".format(args.output_file)): # make sure user want to overwrite TFRecord TerminalColors.formatted_print('not overwriting TFRecord, exiting..', TerminalColors.WARNING) return # Load class file if not os.path.exists(class_annotation_path): TerminalColors.formatted_print( 'class annotation file does not exist: ' + class_annotation_path, TerminalColors.FAIL) return with open(class_annotation_path, 'r') as yml_file: class_dict = yaml.load(yml_file, Loader=yaml.FullLoader) TerminalColors.formatted_print( "\nfound '{}' classes in file '{}'".format(len(class_dict), class_annotation_path), TerminalColors.OKBLUE) # Load annotations file if not os.path.exists(image_annotation_path): TerminalColors.formatted_print( 'image annotation file does not exist: ' + image_annotation_path, TerminalColors.FAIL) return with open(image_annotation_path, 'r') as annotations_f: annotations = yaml.load(annotations_f, Loader=yaml.FullLoader) num_annotations = len(annotations) TerminalColors.formatted_print( "found '{}' image annotations in file '{}'".format( num_annotations, image_annotation_path), TerminalColors.OKBLUE) TerminalColors.formatted_print( 'number of TFRecord shards: {}\n'.format(num_shards), TerminalColors.OKBLUE) with contextlib2.ExitStack() as tf_record_close_stack: output_tfrecords = open_sharded_output_tfrecords( tf_record_close_stack, output_path, num_shards) for idx, example in enumerate(annotations): output_shard_index = idx % num_shards print_progress(idx + 1, num_annotations, prefix="Generating TFRecord for image ") image_path = example['image_name'] if image_dir: # prepend image directory if specified image_path = os.path.join(image_dir, image_path) try: tf_example = create_bbox_detection_tf_example( image_path, example, class_dict) except RuntimeError as e: TerminalColors.formatted_print(str(e), TerminalColors.FAIL) continue output_tfrecords[output_shard_index].write( tf_example.SerializeToString())
) parser.add_argument( 'class_file', help="YAML file containing the mapping from class ID to class name") parser.add_argument('output_file', help="path where TFRecord's should be written to," " e.g. './robocup_train.record'") parser.add_argument( '--image_dir', '-d', default=None, help="if specified, will prepend to image paths in annotation file") parser.add_argument('--num_shards', '-n', default=1, type=int, help="number of fragments to split the TFRecord into") args = parser.parse_args() try: create_tf_record(args.annotation_file, args.class_file, args.output_file, args.image_dir, args.num_shards) TerminalColors.formatted_print('TFRecord generation complete', TerminalColors.OKGREEN) except KeyboardInterrupt: TerminalColors.formatted_print('\nscript interrupted', TerminalColors.WARNING) except Exception as e: TerminalColors.formatted_print(e, TerminalColors.FAIL) raise
required=True, help= "YAML file which contains the mappings from class ID to class names") parser.add_argument('--sleep-time', '-s', default=0.5, help="Delay in seconds between taking each picture") args = parser.parse_args() try: import rospy import cv_bridge from sensor_msgs.msg import Image as ImageMsg except ImportError: TerminalColors.formatted_print( 'This script is meant to work with ROS, please run it from a ROS enabled system.', TerminalColors.FAIL) sys.exit(1) rospy.init_node('image_collector', anonymous=True) try: collect_images(args.topic_name, args.image_dir, args.class_file, args.sleep_time) TerminalColors.formatted_print('image collection complete', TerminalColors.OKGREEN) except KeyboardInterrupt: TerminalColors.formatted_print('\nscript interrupted', TerminalColors.WARNING) except Exception as e: TerminalColors.formatted_print(e, TerminalColors.FAIL)
raise ValueError("invalid segmentation method: " + arguments.method) # create segmentation object and perform segmentation if seg_method_enum == SegmentationMethods.BACKGROUND_SUBTRACTION: bg_segmentor = BackgroundSubtraction(arguments.data_directory, arguments.class_annotations) else: raise ValueError('unsupported segmentation method: ' + seg_method_enum.name) bg_segmentor.segment() if __name__ == '__main__': # Note: using builtin var '__doc__' as script description parser = argparse.ArgumentParser(formatter_class=RawDescriptionAndDefaultsFormatter, description=__doc__) parser.add_argument('--method', '-m', choices=SegmentationMethods.values(), default=SegmentationMethods.BACKGROUND_SUBTRACTION.value, help='background segmentation method') parser.add_argument('--data-directory', '-d', required=True, help='directory where the script will look for images, backgrounds and save object masks') parser.add_argument('--class-annotations', '-c', required=True, help='file containing mapping from class ID to class name') try: segment_background(parser.parse_args()) TerminalColors.formatted_print('segmentation complete', TerminalColors.OKGREEN) except KeyboardInterrupt: TerminalColors.formatted_print('\nscript interrupted', TerminalColors.WARNING) except Exception as e: TerminalColors.formatted_print(e, TerminalColors.FAIL) raise
def generate_detection_data(self, split_name, output_dir_images, output_dir_masks, output_annotation_dir, max_obj_num_per_bg, augmentation_config_file_path, num_images_per_bg=10, write_chunk_ratio=0.05, invert_mask=False, annotation_format=AnnotationFormats.CUSTOM): """Generates: * synthetic images under <output_dir>/synthetic_images/<split_name> * image annotations under <output_dir>/annotations If annotation_format is equal to AnnotationFormats.VOC, an annotation file is generated for each image under <output_dir>/annotations/split_name, such that the name of the annotation is the same as the name of the image file (e.g. if the image name is train_01.jpg, the name of the annotation file will be train_01.xml). """ split_output_dir_images = os.path.join(output_dir_images, split_name) split_output_dir_masks = os.path.join(output_dir_masks, split_name) TerminalColors.formatted_print( "generating images for split '{}' under '{}'".format( split_name, split_output_dir_images), TerminalColors.BOLD) TerminalColors.formatted_print( "generating masks for split '{}' under '{}'".format( split_name, split_output_dir_masks), TerminalColors.BOLD) # check output image directory if not os.path.isdir(split_output_dir_images): print("creating directory: " + split_output_dir_images) os.mkdir(split_output_dir_images) elif os.listdir(split_output_dir_images): if not prompt_for_yes_or_no("directory '{}' not empty. Overwrite?". format(split_output_dir_images)): raise RuntimeError( "not overwriting '{}'".format(split_output_dir_images)) if not os.path.isdir(split_output_dir_masks): print("creating directory: " + split_output_dir_masks) os.mkdir(split_output_dir_masks) elif os.listdir(split_output_dir_masks): if not prompt_for_yes_or_no("directory '{}' not empty. Overwrite?". format(split_output_dir_masks)): raise RuntimeError( "not overwriting '{}'".format(split_output_dir_masks)) config_params = None if os.path.isfile(augmentation_config_file_path): config_params = read_config_params(augmentation_config_file_path) else: raise RuntimeError('Config {0} is not a valid file'.format( augmentation_config_file_path)) # check output annotation file annotation_file_path = os.path.join(output_annotation_dir, split_name + '.yaml') TerminalColors.formatted_print( "generating annotations for split '{}' in '{}'".format( split_name, annotation_file_path), TerminalColors.BOLD) if os.path.isfile(annotation_file_path): if not prompt_for_yes_or_no("file '{}' exists. Overwrite?".format( annotation_file_path)): raise RuntimeError( "not overwriting '{}'".format(annotation_file_path)) if annotation_format == AnnotationFormats.VOC: annotation_dir = os.path.join(output_annotation_dir, split_name) if not os.path.isdir(annotation_dir): os.mkdir(annotation_dir) else: if not prompt_for_yes_or_no("directory '{}' exists. Overwrite?" .format(annotation_dir)): raise RuntimeError( "not overwriting '{}'".format(annotation_dir)) # Total number of images = classes * objects per background * number of backgrounds total_img_cnt = len(self._background_paths) * num_images_per_bg zero_pad_num = len(str(total_img_cnt)) annotations = {} # Prepare multiprocessing img_cnt = mp.Value('i', 0) lock = mp.Lock() pool = mp.Pool(initializer=self.setup, initargs=[img_cnt, lock]) for bg_idx in tqdm(range(len(self._background_paths))): bg_path = self._background_paths[bg_idx] # for bg_path in self._background_paths: # generate new image try: bg_img = cv2.imread(bg_path) except RuntimeError as e: TerminalColors.formatted_print( "Ignoring background {} because {}".format(bg_path, e), TerminalColors.WARNING) continue bg_img_params = [(bg_img, max_obj_num_per_bg, invert_mask, split_name, zero_pad_num, \ split_output_dir_images, split_output_dir_masks, config_params, seed ) \ for seed in range(num_images_per_bg)] annotations_per_bg = pool.map(self.create_image, bg_img_params) for img_file_name, box_annotations in annotations_per_bg: annotations[img_file_name] = box_annotations # Writing annotations if print_progress(img_cnt.value + 1, total_img_cnt, prefix="creating image ", fraction=write_chunk_ratio): # periodically dump annotations self.save_annotations(annotations, split_output_dir_images, output_annotation_dir, split_name, annotation_file_path, annotation_format) annotations = {} self.save_annotations(annotations, split_output_dir_images, output_annotation_dir, split_name, annotation_file_path, annotation_format)
def _load_objects_per_class(self, class_id, obj_img_dir, obj_mask_dir): # check directories if not os.path.isdir(obj_img_dir): raise RuntimeError( "image folder '{}' is not an existing directory".format( obj_img_dir)) if not os.path.isdir(obj_mask_dir): raise RuntimeError( "mask folder '{}' is not an existing directory".format( obj_mask_dir)) # glob object images obj_img_paths = glob_extensions_in_directory(obj_img_dir, ALLOWED_IMAGE_EXTENSIONS) if not obj_img_paths: raise RuntimeError( "found no image of supported types in '{}'".format( obj_img_dir)) # glob mask images obj_mask_paths = glob_extensions_in_directory( obj_mask_dir, ALLOWED_IMAGE_EXTENSIONS) if not obj_img_paths: raise RuntimeError( "found no mask of supported types in '{}'".format(obj_img_dir)) # load images and masks print("found '{}' object images in '{}'".format( len(obj_img_paths), obj_img_dir)) print("found '{}' object masks in '{}'".format(len(obj_mask_paths), obj_mask_dir)) img_indices = list(range(len(obj_img_paths))) np.random.shuffle(img_indices) img_count = 0 current_img_idx = 0 img_paths = [] mask_paths = [] while img_count < self._num_objects_per_class and current_img_idx < len( img_indices): try: # we check if the current image has a corresponding mask img_path = obj_img_paths[img_indices[current_img_idx]] mask_path = get_image_mask_path(img_path, obj_mask_paths) # even if both the image and mask exist, we still need to load them # in order to check that they are valid images cv2.imread(img_path) img_paths.append(img_path) mask_paths.append(mask_path) img_count += 1 except Exception as exc: TerminalColors.formatted_print( "[load_objects_per_class] Error: {0}. Skipping image". format(exc), TerminalColors.WARNING) current_img_idx += 1 print("{} images saved per class {}".format(len(img_paths), class_id)) self._object_collections[class_id] = { 'images': img_paths, 'masks': mask_paths }
def __init__(self, data_dir, background_dir, class_annotation_file, num_objects_per_class): # check required directories TerminalColors.formatted_print('Data directory: ' + data_dir, TerminalColors.OKBLUE) if not os.path.isdir(data_dir): raise RuntimeError( "'{}' is not an existing directory".format(data_dir)) TerminalColors.formatted_print( 'Background directory: ' + background_dir, TerminalColors.OKBLUE) if not os.path.isdir(background_dir): raise RuntimeError( "'{}' is not an existing directory".format(background_dir)) # load backgrounds for image augmentation self._background_paths = glob_extensions_in_directory( background_dir, ALLOWED_IMAGE_EXTENSIONS) TerminalColors.formatted_print( 'Found {} background images '.format(len(self._background_paths)), TerminalColors.OKBLUE) # Saving number of objects per class self._num_objects_per_class = num_objects_per_class # load class annotation file TerminalColors.formatted_print( 'Class annotation file: {}'.format(class_annotation_file), TerminalColors.OKBLUE) if not os.path.exists(class_annotation_file): raise RuntimeError('class annotation file does not exist: ' + class_annotation_file) with open(class_annotation_file, 'r') as infile: self._class_dict = yaml.load(infile, Loader=yaml.FullLoader) # load segmented objects TerminalColors.formatted_print( "Loading object masks for '{}' classes".format( len(self._class_dict)), TerminalColors.OKBLUE) for cls_id, (cls_name, _) in self._class_dict.items(): obj_dir = os.path.join(data_dir, cls_name) obj_img_dir = os.path.join(obj_dir, 'images') obj_mask_dir = os.path.join(obj_dir, 'masks') try: TerminalColors.formatted_print( "loading images and masks for class '{}'".format(cls_name), TerminalColors.BOLD) # segmented_obj = SegmentedObjectCollection(cls_id, obj_img_dir, obj_mask_dir) # self._segmented_object_collections[cls_id] = segmented_obj self._load_objects_per_class(cls_id, obj_img_dir, obj_mask_dir) except RuntimeError as e: TerminalColors.formatted_print( "skipping class '{}': {}".format(cls_name, e), TerminalColors.WARNING) continue self._object_collections_copy = copy.deepcopy(self._object_collections)
def generate_detection_data(self, split_name, output_dir, output_annotation_dir, num_image_per_bg, max_obj_num_per_bg, display_boxes=False, write_chunk_ratio=0.05): """ The main function which generate - generate synthetic images under <outpu_dir>/<split_name> - generate """ split_output_dir = os.path.join(output_dir, split_name) TerminalColors.formatted_print( "generating images for split '{}' under '{}'".format( split_name, split_output_dir), TerminalColors.BOLD) # check output image directory if not os.path.isdir(split_output_dir): print("creating directory: " + split_output_dir) os.mkdir(split_output_dir) elif os.listdir(split_output_dir): if not prompt_for_yes_or_no("directory '{}' not empty. Overwrite?". format(split_output_dir)): raise RuntimeError( "not overwriting '{}'".format(split_output_dir)) # check output annotation file annotation_path = os.path.join(output_annotation_dir, split_name + '.yml') TerminalColors.formatted_print( "generating annotations for split '{}' in '{}'".format( split_name, annotation_path), TerminalColors.BOLD) if os.path.isfile(annotation_path): if not prompt_for_yes_or_no( "file '{}' exists. Overwrite?".format(annotation_path)): raise RuntimeError( "not overwriting '{}'".format(annotation_path)) # store a reasonable value for the maximum number of objects projected onto each background if max_obj_num_per_bg <= 0 or max_obj_num_per_bg > len( self.class_dict): max_obj_num_per_bg = len(self.class_dict) # generate images and annotations img_cnt = 0 total_img_cnt = num_image_per_bg * len(self._augment_backgrounds) zero_pad_num = len(str(total_img_cnt)) annotations = [] for bg_img in self._augment_backgrounds: for _ in range(num_image_per_bg): if print_progress(img_cnt + 1, total_img_cnt, prefix="creating image ", fraction=write_chunk_ratio): # periodically dump annotations with open(annotation_path, 'a') as infile: yaml.dump(annotations, infile, default_flow_style=False) annotations = [] # generate new image generated_image, box_annotations = self.generate_single_image( bg_img, max_obj_num_per_bg) if display_boxes: drawn_img = draw_labeled_boxes(generated_image, box_annotations, self.class_dict) display_image_and_wait(drawn_img, 'box image') # write image and annotations img_file_name = '{}_{}.jpg'.format( split_name, str(img_cnt).zfill(zero_pad_num)) img_file_path = os.path.join(split_output_dir, img_file_name) annotations.append({ 'image_name': img_file_path, 'objects': box_annotations }) cv2.imwrite(img_file_path, generated_image) img_cnt += 1
def __init__(self, data_dir, class_annotation_file): # check required directories self._data_dir = data_dir TerminalColors.formatted_print('Data directory: ' + self._data_dir, TerminalColors.OKBLUE) if not os.path.isdir(self._data_dir): raise RuntimeError("'{}' is not an existing directory".format( self._data_dir)) self._greenbox_image_dir = os.path.join(self._data_dir, 'green_box_images') print('will look for object green box images in: ' + self._greenbox_image_dir) if not os.path.isdir(self._greenbox_image_dir): raise RuntimeError("'{}' is not an existing directory".format( self._greenbox_image_dir)) self._mask_dir = os.path.join(self._data_dir, 'object_masks') print('will look for object masks in: ' + self._mask_dir) if not os.path.isdir(self._mask_dir): raise RuntimeError("'{}' is not an existing directory".format( self._mask_dir)) augment_bg_dir = os.path.join(self._data_dir, 'augmentation_backgrounds') print('will look for backgrounds for image augmentation in: ' + augment_bg_dir) if not os.path.isdir(augment_bg_dir): raise RuntimeError( "'{}' is not an existing directory".format(augment_bg_dir)) # load backgrounds for image augmentation background_paths = glob_extensions_in_directory( augment_bg_dir, ALLOWED_IMAGE_EXTENSIONS) print("found '{}' background images".format(len(background_paths))) self._augment_backgrounds = [] for bg_path in background_paths: bg_img = cv2.imread(bg_path) self._augment_backgrounds.append(bg_img) # load class annotation file TerminalColors.formatted_print( 'Class annotation file: {}'.format(class_annotation_file), TerminalColors.OKBLUE) if not os.path.exists(class_annotation_file): raise RuntimeError('class annotation file does not exist: ' + class_annotation_file) with open(class_annotation_file, 'r') as infile: self.class_dict = yaml.load(infile, Loader=yaml.FullLoader) # load segmented objects TerminalColors.formatted_print( "Loading object masks for '{}' classes".format(len( self.class_dict)), TerminalColors.OKBLUE) self._segmented_object_collections = {} for cls_id, cls_name in self.class_dict.items(): obj_img_dir = os.path.join(self._greenbox_image_dir, cls_name) obj_mask_dir = os.path.join(self._mask_dir, cls_name) try: TerminalColors.formatted_print( "loading images and masks for class '{}'".format(cls_name), TerminalColors.BOLD) segmented_obj = SegmentedObjectCollection( cls_id, obj_img_dir, obj_mask_dir) self._segmented_object_collections[cls_id] = segmented_obj except RuntimeError as e: TerminalColors.formatted_print( "skipping class '{}': {}".format(cls_name, e), TerminalColors.WARNING) continue