def load_exclusion_region_generator(config_yaml): window_dims = tuple(map(int, config_yaml['training']['svm']['window_dims'])) bak_img_dir = config_yaml['dataset']['directory']['generation']['input']['exclusion'] bbinfo_dir = config_yaml['dataset']['directory']['bbinfo'] exl_info_map = utils.load_opencv_bounding_box_info_directory(bbinfo_dir, suffix='exclusion') modifiers = config_yaml['dataset']['modifiers'] return generate_negative_regions_with_exclusions(bak_img_dir, exl_info_map, window_dims, modifiers)
def sampleTrainingImages(image_dir, synsets, sample_size, require_bboxes=False, bbinfo_dir=None): image_list = utils.list_images_in_directory(image_dir) # regexString = '.*({})_.*\.jpg'.format('|'.join(synsets)) # regexString = 'n?({})(_.*)?\.(jpg|png)'.format('|'.join(synsets)) regexString = '(.*/)?({})(_.*)?\.(jpg|png)'.format('|'.join(synsets)) synsetProg = re.compile(regexString) # Filter image file lists to match sysnet specifications: filtered_image_list = filter(lambda x: synsetProg.match(x), image_list) # print regexString # if len(regexString) > 100: # # print image_list # print filtered_image_list # If bounding boxes are required, filter out images without bounding boxes: if require_bboxes: global_info = utils.load_opencv_bounding_box_info_directory(bbinfo_dir, suffix='bbinfo') # global_info = loadGlobalInfo(bbinfo_dir) bbox_filter = lambda img_path: os.path.split(img_path)[1] in global_info filtered_image_list = filter(bbox_filter, filtered_image_list) print len(filtered_image_list) # Truncate file lists to sample the correct number of images: image_sample = filtered_image_list if not sample_size is None: image_sample = random.sample(filtered_image_list, min(sample_size, len(filtered_image_list))) return image_sample
def generate_positive_regions(image_dir, bbinfo_dir, modifiers_config=None, window_dims=None, min_size=(48,48)): print 'generate_positive_regions:' all_images = utils.list_images_in_directory(image_dir) # Create the modifier generator: # Note: Simply generate null modifiers if no modifier config is passed. modifier_generator = itertools.repeat(utils.RegionModifiers()) if modifiers_config: modifier_generator = utils.RegionModifiers.random_generator_from_config_dict(modifiers_config) # Filter out images without bounding boxes: bbinfo_map = utils.load_opencv_bounding_box_info_directory(bbinfo_dir, suffix='bbinfo') source_images = [img_path for img_path in all_images if not utils.info_entry_for_image(bbinfo_map, img_path) is None] # Extract image regions: source_regions = [] for img_path in source_images: rects = utils.info_entry_for_image(bbinfo_map, img_path) for rect in rects: # Reject small samples: if rect.w < float(min_size[0]) or rect.h < float(min_size[1]): continue region = utils.ImageRegion(rect, img_path) source_regions.append(region) print 'Found {} source regions.'.format(len(source_regions)) # Generate an infinite list of samples: while True: # Randomise the order of source images: # Note: Don't randomise if no modifiers are used. if modifiers_config: random.shuffle(source_regions) # For each source region: for reg in source_regions: mod = modifier_generator.next() # Enlarge to correct aspect ratio: new_rect = reg.rect if window_dims: aspect = window_dims[0] / float(window_dims[1]) new_rect = new_rect.enlarge_to_aspect(aspect) imsize = utils.get_image_dimensions(reg.fname) if not new_rect.lies_within_frame(imsize): # print 'bad', new_rect continue # else: # print new_rect # Assign a random modifier, and yield the region: new_reg = utils.ImageRegion(new_rect, reg.fname, mod) yield new_reg # If we're not using modifiers, only use each region once: if not modifiers_config: break
def view_positive_samples(classifier_yaml, output_dir): bbinfo_dir = classifier_yaml['dataset']['directory']['bbinfo'] global_info = utils.load_opencv_bounding_box_info_directory( bbinfo_dir, suffix='bbinfo') # global_info = loadGlobalInfo(bbinfo_dir) positive_dir = classifier_yaml['dataset']['directory']['positive'] # for img_path in glob.glob("{}/*_*.jpg".format(positive_dir)): # for img_path in utils.list_images_in_directory(positive_dir): pos_samples = sampleTrainingImages(positive_dir, ['.*'], None, require_bboxes=True, bbinfo_dir=bbinfo_dir) print 'Selected {} positive samples.'.format(len(pos_samples)) for img_path in pos_samples: img = cv2.imread(img_path) key = img_path.split('/')[-1] rects_str = global_info[key] rects = utils.rectangles_from_cache_string(rects_str) print img_path, len(rects) for rect in rects: lw = max(2, min(img.shape[0], img.shape[1]) / 150) cvDrawRectangle(img, rect, (255, 0, 0), lw) # cv2.rectangle(img,(x,y),(x+w,y+h),(255,255,255),lw+2) # cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),lw) # aspectRect = gm.extendBoundingBox(rect, 83/64.0) # cvDrawRectangle(img, aspectRect, (0,255,0),2) # # paddedRect = gm.padBoundingBox(aspectRect, (0.1, 0.1)) # cvDrawRectangle(img, paddedRect, (0,0,255),2) h, w = img.shape[:2] max_dim = 1200.0 # if w > max_dim + 50 or h > max_dim + 50: if abs(w - max_dim) > 50 or abs(h - max_dim) > 50: sx = max_dim / w sy = max_dim / h current_scale = min(sx, sy) img = cv2.resize(img, dsize=None, fx=current_scale, fy=current_scale) cv2.imshow('img', img) cv2.waitKey(0) cv2.destroyAllWindows()
def checkBoundingBoxes(img_paths, bbinfo_dir): global_info = utils.load_opencv_bounding_box_info_directory( bbinfo_dir, suffix='bbinfo') # global_info = loadGlobalInfo(bbinfo_dir) error_occurred = False bad_images = [] warn_images = [] for img_path in img_paths: imsize = None try: im = Image.open(img_path) imsize = im.size im.close() except Exception as e: print "Error opening image {}: {}".format(img_path, e) error_occurred = True continue # Get bounding box: rects = utils.info_entry_for_image(global_info, img_path) for rect in rects: if not rect.touches_frame_edge(imsize): warn_images.append((img_path, rect, imsize)) if not rect.lies_within_frame(imsize): bad_images.append((img_path, rect, imsize)) if warn_images: print """ WARNING: Some bounding boxes touch the image edges. An older version of this script defined bounding boxes differently in which case the case where rect.x + rect.w == img_width would indicate a bounding box extending outside of the image dimensions. The newer KITTI scripts define bounding box size as the true pixel size, making this test indicate a box touching the image edge, which is fine. If the OpenCV scripts fail, this may be the reason. (Uncomment the following line to see the suspicious boxes) """ # pprint(warn_images) if error_occurred or bad_images: print 'EXITING DUE TO INVALID BOUNDING BOXES:' pprint(bad_images) sys.exit(1) assert (False)
def checkBoundingBoxes(img_paths, bbinfo_dir): global_info = utils.load_opencv_bounding_box_info_directory(bbinfo_dir, suffix='bbinfo') # global_info = loadGlobalInfo(bbinfo_dir) error_occurred = False bad_images = [] warn_images = [] for img_path in img_paths: imsize = None try: im = Image.open(img_path) imsize = im.size im.close() except Exception as e: print "Error opening image {}: {}".format(img_path, e) error_occurred = True continue # Get bounding box: rects = utils.info_entry_for_image(global_info, img_path) for rect in rects: if not rect.touches_frame_edge(imsize): warn_images.append((img_path, rect, imsize)) if not rect.lies_within_frame(imsize): bad_images.append((img_path, rect, imsize)) if warn_images: print """ WARNING: Some bounding boxes touch the image edges. An older version of this script defined bounding boxes differently in which case the case where rect.x + rect.w == img_width would indicate a bounding box extending outside of the image dimensions. The newer KITTI scripts define bounding box size as the true pixel size, making this test indicate a box touching the image edge, which is fine. If the OpenCV scripts fail, this may be the reason. (Uncomment the following line to see the suspicious boxes) """ # pprint(warn_images) if error_occurred or bad_images: print 'EXITING DUE TO INVALID BOUNDING BOXES:' pprint(bad_images) sys.exit(1) assert(False)
def view_positive_samples(classifier_yaml, output_dir): bbinfo_dir = classifier_yaml['dataset']['directory']['bbinfo'] global_info = utils.load_opencv_bounding_box_info_directory(bbinfo_dir, suffix='bbinfo') # global_info = loadGlobalInfo(bbinfo_dir) positive_dir = classifier_yaml['dataset']['directory']['positive'] # for img_path in glob.glob("{}/*_*.jpg".format(positive_dir)): # for img_path in utils.list_images_in_directory(positive_dir): pos_samples = sampleTrainingImages(positive_dir, ['.*'], None, require_bboxes=True, bbinfo_dir=bbinfo_dir) print 'Selected {} positive samples.'.format(len(pos_samples)) for img_path in pos_samples: img = cv2.imread(img_path) key = img_path.split('/')[-1] rects_str = global_info[key] rects = utils.rectangles_from_cache_string(rects_str) print img_path, len(rects) for rect in rects: lw = max(2, min(img.shape[0], img.shape[1]) / 150) cvDrawRectangle(img, rect, (255,0,0), lw) # cv2.rectangle(img,(x,y),(x+w,y+h),(255,255,255),lw+2) # cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),lw) # aspectRect = gm.extendBoundingBox(rect, 83/64.0) # cvDrawRectangle(img, aspectRect, (0,255,0),2) # # paddedRect = gm.padBoundingBox(aspectRect, (0.1, 0.1)) # cvDrawRectangle(img, paddedRect, (0,0,255),2) h, w = img.shape[:2] max_dim = 1200.0 # if w > max_dim + 50 or h > max_dim + 50: if abs(w - max_dim) > 50 or abs(h - max_dim) > 50: sx = max_dim / w sy = max_dim / h current_scale = min(sx, sy) img = cv2.resize(img, dsize=None, fx=current_scale, fy=current_scale) cv2.imshow('img', img) cv2.waitKey(0) cv2.destroyAllWindows()
def sampleTrainingImages(image_dir, synsets, sample_size, require_bboxes=False, bbinfo_dir=None): image_list = utils.list_images_in_directory(image_dir) # regexString = '.*({})_.*\.jpg'.format('|'.join(synsets)) # regexString = 'n?({})(_.*)?\.(jpg|png)'.format('|'.join(synsets)) regexString = '(.*/)?({})(_.*)?\.(jpg|png)'.format('|'.join(synsets)) synsetProg = re.compile(regexString) # Filter image file lists to match sysnet specifications: filtered_image_list = filter(lambda x: synsetProg.match(x), image_list) # print regexString # if len(regexString) > 100: # # print image_list # print filtered_image_list # If bounding boxes are required, filter out images without bounding boxes: if require_bboxes: global_info = utils.load_opencv_bounding_box_info_directory( bbinfo_dir, suffix='bbinfo') # global_info = loadGlobalInfo(bbinfo_dir) bbox_filter = lambda img_path: os.path.split(img_path)[1 ] in global_info filtered_image_list = filter(bbox_filter, filtered_image_list) print len(filtered_image_list) # Truncate file lists to sample the correct number of images: image_sample = filtered_image_list if not sample_size is None: image_sample = random.sample( filtered_image_list, min(sample_size, len(filtered_image_list))) return image_sample
def create_or_load_descriptors(classifier_yaml, hog, window_dims): pos_img_dir = classifier_yaml["dataset"]["directory"]["positive"] pos_num = int(classifier_yaml["training"]["svm"]["pos_num"]) bbinfo_dir = classifier_yaml["dataset"]["directory"]["bbinfo"] bak_img_dir = classifier_yaml["dataset"]["directory"]["background"] neg_num = int(classifier_yaml["training"]["svm"]["neg_num"]) # pos_descriptor_file = 'output/pos_descriptors.pickle' # neg_descriptor_file = 'output/neg_descriptors.pickle' # if not (os.path.isfile(pos_descriptor_file) and os.path.isfile(neg_descriptor_file)): store = DataStore() print "db_name:", store.db_name_for_hog(hog) print "hog_name:", utils.name_from_hog_descriptor(hog) # if not store.has_region_descriptors_for_hog(hog): # Preprocess samples: # - generate/select sample regions # - compute and descriptors for all samples # - save the regions and descriptors to a file curr_pos_num = store.num_region_descriptors(hog, 1) req_pos_num = pos_num if curr_pos_num is None else pos_num - curr_pos_num print "pos_num:", pos_num print "curr_pos_num:", curr_pos_num print "req_pos_num:", req_pos_num if req_pos_num > 0: # if not os.path.isfile(pos_descriptor_file): # pos_reg_generator = generate_positive_regions(pos_img_dir, bbinfo_dir, classifier_yaml['dataset']['modifiers'], 0.5*np.array(window_dims)) pos_reg_generator = generate_samples.generate_positive_regions( pos_img_dir, bbinfo_dir, classifier_yaml["dataset"]["modifiers"], window_dims ) # view_image_regions(pos_reg_generator, window_dims, display_scale=3) pos_regions = list(itertools.islice(pos_reg_generator, 0, req_pos_num)) pos_reg_descriptors = compute_hog_descriptors(hog, pos_regions, window_dims, 1) # save_region_descriptors(hog, pos_regions, pos_descriptors, 'pos_descriptors') store.save_region_descriptors(pos_reg_descriptors, hog) curr_neg_num = store.num_region_descriptors(hog, -1) req_neg_num = neg_num if curr_neg_num is None else neg_num - curr_neg_num print "neg_num:", neg_num print "curr_neg_num:", curr_neg_num print "req_neg_num:", req_neg_num if req_neg_num > 0: # if not os.path.isfile(neg_descriptor_file): # neg_regions = generate_negative_regions(bak_img_dir, req_neg_num, window_dims) exl_info_map = utils.load_opencv_bounding_box_info_directory(bbinfo_dir, suffix="exclusion") neg_reg_generator = generate_samples.generate_negative_regions_with_exclusions( bak_img_dir, exl_info_map, window_dims, classifier_yaml["dataset"]["modifiers"] ) neg_regions = list(itertools.islice(neg_reg_generator, 0, req_neg_num)) neg_reg_descriptors = compute_hog_descriptors(hog, neg_regions, window_dims, -1) # save_region_descriptors(hog, neg_regions, neg_descriptors, 'neg_descriptors') store.save_region_descriptors(neg_reg_descriptors, hog) # else: # Load all descriptors and the hog object used to generate them: # hog, reg_descriptors = store.load_region_descriptors_for_hog(hog) hog, pos_reg_descriptors = store.load_region_descriptors_for_hog(hog, pos_num, 1) hog, neg_reg_descriptors = store.load_region_descriptors_for_hog(hog, neg_num, -1) # hog, reg_descriptors = store.load_region_descriptors('hog_Llht0,2_n64_gcFalse_hnt0_bs8x8_cs8x8_ws4,0_da1') # hog, pos_regions, pos_descriptors = load_region_descriptors(pos_descriptor_file) # hog, neg_regions, neg_descriptors = load_region_descriptors(neg_descriptor_file) reg_descriptors = list(pos_reg_descriptors) + list(neg_reg_descriptors) return reg_descriptors, hog
def create_or_load_descriptors(classifier_yaml, hog, window_dims): pos_img_dir = classifier_yaml['dataset']['directory']['positive'] pos_num = int(classifier_yaml['training']['svm']['pos_num']) bbinfo_dir = classifier_yaml['dataset']['directory']['bbinfo'] bak_img_dir = classifier_yaml['dataset']['directory']['background'] neg_num = int(classifier_yaml['training']['svm']['neg_num']) # pos_descriptor_file = 'output/pos_descriptors.pickle' # neg_descriptor_file = 'output/neg_descriptors.pickle' # if not (os.path.isfile(pos_descriptor_file) and os.path.isfile(neg_descriptor_file)): store = DataStore() print 'db_name:', store.db_name_for_hog(hog) print 'hog_name:', utils.name_from_hog_descriptor(hog) # if not store.has_region_descriptors_for_hog(hog): # Preprocess samples: # - generate/select sample regions # - compute and descriptors for all samples # - save the regions and descriptors to a file curr_pos_num = store.num_region_descriptors(hog, 1) req_pos_num = pos_num if curr_pos_num is None else pos_num - curr_pos_num print 'pos_num:', pos_num print 'curr_pos_num:', curr_pos_num print 'req_pos_num:', req_pos_num if req_pos_num > 0: # if not os.path.isfile(pos_descriptor_file): # pos_reg_generator = generate_positive_regions(pos_img_dir, bbinfo_dir, classifier_yaml['dataset']['modifiers'], 0.5*np.array(window_dims)) pos_reg_generator = generate_samples.generate_positive_regions( pos_img_dir, bbinfo_dir, classifier_yaml['dataset']['modifiers'], window_dims) # view_image_regions(pos_reg_generator, window_dims, display_scale=3) pos_regions = list(itertools.islice(pos_reg_generator, 0, req_pos_num)) pos_reg_descriptors = compute_hog_descriptors(hog, pos_regions, window_dims, 1) # save_region_descriptors(hog, pos_regions, pos_descriptors, 'pos_descriptors') store.save_region_descriptors(pos_reg_descriptors, hog) curr_neg_num = store.num_region_descriptors(hog, -1) req_neg_num = neg_num if curr_neg_num is None else neg_num - curr_neg_num print 'neg_num:', neg_num print 'curr_neg_num:', curr_neg_num print 'req_neg_num:', req_neg_num if req_neg_num > 0: # if not os.path.isfile(neg_descriptor_file): # neg_regions = generate_negative_regions(bak_img_dir, req_neg_num, window_dims) exl_info_map = utils.load_opencv_bounding_box_info_directory( bbinfo_dir, suffix='exclusion') neg_reg_generator = generate_samples.generate_negative_regions_with_exclusions( bak_img_dir, exl_info_map, window_dims, classifier_yaml['dataset']['modifiers']) neg_regions = list(itertools.islice(neg_reg_generator, 0, req_neg_num)) neg_reg_descriptors = compute_hog_descriptors(hog, neg_regions, window_dims, -1) # save_region_descriptors(hog, neg_regions, neg_descriptors, 'neg_descriptors') store.save_region_descriptors(neg_reg_descriptors, hog) # else: # Load all descriptors and the hog object used to generate them: # hog, reg_descriptors = store.load_region_descriptors_for_hog(hog) hog, pos_reg_descriptors = store.load_region_descriptors_for_hog( hog, pos_num, 1) hog, neg_reg_descriptors = store.load_region_descriptors_for_hog( hog, neg_num, -1) # hog, reg_descriptors = store.load_region_descriptors('hog_Llht0,2_n64_gcFalse_hnt0_bs8x8_cs8x8_ws4,0_da1') # hog, pos_regions, pos_descriptors = load_region_descriptors(pos_descriptor_file) # hog, neg_regions, neg_descriptors = load_region_descriptors(neg_descriptor_file) reg_descriptors = list(pos_reg_descriptors) + list(neg_reg_descriptors) return reg_descriptors, hog
# raise ValueError('Not enough images!') raise TooFewImagesError(presentCounts, requiredCounts) # Create the output directory: if not os.path.isdir(output_dir): print '## Creating output directory: {}'.format(output_dir) os.makedirs(output_dir) else: print '## Using existing output directory: {}'.format(output_dir) # Print names of images with invalid bounding boxes: checkBoundingBoxes(pos_image_files, bbinfo_dir) # Load the global info file with bounding boxes for all positive images: # global_info_fname = 'info.dat' global_info = utils.load_opencv_bounding_box_info_directory(bbinfo_dir, suffix='bbinfo') pos_info_fname = '{}/positive.txt'.format(output_dir) neg_info_fname = '{}/negative.txt'.format(output_dir) # Note: image paths in the data file have to be relative to the file itself. abs_output_dir = os.path.abspath(output_dir) def write_img(img_path, dat_file, write_bbox=True): rel_img_path = None if os.path.isabs(img_path): rel_img_path = os.path.relpath(img_path, abs_output_dir) else: rel_img_path = os.path.relpath(img_path, output_dir) dat_line = rel_img_path
# raise ValueError('Not enough images!') raise TooFewImagesError(presentCounts, requiredCounts) # Create the output directory: if not os.path.isdir(output_dir): print '## Creating output directory: {}'.format(output_dir) os.makedirs(output_dir) else: print '## Using existing output directory: {}'.format(output_dir) # Print names of images with invalid bounding boxes: checkBoundingBoxes(pos_image_files, bbinfo_dir) # Load the global info file with bounding boxes for all positive images: # global_info_fname = 'info.dat' global_info = utils.load_opencv_bounding_box_info_directory( bbinfo_dir, suffix='bbinfo') pos_info_fname = '{}/positive.txt'.format(output_dir) neg_info_fname = '{}/negative.txt'.format(output_dir) # Note: image paths in the data file have to be relative to the file itself. abs_output_dir = os.path.abspath(output_dir) def write_img(img_path, dat_file, write_bbox=True): rel_img_path = None if os.path.isabs(img_path): rel_img_path = os.path.relpath(img_path, abs_output_dir) else: rel_img_path = os.path.relpath(img_path, output_dir) dat_line = rel_img_path