Example #1
0
def merge_two_reconstructions(r1, r2, config, threshold=1):
    """Merge two reconstructions with common tracks."""
    t1, t2 = r1.points, r2.points
    common_tracks = list(set(t1) & set(t2))

    if len(common_tracks) > 6:

        # Estimate similarity transform
        p1 = np.array([t1[t].coordinates for t in common_tracks])
        p2 = np.array([t2[t].coordinates for t in common_tracks])

        T, inliers = multiview.fit_similarity_transform(p1,
                                                        p2,
                                                        max_iterations=1000,
                                                        threshold=threshold)

        if len(inliers) >= 10:
            s, A, b = multiview.decompose_similarity_transform(T)
            r1p = r1
            align.apply_similarity(r1p, s, A, b)
            r = r2
            r.shots.update(r1p.shots)
            r.points.update(r1p.points)
            align.align_reconstruction(r, None, config)
            return [r]
        else:
            return [r1, r2]
    else:
        return [r1, r2]
Example #2
0
def merge_two_reconstructions(r1, r2, config, threshold=1):
    """Merge two reconstructions with common tracks."""
    t1, t2 = r1.points, r2.points
    common_tracks = list(set(t1) & set(t2))

    if len(common_tracks) > 6:

        # Estimate similarity transform
        p1 = np.array([t1[t].coordinates for t in common_tracks])
        p2 = np.array([t2[t].coordinates for t in common_tracks])

        T, inliers = multiview.fit_similarity_transform(
            p1, p2, max_iterations=1000, threshold=threshold)

        if len(inliers) >= 10:
            s, A, b = multiview.decompose_similarity_transform(T)
            r1p = r1
            align.apply_similarity(r1p, s, A, b)
            r = r2
            r.shots.update(r1p.shots)
            r.points.update(r1p.points)
            align.align_reconstruction(r, None, config)
            return [r]
        else:
            return [r1, r2]
    else:
        return [r1, r2]
Example #3
0
def reconstruct(problem, data):
    """
    Reconstruct 3D scene and save to the given DataSet.

    Relies on the feature matches and tracks graph to be already computed.

    Returns the reconstruction.
    """
    graph = data.load_tracks_graph()
    reco_triple = problem.get_reconstruction_order()
    reco = bootstrap_reconstruction(
        problem, data, graph,
        reco_triple[0][0], reco_triple[0][1], reco_triple[0][2])
    for prev_img, next_img, hint_forward in reco_triple[1:]:
        result = grow_reconstruction(
            problem, data, graph, reco, prev_img, next_img, hint_forward)
        if not result:
            print "Stopping because grow_reconstruction failed..."
            break

    # Give each 3D point in the reconstruction a color.
    reconstruction.paint_reconstruction(data, graph, reco)

    # Align the reconstruction with the ground plane for a sane visualization.
    align.align_reconstruction(reco, None, data.config)

    data.save_reconstruction([reco])
    return reco
Example #4
0
def merge_two_reconstructions(r1, r2, config, threshold=1):
    """Merge two reconstructions with common tracks IDs."""
    common_tracks = list(set(r1.points) & set(r2.points))
    worked, T, inliers = align_two_reconstruction(r1, r2, common_tracks, threshold)

    if worked and len(inliers) >= 10:
        s, A, b = multiview.decompose_similarity_transform(T)
        r1p = r1
        apply_similarity(r1p, s, A, b)
        r = r2
        r.shots.update(r1p.shots)
        r.points.update(r1p.points)
        align_reconstruction(r, None, config)
        return [r]
    else:
        return [r1, r2]
Example #5
0
def merge_two_reconstructions(r1, r2, config, threshold=1):
    """Merge two reconstructions with common tracks IDs."""
    common_tracks = list(set(r1.points) & set(r2.points))
    worked, T, inliers = align_two_reconstruction(
        r1, r2, common_tracks, threshold)

    if worked and len(inliers) >= 10:
        s, A, b = multiview.decompose_similarity_transform(T)
        r1p = r1
        apply_similarity(r1p, s, A, b)
        r = r2
        r.shots.update(r1p.shots)
        r.points.update(r1p.points)
        align_reconstruction(r, None, config)
        return [r]
    else:
        return [r1, r2]
