Esempio n. 1
0
def locate_thumbnail(thumbnail_filename, source_filename, display=False, save_visualization=False,
                     save_reconstruction=False, reconstruction_format="jpg"):
    thumbnail_basename, thumbnail_image = open_image(thumbnail_filename)
    source_basename, source_image = open_image(source_filename)

    logging.info("Attempting to locate %s within %s", thumbnail_filename, source_filename)
    kp_pairs = match_images(thumbnail_image, source_image)

    if len(kp_pairs) >= 4:
        title = "Found %d matches" % len(kp_pairs)
        logging.info(title)

        H, mask = find_homography(kp_pairs)

        new_thumbnail, corners, rotation = reconstruct_thumbnail(thumbnail_image, source_image, kp_pairs, H)

        print(json.dumps({
            "master": {
                "source": source_filename,
                "dimensions": {
                    "height": source_image.shape[0],
                    "width": source_image.shape[1],
                }
            },
            "thumbnail": {
                "source": thumbnail_filename,
                "dimensions": {
                    "height": thumbnail_image.shape[0],
                    "width": thumbnail_image.shape[1],
                }
            },
            "bounding_box": {
                "height": corners[0][1] - corners[0][0],
                "width": corners[1][1] - corners[1][0],
                "x": corners[1][0],
                "y": corners[0][0],
            },
            "rotation_degrees": rotation
        }))

        if save_reconstruction:
            new_filename = "%s.reconstructed.%s" % (thumbnail_basename, reconstruction_format)
            cv2.imwrite(new_filename, new_thumbnail)
            logging.info("Saved reconstructed thumbnail %s", new_filename)
    else:
        logging.warning("Found only %d matches; skipping reconstruction", len(kp_pairs))
        new_thumbnail = corners = H = mask = None

    if display or save_visualization:
        vis_image = visualize_matches(source_image, thumbnail_image, new_thumbnail, corners, kp_pairs, mask)

    if save_visualization:
        vis_filename = "%s.visualized%s" % os.path.splitext(thumbnail_filename)
        cv2.imwrite(vis_filename, vis_image)
        logging.info("Saved match visualization %s", vis_filename)

    if display:
        cv2.imshow(title, vis_image)
        cv2.waitKey()
        cv2.destroyAllWindows()
