示例#1
0
    def get_scene_reprojection_errors(self) -> np.ndarray:
        """Get the scene reprojection errors for all 3D points and all associated measurements.

        Returns:
            Reprojection errors as a 1D numpy array.
        """
        scene_reproj_errors: List[float] = []
        for track in self._tracks:
            track_errors, _ = reproj_utils.compute_track_reprojection_errors(
                self._cameras, track)
            scene_reproj_errors.extend(track_errors)

        return np.array(scene_reproj_errors)
示例#2
0
    def get_scene_reprojection_errors(self) -> np.ndarray:
        """Get the scene reprojection errors for all 3D points and all associated measurements.

        Returns:
            Reprojection errors (measured in pixels) as a 1D numpy array.
        """
        scene_reproj_errors: List[float] = []
        for track in self._tracks:
            track_errors, _ = reproj_utils.compute_track_reprojection_errors(self._cameras, track)
            # passing an array argument to .extend() will convert the array to a list, and append its elements
            scene_reproj_errors.extend(track_errors)

        return np.array(scene_reproj_errors)
示例#3
0
    def __validate_track(self, track: SfmTrack, reproj_err_thresh: float) -> bool:
        """Validates a track based on reprojection errors and cheirality checks.

        Args:
            track: track with 3D landmark and measurements.
            reproj_err_thresh: reprojection err threshold for each measurement.

        Returns:
            validity of the track.
        """
        errors, avg_reproj_error = reproj_utils.compute_track_reprojection_errors(self._cameras, track)
        # track is valid as all measurements have error below the threshold
        cheirality_success = np.all(~np.isnan(errors))
        return np.all(errors < reproj_err_thresh) and cheirality_success
示例#4
0
def test_compute_track_reprojection_errors():
    """Ensure that reprojection error is computed properly within a track.

    # For camera 0:
    # [13] = [10,0,3]   [1,0,0 | 0]  [1]
    # [24] = [0,10,4] * [0,1,0 | 0] *[2]
    #  [1] = [0, 0,1]   [0,0,1 | 0]  [1]
    #                                [1]

    # For camera 1:
    # [-7] = [10,0,3]   [1,0,0 |-2]  [1]
    # [44] = [0,10,4] * [0,1,0 | 2] *[2]
    #  [1] = [0, 0,1]   [0,0,1 | 0]  [1]
    #                                [1]
    """
    wTi0 = Pose3(Rot3.RzRyRx(0, 0, 0), np.zeros((3, 1)))
    wTi1 = Pose3(Rot3.RzRyRx(0, 0, 0), np.array([2, -2, 0]))

    f = 10
    k1 = 0
    k2 = 0
    u0 = 3
    v0 = 4

    K0 = Cal3Bundler(f, k1, k2, u0, v0)
    K1 = Cal3Bundler(f, k1, k2, u0, v0)

    track_camera_dict = {
        0: PinholeCameraCal3Bundler(wTi0, K0),
        1: PinholeCameraCal3Bundler(wTi1, K1)
    }

    triangulated_pt = np.array([1, 2, 1])
    track_3d = SfmTrack(triangulated_pt)

    # in camera 0
    track_3d.addMeasurement(idx=0, m=np.array([13, 24]))
    # in camera 1
    track_3d.addMeasurement(idx=1, m=np.array(
        [-8, 43]))  # should be (-7,44), 1 px error in each dim

    errors, avg_track_reproj_error = reproj_utils.compute_track_reprojection_errors(
        track_camera_dict, track_3d)

    expected_errors = np.array([0, np.sqrt(2)])
    np.testing.assert_allclose(errors, expected_errors)
    assert avg_track_reproj_error == np.sqrt(2) / 2
示例#5
0
文件: io.py 项目: borglab/gtsfm
def write_points(gtsfm_data: GtsfmData, images: List[Image],
                 save_dir: str) -> None:
    """Writes the point cloud data file in the COLMAP format.

    Reference: https://colmap.github.io/format.html#points3d-txt

    Args:
        gtsfm_data: scene data to write.
        images: list of all images for this scene, in order of image index
        save_dir: folder to put the points3D.txt file in.
    """
    os.makedirs(save_dir, exist_ok=True)

    num_pts = gtsfm_data.number_tracks()
    avg_track_length, _ = gtsfm_data.get_track_length_statistics()

    file_path = os.path.join(save_dir, "points3D.txt")
    with open(file_path, "w") as f:
        f.write("# 3D point list with one line of data per point:\n")
        f.write(
            "#   POINT3D_ID, X, Y, Z, R, G, B, ERROR, TRACK[] as (IMAGE_ID, POINT2D_IDX)\n"
        )
        f.write(
            f"# Number of points: {num_pts}, mean track length: {np.round(avg_track_length, 2)}\n"
        )

        # TODO: assign unique indices to all keypoints (2d points)
        point2d_idx = 0

        for j in range(num_pts):
            track = gtsfm_data.get_track(j)

            r, g, b = image_utils.get_average_point_color(track, images)
            _, avg_track_reproj_error = reproj_utils.compute_track_reprojection_errors(
                gtsfm_data._cameras, track)
            x, y, z = track.point3()
            f.write(
                f"{j} {x} {y} {z} {r} {g} {b} {np.round(avg_track_reproj_error, 2)} "
            )

            for k in range(track.numberMeasurements()):
                i, uv_measured = track.measurement(k)
                f.write(f"{i} {point2d_idx} ")
            f.write("\n")