Example #6
0
def grow_reconstruction(data, graph, reconstruction, images, gcp):
    """Incrementally add shots to an initial reconstruction."""
    bundle(graph, reconstruction, None, data.config)
    align.align_reconstruction(reconstruction, gcp, data.config)

    should_bundle = ShouldBundle(data, reconstruction)
    should_retriangulate = ShouldRetriangulate(data, reconstruction)

    while True:
        if data.config.get('save_partial_reconstructions', False):
            paint_reconstruction(data, graph, reconstruction)
            data.save_reconstruction(
                [reconstruction], 'reconstruction.{}.json'.format(
                    datetime.datetime.now().isoformat().replace(':', '_')))

        common_tracks = reconstructed_points_for_images(
            graph, reconstruction, images)
        if not common_tracks:
            break

        logger.info("-------------------------------------------------------")
        for image, num_tracks in common_tracks:
            if resect(data, graph, reconstruction, image):
                logger.info("Adding {0} to the reconstruction".format(image))
                images.remove(image)

                triangulate_shot_features(
                    graph, reconstruction, image,
                    data.config.get('triangulation_threshold', 0.004),
                    data.config.get('triangulation_min_ray_angle', 2.0))

                if should_bundle.should(reconstruction):
                    bundle(graph, reconstruction, None, data.config)
                    remove_outliers(graph, reconstruction, data.config)
                    align.align_reconstruction(reconstruction, gcp,
                                               data.config)
                    should_bundle.done(reconstruction)
                else:
                    if data.config['local_bundle_radius'] > 0:
                        bundle_local(graph, reconstruction, None, image,
                                     data.config)

                if should_retriangulate.should(reconstruction):
                    logger.info("Re-triangulating")
                    retriangulate(graph, reconstruction, data.config)
                    bundle(graph, reconstruction, None, data.config)
                    should_retriangulate.done(reconstruction)
                break
        else:
            logger.info("Some images can not be added")
            break

    logger.info("-------------------------------------------------------")

    bundle(graph, reconstruction, gcp, data.config)
    align.align_reconstruction(reconstruction, gcp, data.config)
    paint_reconstruction(data, graph, reconstruction)
    return reconstruction
Example #7
0
def grow_reconstruction(data, graph, reconstruction, images, gcp):
    """Incrementally add shots to an initial reconstruction."""
    bundle(graph, reconstruction, None, data.config)
    align.align_reconstruction(reconstruction, gcp, data.config)

    should_bundle = ShouldBundle(data, reconstruction)
    should_retriangulate = ShouldRetriangulate(data, reconstruction)

    while True:
        if data.config.get('save_partial_reconstructions', False):
            paint_reconstruction(data, graph, reconstruction)
            data.save_reconstruction(
                reconstruction, 'reconstruction.{}.json'.format(
                    datetime.datetime.now().isoformat().replace(':', '_')))

        common_tracks = reconstructed_points_for_images(graph, reconstruction,
                                                        images)
        if not common_tracks:
            break

        logger.info("-------------------------------------------------------")
        for image, num_tracks in common_tracks:
            if resect(data, graph, reconstruction, image):
                logger.info("Adding {0} to the reconstruction".format(image))
                images.remove(image)

                triangulate_shot_features(
                    graph, reconstruction, image,
                    data.config.get('triangulation_threshold', 0.004),
                    data.config.get('triangulation_min_ray_angle', 2.0))

                if should_bundle.should(reconstruction):
                    bundle(graph, reconstruction, None, data.config)
                    remove_outliers(graph, reconstruction, data.config)
                    align.align_reconstruction(reconstruction, gcp,
                                               data.config)
                    should_bundle.done(reconstruction)

                if should_retriangulate.should(reconstruction):
                    logger.info("Re-triangulating")
                    retriangulate(graph, reconstruction, data.config)
                    bundle(graph, reconstruction, None, data.config)
                    should_retriangulate.done(reconstruction)
                break
        else:
            logger.info("Some images can not be added")
            break

    logger.info("-------------------------------------------------------")

    bundle(graph, reconstruction, gcp, data.config)
    align.align_reconstruction(reconstruction, gcp, data.config)
    paint_reconstruction(data, graph, reconstruction)
    print 'Done.'
    return reconstruction