Esempio n. 2
0
def display_images(extractor, files):
    window_name = "Controls"

    images = []
    for f in files:
        print("Loading %s" % f)

        try:
            images.append(open_image(f))
        except Exception as exc:
            print(exc, file=sys.stderr)
            continue

    def update_display(*args):
        extractor.canny_threshold = cv2.getTrackbarPos("Canny Threshold",
                                                       window_name)
        extractor.erosion_element = cv2.getTrackbarPos("Erosion Element",
                                                       window_name)
        extractor.erosion_size = cv2.getTrackbarPos("Erosion Size",
                                                    window_name)
        extractor.dilation_element = cv2.getTrackbarPos(
            "Dilation Element", window_name)
        extractor.dilation_size = cv2.getTrackbarPos("Dilation Size",
                                                     window_name)

        # TODO: tame configuration hideousness:
        labels = [
            "Canny Threshold: %s" % extractor.canny_threshold,
            "Erosion Element: %s" %
            FigureExtractor.MORPH_TYPE_KEYS[extractor.erosion_element],
            "Erosion Size: %s" % extractor.erosion_size,
            "Dilation Element: %s" %
            FigureExtractor.MORPH_TYPE_KEYS[extractor.dilation_element],
            "Dilation Size: %s" % extractor.dilation_size
        ]

        labels_img = numpy.zeros((30 * (len(labels) + 1), 600, 3), numpy.uint8)
        for i, label in enumerate(labels, 1):
            cv2.putText(labels_img, label, (0, i * 30),
                        cv2.FONT_HERSHEY_SIMPLEX, 1.0, (192, 192, 192))
        cv2.imshow("Controls", labels_img)

        print("Settings:\n\t", "\n\t".join(labels))
        print()

        for name, image in images:
            filtered_image = extractor.filter_image(image)
            contours, hierarchy = extractor.find_contours(filtered_image)

            # The filtered image will be heavily processed down to 1-bit depth. We'll convert it to RGB
            # so we can display the effects of the filters with full-color overlays for detected figures:
            output = cv2.cvtColor(filtered_image, cv2.COLOR_GRAY2RGB)

            print("Processing %s" % name)

            for bbox in extractor.get_bounding_boxes_from_contours(
                    contours, filtered_image):
                print("\tExtract: %s" % bbox)
                output[bbox.image_slice] = image[bbox.image_slice]

                cv2.polylines(output,
                              bbox.poly,
                              True, (32, 192, 32),
                              thickness=3)
                cv2.drawContours(output,
                                 contours,
                                 bbox.contour_index, (32, 192, 32),
                                 hierarchy=hierarchy,
                                 maxLevel=0)

                cv2.rectangle(output, (bbox.x1, bbox.y1), (bbox.x2, bbox.y2),
                              color=(32, 192, 192))

            cv2.imshow(name, output)

    cv2.namedWindow(window_name)
    cv2.resizeWindow(window_name, 600, 340)

    cv2.createTrackbar("Canny Threshold", window_name,
                       extractor.canny_threshold, 255, update_display)
    cv2.createTrackbar("Erosion Element", window_name,
                       extractor.erosion_element,
                       len(extractor.MORPH_TYPES) - 1, update_display)
    cv2.createTrackbar("Erosion Size", window_name, extractor.erosion_size, 64,
                       update_display)
    cv2.createTrackbar("Dilation Element", window_name,
                       extractor.dilation_element,
                       len(extractor.MORPH_TYPES) - 1, update_display)
    cv2.createTrackbar("Dilation Size", window_name, extractor.dilation_size,
                       64, update_display)

    update_display()

    if args.interactive:
        while cv2.waitKey() not in (13, 27):
            continue
    cv2.destroyAllWindows()
Esempio n. 3
0
        except ImportError:
            import pdb

    # FIXME: we should have a way to enumerate this from FigureExtractor and feed argparse that way:
    param_names = [action.dest for action in extraction_params._group_actions]
    params = {k: v for (k, v) in args._get_kwargs() if k in param_names}

    try:
        extractor = FigureExtractor(**params)

        if args.interactive:
            display_images(extractor, args.files)
        else:
            for f in args.files:
                try:
                    base_name, source_image = open_image(f)
                except Exception as exc:
                    print(exc, file=sys.stderr)
                    continue

                output_base = os.path.join(output_dir, base_name)

                print("Processing %s" % f)

                boxes = []

                for i, bbox in enumerate(extractor.find_figures(source_image),
                                         1):
                    extracted = source_image[bbox.image_slice]
                    extract_filename = os.path.join(
                        output_dir, "%s-%d.jpg" % (output_base, i))
