Esempio n. 1
0
def generate_negative_regions(image_dir, window_dims, modifiers_config=None):
    print 'generate_negative_regions:'
    image_list = utils.list_images_in_directory(image_dir)
    if len(image_list) == 0:
        raise ValueError('The given directory \'{}\' contains no images.'.format(image_dir))
    print '  Found {} images.'.format(len(image_list))

    # 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)

    min_w, min_h = window_dims
    min_size_length = min(min_w, min_h) / 2.0

    while True:
        random.shuffle(image_list)

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

            # Reject small images:
            w, h = imsize
            if w < min_w or h < min_h:
                continue

            # Generate a number of regions per image:
            for i in xrange(10):
                rect = gm.PixelRectangle.random_with_same_aspect(window_dims, imsize, min_size_length)
                mod = modifier_generator.next()
                reg = utils.ImageRegion(rect, img_path, mod)
                yield reg
Esempio n. 2
0
def choose_positive_samples(image_dir, sample_size, bbinfo_dir):
    filtered_image_list = utils.list_images_in_directory(image_dir)

    # Filter out images without bounding boxes:
    global_info = training.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)

    # Extract image regions:
    img_regions = []
    for img_path in filtered_image_list:
        key = os.path.split(img_path)[1]
        rects = utils.rectangles_from_cache_string(global_info[key])
        for rect in rects:
            region = utils.ImageRegion(rect, img_path)
            img_regions.append(region)

    # Truncate region list to sample the correct number of images:
    if sample_size is None:
        random.shuffle(img_regions)
    else:
        img_regions = random.sample(img_regions, min(sample_size, len(img_regions)))

    if len(img_regions) < sample_size:
        raise ValueError(
            "Requested {} positive samples, but only {} could be found in '{}'!".format(
                sample_size, len(img_regions), image_dir
            )
        )

    return img_regions
Esempio n. 3
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)
Esempio n. 4
0
def choose_positive_samples(image_dir, sample_size, bbinfo_dir):
    filtered_image_list = utils.list_images_in_directory(image_dir)

    # Filter out images without bounding boxes:
    global_info = training.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)

    # Extract image regions:
    img_regions = []
    for img_path in filtered_image_list:
        key = os.path.split(img_path)[1]
        rects = utils.rectangles_from_cache_string(global_info[key])
        for rect in rects:
            region = utils.ImageRegion(rect, img_path)
            img_regions.append(region)

    # Truncate region list to sample the correct number of images:
    if sample_size is None:
        random.shuffle(img_regions)
    else:
        img_regions = random.sample(img_regions,
                                    min(sample_size, len(img_regions)))

    if len(img_regions) < sample_size:
        raise ValueError(
            'Requested {} positive samples, but only {} could be found in \'{}\'!'
            .format(sample_size, len(img_regions), image_dir))

    return img_regions
Esempio n. 5
0
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
Esempio n. 6
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
def runClassifier(classifier_yaml, output_dir):
    traincascade_data_dir = '{}/data'.format(output_dir)
    classifier_xml = '{}/cascade.xml'.format(traincascade_data_dir)

    if not os.path.isfile(classifier_xml):
        print 'ERROR: Classifier does not exist:', classifier_xml
        sys.exit(1)

    classifier = cv2.CascadeClassifier(classifier_xml)

    for test_dir in classifier_yaml['testing']['directories']:
        test_source_name = test_dir.strip('/').split('/')[-1]

        results_dir = '{}/{}_results'.format(output_dir, test_source_name)
        detections_fname = '{}/{}_detections.dat'.format(
            output_dir, test_source_name)

        img_list = utils.list_images_in_directory(test_dir)
        random.shuffle(img_list)

        for img_path in img_list:
            img = cv2.imread(img_path)

            while img.shape[0] > 1024:
                print 'resize:', img_path, img.shape
                img = cv2.resize(img, dsize=None, fx=0.5, fy=0.5)

            # # Check whether the image is upside-down:
            # if checkImageOrientation(img_path):
            #     print 'Flipped!'
            #     img = cv2.flip(img, -1)

            gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

            minSize = (img.shape[0] / 50, img.shape[1] / 50)
            cars = classifier.detectMultiScale(
                image=gray,
                # scaleFactor=1.05,
                scaleFactor=1.01,
                minNeighbors=4,
                minSize=minSize,
            )

            print img_path, len(cars)
            if len(cars) > 0:
                for (x, y, w, h) in cars:
                    # img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
                    lw = max(2, img.shape[0] / 100)
                    cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), lw)
                    # roi_gray = gray[y:y+h, x:x+w]
                    # roi_color = img[y:y+h, x:x+w]

                # img = cv2.resize(img, dsize=None, fx=0.1, fy=0.1)
                # cv2.namedWindow("img", cv2.WINDOW_NORMAL)
                # cv2.resizeWindow('img', 500, 500)
                cv2.imshow('img', img)
                # cv2.imshow('img',img)
                cv2.waitKey(0)
                cv2.destroyAllWindows()