Example #8
0
def grow_reconstruction(data, graph, reconstruction, images, gcp):
    """Incrementally add shots to an initial reconstruction."""
    config = data.config
    report = {'steps': []}

    bundle(graph, reconstruction, None, config)
    remove_outliers(graph, reconstruction, config)
    align_reconstruction(reconstruction, gcp, config)

    should_bundle = ShouldBundle(data, reconstruction)
    should_retriangulate = ShouldRetriangulate(data, reconstruction)
    while True:
        if config['save_partial_reconstructions']:
            paint_reconstruction(data, graph, reconstruction)
            data.save_reconstruction(
                [reconstruction], 'reconstruction.{}.json'.format(
                    datetime.datetime.now().isoformat().replace(':', '_')))

        candidates = reconstructed_points_for_images(
            graph, reconstruction, images)
        if not candidates:
            break

        logger.info("-------------------------------------------------------")
        threshold = data.config['resection_threshold']
        min_inliers = data.config['resection_min_inliers']
        for image, num_tracks in candidates:

            camera = reconstruction.cameras[data.load_exif(image)['camera']]
            metadata = get_image_metadata(data, image)
            ok, resrep = resect(graph, reconstruction, image,
                                camera, metadata, threshold, min_inliers)
            if not ok:
                continue

            bundle_single_view(graph, reconstruction, image, data.config)

            logger.info("Adding {0} to the reconstruction".format(image))
            step = {
                'image': image,
                'resection': resrep,
                'memory_usage': current_memory_usage()
            }
            report['steps'].append(step)
            images.remove(image)

            np_before = len(reconstruction.points)
            triangulate_shot_features(graph, reconstruction, image, config)
            np_after = len(reconstruction.points)
            step['triangulated_points'] = np_after - np_before

            if should_retriangulate.should():
                logger.info("Re-triangulating")
                b1rep = bundle(graph, reconstruction, None, config)
                rrep = retriangulate(graph, reconstruction, config)
                b2rep = bundle(graph, reconstruction, None, config)
                remove_outliers(graph, reconstruction, config)
                align_reconstruction(reconstruction, gcp, config)
                step['bundle'] = b1rep
                step['retriangulation'] = rrep
                step['bundle_after_retriangulation'] = b2rep
                should_retriangulate.done()
                should_bundle.done()
            elif should_bundle.should():
                brep = bundle(graph, reconstruction, None, config)
                remove_outliers(graph, reconstruction, config)
                align_reconstruction(reconstruction, gcp, config)
                step['bundle'] = brep
                should_bundle.done()
            elif config['local_bundle_radius'] > 0:
                brep = bundle_local(graph, reconstruction, None, image, config)
                remove_outliers(graph, reconstruction, config)
                step['local_bundle'] = brep

            break
        else:
            logger.info("Some images can not be added")
            break

    logger.info("-------------------------------------------------------")

    bundle(graph, reconstruction, gcp, config)
    remove_outliers(graph, reconstruction, config)
    align_reconstruction(reconstruction, gcp, config)
    paint_reconstruction(data, graph, reconstruction)
    return reconstruction, report
