Skip to content

Camera

Pose File Formats

Please see the resources page on pose file formats to learn more about the expected/supported formats commonly used in this library.

A suite of common camera utilities.

This module includes several functions for manipulating and extracting information from camera intrinsics and extrinsics, as well as converting between specific formats.

This module contains the following functions:

  • camera_center(cam) - Computes the center of a camera in world coordinates.
  • relative_transform(cams_1, cams_2) - Computes the relative transformation between two sets of cameras.
  • sfm_to_trajectory(cams, log_file) - Convert a set of cameras from SFM format to Trajectory File format.
  • trajectory_to_sfm(log_file, camera_path, intrinsics) - Convert a set of cameras from Trajectory File format to SFM format.
  • y_axis_rotation(P, theta) - Applies a rotation to the given camera extrinsics matrix along the y-axis.

camera_center(cam)

Computes the center of a camera in world coordinates.

Parameters:

Name Type Description Default
cam np.ndarray

The extrinsics matrix (4x4) of a given camera.

required

Returns:

Type Description
np.ndarray

The camera center vector (3x1) in world coordinates.

Source code in cvt/camera.py
101
102
103
104
105
106
107
108
109
110
111
112
113
def camera_center(cam: np.ndarray) -> np.ndarray:
    """Computes the center of a camera in world coordinates.

    Args:
        cam: The extrinsics matrix (4x4) of a given camera.

    Returns:
        The camera center vector (3x1) in world coordinates.
    """
    C = null_space(cam[:3,:4])
    C /= C[3,:]

    return C

relative_transform(cams_1, cams_2)

Computes the relative transformation between two sets of cameras.

Parameters:

Name Type Description Default
cams_1 np.ndarray

Array of the first set of cameras (Nx4x4).

required
cams_2 np.ndarray

Array of the second set of cameras (Nx4x4).

required

Returns:

Type Description
np.ndarray

The relative transformation matrix (4x4) between the two trajectories.

Source code in cvt/camera.py
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
def relative_transform(cams_1: np.ndarray, cams_2: np.ndarray) -> np.ndarray:
    """Computes the relative transformation between two sets of cameras.

    Args:
        cams_1: Array of the first set of cameras (Nx4x4).
        cams_2: Array of the second set of cameras (Nx4x4).

    Returns:
        The relative transformation matrix (4x4) between the two trajectories.
    """
    centers_1 = np.squeeze(np.array([ camera_center(c) for c in cams_1 ]), axis=2)
    centers_2 = np.squeeze(np.array([ camera_center(c) for c in cams_2 ]), axis=2)

    ### determine scale
    # grab first camera pair
    c1_0 = centers_1[0][:3]
    c2_0 = centers_2[0][:3]

    # grab one-hundreth camera pair
    c1_1 = centers_1[99][:3]
    c2_1 = centers_2[99][:3]

    # calculate the baseline between both sets of cameras
    baseline_1 = np.linalg.norm(c1_0 - c1_1)
    baseline_2 = np.linalg.norm(c2_0 - c2_1)

    # compute the scale based on the baseline ratio
    scale = baseline_2/baseline_1

    ### determine 1->2 Rotation 
    b1 = np.array([c[:3] for c in centers_1])
    b2 = np.array([c[:3] for c in centers_2])
    R = Rotation.align_vectors(b2,b1)[0].as_matrix()
    R = scale * R

    ### create transformation matrix
    M = np.eye(4)
    M[:3,:3] = R

    ### determine 1->2 Translation
    num_cams = len(cams_1)
    t = np.array([ c2-(M@c1) for c1,c2 in zip(centers_1,centers_2) ])
    t = np.mean(t, axis=0)

    ### add translation
    M[:3,3] = t[:3]

    return M

sfm_to_trajectory(cams, log_file)

Convert a set of cameras from SFM format to Trajectory File format.

Parameters:

Name Type Description Default
cams np.ndarray

Array of camera extrinsics (Nx4x4) to be converted.