Esempio n. 8
0
def runClassifier(classifier_yaml, output_dir):
    traincascade_data_dir = '{}/data'.format(output_dir)
    classifier_xml = '{}/cascade.xml'.format(traincascade_data_dir)

    if not os.path.isfile(classifier_xml):
        print 'ERROR: Classifier does not exist:', classifier_xml
        sys.exit(1)

    classifier = cv2.CascadeClassifier(classifier_xml)

    for test_dir in classifier_yaml['testing']['directories']:
        test_source_name = test_dir.strip('/').split('/')[-1]

        results_dir = '{}/{}_results'.format(output_dir, test_source_name)
        detections_fname = '{}/{}_detections.dat'.format(output_dir, test_source_name)

        img_list = utils.list_images_in_directory(test_dir)
        random.shuffle(img_list)

        for img_path in img_list:
            img = cv2.imread(img_path)

            while img.shape[0] > 1024:
                print 'resize:', img_path, img.shape
                img = cv2.resize(img, dsize=None, fx=0.5, fy=0.5)

            # # Check whether the image is upside-down:
            # if checkImageOrientation(img_path):
            #     print 'Flipped!'
            #     img = cv2.flip(img, -1)

            gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

            minSize = (img.shape[0] / 50, img.shape[1] / 50)
            cars = classifier.detectMultiScale(
                image=gray,
                # scaleFactor=1.05,
                scaleFactor=1.01,
                minNeighbors=4,
                minSize=minSize,
            )

            print img_path, len(cars)
            if len(cars) > 0:
                for (x,y,w,h) in cars:
                    # img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
                    lw = max(2, img.shape[0] / 100)
                    cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),lw)
                    # roi_gray = gray[y:y+h, x:x+w]
                    # roi_color = img[y:y+h, x:x+w]

                # img = cv2.resize(img, dsize=None, fx=0.1, fy=0.1)
                # cv2.namedWindow("img", cv2.WINDOW_NORMAL)
                # cv2.resizeWindow('img', 500, 500)
                cv2.imshow('img', img)
                # cv2.imshow('img',img)
                cv2.waitKey(0)
                cv2.destroyAllWindows()
Esempio n. 9
0
def generate_hard_negative_regions(bak_img_dir, classifier_dir, window_dims):
    all_images = utils.list_images_in_directory(bak_img_dir)

    w, h = window_dims
    window_aspect = w / float(h)

    with ObjectDetector(classifier_dir) as detector:
        while True:
            random.shuffle(all_images)

            for img_path in all_images:
                # Detect objects:
                img = cv2.imread(img_path)
                img_h, img_w = img.shape[:2]
                img_dims = (img_w, img_h)
                opencv_rects, scaled_img_dims = detector.detect_objects_in_image(
                    img,
                    resize=False,
                    return_detection_img=False,
                    progress=False
                )
                pixel_rects = map(gm.PixelRectangle.from_opencv_bbox, opencv_rects)

                # Find rectangles in original image dimensions:
                pixel_rects = [rect.scale_image(scaled_img_dims, img_dims) for rect in pixel_rects]

                # Enlarge to window_dims:
                pixel_rects = [rect.enlarge_to_aspect(window_aspect) for rect in pixel_rects]

                # Ensure new rectangles are located within their images:
                pixel_rects = [rect.translated([0,0], img_dims) for rect in pixel_rects]
                pixel_rects = [rect for rect in pixel_rects if rect.lies_within_frame(img_dims)]

                # Convert to image regions:
                image_regions = [utils.ImageRegion(rect, img_path) for rect in pixel_rects]

                # Yield results:
                for reg in image_regions:
                    yield reg
