Exemple #1
0
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
Exemple #2
0
def generate_negative_regions_with_exclusions(bak_img_dir, exl_info_map, window_dims, modifiers_config=None):
    print 'generate_negative_regions_with_exclusions:'
    all_images = utils.list_images_in_directory(bak_img_dir)
    if len(all_images) == 0:
        raise ValueError('The given directory \'{}\' contains no images.'.format(bak_img_dir))
    print '  Found {} images.'.format(len(all_images))

    all_images = [img_path for img_path in all_images if not utils.info_entry_for_image(exl_info_map, img_path) is None]
    print '  Found {} images with exclusion info.'.format(len(all_images))

    if len(all_images) == 0:
        raise ValueError('The given directory \'{}\' contains no images with exclusion info.'.format(bak_img_dir))

    image_list = all_images
    random.shuffle(image_list)

    modifier_generator = itertools.repeat(utils.RegionModifiers())
    if modifiers_config:
        modifier_generator = utils.RegionModifiers.random_generator_from_config_dict(modifiers_config)

    while True:
        for img_path in image_list:
            imsize = utils.get_image_dimensions(img_path)

            for reg in generate_negative_regions_in_image_with_exclusions(img_path, exl_info_map, window_dims):
                mod = modifier_generator.next()

                # Assign a random modifier, and yield the region:
                new_reg = utils.ImageRegion(reg.rect, reg.fname, mod)
                yield new_reg

        # Shuffle the image list:
        random.shuffle(image_list)
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 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
        if write_bbox:
            rects = utils.info_entry_for_image(global_info, img_path)
            details = ' '.join([' '.join(map(str, rect.opencv_bbox)) for rect in rects])
            dat_line = "{} {} {}".format(rel_img_path, len(rects), details)

        # print 'dat_line:', dat_line
        dat_file.write(dat_line)
    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
        if write_bbox:
            rects = utils.info_entry_for_image(global_info, img_path)
            details = ' '.join(
                [' '.join(map(str, rect.opencv_bbox)) for rect in rects])
            dat_line = "{} {} {}".format(rel_img_path, len(rects), details)

        # print 'dat_line:', dat_line
        dat_file.write(dat_line)
Exemple #7
0
def generate_negative_regions_in_image_with_exclusions(img_path, exl_info_map, window_dims):
    excl_info = utils.info_entry_for_image(exl_info_map, img_path)
    # Only consider images with exclusions:
    if excl_info is None:
        return
    imsize = utils.get_image_dimensions(img_path)

    img_w, img_h = imsize

    aspect = window_dims[0] / float(window_dims[1])

    scale_step = 1.25
    window_step = 0.5
    max_scale = 0.5
    min_w = 64
    min_scale = min_w / float(img_w)
    scale = min_scale

    # Used to probabilistically reject a fraction of samples at each scale
    # level. This decreases the difference in the number of samples selected
    # from each scale level (otherwise, small scale levels would contain an
    # overwhelmingly large number of sample windows).
    def accept_sample(curr_scale):
        f = (curr_scale - min_scale) / (max_scale - min_scale)
        min_prob = 0.3**0.5
        max_prob = 1.0
        prob = min_prob*(1-f) + max_prob*(f)
        return np.random.uniform() < prob*prob

    # Probability of rejecting samples that are not close to exclusion regions.
    # (Most images have large portions of sky and ground, and this prevents
    # oversampling those areas)
    far_reject_prob = 0.97

    num_found = 0
    while True:
        w = int(round(img_w * scale))
        h = int(round(img_w * scale / aspect))
        sw = int(window_step*w)
        sh = int(window_step*h)
        # print 'scale, (w, h), (sw, sh):', scale, (w, h), (sw, sh)

        if scale > max_scale:
            return
        scale *= scale_step

        count = 0
        for x in xrange(0, img_w, sw):
            for y in xrange(0, img_h, sh):
                if x + w > img_w or y + h > img_h:
                    break

                # Randomly reject samples based on scale:
                if not accept_sample(scale):
                    continue

                rect = gm.PixelRectangle.from_opencv_bbox([x, y, w, h])

                # Nudge rectangles to avoid exclusion regions:
                intersecting = filter(rect.intersects_pixelrectangle, excl_info)
                if len(intersecting) == 1:
                    excl = intersecting[0]
                    rect, offset = rect.moved_to_clear(excl, return_offset=True)
                    if abs(offset[0]) >= sw or  abs(offset[1]) >= sh:
                        continue
                    rect = rect.translated((0,0), imsize)

                # Ensure the rectangle does not intersect an exclusion region:
                if not any((rect.intersects_pixelrectangle(pr) for pr in excl_info)):
                    # Determing whether the rectangle is close to an exclusion
                    # region:
                    is_close_to_exclusion = any((rect.distance_pixelrectangle(pr) < w for pr in excl_info))

                    # Prefer rectangles that are close to exclusion regions:
                    if not is_close_to_exclusion:
                        if np.random.uniform() < far_reject_prob:
                            continue

                    reg = utils.ImageRegion(rect, img_path)
                    num_found += 1
                    # import sys
                    # sys.stdout.write(str(num_found) + ',')
                    # sys.stdout.flush()
                    yield reg
                    count += 1