Esempio n. 4
0
def display_images(extractor, files):
    window_name = "Controls"

    images = []
    for f in files:
        print "Loading %s" % f

        try:
            images.append(open_image(f))
        except StandardError as exc:
            print >>sys.stderr, exc
            continue

    def update_display(*args):
        extractor.canny_threshold = cv2.getTrackbarPos("Canny Threshold", window_name)
        extractor.erosion_element = cv2.getTrackbarPos("Erosion Element", window_name)
        extractor.erosion_size = cv2.getTrackbarPos("Erosion Size", window_name)
        extractor.dilation_element = cv2.getTrackbarPos("Dilation Element", window_name)
        extractor.dilation_size = cv2.getTrackbarPos("Dilation Size", window_name)

        # TODO: tame configuration hideousness:
        labels = ["Canny Threshold: %s" % extractor.canny_threshold,
                  "Erosion Element: %s" % FigureExtractor.MORPH_TYPE_KEYS[extractor.erosion_element],
                  "Erosion Size: %s" % extractor.erosion_size,
                  "Dilation Element: %s" % FigureExtractor.MORPH_TYPE_KEYS[extractor.dilation_element],
                  "Dilation Size: %s" % extractor.dilation_size]

        labels_img = numpy.zeros((30 * (len(labels) + 1), 600, 3), numpy.uint8)
        for i, label in enumerate(labels, 1):
            cv2.putText(labels_img, label, (0, i * 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (192, 192, 192))
        cv2.imshow("Controls", labels_img)

        print "Settings:\n\t", "\n\t".join(labels)
        print

        for name, image in images:
            filtered_image = extractor.filter_image(image)
            contours, hierarchy = extractor.find_contours(filtered_image)

            # The filtered image will be heavily processed down to 1-bit depth. We'll convert it to RGB
            # so we can display the effects of the filters with full-color overlays for detected figures:
            output = cv2.cvtColor(filtered_image, cv2.COLOR_GRAY2RGB)

            print "Processing %s" % name

            for bbox in extractor.get_bounding_boxes_from_contours(contours, filtered_image):
                print "\tExtract: %s" % bbox
                output[bbox.image_slice] = image[bbox.image_slice]

                cv2.polylines(output, bbox.poly, True, (32, 192, 32), thickness=3)
                cv2.drawContours(output, contours, bbox.contour_index, (32, 192, 32), hierarchy=hierarchy, maxLevel=0)

                cv2.rectangle(output, (bbox.x1, bbox.y1), (bbox.x2, bbox.y2), color=(32, 192, 192))

            cv2.imshow(name, output)

    cv2.namedWindow(window_name)
    cv2.resizeWindow(window_name, 600, 340)

    cv2.createTrackbar("Canny Threshold", window_name, extractor.canny_threshold, 255, update_display)
    cv2.createTrackbar("Erosion Element", window_name, extractor.erosion_element, len(extractor.MORPH_TYPES) - 1, update_display)
    cv2.createTrackbar("Erosion Size", window_name, extractor.erosion_size, 64, update_display)
    cv2.createTrackbar("Dilation Element", window_name, extractor.dilation_element, len(extractor.MORPH_TYPES) - 1, update_display)
    cv2.createTrackbar("Dilation Size", window_name, extractor.dilation_size, 64, update_display)

    update_display()

    if args.interactive:
        while cv2.waitKey() not in (13, 27):
            continue
    cv2.destroyAllWindows()
Esempio n. 5
0
            import pdb

    # FIXME: we should have a way to enumerate this from FigureExtractor and feed argparse that way:
    param_names = [action.dest for action in extraction_params._group_actions]
    params = {k: v for (k, v) in args._get_kwargs() if k in param_names}

    try:
        extractor = FigureExtractor(**params)
        print("MADE EXTRACTOR")
        
        if args.interactive:
            display_images(extractor, args.files)
        else:
            for f in args.files:
                try:
                    base_name, source_image = open_image(f)
                except StandardError as exc:
                    print >>sys.stderr, exc
                    continue

                output_base = os.path.join(output_dir, base_name)

                print "Processing %s" % f

                boxes = []

                for i, bbox in enumerate(extractor.find_figures(source_image), 1):
                    extracted = source_image[bbox.image_slice]
                    extract_filename = os.path.join(output_dir, "%s-%d.jpg" % (output_base, i))
                    print "\tSaving %s" % extract_filename
                    cv2.imwrite(extract_filename, extracted)
Esempio n. 6
0
def locate_thumbnail(thumbnail_filename, source_filename, display=False, save_visualization=False,
                     save_reconstruction=False, reconstruction_format="jpg",
                     max_aspect_ratio_delta=0.1, match_aspect_ratio=False,
                     minimum_matches=10,
                     json_output_filename=None, max_master_edge=4096, max_output_edge=2048):
    thumbnail_basename, thumbnail_image = open_image(thumbnail_filename)
    source_basename, source_image = open_image(source_filename)

    if (((source_image.shape[0] <= thumbnail_image.shape[0])
         or (source_image.shape[1] <= thumbnail_image.shape[1]))):
        raise RuntimeError("Master file wasn't larger than the thumbnail: %r vs %r" % (source_image.shape,
                                                                                       thumbnail_image.shape))

    logging.info("Attempting to locate %s within %s", thumbnail_filename, source_filename)

    full_source_image = source_image
    if max_master_edge and any(i for i in source_image.shape if i > max_master_edge):
        logging.info("Resizing master to fit within %d pixels", max_master_edge)
        source_image = fit_image_within(source_image, max_master_edge, max_master_edge)

    logging.info('Finding common features')
    kp_pairs = match_images(thumbnail_image, source_image)

    if len(kp_pairs) >= minimum_matches:
        title = "Found %d matches" % len(kp_pairs)
        logging.info(title)

        H, mask = find_homography(kp_pairs)

        corners = get_scaled_corners(thumbnail_image, source_image, full_source_image, kp_pairs, H)

        new_thumbnail, corners, rotation = reconstruct_thumbnail(thumbnail_image, full_source_image, corners,
                                                                 match_aspect_ratio=match_aspect_ratio,
                                                                 max_aspect_ratio_delta=max_aspect_ratio_delta)

        if json_output_filename:
            with open(json_output_filename, mode='wb') as json_file:
                json.dump({
                    "master": {
                        "source": source_filename,
                        "dimensions": {
                            "height": full_source_image.shape[0],
                            "width": full_source_image.shape[1],
                        }
                    },
                    "thumbnail": {
                        "source": thumbnail_filename,
                        "dimensions": {
                            "height": thumbnail_image.shape[0],
                            "width": thumbnail_image.shape[1],
                        }
                    },
                    "bounding_box": {
                        "height": corners[0][1] - corners[0][0],
                        "width": corners[1][1] - corners[1][0],
                        "x": corners[1][0],
                        "y": corners[0][0],
                    },
                    "rotation_degrees": rotation
                }, json_file, indent=4)

        if save_reconstruction:
            new_filename = "%s.reconstructed.%s" % (thumbnail_basename, reconstruction_format)

            new_thumb_img = fit_image_within(new_thumbnail, max_output_edge, max_output_edge)
            cv2.imwrite(new_filename, new_thumb_img)
            logging.info("Saved reconstructed %s thumbnail %s", new_thumb_img.shape[:2], new_filename)
    else:
        logging.warning("Found only %d matches; skipping reconstruction", len(kp_pairs))
        title = "MATCH FAILED: %d pairs" % len(kp_pairs)
        new_thumbnail = corners = H = mask = None

    if display or save_visualization:
        vis_image = visualize_matches(source_image, thumbnail_image, new_thumbnail, corners, kp_pairs, mask)

    if save_visualization:
        vis_filename = "%s.visualized%s" % os.path.splitext(thumbnail_filename)
        cv2.imwrite(vis_filename, vis_image)
        logging.info("Saved match visualization %s", vis_filename)

    if display:
        # This may or may not exist depending on whether OpenCV was compiled using the QT backend:
        window_flags = getattr(cv, 'CV_WINDOW_NORMAL', cv.CV_WINDOW_AUTOSIZE)
        window_title = '%s - %s' % (thumbnail_basename, title)
        cv2.namedWindow(window_title, flags=window_flags)
        cv2.imshow(window_title, vis_image)
        cv2.waitKey()
        cv2.destroyAllWindows()
Esempio n. 7
0
def locate_thumbnail(thumbnail_filename,
                     source_filename,
                     display=False,
                     save_visualization=False,
                     save_reconstruction=False,
                     reconstruction_format="jpg",
                     max_aspect_ratio_delta=0.1,
                     match_aspect_ratio=False,
                     minimum_matches=10,
                     json_output_filename=None,
                     max_master_edge=4096,
                     max_output_edge=2048):
    thumbnail_basename, thumbnail_image = open_image(thumbnail_filename)
    source_basename, source_image = open_image(source_filename)

    if (((source_image.shape[0] <= thumbnail_image.shape[0])
         or (source_image.shape[1] <= thumbnail_image.shape[1]))):
        raise RuntimeError(
            "Master file wasn't larger than the thumbnail: %r vs %r" %
            (source_image.shape, thumbnail_image.shape))

    logging.info("Attempting to locate %s within %s", thumbnail_filename,
                 source_filename)

    full_source_image = source_image
    if max_master_edge and any(
            i for i in source_image.shape if i > max_master_edge):
        logging.info("Resizing master to fit within %d pixels",
                     max_master_edge)
        source_image = fit_image_within(source_image, max_master_edge,
                                        max_master_edge)

    logging.info('Finding common features')
    kp_pairs = match_images(thumbnail_image, source_image)

    if len(kp_pairs) >= minimum_matches:
        title = "Found %d matches" % len(kp_pairs)
        logging.info(title)

        H, mask = find_homography(kp_pairs)

        corners = get_scaled_corners(thumbnail_image, source_image,
                                     full_source_image, kp_pairs, H)

        new_thumbnail, corners, rotation = reconstruct_thumbnail(
            thumbnail_image,
            full_source_image,
            corners,
            match_aspect_ratio=match_aspect_ratio,
            max_aspect_ratio_delta=max_aspect_ratio_delta)

        if json_output_filename:
            with open(json_output_filename, mode='wb') as json_file:
                json.dump(
                    {
                        "master": {
                            "source": source_filename,
                            "dimensions": {
                                "height": full_source_image.shape[0],
                                "width": full_source_image.shape[1],
                            }
                        },
                        "thumbnail": {
                            "source": thumbnail_filename,
                            "dimensions": {
                                "height": thumbnail_image.shape[0],
                                "width": thumbnail_image.shape[1],
                            }
                        },
                        "bounding_box": {
                            "height": corners[0][1] - corners[0][0],
                            "width": corners[1][1] - corners[1][0],
                            "x": corners[1][0],
                            "y": corners[0][0],
                        },
                        "rotation_degrees": rotation
                    },
                    json_file,
                    indent=4)

        if save_reconstruction:
            new_filename = "%s.reconstructed.%s" % (thumbnail_basename,
                                                    reconstruction_format)

            new_thumb_img = fit_image_within(new_thumbnail, max_output_edge,
                                             max_output_edge)
            cv2.imwrite(new_filename, new_thumb_img)
            logging.info("Saved reconstructed %s thumbnail %s",
                         new_thumb_img.shape[:2], new_filename)
    else:
        logging.warning("Found only %d matches; skipping reconstruction",
                        len(kp_pairs))
        title = "MATCH FAILED: %d pairs" % len(kp_pairs)
        new_thumbnail = corners = H = mask = None

    if display or save_visualization:
        vis_image = visualize_matches(source_image, thumbnail_image,
                                      new_thumbnail, corners, kp_pairs, mask)

    if save_visualization:
        vis_filename = "%s.visualized%s" % os.path.splitext(thumbnail_filename)
        cv2.imwrite(vis_filename, vis_image)
        logging.info("Saved match visualization %s", vis_filename)

    if display:
        # This may or may not exist depending on whether OpenCV was compiled using the QT backend:
        window_flags = getattr(cv, 'CV_WINDOW_NORMAL', cv.CV_WINDOW_AUTOSIZE)
        window_title = '%s - %s' % (thumbnail_basename, title)
        cv2.namedWindow(window_title, flags=window_flags)
        cv2.imshow(window_title, vis_image)
        cv2.waitKey()
        cv2.destroyAllWindows()