Esempio n. 10
0
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
Esempio n. 11
0
    def annotate_directory(self, img_dir, bbinfo_file, display_width):
        self.display_width = display_width

        # Get sorted image list:
        img_paths = sorted(utils.list_images_in_directory(img_dir))

        self.img_index = 0 # Set initial index.
        self.current_path = img_paths[self.img_index]
        self.current_img = cv2.imread(self.current_path)
        self.original_img = self.current_img
        self.original_shape = self.current_img.shape
        self.current_scale = 1.0
        self.flipped = False

        self.deleting = False
        self.editing = False
        self.rect_tl = None
        self.rect_br = None

        if os.path.isfile(bbinfo_file):
            self.load_opencv_bounding_box_info(bbinfo_file)

        cv2.setMouseCallback(self.winName, annotate_mouse_callback, self)
        while True:
            self.update_display()
            key = cv2.waitKey(1) & 0xFF

            # Use arrow keys, or < and > to move between images.
            # ASCII Codes:
            #   {28: 'right arrow', 29: 'left arrow'}
            #   {30: 'up arrow', 31: 'down arrow'}
            # Non-standard codes that work for me:
            #   r: 3, l: 2, u: 0, d: 1
            right_pressed = (key == 28 or key == 46 or key == 3)
            left_pressed = (key == 29 or key == 44 or key == 2)

            # Use delete or backspace to enter delete mode.
            # ASCII DEL: 127 (the backspace key on OSX)
            # What OpenCV makes of my delete key: 40
            delete_pressed = (key == 127 or key == 40 or key == 8)

            # Use up arrow or 'f' to flip an image.
            up_pressed = (key == 30 or key == 0)
            flip_pressed = up_pressed or key == ord('f')

            # Space pressed:
            space_pressed = key == 32

            if key == ord('q'):
                print 'Quitting'
                break

            # Save all bounding boxes to the output file:
            elif key == ord('s'):
                print 'Saved: {}'.format(bbinfo_file)
                self.save_opencv_bounding_box_info(bbinfo_file)

            # Overwrite current image with a rotated copy:
            elif key == ord('i'):
                if self.flipped:
                    print 'Overwritten with flipped image: {}'.format(bbinfo_file)
                    self.current_img = cv2.imread(self.current_path)
                    self.current_img = cv2.flip(self.current_img, -1)
                    cv2.imwrite(self.current_path, self.current_img)
                    self.original_img = self.current_img
                    self.flipped = False
                    h, w = self.current_img.shape[:2]
                    rects = self.get_image_rectangles(self.current_path)
                    rects = map(lambda r: r.rotated_180((w,h)), rects)
                    _, key = os.path.split(self.current_path)
                    self.bbinfo_map[key] = rects
                else:
                    print 'Current image has not been rotated.'

            # Add a new bounding box:
            elif key == ord('n') or (space_pressed and not self.editing):
                print 'New bounding box'
                self.editing = True

            # Cancel:
            elif key == 27: # ESC key
                print 'Cancel'
                self.editing = False

            # Accept bounding box:
            elif key == 13 or (space_pressed and self.editing): # Enter / CR key
                if not self.rect_tl is None and not self.rect_br is None:
                    rect = gm.PixelRectangle.fromCorners(self.rect_tl, self.rect_br)
                    if rect.w > 10 and rect.h > 10:
                        self.add_rectangle_to_image(self.current_path, rect)
                        print 'Bounding box {} added.'.format(self.get_annotation_count())
                        self.editing = False
                        self.rect_tl = None
                        self.rect_br = None
                    else:
                        print 'WARNING: Small ({}x{}) bounding box was not added'.format(rect.w, rect.h)
                else:
                    print 'WARNING: Invalid bounding box was not added'

            # Move to next/previous image:
            elif right_pressed or left_pressed:
                self.img_index += 1 if right_pressed else -1
                self.img_index %= len(img_paths)
                self.current_path = img_paths[self.img_index]
                self.current_img = cv2.imread(self.current_path)
                self.original_img = self.current_img
                self.original_shape = self.current_img.shape[:2]
                self.flipped = False
                print 'Moved to image: {}, {}'.format(self.img_index, self.current_path)

            elif flip_pressed: # up arrow
                self.current_img = cv2.flip(self.current_img, -1)
                self.original_img = cv2.flip(self.original_img, -1)
                self.flipped = not self.flipped

                if self.rect_tl and self.rect_br:
                    h, w = self.current_img.shape[:2]
                    rect = gm.PixelRectangle.fromCorners(self.rect_tl, self.rect_br)
                    rect = rect.rotated_180((w,h))
                    self.rect_tl = tuple(rect.tl)
                    self.rect_br = tuple(rect.br)
                print 'Flipped image.'

            elif delete_pressed:
                self.deleting = True
                print 'Click a bounding box to DELETE it.'

            elif key != 255: # 255 means no key was pressed
                print 'Unused keycode: {}'.format(key)