required
log_file str

Output path to the *.log file that is to be created.

required
Source code in cvt/camera.py
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
def sfm_to_trajectory(cams: np.ndarray, log_file: str) -> None:
    """Convert a set of cameras from SFM format to Trajectory File format.

    Args:
        cams: Array of camera extrinsics (Nx4x4) to be converted.
        log_file: Output path to the *.log file that is to be created.
    """
    num_cams = len(cams)

    with open(log_file, 'w') as f:
        for i,cam in enumerate(cams):
            # write camera to output_file
            f.write("{} {} 0\n".format(str(i),str(i)))
            for row in cam:
                for c in row:
                    f.write("{} ".format(str(c)))
                f.write("\n")

    return

to_opengl_pose(pose)

OpenGL pose: (right-up-back) (cam-to-world)

Source code in cvt/camera.py
49
50
51
52
53
54
55
56
57
def to_opengl_pose(pose):
    """
    OpenGL pose: (right-up-back) (cam-to-world)
    """
    #pose = torch.linalg.inv(pose)
    pose = np.linalg.inv(pose)
    pose[:3,1] *= -1
    pose[:3,2] *= -1
    return pose

trajectory_to_sfm(log_file, camera_path, intrinsics)

Convert a set of cameras from Trajectory File format to SFM format.

Parameters:

Name Type Description Default
log_file str

Input *.log file that stores the trajectory information.

required
camera_path str

Output path where the SFM camera files will be written.

required
intrinsics np.ndarray

Array of intrinsics matrices (Nx3x3) for each camera.

required
Source code in cvt/camera.py
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
def trajectory_to_sfm(log_file: str, camera_path: str, intrinsics: np.ndarray) -> None:
    """Convert a set of cameras from Trajectory File format to SFM format.

    Args:
        log_file: Input *.log file that stores the trajectory information.
        camera_path: Output path where the SFM camera files will be written.
        intrinsics: Array of intrinsics matrices (Nx3x3) for each camera.
    """
    with open(log_file, 'r') as f:
        lines = f.readlines()
        num_lines = len(lines)
        i = 0

        while(i < num_lines-5):
            view_num = int(lines[i].strip().split(" ")[0])

            cam = np.zeros((2,4,4))
            cam[0,0,:] = np.asarray(lines[i+1].strip().split(" "), dtype=float)
            cam[0,1,:] = np.asarray(lines[i+2].strip().split(" "), dtype=float)
            cam[0,2,:] = np.asarray(lines[i+3].strip().split(" "), dtype=float)
            cam[0,3,:] = np.asarray(lines[i+4].strip().split(" "), dtype=float)
            cam[0,:,:] = np.linalg.inv(cam[0,:,:])

            cam_file = "{:08d}_cam.txt".format(view_num)
            cam_path = os.path.join(camera_path, cam_file)

            cam[1,:,:] = intrinsics[view_num]

            write_cam(cam_path, cam)
            i = i+5
    return

y_axis_rotation(P, theta)

Applies a rotation to the given camera extrinsics matrix along the y-axis.

Parameters:

Name Type Description Default
P np.ndarray

Initial extrinsics camera matrix.

required
theta float

Angle (in radians) to rotate the camera.

required

Returns:

Type Description
np.ndarray

The rotated extrinsics matrix for the camera.

Source code in cvt/camera.py
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
def y_axis_rotation(P: np.ndarray, theta: float) -> np.ndarray:
    """Applies a rotation to the given camera extrinsics matrix along the y-axis.

    Parameters:
        P: Initial extrinsics camera matrix.
        theta: Angle (in radians) to rotate the camera.

    Returns:
        The rotated extrinsics matrix for the camera.
    """
    R = np.eye(4)
    R[0,0] = math.cos(theta)
    R[0,2] = math.sin(theta)
    R[2,0] = -(math.sin(theta))
    R[2,2] = math.cos(theta)

    P_rot = R @ P

    return P_rot