Пример #1
0
def main():

    example = tf.train.Example()
    for record_path in args.records:
        if not os.path.isfile(record_path):
            print("Record %s does not exist!" % record_path)
            continue

        for record in tf.io.tf_record_iterator(record_path):
            example.ParseFromString(record)
            features = example.features.feature  # dict mapping

            image_bytes = np.frombuffer(
                features["image/encoded"].bytes_list.value[0], dtype=np.uint8)
            image = cv2.imdecode(image_bytes, cv2.IMREAD_COLOR)

            im_height, im_width, _ = image.shape
            xmin = np.array(
                    features['image/object/bbox/xmin'].float_list.value) * \
                            im_width
            xmax = np.array(
                    features['image/object/bbox/xmax'].float_list.value) * \
                            im_width
            ymin = np.array(
                    features['image/object/bbox/ymin'].float_list.value) * \
                            im_height
            ymax = np.array(
                    features['image/object/bbox/ymax'].float_list.value) * \
                            im_height

            text = features['image/object/class/text'].bytes_list.value
            text = [text[i].decode('utf-8') for i in range(len(text))]

            width = xmax - xmin
            height = ymax - ymin

            bboxes = np.column_stack((xmin, ymin, width, height))
            print("Bounding Boxes:", bboxes)

            image = cv2.resize(image, (0, 0), fx=args.scale, fy=args.scale)

            scaled_bboxes = bboxes * args.scale
            drawing_utils.draw_bboxes(image, scaled_bboxes, text)

            lines = []
            filename = features['image/filename'].bytes_list.value[0]
            filename = filename.decode('utf-8')
            filename = "/".join(filename.split("/")[-3:])
            lines.append("Record: %s" % record_path)
            lines.append(filename)
            lines.append("Num boxes: %d" % len(text))
            for i, line in enumerate(lines):
                drawing_utils.shadow_text(image,
                                          line, (5, 20 * i + 15),
                                          font_scale=0.5,
                                          font_weight=1)

            cv2.imshow("window", image)
            if (cv2.waitKey(0) & 0xFF) == ord('q'):
                return
Пример #2
0
    def mouse_callback(event, x, y, flags, params):
        nonlocal tracked_box, tracked_point

        orig, trackers, bboxes, classes = params
        im = orig.copy()

        # Determine which bbox is corresponded to by the click
        click = np.array([x, y]) / WINDOW_SCALE
        radius = 10

        # If there is no tracked point, determine which point gets clicked, if
        # any, and set variables accordingly.
        if tracked_point is None and event == cv2.EVENT_LBUTTONDOWN:
            for i, bbox in enumerate(bboxes):
                top_left = bbox[:2]
                top_right = top_left + [bbox[2], 0]
                bottom_left = top_left + [0, bbox[3]]
                bottom_right = top_left + bbox[2:]

                found = False
                for j, p in enumerate(
                    [top_left, top_right, bottom_left, bottom_right]):
                    if np.linalg.norm(p - click) < radius:
                        tracked_point = POSITIONS[j]
                        tracked_box = i
                        modified.add(tracked_box)
                        found = True

                if found:
                    break

        elif tracked_point is not None and event == cv2.EVENT_LBUTTONDOWN:
            tracked_point = None
        elif tracked_point is not None:
            # There must be a tracked point, so move the point to the location
            # of the mouse click.
            p0 = bboxes[tracked_box][:2]
            p1 = p0 + bboxes[tracked_box][2:]

            if tracked_point == TOP_LEFT:
                p0 = click
            elif tracked_point == TOP_RIGHT:
                p0[1] = click[1]
                p1[0] = click[0]
            elif tracked_point == BOTTOM_LEFT:
                p0[0] = click[0]
                p1[1] = click[1]
            elif tracked_point == BOTTOM_RIGHT:
                p1 = click

            bboxes[tracked_box][:2] = p0
            bboxes[tracked_box][2:] = p1 - p0

        drawing_utils.draw_bboxes(im, bboxes, classes, args.scale)
        drawing_utils.draw_dots(im, bboxes)
        show_scaled(window, im)