Esempio n. 12
0
def test_classifier(classifier_yaml, svm_file_path, window_dims):
    print "Loading detector..."
    print svm_file_path
    #  Set the trained svm to my_hog
    hog_detector = get_svm_detector(svm_file_path)
    hog = get_hog_object(window_dims)
    print "len(hog_detector)", len(hog_detector)
    print "hog.getDescriptorSize()", hog.getDescriptorSize()
    hog.setSVMDetector(hog_detector)
    print "...[done]"

    for test_dir in classifier_yaml["testing"]["directories"]:
        test_source_name = test_dir.strip("/").split("/")[-1]

        # results_dir = '{}/{}_results'.format(output_dir, test_source_name)
        # detections_fname = '{}/{}_detections.dat'.format(output_dir, test_source_name)

        img_list = sorted(utils.list_images_in_directory(test_dir))

        for img_path in img_list:
            img = cv2.imread(img_path)

            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)

            # img = cv2.resize(img, dsize=None, fx=1.5, fy=1.5)

            # while img.shape[1] > 2000:
            #     print 'resize:', img_path, img.shape
            #     img = cv2.resize(img, dsize=None, fx=0.5, fy=0.5)

            # # Check whether the image is upside-down:
            # if checkImageOrientation(img_path):
            #     print 'Flipped!'
            #     img = cv2.flip(img, -1)

            gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

            print "Detecting: {}".format(img_path)
            # winStride = (4,4)
            winStride = (8, 8)
            padding = (0, 0)
            # minSize = (img.shape[0] / 50, img.shape[1] / 50)
            cars, weights = hog.detectMultiScale(
                img, winStride=winStride, padding=padding, scale=1.05, useMeanshiftGrouping=False
            )
            print "cars:", cars
            print "weights:", weights

            print img_path, len(cars)
            if len(cars) > 0:
                for (x, y, w, h) in cars:
                    # img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
                    lw = max(2, min(img.shape[0], img.shape[1]) / 150)
                    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)
                    # roi_gray = gray[y:y+h, x:x+w]
                    # roi_color = img[y:y+h, x:x+w]

                # img = cv2.resize(img, dsize=None, fx=0.1, fy=0.1)
                # cv2.namedWindow("img", cv2.WINDOW_NORMAL)
                # cv2.resizeWindow('img', 500, 500)
                cv2.imshow("img", img)
                # cv2.imshow('img',img)

                while True:
                    key = cv2.waitKey(1) & 0xFF
                    if key == 27:  # ESC key
                        cv2.destroyAllWindows()
                        return
                    elif key != 255:
                        break
