예제 #1
0
def bootstrap_reconstruction(data, graph, im1, im2):
    '''Starts a reconstruction using two shots.
    '''
    print 'Initial reconstruction with', im1, 'and', im2
    d1 = data.load_exif(im1)
    d2 = data.load_exif(im2)
    cameras = data.load_camera_models()
    camera1 = cameras[d1['camera']]
    camera2 = cameras[d2['camera']]

    tracks, p1, p2 = matching.common_tracks(graph, im1, im2)
    print 'Number of common tracks', len(tracks)

    threshold = data.config.get('five_point_algo_threshold', 0.006)
    R, t, inliers = two_view_reconstruction(p1, p2, camera1, camera2,
                                            threshold)
    if len(inliers) > 5:
        print 'Number of inliers', len(inliers)
        reconstruction = types.Reconstruction()
        reconstruction.cameras = cameras

        shot1 = types.Shot()
        shot1.id = im1
        shot1.camera = cameras[str(d1['camera'])]
        shot1.pose = types.Pose()
        shot1.metadata = get_image_metadata(data, im1)
        reconstruction.add_shot(shot1)

        shot2 = types.Shot()
        shot2.id = im2
        shot2.camera = cameras[str(d2['camera'])]
        shot2.pose = types.Pose()
        shot2.pose.rotation = R
        shot2.pose.translation = t
        shot2.metadata = get_image_metadata(data, im2)
        reconstruction.add_shot(shot2)

        triangulate_shot_features(
            graph, reconstruction, im1,
            data.config.get('triangulation_threshold', 0.004),
            data.config.get('triangulation_min_ray_angle', 2.0))
        print 'Number of reconstructed 3D points :{}'.format(
            len(reconstruction.points))
        if len(reconstruction.points) > data.config.get(
                'five_point_algo_min_inliers', 50):
            print 'Found initialize good pair', im1, 'and', im2
            bundle_single_view(graph, reconstruction, im2, data.config)
            retriangulate(graph, reconstruction, data.config)
            bundle_single_view(graph, reconstruction, im2, data.config)
            return reconstruction

    print 'Pair', im1, ':', im2, 'fails'
    return None
예제 #2
0
def bootstrap_reconstruction(data, graph, im1, im2):
    '''Starts a reconstruction using two shots.
    '''
    print 'Initial reconstruction with', im1, 'and', im2
    d1 = data.load_exif(im1)
    d2 = data.load_exif(im2)
    cameras = data.load_camera_models()
    camera1 = cameras[d1['camera']]
    camera2 = cameras[d2['camera']]

    tracks, p1, p2 = matching.common_tracks(graph, im1, im2)
    print 'Number of common tracks', len(tracks)

    threshold = data.config.get('five_point_algo_threshold', 0.006)
    R, t, inliers = two_view_reconstruction(p1, p2, camera1, camera2, threshold)
    if len(inliers) > 5:
        print 'Number of inliers', len(inliers)
        reconstruction = types.Reconstruction()
        reconstruction.cameras = cameras

        shot1 = types.Shot()
        shot1.id = im1
        shot1.camera = cameras[str(d1['camera'])]
        shot1.pose = types.Pose()
        shot1.metadata = get_image_metadata(data, im1)
        reconstruction.add_shot(shot1)

        shot2 = types.Shot()
        shot2.id = im2
        shot2.camera = cameras[str(d2['camera'])]
        shot2.pose = types.Pose()
        shot2.pose.rotation = R
        shot2.pose.translation = t
        shot2.metadata = get_image_metadata(data, im2)
        reconstruction.add_shot(shot2)

        triangulate_shot_features(
                    graph, reconstruction, im1,
                    data.config.get('triangulation_threshold', 0.004),
                    data.config.get('triangulation_min_ray_angle', 2.0))
        print 'Number of reconstructed 3D points :{}'.format(len(reconstruction.points))
        if len(reconstruction.points) > data.config.get('five_point_algo_min_inliers', 50):
            print 'Found initialize good pair', im1 , 'and', im2
            bundle_single_view(graph, reconstruction, im2, data.config)
            retriangulate(graph, reconstruction, data.config)
            bundle_single_view(graph, reconstruction, im2, data.config)
            return reconstruction

    print 'Pair', im1, ':', im2, 'fails'
    return None
예제 #3
0
def compute_image_pairs(graph, image_graph, config):
    '''All matched image pairs sorted by reconstructability.
    '''
    pairs = []
    score = []
    for im1, im2, d in image_graph.edges(data=True):
        tracks, p1, p2 = matching.common_tracks(graph, im1, im2)
        if len(tracks) >= 50:
            H, inliers = cv2.findHomography(p1, p2, cv2.RANSAC, config.get('homography_threshold', 0.004))
            r = pairwise_reconstructability(len(tracks), inliers.sum())
            if r > 0:
                pairs.append((im1,im2))
                score.append(r)
    order = np.argsort(-np.array(score))
    return [pairs[o] for o in order]
예제 #4
0
def compute_image_pairs(graph, image_graph, config):
    '''All matched image pairs sorted by reconstructability.
    '''
    pairs = []
    score = []
    for im1, im2, d in image_graph.edges(data=True):
        tracks, p1, p2 = matching.common_tracks(graph, im1, im2)
        if len(tracks) >= 50:
            H, inliers = cv2.findHomography(p1, p2, cv2.RANSAC, config.get('homography_threshold', 0.004))
            r = pairwise_reconstructability(len(tracks), inliers.sum())
            if r > 0:
                pairs.append((im1,im2))
                score.append(r)
    order = np.argsort(-np.array(score))
    return [pairs[o] for o in order]