Пример #3
0
def save_frame(orig, frame, bboxes, classes, run_name, frame_count):
    # Scale the bboxes back down by original scale factor.
    # This gives us the tight bounding box for the object, rather than the one
    # which has been scaled for the tracker.
    bboxes = drawing_utils.scale_bboxes(bboxes, 1 / args.scale)

    frame_to_draw = orig.copy()
    drawing_utils.draw_bboxes(frame_to_draw, bboxes, classes)
    show_scaled("Saved Frame", frame_to_draw)

    cv2.imwrite(os.path.join(run_name, "%05d.png" % frame_count), orig)
    cv2.imwrite(os.path.join(run_name, "rect_%05d.png" % frame_count), frame)
    bbox_writer.write_bboxes(bboxes, classes,
                             os.path.join(run_name, "%05d.txt" % frame_count))
Пример #4
0
def verify_bboxes(frame, bboxes, classes, yes):
    frame_to_draw = frame.copy()
    drawing_utils.draw_bboxes(frame_to_draw, bboxes, classes, args.scale)
    cv2.putText(frame_to_draw, "Do boxes look okay (y/n)?", (100, 80),
                cv2.FONT_HERSHEY_SIMPLEX, 0.75, (255, 0, 0), 2)
    show_scaled(window, frame_to_draw)

    if yes:
        return

    # Confirm sanity check
    key = cv2.waitKey(0) & 0xFF
    if key == ord('n'):
        print("Poor bounding boxes. Quitting!")
        sys.exit()
Пример #5
0
    def mouse_callback(event, x, y, flags, params):
        nonlocal tracked_point, is_top_left

        orig, trackers, bboxes, classes = params
        im = orig.copy()

        # Determine which bbox is corresponded to by the click
        click = np.array([x, y]) / WINDOW_SCALE
        radius = 10

        # If there is no tracked point, determine which point gets clicked, if
        # any, and set variables accordingly.
        if tracked_point is None and event == cv2.EVENT_LBUTTONDOWN:
            for i, bbox in enumerate(bboxes):
                p0 = bbox[:2]
                p1 = p0 + bbox[2:]

                if np.linalg.norm(p0 - click) < radius:
                    tracked_point = i
                    modified.add(tracked_point)
                    is_top_left = True
                    break
                elif np.linalg.norm(p1 - click) < radius:
                    tracked_point = i
                    modified.add(tracked_point)
                    is_top_left = False
                    break
        elif tracked_point is not None and event == cv2.EVENT_LBUTTONDOWN:
            tracked_point = None
        elif tracked_point is not None:
            # There must be a tracked point, so move the point to the location
            # of the mouse click.
            p0 = bboxes[tracked_point][:2]
            p1 = p0 + bboxes[tracked_point][2:]
            if is_top_left: # No fancy handling necessary
                bboxes[tracked_point][:2] = click
                bboxes[tracked_point][2:] = p1 - click
            else:
                bboxes[tracked_point][2:] = click - bboxes[tracked_point][:2]

        drawing_utils.draw_bboxes(im, bboxes, classes, args.scale)
        drawing_utils.draw_dots(im, bboxes)
        show_scaled(window, im)