Esempio n. 13
0
def update_preview_state():
    """Return the new state of the UI given the new settings."""
    print 'update_preview_state'

    print 'request data:'
    pprint.pprint(request.json)

    # Get the inputs:
    currentImgIndex = request.json['currentImgIndex']
    hashed_image_dir = request.json['imageDir']
    hashed_detector_dir = request.json['detectorDir']
    performDetection = request.json['performDetection']
    returnImage = request.json['returnImage']

    config_yaml = fileutils.load_yaml_file(detector_config_fname)

    imageDir = validate_image_directory(hashed_image_dir, config_yaml)

    # Get the images:
    image_list = sorted(utils.list_images_in_directory(imageDir))
    num_images = len(image_list)

    if num_images == 0:
        print 'ERROR: The directory \'{}\' contains no images.'.format(
            imageDir)
        # TODO: Display a better error to the client.
        flask.abort(404)  # HTTP status codes: Not Found

    # Find the current image:
    if not currentImgIndex:
        currentImgIndex = 0
    current_img_index = currentImgIndex % num_images
    current_img_path = image_list[current_img_index]
    send_img_path = current_img_path

    # Perform detection:
    detections = []
    if performDetection:
        save_img_dir = os.path.join(app.root_path, 'static', 'cache')
        save_img_fname = '{}.jpg'.format(
            url_safe_hash(current_img_path + hashed_detector_dir))
        save_img_path = os.path.join(save_img_dir, save_img_fname)
        send_img_path = save_img_path
        detection_img_exists = os.path.isfile(save_img_path)
        # if not returnImage and detection_img_exists:
        #     # Delete the current image so that it isn't returned by mistake if
        #     # the detection process fails.
        #     os.remove(save_img_path)
        if not returnImage or not detection_img_exists:
            # Perform the detection.

            detectorDir = validate_detector_directory(hashed_detector_dir,
                                                      config_yaml)

            # detector = ObjectDetector.load_from_directory(detectorDir)
            with ObjectDetector(detectorDir) as detector:
                img = cv2.imread(current_img_path)
                detections, img = detector.detect_objects_in_image(img)

                # cv2.imwrite fails silently if it can't save the image for any
                # reason. We manually check access permissions here, and throw
                # an exception to inform the webmaster if they're incorrect.
                sav_img_dir, _ = os.path.split(save_img_path)
                if not os.path.isdir(sav_img_dir):
                    raise IOError(
                        'The sav_img_dir \'{}\' does not exist.'.format(
                            sav_img_dir))
                if not os.access(sav_img_dir, os.W_OK):
                    raise IOError(
                        'The server user (probably www-data) does not have write permissions for the save_img_path: \'{sav_img_dir}\''
                        .format(sav_img_dir))
                cv2.imwrite(save_img_path, img)

    previewState = jsonify({
        'numImages': num_images,
        'currentImgIndex': current_img_index,
        'currentImgPath': current_img_path,
        # 'currentImgUrl' : None,
        'detections': detections
    })

    if returnImage:
        print 'preview state:', previewState.data
        # Return the image
        return flask.send_file(send_img_path)
    else:
        # Return the new preview state:
        print 'response data:', previewState.data
        return previewState