Example #9
0
def bootstrap_reconstruction(
    data: DataSetBase,
    tracks_manager: pymap.TracksManager,
    im1: str,
    im2: str,
    p1: np.ndarray,
    p2: np.ndarray,
) -> Tuple[Optional[types.Reconstruction], Dict[str, Any]]:
    """Start a reconstruction using two shots."""
    logger.info("Starting reconstruction with {} and {}".format(im1, im2))
    report: Dict[str, Any] = {
        "image_pair": (im1, im2),
        "common_tracks": len(p1),
    }

    camera_priors = data.load_camera_models()
    camera1 = camera_priors[data.load_exif(im1)["camera"]]
    camera2 = camera_priors[data.load_exif(im2)["camera"]]

    threshold = data.config["five_point_algo_threshold"]
    min_inliers = data.config["five_point_algo_min_inliers"]
    iterations = data.config["five_point_refine_rec_iterations"]
    R, t, inliers, report[
        "two_view_reconstruction"] = two_view_reconstruction_general(
            p1, p2, camera1, camera2, threshold, iterations)

    logger.info("Two-view reconstruction inliers: {} / {}".format(
        len(inliers), len(p1)))
    if len(inliers) <= 5:
        report["decision"] = "Could not find initial motion"
        logger.info(report["decision"])
        return None, report

    rig_camera_priors = data.load_rig_cameras()
    rig_assignments = data.load_rig_assignments_per_image()

    reconstruction = types.Reconstruction()
    reconstruction.reference = data.load_reference()
    reconstruction.cameras = camera_priors
    reconstruction.rig_cameras = rig_camera_priors

    new_shots = add_shot(data, reconstruction, rig_assignments, im1,
                         pygeometry.Pose())

    if im2 not in new_shots:
        new_shots |= add_shot(data, reconstruction, rig_assignments, im2,
                              pygeometry.Pose(R, t))

    align_reconstruction(reconstruction, None, data.config)
    triangulate_shot_features(tracks_manager, reconstruction, new_shots,
                              data.config)

    logger.info("Triangulated: {}".format(len(reconstruction.points)))
    report["triangulated_points"] = len(reconstruction.points)
    if len(reconstruction.points) < min_inliers:
        report["decision"] = "Initial motion did not generate enough points"
        logger.info(report["decision"])
        return None, report

    to_adjust = {s for s in new_shots if s != im1}
    bundle_shot_poses(reconstruction, to_adjust, camera_priors,
                      rig_camera_priors, data.config)

    retriangulate(tracks_manager, reconstruction, data.config)
    if len(reconstruction.points) < min_inliers:
        report[
            "decision"] = "Re-triangulation after initial motion did not generate enough points"
        logger.info(report["decision"])
        return None, report

    bundle_shot_poses(reconstruction, to_adjust, camera_priors,
                      rig_camera_priors, data.config)

    report["decision"] = "Success"
    report["memory_usage"] = current_memory_usage()
    return reconstruction, report
Example #10
0
def grow_reconstruction(
    data: DataSetBase,
    tracks_manager: pymap.TracksManager,
    reconstruction: types.Reconstruction,
    images: Set[str],
    gcp: List[pymap.GroundControlPoint],
) -> Tuple[types.Reconstruction, Dict[str, Any]]:
    """Incrementally add shots to an initial reconstruction."""
    config = data.config
    report = {"steps": []}

    camera_priors = data.load_camera_models()
    rig_camera_priors = data.load_rig_cameras()

    paint_reconstruction(data, tracks_manager, reconstruction)
    align_reconstruction(reconstruction, gcp, config)

    bundle(reconstruction, camera_priors, rig_camera_priors, None, config)
    remove_outliers(reconstruction, config)
    paint_reconstruction(data, tracks_manager, reconstruction)

    should_bundle = ShouldBundle(data, reconstruction)
    should_retriangulate = ShouldRetriangulate(data, reconstruction)
    while True:
        if config["save_partial_reconstructions"]:
            paint_reconstruction(data, tracks_manager, reconstruction)
            data.save_reconstruction(
                [reconstruction],
                "reconstruction.{}.json".format(
                    datetime.datetime.now().isoformat().replace(":", "_")),
            )

        candidates = reconstructed_points_for_images(tracks_manager,
                                                     reconstruction, images)
        if not candidates:
            break

        logger.info("-------------------------------------------------------")
        threshold = data.config["resection_threshold"]
        min_inliers = data.config["resection_min_inliers"]
        for image, _ in candidates:
            ok, new_shots, resrep = resect(
                data,
                tracks_manager,
                reconstruction,
                image,
                threshold,
                min_inliers,
            )
            if not ok:
                continue

            images -= new_shots
            bundle_shot_poses(
                reconstruction,
                new_shots,
                camera_priors,
                rig_camera_priors,
                data.config,
            )

            logger.info(
                f"Adding {' and '.join(new_shots)} to the reconstruction")
            step = {
                "images": list(new_shots),
                "resection": resrep,
                "memory_usage": current_memory_usage(),
            }
            report["steps"].append(step)

            np_before = len(reconstruction.points)
            triangulate_shot_features(tracks_manager, reconstruction,
                                      new_shots, config)
            np_after = len(reconstruction.points)
            step["triangulated_points"] = np_after - np_before

            if should_retriangulate.should():
                logger.info("Re-triangulating")
                align_reconstruction(reconstruction, gcp, config)
                b1rep = bundle(reconstruction, camera_priors,
                               rig_camera_priors, None, config)
                rrep = retriangulate(tracks_manager, reconstruction, config)
                b2rep = bundle(reconstruction, camera_priors,
                               rig_camera_priors, None, config)
                remove_outliers(reconstruction, config)
                step["bundle"] = b1rep
                step["retriangulation"] = rrep
                step["bundle_after_retriangulation"] = b2rep
                should_retriangulate.done()
                should_bundle.done()
            elif should_bundle.should():
                align_reconstruction(reconstruction, gcp, config)
                brep = bundle(reconstruction, camera_priors, rig_camera_priors,
                              None, config)
                remove_outliers(reconstruction, config)
                step["bundle"] = brep
                should_bundle.done()
            elif config["local_bundle_radius"] > 0:
                bundled_points, brep = bundle_local(
                    reconstruction,
                    camera_priors,
                    rig_camera_priors,
                    None,
                    image,
                    config,
                )
                remove_outliers(reconstruction, config, bundled_points)
                step["local_bundle"] = brep

            break
        else:
            logger.info("Some images can not be added")
            break

    logger.info("-------------------------------------------------------")

    align_reconstruction(reconstruction, gcp, config)
    bundle(reconstruction, camera_priors, rig_camera_priors, gcp, config)
    remove_outliers(reconstruction, config)
    paint_reconstruction(data, tracks_manager, reconstruction)
    return reconstruction, report
