Exemple #1
0
 def untransform(self, points):
     points = ensure_homogeneous(points, d=3)
     if len(self.shuffle_indices) > 0:
         inv_shuffle_indices = list(range(len(self.shuffle_indices)))
         for i, j in enumerate(self.shuffle_indices):
             inv_shuffle_indices[j] = i
         points = points[..., inv_shuffle_indices, :]
     return points @ cast_array(np.linalg.inv(self.matrix).T, points)
Exemple #2
0
 def from_ccd_params(cls, alpha_x, alpha_y, x_0, y_0):
     """Create a CameraIntrinsics instance from CCD parameters (4 DOF)."""
     matrix = cast_array([
         [alpha_x, 0.0, x_0, 0.0],
         [0.0, alpha_y, y_0, 0.0],
         [0.0, 0.0, 1.0, 0.0],
     ], np.float64)
     return cls(matrix)
Exemple #3
0
 def untransform(self, camera: CameraIntrinsics):
     camera = camera.clone()
     x_0, y_0 = camera.x_0, camera.y_0
     camera.x_0, camera.y_0 = 0, 0
     camera.matrix = cast_array(np.linalg.inv(self.matrix),
                                camera.matrix) @ camera.matrix
     camera.x_0, camera.y_0 = x_0 / self.sx, y_0 / self.sy
     return camera
Exemple #4
0
def denormalise_points(norm_points, z_ref, intrinsics, height, width):
    """Denormalise a set of points, adding scale and z offset.

    Args:
        norm_points (np.ndarray): The points to denormalise.
        z_ref (float): The depth of the plane that z=0 should map to.
        intrinsics (CameraIntrinsics): The camera which projects 3D points onto the 2D image.
        height (float): The image height.
        width (float): The image width.

    Returns:
        np.ndarray: The denormalised points.
    """
    m_proj = cast_array(
        camera_to_clip_matrix(z_ref, intrinsics, height, width), norm_points)
    return ndc_to_camera_space(norm_points, m_proj)
Exemple #5
0
def normalise_points(denorm_points, z_ref, intrinsics, height, width):
    """Normalise a set of points, removing scale and z offset.

    Points within the image frame should have coordinate values between -1 and 1.

    Args:
        denorm_points (np.ndarray): The points to normalise.
        z_ref (float): The depth of the plane which will become z=0.
        intrinsics (CameraIntrinsics): The camera which projects 3D points onto the 2D image.
        height (float): The image height.
        width (float): The image width.

    Returns:
        np.ndarray: The normalised points.
    """
    m_proj = cast_array(
        camera_to_clip_matrix(z_ref, intrinsics, height, width), denorm_points)
    return camera_space_to_ndc(denorm_points, m_proj)
Exemple #6
0
    def _transform_image(self, image, inverse=False):
        matrix = self.centred_matrix

        if inverse:
            matrix = np.linalg.inv(matrix)
            output_size = cast_array([self.orig_width, self.orig_height],
                                     np.int)
        else:
            output_size = self.dest_size.round().astype(np.int)

        # Scale up
        matrix = self._mm(mat3.scale(self.msaa), matrix)

        # Apply affine image transformation
        inv_matrix = np.linalg.inv(matrix)
        image = image.transform(tuple(output_size * self.msaa), Image.AFFINE,
                                tuple(inv_matrix[0:2].ravel()), Image.BILINEAR)

        # Scale down to output size
        if self.msaa != 1:
            image = image.resize(tuple(output_size), Image.ANTIALIAS)

        return image
Exemple #7
0
def camera_to_clip_matrix(z_ref, intrinsics, height, width):
    """Build a matrix that projects from camera space into clip space.

    Args:
        z_ref (float): The reference depth (will become z=0).
        intrinsics (CameraIntrinsics): The camera object specifying focal length and optical centre.
        height (float): The image height.
        width (float): The image width.

    Returns:
        np.ndarray: The projection matrix.
    """

    # Set the z-size (depth) of the viewing frustum to be equal to the
    # size of the portion of the XY plane at z_ref which projects
    # onto the image.
    size = z_ref * max(width / intrinsics.alpha_x, height / intrinsics.alpha_y)

    # Set near and far planes such that:
    # a) z_ref will correspond to z=0 after normalisation
    #    $z_ref = 2fn/(f+n)$
    # b) The distance from z=-1 to z=1 (normalised) will correspond
    #    to `size` in camera space
    #    $f - n = size$
    far = 0.5 * (sqrt(z_ref**2 + size**2) + z_ref - size)
    near = 0.5 * (sqrt(z_ref**2 + size**2) + z_ref + size)

    # Construct the perspective projection matrix.
    m_proj = cast_array([
        [intrinsics.alpha_x / intrinsics.x_0, 0, 0, 0],
        [0, intrinsics.alpha_y / intrinsics.y_0, 0, 0],
        [0, 0, -(far + near) / (far - near), 2 * far * near / (far - near)],
        [0, 0, 1, 0],
    ], intrinsics.matrix)

    return m_proj
Exemple #8
0
 def back_project(self, coords):
     """Project points from image space to camera space (ideal points)."""
     assert coords.shape[
         -1] == 3, 'expected homogeneous coordinates in 2D space'
     return coords @ cast_array(np.linalg.pinv(self.matrix).T, coords)
Exemple #9
0
 def project(self, coords):
     """Project points from camera space to image space."""
     assert coords.shape[
         -1] == 4, 'expected homogeneous coordinates in 3D space'
     return coords @ cast_array(self.matrix.T, coords)
Exemple #10
0
 def __init__(self, matrix):
     matrix = cast_array(matrix, np.float64)
     if matrix.shape == (3, 3):
         matrix = np.concatenate([matrix, np.zeros((3, 1))], 1)
     assert matrix.shape == (3, 4), 'intrinsic matrix must be 3x4'
     self.matrix = matrix
Exemple #11
0
 def transform(self, camera: CameraIntrinsics):
     camera = camera.clone()
     camera.matrix = cast_array(self.get_centred_matrix(camera),
                                camera.matrix) @ camera.matrix
     return camera
Exemple #12
0
 def _mm(self, a, b):
     a = cast_array(a, self.matrix)
     b = cast_array(b, self.matrix)
     return a @ b
Exemple #13
0
 def transform(self, points):
     points = ensure_homogeneous(points, d=3)
     if len(self.shuffle_indices) > 0:
         points = points[..., self.shuffle_indices, :]
     return points @ cast_array(self.matrix.T, points)
Exemple #14
0
 def set_output_size(self, width, height):
     self.dest_size = cast_array([width, height], self.dest_size)
     return self.dest_size