Esempio n. 14
0
    def annotate_directory(self, img_dir, bbinfo_file, display_width):
        self.display_width = display_width

        # Get sorted image list:
        img_paths = sorted(utils.list_images_in_directory(img_dir))

        self.img_index = 0  # Set initial index.
        self.current_path = img_paths[self.img_index]
        self.current_img = cv2.imread(self.current_path)
        self.original_img = self.current_img
        self.original_shape = self.current_img.shape
        self.current_scale = 1.0
        self.flipped = False

        self.deleting = False
        self.editing = False
        self.rect_tl = None
        self.rect_br = None

        if os.path.isfile(bbinfo_file):
            self.load_opencv_bounding_box_info(bbinfo_file)

        cv2.setMouseCallback(self.winName, annotate_mouse_callback, self)
        while True:
            self.update_display()
            key = cv2.waitKey(1) & 0xFF

            # Use arrow keys, or < and > to move between images.
            # ASCII Codes:
            #   {28: 'right arrow', 29: 'left arrow'}
            #   {30: 'up arrow', 31: 'down arrow'}
            # Non-standard codes that work for me:
            #   r: 3, l: 2, u: 0, d: 1
            right_pressed = (key == 28 or key == 46 or key == 3)
            left_pressed = (key == 29 or key == 44 or key == 2)

            # Use delete or backspace to enter delete mode.
            # ASCII DEL: 127 (the backspace key on OSX)
            # What OpenCV makes of my delete key: 40
            delete_pressed = (key == 127 or key == 40 or key == 8)

            # Use up arrow or 'f' to flip an image.
            up_pressed = (key == 30 or key == 0)
            flip_pressed = up_pressed or key == ord('f')

            # Space pressed:
            space_pressed = key == 32

            if key == ord('q'):
                print 'Quitting'
                break

            # Save all bounding boxes to the output file:
            elif key == ord('s'):
                print 'Saved: {}'.format(bbinfo_file)
                self.save_opencv_bounding_box_info(bbinfo_file)

            # Overwrite current image with a rotated copy:
            elif key == ord('i'):
                if self.flipped:
                    print 'Overwritten with flipped image: {}'.format(
                        bbinfo_file)
                    self.current_img = cv2.imread(self.current_path)
                    self.current_img = cv2.flip(self.current_img, -1)
                    cv2.imwrite(self.current_path, self.current_img)
                    self.original_img = self.current_img
                    self.flipped = False
                    h, w = self.current_img.shape[:2]
                    rects = self.get_image_rectangles(self.current_path)
                    rects = map(lambda r: r.rotated_180((w, h)), rects)
                    _, key = os.path.split(self.current_path)
                    self.bbinfo_map[key] = rects
                else:
                    print 'Current image has not been rotated.'

            # Add a new bounding box:
            elif key == ord('n') or (space_pressed and not self.editing):
                print 'New bounding box'
                self.editing = True

            # Cancel:
            elif key == 27:  # ESC key
                print 'Cancel'
                self.editing = False

            # Accept bounding box:
            elif key == 13 or (space_pressed
                               and self.editing):  # Enter / CR key
                if not self.rect_tl is None and not self.rect_br is None:
                    rect = gm.PixelRectangle.fromCorners(
                        self.rect_tl, self.rect_br)
                    if rect.w > 10 and rect.h > 10:
                        self.add_rectangle_to_image(self.current_path, rect)
                        print 'Bounding box {} added.'.format(
                            self.get_annotation_count())
                        self.editing = False
                        self.rect_tl = None
                        self.rect_br = None
                    else:
                        print 'WARNING: Small ({}x{}) bounding box was not added'.format(
                            rect.w, rect.h)
                else:
                    print 'WARNING: Invalid bounding box was not added'

            # Move to next/previous image:
            elif right_pressed or left_pressed:
                self.img_index += 1 if right_pressed else -1
                self.img_index %= len(img_paths)
                self.current_path = img_paths[self.img_index]
                self.current_img = cv2.imread(self.current_path)
                self.original_img = self.current_img
                self.original_shape = self.current_img.shape[:2]
                self.flipped = False
                print 'Moved to image: {}, {}'.format(self.img_index,
                                                      self.current_path)

            elif flip_pressed:  # up arrow
                self.current_img = cv2.flip(self.current_img, -1)
                self.original_img = cv2.flip(self.original_img, -1)
                self.flipped = not self.flipped

                if self.rect_tl and self.rect_br:
                    h, w = self.current_img.shape[:2]
                    rect = gm.PixelRectangle.fromCorners(
                        self.rect_tl, self.rect_br)
                    rect = rect.rotated_180((w, h))
                    self.rect_tl = tuple(rect.tl)
                    self.rect_br = tuple(rect.br)
                print 'Flipped image.'

            elif delete_pressed:
                self.deleting = True
                print 'Click a bounding box to DELETE it.'

            elif key != 255:  # 255 means no key was pressed
                print 'Unused keycode: {}'.format(key)