Example #11
0
def grow_reconstruction(data, graph, reconstruction, images, gcp):
    """Incrementally add shots to an initial reconstruction."""
    bundle(graph, reconstruction, None, data.config)
    # align the reconstruction points to the ground controlling points
    align.align_reconstruction(reconstruction, gcp, data.config)

    should_bundle = ShouldBundle(data, reconstruction)
    should_retriangulate = ShouldRetriangulate(data, reconstruction)
    bundle_local_neighbour = data.config.get("bundle_local_neighbour", 0)

    while True:
        if data.config.get('save_partial_reconstructions', False):
            paint_reconstruction(data, graph, reconstruction)
            data.save_reconstruction(
                [reconstruction], 'reconstruction.{}.json'.format(
                    datetime.datetime.now().isoformat().replace(':', '_')))

        # A list of (image, num_point) pairs sorted by decreasing number of points.
        common_tracks = reconstructed_points_for_images(graph, reconstruction,
                                                        images)
        if not common_tracks:
            break

        logger.info("-------------------------------------------------------")
        # go through the order of overlapping most
        for image, num_tracks in common_tracks:
            if resect(data, graph, reconstruction, image):
                logger.info("Adding {0} to the reconstruction".format(image))
                images.remove(image)

                # TODO: looser threshold is better, but we haven't determined which is best
                triangulate_shot_features(
                    graph, reconstruction, image,
                    0.032,
                    data.config.get('triangulation_min_ray_angle', 2.0))
                '''
                triangulate_shot_features(
                    graph, reconstruction, image,
                    data.config.get('triangulation_threshold', 0.004),
                    data.config.get('triangulation_min_ray_angle', 2.0))
                '''
                if should_bundle.should(reconstruction):
                    if bundle_local_neighbour > 0:
                        bundle_local(graph, reconstruction, data.config,
                                     bundle_local_neighbour, None, image)
                    else:
                        bundle(graph, reconstruction, None, data.config)
                    # delete the keypoints with large reprojection errors.
                    # should not be a big problem, since not removing a lot in output
                    remove_outliers(graph, reconstruction, data.config)
                    align.align_reconstruction(reconstruction, gcp,
                                               data.config)
                    should_bundle.done(reconstruction)

                # the default behavior is not retriangulate
                # TODO: check whether this is needed
                if should_retriangulate.should(reconstruction):
                    logger.info("Re-triangulating")
                    retriangulate(graph, reconstruction, data.config)
                    if bundle_local_neighbour > 0:
                        bundle_local(graph, reconstruction, data.config,
                                     bundle_local_neighbour, None, image)
                    else:
                        bundle(graph, reconstruction, None, data.config)
                    should_retriangulate.done(reconstruction)
                break
        else:
            logger.info("Some images can not be added")
            break

    logger.info("-------------------------------------------------------")

    bundle(graph, reconstruction, gcp, data.config)
    align.align_reconstruction(reconstruction, gcp, data.config)
    paint_reconstruction(data, graph, reconstruction)
    return reconstruction