Пример #6
0
def mouse_callback(event, x, y, flags, params):
    im = params.copy()
    h, w, c = im.shape

    x = int(x / WINDOW_SCALE)
    y = int(y / WINDOW_SCALE)

    if event == cv2.EVENT_LBUTTONDOWN:
        points.append(np.array([x, y]))

    if len(points) == 1:  # Still drawing a rectangle
        cv2.rectangle(im, tuple(points[0]), (x, y), (255, 255, 0), 1, 1)

    # If the mouse is moved, draw crosshairs
    cv2.line(im, (x, 0), (x, h), (255, 0, 0))
    cv2.line(im, (0, y), (w, y), (255, 0, 0))

    if len(points) == 2:  # We've got a rectangle
        bbox = np.array([points[0], points[1] - points[0]]).reshape(-1)
        bbox = standardize_bbox(bbox)

        cls = str(current_class)
        bboxes.append(bbox)
        classes.append(cls)
        points.clear()

        # Write the bboxes out to file.
        # We get the filename itself, not the full path.
        filename = args.filename.name
        bbox_filename = bbox_writer.get_bbox_filename(filename)
        bbox_path = os.path.join(os.path.dirname(filename), bbox_filename)
        bbox_writer.write_bboxes(bboxes, classes, bbox_path)
        print("Wrote bboxes to file:", bbox_path)

    drawing_utils.draw_bboxes(im, bboxes, classes)

    cv2.putText(im, "Current class: %s" % current_class, (100, 20),
                cv2.FONT_HERSHEY_SIMPLEX, 0.75, (50, 170, 50), 2)

    show_scaled(window, im)