Esempio n. 15
0
def update_preview_state():
    """Return the new state of the UI given the new settings."""
    print 'update_preview_state'

    print 'request data:'
    pprint.pprint(request.json)

    # Get the inputs:
    currentImgIndex = request.json['currentImgIndex']
    hashed_image_dir = request.json['imageDir']
    hashed_detector_dir = request.json['detectorDir']
    performDetection = request.json['performDetection']
    returnImage = request.json['returnImage']

    config_yaml = fileutils.load_yaml_file(detector_config_fname)

    imageDir = validate_image_directory(hashed_image_dir, config_yaml)

    # Get the images:
    image_list = sorted(utils.list_images_in_directory(imageDir))
    num_images = len(image_list)

    if num_images == 0:
        print 'ERROR: The directory \'{}\' contains no images.'.format(imageDir)
        # TODO: Display a better error to the client.
        flask.abort(404) # HTTP status codes: Not Found

    # Find the current image:
    if not currentImgIndex:
        currentImgIndex = 0
    current_img_index = currentImgIndex % num_images
    current_img_path = image_list[current_img_index]
    send_img_path = current_img_path

    # Perform detection:
    detections = []
    if performDetection:
        save_img_dir = os.path.join(app.root_path, 'static', 'cache')
        save_img_fname = '{}.jpg'.format(url_safe_hash(current_img_path + hashed_detector_dir))
        save_img_path = os.path.join(save_img_dir, save_img_fname)
        send_img_path = save_img_path
        detection_img_exists = os.path.isfile(save_img_path)
        # if not returnImage and detection_img_exists:
        #     # Delete the current image so that it isn't returned by mistake if
        #     # the detection process fails.
        #     os.remove(save_img_path)
        if not returnImage or not detection_img_exists:
            # Perform the detection.

            detectorDir = validate_detector_directory(hashed_detector_dir, config_yaml)

            # detector = ObjectDetector.load_from_directory(detectorDir)
            with ObjectDetector(detectorDir) as detector:
                img = cv2.imread(current_img_path)
                detections, img = detector.detect_objects_in_image(img)

                # cv2.imwrite fails silently if it can't save the image for any
                # reason. We manually check access permissions here, and throw
                # an exception to inform the webmaster if they're incorrect.
                sav_img_dir, _ = os.path.split(save_img_path)
                if not os.path.isdir(sav_img_dir):
                    raise IOError('The sav_img_dir \'{}\' does not exist.'.format(sav_img_dir))
                if not os.access(sav_img_dir, os.W_OK):
                    raise IOError('The server user (probably www-data) does not have write permissions for the save_img_path: \'{sav_img_dir}\''.format(sav_img_dir))
                cv2.imwrite(save_img_path, img)

    previewState = jsonify({
        'numImages' : num_images,
        'currentImgIndex' : current_img_index,
        'currentImgPath' : current_img_path,
        # 'currentImgUrl' : None,
        'detections' : detections
    })

    if returnImage:
        print 'preview state:', previewState.data
        # Return the image
        return flask.send_file(send_img_path)
    else:
        # Return the new preview state:
        print 'response data:', previewState.data
        return previewState
Esempio n. 16
0
def test_classifier(classifier_yaml, svm_file_path, window_dims):
    print 'Loading detector...'
    print svm_file_path
    #  Set the trained svm to my_hog
    hog_detector = get_svm_detector(svm_file_path)
    hog = get_hog_object(window_dims)
    print 'len(hog_detector)', len(hog_detector)
    print 'hog.getDescriptorSize()', hog.getDescriptorSize()
    hog.setSVMDetector(hog_detector)
    print '...[done]'

    for test_dir in classifier_yaml['testing']['directories']:
        test_source_name = test_dir.strip('/').split('/')[-1]

        # results_dir = '{}/{}_results'.format(output_dir, test_source_name)
        # detections_fname = '{}/{}_detections.dat'.format(output_dir, test_source_name)

        img_list = sorted(utils.list_images_in_directory(test_dir))

        for img_path in img_list:
            img = cv2.imread(img_path)

            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)

            # img = cv2.resize(img, dsize=None, fx=1.5, fy=1.5)

            # while img.shape[1] > 2000:
            #     print 'resize:', img_path, img.shape
            #     img = cv2.resize(img, dsize=None, fx=0.5, fy=0.5)

            # # Check whether the image is upside-down:
            # if checkImageOrientation(img_path):
            #     print 'Flipped!'
            #     img = cv2.flip(img, -1)

            gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

            print 'Detecting: {}'.format(img_path)
            # winStride = (4,4)
            winStride = (8, 8)
            padding = (0, 0)
            # minSize = (img.shape[0] / 50, img.shape[1] / 50)
            cars, weights = hog.detectMultiScale(img,
                                                 winStride=winStride,
                                                 padding=padding,
                                                 scale=1.05,
                                                 useMeanshiftGrouping=False)
            print 'cars:', cars
            print 'weights:', weights

            print img_path, len(cars)
            if len(cars) > 0:
                for (x, y, w, h) in cars:
                    # img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
                    lw = max(2, min(img.shape[0], img.shape[1]) / 150)
                    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)
                    # roi_gray = gray[y:y+h, x:x+w]
                    # roi_color = img[y:y+h, x:x+w]

                # img = cv2.resize(img, dsize=None, fx=0.1, fy=0.1)
                # cv2.namedWindow("img", cv2.WINDOW_NORMAL)
                # cv2.resizeWindow('img', 500, 500)
                cv2.imshow('img', img)
                # cv2.imshow('img',img)

                while True:
                    key = cv2.waitKey(1) & 0xFF
                    if key == 27:  # ESC key
                        cv2.destroyAllWindows()
                        return
                    elif key != 255:
                        break