Example #12
0
def grow_reconstruction(data, graph, reconstruction, images, gcp):
    """Incrementally add shots to an initial reconstruction."""
    bundle(graph, reconstruction, None, data.config)
    align.align_reconstruction(reconstruction, gcp, data.config)

    should_bundle = ShouldBundle(data, reconstruction)
    should_retriangulate = ShouldRetriangulate(data, reconstruction)
    report = {
        'steps': [],
    }
    while True:
        if data.config['save_partial_reconstructions']:
            paint_reconstruction(data, graph, reconstruction)
            data.save_reconstruction(
                [reconstruction], 'reconstruction.{}.json'.format(
                    datetime.datetime.now().isoformat().replace(':', '_')))

        common_tracks = reconstructed_points_for_images(
            graph, reconstruction, images)
        if not common_tracks:
            break

        logger.info("-------------------------------------------------------")
        for image, num_tracks in common_tracks:
            ok, resrep = resect(data, graph, reconstruction, image)
            if ok:
                logger.info("Adding {0} to the reconstruction".format(image))
                step = {
                    'image': image,
                    'resection': resrep,
                    'memory_usage': current_memory_usage()
                }
                report['steps'].append(step)
                images.remove(image)

                np_before = len(reconstruction.points)
                triangulate_shot_features(
                    graph, reconstruction, image,
                    data.config['triangulation_threshold'],
                    data.config['triangulation_min_ray_angle'])
                np_after = len(reconstruction.points)
                step['triangulated_points'] = np_after - np_before

                if should_bundle.should(reconstruction):
                    brep = bundle(graph, reconstruction, None, data.config)
                    step['bundle'] = brep
                    remove_outliers(graph, reconstruction, data.config)
                    align.align_reconstruction(reconstruction, gcp,
                                               data.config)
                    should_bundle.done(reconstruction)
                else:
                    if data.config['local_bundle_radius'] > 0:
                        brep = bundle_local(graph, reconstruction, None, image,
                                            data.config)
                        step['local_bundle'] = brep

                if should_retriangulate.should(reconstruction):
                    logger.info("Re-triangulating")
                    rrep = retriangulate(graph, reconstruction, data.config)
                    step['retriangulation'] = rrep
                    bundle(graph, reconstruction, None, data.config)
                    should_retriangulate.done(reconstruction)
                break
        else:
            logger.info("Some images can not be added")
            break

    logger.info("-------------------------------------------------------")

    bundle(graph, reconstruction, gcp, data.config)
    align.align_reconstruction(reconstruction, gcp, data.config)
    paint_reconstruction(data, graph, reconstruction)
    return reconstruction, report