Пример #7
0
def main():
    vid = open_vid(args.filename.name)

    autoplay = False
    autoplay_delay = 32
    stop_at_next_save = False

    current_frame_number = 0
    last_removed_frame = -1

    stored_frames = dict()

    # Initialize the storage on disk
    filename = os.path.splitext(os.path.basename(args.filename.name))[0]
    run_name = "%s" % (filename) + "_labels"
    run_path = os.path.join(os.path.dirname(args.filename.name), run_name)

    try:
        os.mkdir(run_path)
    except:
        print("Directory probably exists already, continuing anyway.")

    while True:

        is_save_frame = (args.frames > 0
                         and current_frame_number % args.frames == 0)

        if current_frame_number not in stored_frames:
            ret, frame = vid.read()

            if not ret:
                print("Unable to open frame, quitting!")
                break

            # If this is a frame we care about, save it to disk. Also, see if
            # there is already a saved set of bboxes, and load those if they
            # exist.
            bboxes, classes = load_bboxes(current_frame_number, run_path)

            stored_frames[current_frame_number] = (frame, bboxes, classes)
            if len(stored_frames) > CACHE_SIZE:
                last_removed_frame += 1
                print("Removing frame", last_removed_frame, " from cache")
                stored_frames.pop(last_removed_frame)

        else:
            frame, bboxes, classes = stored_frames[current_frame_number]

        drawable_frame = frame.copy()
        frame_text = [
            "Frame number: " + str(current_frame_number) +
            (" (saved)" if is_save_frame else ""),
            "Autoplay: " + str(autoplay),
            "Autoplay delay: " + str(autoplay_delay),
            "Stopping at next save frame: " + str(stop_at_next_save),
        ]
        draw_frame_text(drawable_frame, frame_text)
        drawing_utils.draw_bboxes(drawable_frame, bboxes, classes)

        show_scaled(WINDOW, drawable_frame)

        if autoplay:
            delay = autoplay_delay if autoplay else 0
            key = cv2.waitKey(delay) & 0xFF
        else:
            key = label_frame(frame, bboxes, classes, frame_text)

        if is_save_frame:
            save_frame(frame, bboxes, classes, run_path, current_frame_number)

            if stop_at_next_save:
                stop_at_next_save = False
                autoplay = False

        # Handle whatever key the user pressed. The user may have potentially
        # labeled something, as above.
        if key == ord('q'):
            break
        if key == ord('l'):
            current_frame_number += 1
        elif key == ord('h'):
            current_frame_number -= 1
            current_frame_number = max(current_frame_number,
                                       last_removed_frame + 1)
        elif key == ord('j'):
            autoplay_delay = max(autoplay_delay // 2, 1)
        elif key == ord('k'):
            autoplay_delay *= 2
        elif key == ord(' '):
            autoplay = not autoplay
            autoplay_delay = 32
        elif key == ord('n'):
            stop_at_next_save = True
            autoplay = True
            autoplay_delay = 1
            current_frame_number += 1
        elif autoplay:
            current_frame_number += 1

    vid.release()
    cv2.destroyAllWindows()
Пример #8
0
 def draw(frame):
     drawing_utils.draw_bboxes(frame, bboxes, classes)
     draw_frame_text(frame,
                     frame_text + ["Current class: %s" % current_class])
     show_scaled(WINDOW, frame)
Пример #9
0
def main():
    vid = open_vid(args.filename.name)

    rotate_image = args.rotate
    validation = args.validation
    autoplay = False
    autoplay_delay = 32
    stop_at_next_save = False
    global brightness

    current_frame_number = 0
    last_removed_frame = -1

    stored_frames = dict()

    # Initialize the storage on disk
    filename = os.path.splitext(os.path.basename(args.filename.name))[0]

    if args.run_path == "":
        run_name = "%s" % (filename)
        run_path = os.path.join(os.path.dirname(args.filename.name), run_name)
    
        try:
            os.mkdir(run_path)
        except:
            print("Directory probably exists already, continuing anyway.")
    else:
        run_path = args.run_path
        if not os.path.isdir(run_path):
            print("Run path %s is not a directory!" % run_path)
            return

    while True:
        is_save_frame = (args.frames > 0 and
                current_frame_number % args.frames == 0)

        if current_frame_number not in stored_frames:
            ret, frame = vid.read()

            if not ret:
                print("Unable to open frame, quitting!")
                break


            # If this is a frame we care about, save it to disk. Also, see if
            # there is already a saved set of bboxes, and load those if they
            # exist.
            bboxes, classes = load_bboxes(current_frame_number, run_path)

            stored_frames[current_frame_number] = (frame, bboxes, classes)
            if len(stored_frames) > CACHE_SIZE:
                last_removed_frame += 1
                stored_frames.pop(last_removed_frame)

        else:
            frame, bboxes, classes = stored_frames[current_frame_number]
            
        if rotate_image:
            frame = frame[::-1, ::-1, :] # Makes a copy

        drawable_frame = frame.copy()
        frame_text = [
            "Frame number: " + str(current_frame_number) +
            (" (saved)" if is_save_frame else ""),
            "Autoplay: " + str(autoplay),
            "Autoplay delay: " + str(autoplay_delay),
            "Stopping at next save frame: " + str(stop_at_next_save),
            "Validation mode: " + str(validation),
        ]
        draw_frame_text(drawable_frame, frame_text)
        drawing_utils.draw_bboxes(drawable_frame, bboxes, classes)

        show_scaled(WINDOW, drawable_frame)

        if autoplay:
            delay = autoplay_delay if autoplay else 0
            key = cv2.waitKey(delay) & 0xFF
        else:
            key = label_frame(frame, bboxes, classes, frame_text)

        if is_save_frame:
            save_frame(frame, bboxes, classes, run_path, current_frame_number,
                    validation)

            if stop_at_next_save:
                stop_at_next_save = False
                autoplay = False


        # Handle whatever key the user pressed. The user may have potentially
        # labeled something, as above.
        if key == ord('q'):
            break
        elif key == ord('r'):
            rotate_image = not rotate_image
        elif key == ord('v'):
            validation = not validation
        elif key == ord('l'):
            current_frame_number += 1
        elif key == ord('h'):
            current_frame_number -= 1
            current_frame_number = max(current_frame_number,
                    last_removed_frame + 1)
        elif key == ord('j'):
            autoplay_delay = max(autoplay_delay // 2, 1)
        elif key == ord('k'):
            autoplay_delay *= 2
        elif key == ord(' '):
            autoplay = not autoplay
            autoplay_delay = 32
        elif key == ord('n'):
            stop_at_next_save = True
            autoplay = True
            autoplay_delay = 1
            current_frame_number += 1
        elif key == ord('+') or key == ord('='):
            brightness = min(brightness + 0.1, 3.0)
        elif key == ord('-') or key == ord('_'):
            brightness = max(brightness - 0.1, 0)
        elif autoplay:
            current_frame_number += 1

    vid.release()
    cv2.destroyAllWindows()
Пример #10
0
    boxes = []
    for i in range(result['num_detections']):
        if result['detection_scores'][i] > args.threshold:
            class_ = result['detection_classes'][i]
            box = result['detection_boxes'][i]
            score = result['detection_scores'][i]
            y1, x1 = int(box[0] * h), int(box[1] * w)
            y2, x2 = int(box[2] * h), int(box[3] * w)
            boxes.append((class_, score, x1, y1, x2, y2))

    bboxes = [
        np.array([x1, y1, x2 - x1, y2 - y1])
        for (cls, score, x1, y1, x2, y2) in boxes
    ]
    classes = [objdet.category_index[int(cls)]['name'] for cls, *_ in boxes]
    drawing_utils.draw_bboxes(img, bboxes, classes)

    print("Frame:", counter, end="\r")
    img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
    drawing_utils.shadow_text(
        img, "Frame Rate: %0.2f" % (1.0 / (det_end - det_start)), (0, 20))

    if not args.headless:
        cv2.imshow('image', img)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    if args.write_movie:
        writer.write(img)

    if args.write_images:
Пример #11
0
def correction_mode(orig, trackers, bboxes, classes, annotated_classes):

    frame = orig.copy()
    drawing_utils.draw_bboxes(frame, bboxes, annotated_classes, args.scale)
    drawing_utils.draw_dots(frame, bboxes)

    show_scaled(window, frame)

    modified = set()
    tracked_point = None
    is_top_left = False

    def mouse_callback(event, x, y, flags, params):
        nonlocal tracked_point, is_top_left

        orig, trackers, bboxes, classes = params
        im = orig.copy()

        # Determine which bbox is corresponded to by the click
        click = np.array([x, y]) / WINDOW_SCALE
        radius = 10

        # If there is no tracked point, determine which point gets clicked, if
        # any, and set variables accordingly.
        if tracked_point is None and event == cv2.EVENT_LBUTTONDOWN:
            for i, bbox in enumerate(bboxes):
                p0 = bbox[:2]
                p1 = p0 + bbox[2:]

                if np.linalg.norm(p0 - click) < radius:
                    tracked_point = i
                    modified.add(tracked_point)
                    is_top_left = True
                    break
                elif np.linalg.norm(p1 - click) < radius:
                    tracked_point = i
                    modified.add(tracked_point)
                    is_top_left = False
                    break
        elif tracked_point is not None and event == cv2.EVENT_LBUTTONDOWN:
            tracked_point = None
        elif tracked_point is not None:
            # There must be a tracked point, so move the point to the location
            # of the mouse click.
            p0 = bboxes[tracked_point][:2]
            p1 = p0 + bboxes[tracked_point][2:]
            if is_top_left: # No fancy handling necessary
                bboxes[tracked_point][:2] = click
                bboxes[tracked_point][2:] = p1 - click
            else:
                bboxes[tracked_point][2:] = click - bboxes[tracked_point][:2]

        drawing_utils.draw_bboxes(im, bboxes, classes, args.scale)
        drawing_utils.draw_dots(im, bboxes)
        show_scaled(window, im)

    cv2.setMouseCallback(window, mouse_callback,
            param=(orig, trackers, bboxes, annotated_classes))

    while True:
        key = cv2.waitKey(1) & 0xFF
        if key == ord('c') or key == ord(' '):
            for mod in modified:
                print("Reinitializing tracker %d" % mod)
                new_tracker = init_trackers(args.tracker, orig, [bboxes[mod]])
                trackers[mod] = new_tracker[0]
            break
        elif key == ord('r'):
            refine_bboxes(bboxes, classes, orig, trackers)

    # Clear the mouse callback
    cv2.setMouseCallback(window, lambda *args: None)
Пример #12
0
            if not ret:
                print("Tracking failure for object", i)
                bboxes.append(None)
                annotated_classes.append("[FAILURE] %d:%s" % (i, classes[i]))
            else:
                bboxes.append(np.array(bbox))
                annotated_classes.append("%d:%s" % (i, classes[i]))

        if args.refine:
            refine_bboxes(bboxes, classes, frame, trackers)

        end = time.time()
        fps = 1.0 / (end - start)

        original = frame.copy()
        drawing_utils.draw_bboxes(frame, bboxes, annotated_classes, args.scale)

        # Potentially save the frame to disk using @dek's format
        if args.frames > 0 and frame_count % args.frames == 0:
            save_frame(original, frame, bboxes, classes, run_path, frame_count)

        drawing_utils.shadow_text(frame, tracker_name, (100, 20))
        drawing_utils.shadow_text(frame, "FPS: " + str(int(fps)), (100, 50))
        drawing_utils.shadow_text(frame, "Frame: " + str(frame_count), 
                (100, 80))

        # Display result
        show_scaled(window, frame)
        if not args.experiment:
            writer.write(frame)
Пример #13
0
def correction_mode(orig, trackers, bboxes, classes, annotated_classes):

    frame = orig.copy()
    drawing_utils.draw_bboxes(frame, bboxes, annotated_classes, args.scale)
    drawing_utils.draw_dots(frame, bboxes)

    show_scaled(window, frame)

    modified = set()
    tracked_box = None
    tracked_point = None

    TOP_LEFT = 0
    TOP_RIGHT = 1
    BOTTOM_LEFT = 2
    BOTTOM_RIGHT = 3
    POSITIONS = [TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT]

    def mouse_callback(event, x, y, flags, params):
        nonlocal tracked_box, tracked_point

        orig, trackers, bboxes, classes = params
        im = orig.copy()

        # Determine which bbox is corresponded to by the click
        click = np.array([x, y]) / WINDOW_SCALE
        radius = 10

        # If there is no tracked point, determine which point gets clicked, if
        # any, and set variables accordingly.
        if tracked_point is None and event == cv2.EVENT_LBUTTONDOWN:
            for i, bbox in enumerate(bboxes):
                top_left = bbox[:2]
                top_right = top_left + [bbox[2], 0]
                bottom_left = top_left + [0, bbox[3]]
                bottom_right = top_left + bbox[2:]

                found = False
                for j, p in enumerate(
                    [top_left, top_right, bottom_left, bottom_right]):
                    if np.linalg.norm(p - click) < radius:
                        tracked_point = POSITIONS[j]
                        tracked_box = i
                        modified.add(tracked_box)
                        found = True

                if found:
                    break

        elif tracked_point is not None and event == cv2.EVENT_LBUTTONDOWN:
            tracked_point = None
        elif tracked_point is not None:
            # There must be a tracked point, so move the point to the location
            # of the mouse click.
            p0 = bboxes[tracked_box][:2]
            p1 = p0 + bboxes[tracked_box][2:]

            if tracked_point == TOP_LEFT:
                p0 = click
            elif tracked_point == TOP_RIGHT:
                p0[1] = click[1]
                p1[0] = click[0]
            elif tracked_point == BOTTOM_LEFT:
                p0[0] = click[0]
                p1[1] = click[1]
            elif tracked_point == BOTTOM_RIGHT:
                p1 = click

            bboxes[tracked_box][:2] = p0
            bboxes[tracked_box][2:] = p1 - p0

        drawing_utils.draw_bboxes(im, bboxes, classes, args.scale)
        drawing_utils.draw_dots(im, bboxes)
        show_scaled(window, im)

    cv2.setMouseCallback(window,
                         mouse_callback,
                         param=(orig, trackers, bboxes, annotated_classes))

    while True:
        key = cv2.waitKey(1) & 0xFF
        if key == ord('c') or key == ord(' '):
            for mod in modified:
                print("Reinitializing tracker %d" % mod)
                new_tracker = init_trackers(args.tracker, orig, [bboxes[mod]])
                trackers[mod] = new_tracker[0]
            break
        elif key == ord('r'):
            refine_bboxes(bboxes, classes, orig, trackers)

    # Clear the mouse callback
    cv2.setMouseCallback(window, lambda *args: None)
Пример #14
0
def main():
    vid = open_vid(args.filename.name)
    back_track = False
    prev_classes = []
    backward = False
    frame_classes = []
    trackers = []
    classes = []
    bboxes = []
    back_first = False
    tracker_index = args.tracker
    tracker_fn = tracker_fns[tracker_index]
    tracker_name = tracker_fn.__name__.split("_")[0]

    rotate_image = args.rotate
    validation = args.validation
    autoplay = False
    autoplay_delay = 32
    stop_at_next_save = False
    global brightness

    current_frame_number = 0
    last_removed_frame = -1

    stored_frames = dict()

    # Initialize the storage on disk
    filename = os.path.splitext(os.path.basename(args.filename.name))[0]

    if args.run_path == "":
        run_name = "%s" % (filename)
        run_path = os.path.join(os.path.dirname(args.filename.name), run_name)

        if not args.experiment:
            try:
                os.mkdir(run_path)
            except:
                print("Directory probably exists already, continuing anyway.")
    else:
        run_path = args.run_path
        if not os.path.isdir(run_path):
            print("Run path %s is not a directory!" % run_path)
            return

    while True:
        is_save_frame = (args.frames > 0
                         and current_frame_number % args.frames == 0)
        new_bboxes = []
        temp_bboxes = []
        annotated_classes = []
        bboxes = []
        #        print("%d:%d:%d" % (len(bboxes), len(classes), current_frame_number))

        if (current_frame_number not in stored_frames):
            ret, frame = vid.read()
            if not ret:
                print("Unable to open frame, quitting!")
                break

            # If this is a frame we care about, save it to disk. Also, see if
            # there is already a saved set of bboxes, and load those if they
            # exist.
            if validation:
                bboxes, classes = load_bboxes(current_frame_number, run_path)
            else:
                scaled_frame = scale_frame_for_tracking(frame)
                rem = []
                for i, tracker in enumerate(trackers):
                    ret, bbox = tracker.update(scaled_frame)
                    bbox = unscale_bbox_for_tracking(bbox)
                    if not ret:
                        bboxes.append(None)
                        rem.append(i)
                        print("Tracking failure for %s" % classes[i])
                    elif not check_bbox(bbox, frame):
                        bboxes.append(None)
                        rem.append(i)
                        print("%s lost" % classes[i])
                    else:
                        bboxes.append(np.array(bbox))
                        #annotated_classes.append("%d:%s" % (i, classes[i]))
                n = 0
                for i in rem:
                    j = i - n
                    bboxes.pop(j)
                    classes.pop(j)
                    trackers.pop(j)
                    n += 1

                if args.refine:
                    refine_bboxes(bboxes, classes, frame, trackers)

#            stored_frames[current_frame_number] = (frame.copy(), bboxes.copy(), classes.copy())

            if len(stored_frames) > CACHE_SIZE:
                last_removed_frame += 1
                stored_frames.pop(last_removed_frame)

        else:
            frame, temp_bboxes, temp_classes = stored_frames[
                current_frame_number]
            if (not validation) and ((back_track and not back_first)
                                     or not temp_bboxes):
                scaled_frame = scale_frame_for_tracking(frame)
                rem = []
                for i, tracker in enumerate(trackers):
                    ret, bbox = tracker.update(scaled_frame)
                    bbox = unscale_bbox_for_tracking(bbox)
                    if not ret:
                        bboxes.append(None)
                        rem.append(i)
                        print("Tracking failure for %s" % classes[i])
                    elif not check_bbox(bbox, frame):
                        bboxes.append(None)
                        rem.append(i)
                        print("%s lost" % classes[i])
                    else:
                        bboxes.append(np.array(bbox))
                        #annotated_classes.append("%d:%s" % (i, classes[i]))
                n = 0
                for i in rem:
                    j = i - n
                    bboxes.pop(j)
                    classes.pop(j)
                    trackers.pop(j)
                    n += 1
                if args.refine:
                    refine_bboxes(bboxes, classes, frame, trackers)
            elif back_first:
                back_first = False
                bboxes = temp_bboxes
                classes = temp_classes
            else:
                bboxes = temp_bboxes
                classes = temp_classes
                trackers.clear()
                add_trackers(tracker_index, frame.copy(), bboxes.copy(),
                             trackers)


#            stored_frames[current_frame_number] = (frame.copy(), bboxes.copy(), classes.copy())

        if rotate_image:
            frame = frame[::-1, ::-1, :]  # Makes a copy

        drawable_frame = frame.copy()
        frame_text = [
            "Frame number: " + str(current_frame_number) +
            (" (saved)" if is_save_frame else ""),
            "Autoplay: " + str(autoplay),
            "Autoplay delay: " + str(autoplay_delay),
            "Stopping at next save frame: " + str(stop_at_next_save),
            "Validation mode: " + str(validation),
            "Backward Tracking: " + str(back_track),
        ]
        draw_frame_text(drawable_frame, frame_text)
        # print("%d:%d:%d" % (len(bboxes), len(classes), current_frame_number))
        drawing_utils.draw_bboxes(drawable_frame, bboxes, classes)

        show_scaled(WINDOW, drawable_frame)

        if autoplay:
            delay = autoplay_delay if autoplay else 0
            key = cv2.waitKey(delay) & 0xFF
        elif backward:
            delay = autoplay_delay if backward else 0
            key = cv2.waitKey(delay) & 0xFF
        else:
            key = label_frame(frame, bboxes, new_bboxes, classes, frame_text,
                              trackers)
        if is_save_frame:
            save_frame(frame, bboxes, classes, run_path, current_frame_number,
                       validation)

            if stop_at_next_save:
                stop_at_next_save = False
                autoplay = False
                backward = False

        ##
        if not validation:
            add_trackers(tracker_index, frame.copy(), new_bboxes.copy(),
                         trackers)

        stored_frames[current_frame_number] = (frame.copy(), bboxes.copy(),
                                               classes.copy())
        original = frame.copy()
        # Handle whatever key the user pressed. The user may have potentially
        # labeled something, as above.
        if key == ord('q'):
            break
        elif key == ord('d'):
            rotate_image = not rotate_image
        elif key == ord('w'):
            validation = not validation
        elif key == ord('l'):
            current_frame_number += 1
            back_track = False
        elif key == ord('g'):
            current_frame_number -= 1
            current_frame_number = max(current_frame_number,
                                       last_removed_frame + 1)
        elif key == ord('j'):
            autoplay_delay = max(autoplay_delay // 2, 1)
        elif key == ord('k'):
            autoplay_delay *= 2
        elif key == ord(' '):
            autoplay = not autoplay
            autoplay_delay = 32
            back_track = False
        elif key == ord('m'):
            back_track = not back_track
            back_first = True
        elif key == ord('v'):
            backward = True
            stop_at_next_save = True
            current_frame_number -= 1
        elif key == ord('e'):
            correction_mode(original, trackers, bboxes, classes)
            stored_frames[current_frame_number] = (original.copy(),
                                                   bboxes.copy(),
                                                   classes.copy())
        elif key == ord('n'):
            stop_at_next_save = True
            autoplay = True
            autoplay_delay = 1
            current_frame_number += 1
            back_track = False
        elif key == ord('+') or key == ord('='):
            brightness = min(brightness + 0.1, 3.0)
        elif key == ord('-') or key == ord('_'):
            brightness = max(brightness - 0.1, 0)
        elif autoplay:
            current_frame_number += 1
        elif backward:
            current_frame_number -= 1

        current_frame_number = max(current_frame_number,
                                   last_removed_frame + 1)
    vid.release()
    cv2.destroyAllWindows()