예제 #5
0
def bootstrap_reconstruction(data, graph, im1, im2):
    """Start a reconstruction using two shots."""
    logger.info("Starting reconstruction with {} and {}".format(im1, im2))
    d1 = data.load_exif(im1)
    d2 = data.load_exif(im2)
    cameras = data.load_camera_models()
    camera1 = cameras[d1['camera']]
    camera2 = cameras[d2['camera']]

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

    thresh = data.config.get('five_point_algo_threshold', 0.006)
    min_inliers = data.config.get('five_point_algo_min_inliers', 50)
    R, t, inliers = two_view_reconstruction(p1, p2, camera1, camera2, thresh)
    if len(inliers) > 5:
        logger.info("Two-view reconstruction inliers {}".format(len(inliers)))
        reconstruction = types.Reconstruction()
        reconstruction.cameras = cameras

        shot1 = types.Shot()
        shot1.id = im1
        shot1.camera = cameras[str(d1['camera'])]
        shot1.pose = types.Pose()
        shot1.metadata = get_image_metadata(data, im1)
        reconstruction.add_shot(shot1)

        shot2 = types.Shot()
        shot2.id = im2
        shot2.camera = cameras[str(d2['camera'])]
        shot2.pose = types.Pose(R, t)
        shot2.metadata = get_image_metadata(data, im2)
        reconstruction.add_shot(shot2)

        triangulate_shot_features(
            graph, reconstruction, im1,
            data.config.get('triangulation_threshold', 0.004),
            data.config.get('triangulation_min_ray_angle', 2.0))
        logger.info("Triangulated: {}".format(len(reconstruction.points)))
        if len(reconstruction.points) > min_inliers:
            bundle_single_view(graph, reconstruction, im2, data.config)
            retriangulate(graph, reconstruction, data.config)
            bundle_single_view(graph, reconstruction, im2, data.config)
            return reconstruction

    logger.info("Starting reconstruction with {} and {} failed")
예제 #6
0
파일: dense.py 프로젝트: xczhanjun/OpenSfM
def find_neighboring_images(shot, graph, reconstruction, num_neighbors=5):
    """Find neighbouring images based on common tracks."""
    theta_min = np.pi / 60
    theta_max = np.pi / 6
    ns = []
    C1 = shot.pose.get_origin()
    others = (s for s in reconstruction.shots.values() if s.id != shot.id)
    for other in others:
        score = 0
        C2 = other.pose.get_origin()
        tracks, p1s, p2s = matching.common_tracks(graph, shot.id, other.id)
        for track in tracks:
            if track in reconstruction.points:
                p = np.array(reconstruction.points[track].coordinates)
                theta = angle_between_points(p, C1, C2)
                if theta > theta_min and theta < theta_max:
                    score += 1

        if (score > 20):
            ns.append((other, score))

    ns.sort(key=lambda ns: ns[1], reverse=True)
    return [shot.id] + [n.id for n, s in ns[:num_neighbors]]
예제 #7
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
예제 #8
0
def bootstrap_reconstruction(
        problem, data, graph, im1, im2, hint_forward=False):
    """
    Build 3D reconstruction based on two images `im1` and `im2`.

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

    Returns the `Reconstruction` object, or None if reconstruction failed.
    """
    print "----------------"
    print "bootstrap_reconstruction({}, {}, hint_forward={})".format(
        im1, im2, hint_forward)

    camera1 = problem.image2camera[im1]
    camera2 = problem.image2camera[im2]
    cameras = {camera1.id: camera1, camera2.id: camera2}

    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)
    min_inliers = data.config.get('five_point_algo_min_inliers', 50)
    R, t, inliers = custom_two_view_reconstruction(
        p1, p2, camera1, camera2, thresh, hint_forward)
    print "bootstrap: R={} t={} len(inliers)={}".format(R, t, len(inliers))
    if len(inliers) <= 5:  # FIXME: put const in config
        print "bootstrap failed: not enough points in initial reconstruction"
        return

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

    reco = types.Reconstruction()
    reco.cameras = cameras

    shot1 = types.Shot()
    shot1.id = im1
    shot1.camera = camera1
    shot1.pose = types.Pose()
    shot1.metadata = get_empty_metadata()
    reco.add_shot(shot1)

    shot2 = types.Shot()
    shot2.id = im2
    shot2.camera = camera2
    shot2.pose = types.Pose(R, t)
    shot2.metadata = get_empty_metadata()
    reco.add_shot(shot2)

    reconstruction.triangulate_shot_features(
        graph, reco, im1,
        data.config.get('triangulation_threshold', 0.004),
        data.config.get('triangulation_min_ray_angle', 2.0))
    if len(reco.points) < min_inliers:
        print "bootstrap failed: not enough points after triangulation"
        return

    reconstruction.bundle_single_view(graph, reco, im2, data.config)
    reconstruction.retriangulate(graph, reco, data.config)
    reconstruction.bundle_single_view(graph, reco, im2, data.config)

    debug = partial(_debug_short, graph, reco, im1, im2)
    debug("bootstraped reconstruction")

    return reco