Example #13
0
def grow_reconstruction(data, tracks_manager, reconstruction, images,
                        camera_priors, gcp):
    """Incrementally add shots to an initial reconstruction."""
    config = data.config
    report = {"steps": []}

    align_reconstruction(reconstruction, gcp, config)
    bundle(reconstruction, camera_priors, None, config)
    remove_outliers(reconstruction, config)

    should_bundle = ShouldBundle(data, reconstruction)
    should_retriangulate = ShouldRetriangulate(data, reconstruction)
    while True:
        if config["save_partial_reconstructions"]:
            paint_reconstruction(data, tracks_manager, reconstruction)
            data.save_reconstruction(
                [reconstruction],
                "reconstruction.{}.json".format(
                    datetime.datetime.now().isoformat().replace(":", "_")),
            )

        candidates = reconstructed_points_for_images(tracks_manager,
                                                     reconstruction, images)
        if not candidates:
            break

        logger.info("-------------------------------------------------------")
        threshold = data.config["resection_threshold"]
        min_inliers = data.config["resection_min_inliers"]
        for image, _ in candidates:

            camera = reconstruction.cameras[data.load_exif(image)["camera"]]
            metadata = get_image_metadata(data, image)
            ok, resrep = resect(
                tracks_manager,
                reconstruction,
                image,
                camera,
                metadata,
                threshold,
                min_inliers,
            )
            if not ok:
                continue

            bundle_single_view(reconstruction, image, camera_priors,
                               data.config)

            logger.info("Adding {0} to the reconstruction".format(image))
            step = {
                "image": image,
                "resection": resrep,
                "memory_usage": current_memory_usage(),
            }
            report["steps"].append(step)
            images.remove(image)

            np_before = len(reconstruction.points)
            triangulate_shot_features(tracks_manager, reconstruction, image,
                                      config)
            np_after = len(reconstruction.points)
            step["triangulated_points"] = np_after - np_before

            if should_retriangulate.should():
                logger.info("Re-triangulating")
                align_reconstruction(reconstruction, gcp, config)
                b1rep = bundle(reconstruction, camera_priors, None, config)
                rrep = retriangulate(tracks_manager, reconstruction, config)
                b2rep = bundle(reconstruction, camera_priors, None, config)
                remove_outliers(reconstruction, config)
                step["bundle"] = b1rep
                step["retriangulation"] = rrep
                step["bundle_after_retriangulation"] = b2rep
                should_retriangulate.done()
                should_bundle.done()
            elif should_bundle.should():
                align_reconstruction(reconstruction, gcp, config)
                brep = bundle(reconstruction, camera_priors, None, config)
                remove_outliers(reconstruction, config)
                step["bundle"] = brep
                should_bundle.done()
            elif config["local_bundle_radius"] > 0:
                bundled_points, brep = bundle_local(reconstruction,
                                                    camera_priors, None, image,
                                                    config)
                remove_outliers(reconstruction, config, bundled_points)
                step["local_bundle"] = brep

            break
        else:
            logger.info("Some images can not be added")
            break

    logger.info("-------------------------------------------------------")

    align_reconstruction(reconstruction, gcp, config)
    bundle(reconstruction, camera_priors, gcp, config)
    remove_outliers(reconstruction, config)

    paint_reconstruction(data, tracks_manager, reconstruction)
    return reconstruction, report
Example #14
0
def grow_reconstruction(data, graph, reconstruction, images, gcp):
    """Incrementally add shots to an initial reconstruction."""
    bundle(graph, reconstruction, None, data.config)
    align.align_reconstruction(reconstruction, gcp, data.config)

    should_bundle = ShouldBundle(data, reconstruction)
    should_retriangulate = ShouldRetriangulate(data, reconstruction)
    report = {
        'steps': [],
    }
    while True:
        if data.config['save_partial_reconstructions']:
            paint_reconstruction(data, graph, reconstruction)
            data.save_reconstruction(
                [reconstruction], 'reconstruction.{}.json'.format(
                    datetime.datetime.now().isoformat().replace(':', '_')))

        common_tracks = reconstructed_points_for_images(graph, reconstruction,
                                                        images)
        if not common_tracks:
            break

        logger.info("-------------------------------------------------------")
        for image, num_tracks in common_tracks:
            ok, resrep = resect(data, graph, reconstruction, image)
            if ok:
                logger.info("Adding {0} to the reconstruction".format(image))
                step = {
                    'image': image,
                    'resection': resrep,
                    'memory_usage': current_memory_usage()
                }
                report['steps'].append(step)
                images.remove(image)

                np_before = len(reconstruction.points)
                triangulate_shot_features(
                    graph, reconstruction, image,
                    data.config['triangulation_threshold'],
                    data.config['triangulation_min_ray_angle'])
                np_after = len(reconstruction.points)
                step['triangulated_points'] = np_after - np_before

                if should_bundle.should(reconstruction):
                    brep = bundle(graph, reconstruction, None, data.config)
                    step['bundle'] = brep
                    remove_outliers(graph, reconstruction, data.config)
                    align.align_reconstruction(reconstruction, gcp,
                                               data.config)
                    should_bundle.done(reconstruction)
                else:
                    if data.config['local_bundle_radius'] > 0:
                        brep = bundle_local(graph, reconstruction, None, image,
                                            data.config)
                        step['local_bundle'] = brep

                if should_retriangulate.should(reconstruction):
                    logger.info("Re-triangulating")
                    rrep = retriangulate(graph, reconstruction, data.config)
                    step['retriangulation'] = rrep
                    bundle(graph, reconstruction, None, data.config)
                    should_retriangulate.done(reconstruction)
                break
        else:
            logger.info("Some images can not be added")
            break

    logger.info("-------------------------------------------------------")

    bundle(graph, reconstruction, gcp, data.config)
    align.align_reconstruction(reconstruction, gcp, data.config)
    paint_reconstruction(data, graph, reconstruction)
    return reconstruction, report
Example #15
0
def grow_reconstruction(
        problem, data, graph, reco, im1, im2, hint_forward=False):
    """
    Grow the given reconstruction `reco` by adding a new image `im2` to it.

    The new image `im2` is initially matched against an image `im1`, which must
    already exist in the reconstruction.

    See `custom_two_view_reconstruction` for the meaning of `hint_forward`.

    Updates the reconstruction in-place and returns `True` on success.
    """
    # FIXME:
    # - Make DRY with bootstrap_reconstruction; they look similar but they're
    #   different in subtle ways.
    # - Could probably align once at the end, instead of aligning at every
    #   step.
    # - Sometimes we get "Termination: NO_CONVERGENCE" from Ceres. Check for
    #   that error case and perhaps run it for more iterations.

    print "----------------"
    print "grow_reconstruction({}, {}, hint_forward={})".format(
        im1, im2, hint_forward)

    reconstruction.bundle(graph, reco, None, data.config)
    align.align_reconstruction(reco, None, data.config)

    assert im1 in reco.shots
    assert im2 not in reco.shots

    camera1 = problem.image2camera[im1]
    camera2 = problem.image2camera[im2]

    tracks, p1, p2 = matching.common_tracks(graph, im1, im2)
    print "Common tracks: {}".format(len(tracks))

    thresh = data.config.get('five_point_algo_threshold', 0.006)
    R, t, inliers = custom_two_view_reconstruction(
        p1, p2, camera1, camera2, thresh, hint_forward)
    print "grow: R={} t={} len(inliers)={}".format(R, t, len(inliers))
    if len(inliers) <= 5:
        print "grow failed: not enough points in initial reconstruction"
        return False

    # Reconstruction is up to scale; set translation to 1.
    # (This will be corrected later in the bundle adjustment step.)
    t /= np.linalg.norm(t)

    assert camera1.id in reco.cameras
    if camera2.id not in reco.cameras:
        reco.add_camera(camera2)

    shot1_pose = reco.shots[im1].pose
    shot2 = types.Shot()
    shot2.id = im2
    shot2.camera = camera2
    shot2.pose = types.Pose(R, t).compose(shot1_pose)
    shot2.metadata = get_empty_metadata()
    reco.add_shot(shot2)

    debug = partial(_debug_short, graph, reco, im1, im2)
    debug("started with")

    # FIXME: fail here if im2 does not have enough tracks in common with reco

    pose_before = deepcopy(reco.shots[im2].pose)
    reconstruction.bundle_single_view(graph, reco, im2, data.config)

    # It's possible that bundle_single_view caused hint_forward to be violated.
    # If that's the case, revert to the pose before bundle_single_view, and
    # hope that after triangulating the points from `im2`, bundle adjustment
    # will find a better solution.
    rel_pose_after = reco.shots[im2].pose.compose(
        reco.shots[im1].pose.inverse())
    t_after_norm = rel_pose_after.translation / np.linalg.norm(
        rel_pose_after.translation)
    # print "*** t_after_norm={}".format(t_after_norm)
    if hint_forward and t_after_norm[2] >= -0.75:  # FIXME put const in config
        print "*** hint_forward violated; undoing bundle_single_view"
        reco.shots[im2].pose = pose_before
        rel_pose_after = reco.shots[im2].pose.compose(
            reco.shots[im1].pose.inverse())
        t_after_norm = rel_pose_after.translation / np.linalg.norm(
            rel_pose_after.translation)
        print "*** after undo: t_after_norm={}".format(t_after_norm)
    # print

    reconstruction.triangulate_shot_features(
        graph, reco, im2,
        data.config.get('triangulation_threshold', 0.004),
        data.config.get('triangulation_min_ray_angle', 2.0))
    reconstruction.bundle(graph, reco, None, data.config)
    reconstruction.remove_outliers(graph, reco, data.config)
    align.align_reconstruction(reco, None, data.config)
    reconstruction.retriangulate(graph, reco, data.config)
    reconstruction.bundle(graph, reco, None, data.config)

    debug("ended with")

    return True