Spaces:
Runtime error
Runtime error
| # Auto-generated interface file | |
| from typing import List, Tuple, Dict, Union, Optional, Any, overload, Literal, Callable | |
| import numpy as numpy_ | |
| import torch as torch_ | |
| import nvdiffrast.torch | |
| import numbers | |
| from . import numpy, torch | |
| import utils3d.numpy, utils3d.torch | |
| __all__ = ["triangulate", | |
| "compute_face_normal", | |
| "compute_face_angle", | |
| "compute_vertex_normal", | |
| "compute_vertex_normal_weighted", | |
| "remove_corrupted_faces", | |
| "merge_duplicate_vertices", | |
| "remove_unreferenced_vertices", | |
| "subdivide_mesh_simple", | |
| "mesh_relations", | |
| "flatten_mesh_indices", | |
| "calc_quad_candidates", | |
| "calc_quad_distortion", | |
| "calc_quad_direction", | |
| "calc_quad_smoothness", | |
| "sovle_quad", | |
| "sovle_quad_qp", | |
| "tri_to_quad", | |
| "sliding_window_1d", | |
| "sliding_window_nd", | |
| "sliding_window_2d", | |
| "max_pool_1d", | |
| "max_pool_2d", | |
| "max_pool_nd", | |
| "depth_edge", | |
| "normals_edge", | |
| "depth_aliasing", | |
| "interpolate", | |
| "image_scrcoord", | |
| "image_uv", | |
| "image_pixel_center", | |
| "image_pixel", | |
| "image_mesh", | |
| "image_mesh_from_depth", | |
| "depth_to_normals", | |
| "points_to_normals", | |
| "chessboard", | |
| "cube", | |
| "icosahedron", | |
| "square", | |
| "camera_frustum", | |
| "perspective", | |
| "perspective_from_fov", | |
| "perspective_from_fov_xy", | |
| "intrinsics_from_focal_center", | |
| "intrinsics_from_fov", | |
| "fov_to_focal", | |
| "focal_to_fov", | |
| "intrinsics_to_fov", | |
| "view_look_at", | |
| "extrinsics_look_at", | |
| "perspective_to_intrinsics", | |
| "perspective_to_near_far", | |
| "intrinsics_to_perspective", | |
| "extrinsics_to_view", | |
| "view_to_extrinsics", | |
| "normalize_intrinsics", | |
| "crop_intrinsics", | |
| "pixel_to_uv", | |
| "pixel_to_ndc", | |
| "uv_to_pixel", | |
| "project_depth", | |
| "depth_buffer_to_linear", | |
| "unproject_cv", | |
| "unproject_gl", | |
| "project_cv", | |
| "project_gl", | |
| "quaternion_to_matrix", | |
| "axis_angle_to_matrix", | |
| "matrix_to_quaternion", | |
| "extrinsics_to_essential", | |
| "euler_axis_angle_rotation", | |
| "euler_angles_to_matrix", | |
| "skew_symmetric", | |
| "rotation_matrix_from_vectors", | |
| "ray_intersection", | |
| "se3_matrix", | |
| "slerp_quaternion", | |
| "slerp_vector", | |
| "lerp", | |
| "lerp_se3_matrix", | |
| "piecewise_lerp", | |
| "piecewise_lerp_se3_matrix", | |
| "apply_transform", | |
| "linear_spline_interpolate", | |
| "RastContext", | |
| "rasterize_triangle_faces", | |
| "rasterize_edges", | |
| "texture", | |
| "warp_image_by_depth", | |
| "test_rasterization", | |
| "compute_face_angles", | |
| "compute_face_tbn", | |
| "compute_vertex_tbn", | |
| "laplacian", | |
| "laplacian_smooth_mesh", | |
| "taubin_smooth_mesh", | |
| "laplacian_hc_smooth_mesh", | |
| "get_rays", | |
| "get_image_rays", | |
| "get_mipnerf_cones", | |
| "volume_rendering", | |
| "bin_sample", | |
| "importance_sample", | |
| "nerf_render_rays", | |
| "mipnerf_render_rays", | |
| "nerf_render_view", | |
| "mipnerf_render_view", | |
| "InstantNGP", | |
| "point_to_normal", | |
| "depth_to_normal", | |
| "masked_min", | |
| "masked_max", | |
| "bounding_rect", | |
| "intrinsics_from_fov_xy", | |
| "matrix_to_euler_angles", | |
| "matrix_to_axis_angle", | |
| "axis_angle_to_quaternion", | |
| "quaternion_to_axis_angle", | |
| "slerp", | |
| "interpolate_extrinsics", | |
| "interpolate_view", | |
| "to4x4", | |
| "rotation_matrix_2d", | |
| "rotate_2d", | |
| "translate_2d", | |
| "scale_2d", | |
| "apply_2d", | |
| "warp_image_by_forward_flow"] | |
| def triangulate(faces: numpy_.ndarray, vertices: numpy_.ndarray = None, backslash: numpy_.ndarray = None) -> numpy_.ndarray: | |
| """Triangulate a polygonal mesh. | |
| Args: | |
| faces (np.ndarray): [L, P] polygonal faces | |
| vertices (np.ndarray, optional): [N, 3] 3-dimensional vertices. | |
| If given, the triangulation is performed according to the distance | |
| between vertices. Defaults to None. | |
| backslash (np.ndarray, optional): [L] boolean array indicating | |
| how to triangulate the quad faces. Defaults to None. | |
| Returns: | |
| (np.ndarray): [L * (P - 2), 3] triangular faces""" | |
| utils3d.numpy.mesh.triangulate | |
| def compute_face_normal(vertices: numpy_.ndarray, faces: numpy_.ndarray) -> numpy_.ndarray: | |
| """Compute face normals of a triangular mesh | |
| Args: | |
| vertices (np.ndarray): [..., N, 3] 3-dimensional vertices | |
| faces (np.ndarray): [T, 3] triangular face indices | |
| Returns: | |
| normals (np.ndarray): [..., T, 3] face normals""" | |
| utils3d.numpy.mesh.compute_face_normal | |
| def compute_face_angle(vertices: numpy_.ndarray, faces: numpy_.ndarray, eps: float = 1e-12) -> numpy_.ndarray: | |
| """Compute face angles of a triangular mesh | |
| Args: | |
| vertices (np.ndarray): [..., N, 3] 3-dimensional vertices | |
| faces (np.ndarray): [T, 3] triangular face indices | |
| Returns: | |
| angles (np.ndarray): [..., T, 3] face angles""" | |
| utils3d.numpy.mesh.compute_face_angle | |
| def compute_vertex_normal(vertices: numpy_.ndarray, faces: numpy_.ndarray, face_normal: numpy_.ndarray = None) -> numpy_.ndarray: | |
| """Compute vertex normals of a triangular mesh by averaging neightboring face normals | |
| TODO: can be improved. | |
| Args: | |
| vertices (np.ndarray): [..., N, 3] 3-dimensional vertices | |
| faces (np.ndarray): [T, 3] triangular face indices | |
| face_normal (np.ndarray, optional): [..., T, 3] face normals. | |
| None to compute face normals from vertices and faces. Defaults to None. | |
| Returns: | |
| normals (np.ndarray): [..., N, 3] vertex normals""" | |
| utils3d.numpy.mesh.compute_vertex_normal | |
| def compute_vertex_normal_weighted(vertices: numpy_.ndarray, faces: numpy_.ndarray, face_normal: numpy_.ndarray = None) -> numpy_.ndarray: | |
| """Compute vertex normals of a triangular mesh by weighted sum of neightboring face normals | |
| according to the angles | |
| Args: | |
| vertices (np.ndarray): [..., N, 3] 3-dimensional vertices | |
| faces (np.ndarray): [..., T, 3] triangular face indices | |
| face_normal (np.ndarray, optional): [..., T, 3] face normals. | |
| None to compute face normals from vertices and faces. Defaults to None. | |
| Returns: | |
| normals (np.ndarray): [..., N, 3] vertex normals""" | |
| utils3d.numpy.mesh.compute_vertex_normal_weighted | |
| def remove_corrupted_faces(faces: numpy_.ndarray) -> numpy_.ndarray: | |
| """Remove corrupted faces (faces with duplicated vertices) | |
| Args: | |
| faces (np.ndarray): [T, 3] triangular face indices | |
| Returns: | |
| np.ndarray: [T_, 3] triangular face indices""" | |
| utils3d.numpy.mesh.remove_corrupted_faces | |
| def merge_duplicate_vertices(vertices: numpy_.ndarray, faces: numpy_.ndarray, tol: float = 1e-06) -> Tuple[numpy_.ndarray, numpy_.ndarray]: | |
| """Merge duplicate vertices of a triangular mesh. | |
| Duplicate vertices are merged by selecte one of them, and the face indices are updated accordingly. | |
| Args: | |
| vertices (np.ndarray): [N, 3] 3-dimensional vertices | |
| faces (np.ndarray): [T, 3] triangular face indices | |
| tol (float, optional): tolerance for merging. Defaults to 1e-6. | |
| Returns: | |
| vertices (np.ndarray): [N_, 3] 3-dimensional vertices | |
| faces (np.ndarray): [T, 3] triangular face indices""" | |
| utils3d.numpy.mesh.merge_duplicate_vertices | |
| def remove_unreferenced_vertices(faces: numpy_.ndarray, *vertice_attrs, return_indices: bool = False) -> Tuple[numpy_.ndarray, ...]: | |
| """Remove unreferenced vertices of a mesh. | |
| Unreferenced vertices are removed, and the face indices are updated accordingly. | |
| Args: | |
| faces (np.ndarray): [T, P] face indices | |
| *vertice_attrs: vertex attributes | |
| Returns: | |
| faces (np.ndarray): [T, P] face indices | |
| *vertice_attrs: vertex attributes | |
| indices (np.ndarray, optional): [N] indices of vertices that are kept. Defaults to None.""" | |
| utils3d.numpy.mesh.remove_unreferenced_vertices | |
| def subdivide_mesh_simple(vertices: numpy_.ndarray, faces: numpy_.ndarray, n: int = 1) -> Tuple[numpy_.ndarray, numpy_.ndarray]: | |
| """Subdivide a triangular mesh by splitting each triangle into 4 smaller triangles. | |
| NOTE: All original vertices are kept, and new vertices are appended to the end of the vertex list. | |
| Args: | |
| vertices (np.ndarray): [N, 3] 3-dimensional vertices | |
| faces (np.ndarray): [T, 3] triangular face indices | |
| n (int, optional): number of subdivisions. Defaults to 1. | |
| Returns: | |
| vertices (np.ndarray): [N_, 3] subdivided 3-dimensional vertices | |
| faces (np.ndarray): [4 * T, 3] subdivided triangular face indices""" | |
| utils3d.numpy.mesh.subdivide_mesh_simple | |
| def mesh_relations(faces: numpy_.ndarray) -> Tuple[numpy_.ndarray, numpy_.ndarray]: | |
| """Calculate the relation between vertices and faces. | |
| NOTE: The input mesh must be a manifold triangle mesh. | |
| Args: | |
| faces (np.ndarray): [T, 3] triangular face indices | |
| Returns: | |
| edges (np.ndarray): [E, 2] edge indices | |
| edge2face (np.ndarray): [E, 2] edge to face relation. The second column is -1 if the edge is boundary. | |
| face2edge (np.ndarray): [T, 3] face to edge relation | |
| face2face (np.ndarray): [T, 3] face to face relation""" | |
| utils3d.numpy.mesh.mesh_relations | |
| def flatten_mesh_indices(*args: numpy_.ndarray) -> Tuple[numpy_.ndarray, ...]: | |
| utils3d.numpy.mesh.flatten_mesh_indices | |
| def calc_quad_candidates(edges: numpy_.ndarray, face2edge: numpy_.ndarray, edge2face: numpy_.ndarray): | |
| """Calculate the candidate quad faces. | |
| Args: | |
| edges (np.ndarray): [E, 2] edge indices | |
| face2edge (np.ndarray): [T, 3] face to edge relation | |
| edge2face (np.ndarray): [E, 2] edge to face relation | |
| Returns: | |
| quads (np.ndarray): [Q, 4] quad candidate indices | |
| quad2edge (np.ndarray): [Q, 4] edge to quad candidate relation | |
| quad2adj (np.ndarray): [Q, 8] adjacent quad candidates of each quad candidate | |
| quads_valid (np.ndarray): [E] whether the quad corresponding to the edge is valid""" | |
| utils3d.numpy.quadmesh.calc_quad_candidates | |
| def calc_quad_distortion(vertices: numpy_.ndarray, quads: numpy_.ndarray): | |
| """Calculate the distortion of each candidate quad face. | |
| Args: | |
| vertices (np.ndarray): [N, 3] 3-dimensional vertices | |
| quads (np.ndarray): [Q, 4] quad face indices | |
| Returns: | |
| distortion (np.ndarray): [Q] distortion of each quad face""" | |
| utils3d.numpy.quadmesh.calc_quad_distortion | |
| def calc_quad_direction(vertices: numpy_.ndarray, quads: numpy_.ndarray): | |
| """Calculate the direction of each candidate quad face. | |
| Args: | |
| vertices (np.ndarray): [N, 3] 3-dimensional vertices | |
| quads (np.ndarray): [Q, 4] quad face indices | |
| Returns: | |
| direction (np.ndarray): [Q, 4] direction of each quad face. | |
| Represented by the angle between the crossing and each edge.""" | |
| utils3d.numpy.quadmesh.calc_quad_direction | |
| def calc_quad_smoothness(quad2edge: numpy_.ndarray, quad2adj: numpy_.ndarray, quads_direction: numpy_.ndarray): | |
| """Calculate the smoothness of each candidate quad face connection. | |
| Args: | |
| quad2adj (np.ndarray): [Q, 8] adjacent quad faces of each quad face | |
| quads_direction (np.ndarray): [Q, 4] direction of each quad face | |
| Returns: | |
| smoothness (np.ndarray): [Q, 8] smoothness of each quad face connection""" | |
| utils3d.numpy.quadmesh.calc_quad_smoothness | |
| def sovle_quad(face2edge: numpy_.ndarray, edge2face: numpy_.ndarray, quad2adj: numpy_.ndarray, quads_distortion: numpy_.ndarray, quads_smoothness: numpy_.ndarray, quads_valid: numpy_.ndarray): | |
| """Solve the quad mesh from the candidate quad faces. | |
| Args: | |
| face2edge (np.ndarray): [T, 3] face to edge relation | |
| edge2face (np.ndarray): [E, 2] edge to face relation | |
| quad2adj (np.ndarray): [Q, 8] adjacent quad faces of each quad face | |
| quads_distortion (np.ndarray): [Q] distortion of each quad face | |
| quads_smoothness (np.ndarray): [Q, 8] smoothness of each quad face connection | |
| quads_valid (np.ndarray): [E] whether the quad corresponding to the edge is valid | |
| Returns: | |
| weights (np.ndarray): [Q] weight of each valid quad face""" | |
| utils3d.numpy.quadmesh.sovle_quad | |
| def sovle_quad_qp(face2edge: numpy_.ndarray, edge2face: numpy_.ndarray, quad2adj: numpy_.ndarray, quads_distortion: numpy_.ndarray, quads_smoothness: numpy_.ndarray, quads_valid: numpy_.ndarray): | |
| """Solve the quad mesh from the candidate quad faces. | |
| Args: | |
| face2edge (np.ndarray): [T, 3] face to edge relation | |
| edge2face (np.ndarray): [E, 2] edge to face relation | |
| quad2adj (np.ndarray): [Q, 8] adjacent quad faces of each quad face | |
| quads_distortion (np.ndarray): [Q] distortion of each quad face | |
| quads_smoothness (np.ndarray): [Q, 8] smoothness of each quad face connection | |
| quads_valid (np.ndarray): [E] whether the quad corresponding to the edge is valid | |
| Returns: | |
| weights (np.ndarray): [Q] weight of each valid quad face""" | |
| utils3d.numpy.quadmesh.sovle_quad_qp | |
| def tri_to_quad(vertices: numpy_.ndarray, faces: numpy_.ndarray) -> Tuple[numpy_.ndarray, numpy_.ndarray]: | |
| """Convert a triangle mesh to a quad mesh. | |
| NOTE: The input mesh must be a manifold mesh. | |
| Args: | |
| vertices (np.ndarray): [N, 3] 3-dimensional vertices | |
| faces (np.ndarray): [T, 3] triangular face indices | |
| Returns: | |
| vertices (np.ndarray): [N_, 3] 3-dimensional vertices | |
| faces (np.ndarray): [Q, 4] quad face indices""" | |
| utils3d.numpy.quadmesh.tri_to_quad | |
| def sliding_window_1d(x: numpy_.ndarray, window_size: int, stride: int, axis: int = -1): | |
| """Return x view of the input array with x sliding window of the given kernel size and stride. | |
| The sliding window is performed over the given axis, and the window dimension is append to the end of the output array's shape. | |
| Args: | |
| x (np.ndarray): input array with shape (..., axis_size, ...) | |
| kernel_size (int): size of the sliding window | |
| stride (int): stride of the sliding window | |
| axis (int): axis to perform sliding window over | |
| Returns: | |
| a_sliding (np.ndarray): view of the input array with shape (..., n_windows, ..., kernel_size), where n_windows = (axis_size - kernel_size + 1) // stride""" | |
| utils3d.numpy.utils.sliding_window_1d | |
| def sliding_window_nd(x: numpy_.ndarray, window_size: Tuple[int, ...], stride: Tuple[int, ...], axis: Tuple[int, ...]) -> numpy_.ndarray: | |
| utils3d.numpy.utils.sliding_window_nd | |
| def sliding_window_2d(x: numpy_.ndarray, window_size: Union[int, Tuple[int, int]], stride: Union[int, Tuple[int, int]], axis: Tuple[int, int] = (-2, -1)) -> numpy_.ndarray: | |
| utils3d.numpy.utils.sliding_window_2d | |
| def max_pool_1d(x: numpy_.ndarray, kernel_size: int, stride: int, padding: int = 0, axis: int = -1): | |
| utils3d.numpy.utils.max_pool_1d | |
| def max_pool_2d(x: numpy_.ndarray, kernel_size: Union[int, Tuple[int, int]], stride: Union[int, Tuple[int, int]], padding: Union[int, Tuple[int, int]], axis: Tuple[int, int] = (-2, -1)): | |
| utils3d.numpy.utils.max_pool_2d | |
| def max_pool_nd(x: numpy_.ndarray, kernel_size: Tuple[int, ...], stride: Tuple[int, ...], padding: Tuple[int, ...], axis: Tuple[int, ...]) -> numpy_.ndarray: | |
| utils3d.numpy.utils.max_pool_nd | |
| def depth_edge(depth: numpy_.ndarray, atol: float = None, rtol: float = None, kernel_size: int = 3, mask: numpy_.ndarray = None) -> numpy_.ndarray: | |
| """Compute the edge mask from depth map. The edge is defined as the pixels whose neighbors have large difference in depth. | |
| Args: | |
| depth (np.ndarray): shape (..., height, width), linear depth map | |
| atol (float): absolute tolerance | |
| rtol (float): relative tolerance | |
| Returns: | |
| edge (np.ndarray): shape (..., height, width) of dtype torch.bool""" | |
| utils3d.numpy.utils.depth_edge | |
| def normals_edge(normals: numpy_.ndarray, tol: float, kernel_size: int = 3, mask: numpy_.ndarray = None) -> numpy_.ndarray: | |
| """Compute the edge mask from normal map. | |
| Args: | |
| normal (np.ndarray): shape (..., height, width, 3), normal map | |
| tol (float): tolerance in degrees | |
| Returns: | |
| edge (np.ndarray): shape (..., height, width) of dtype torch.bool""" | |
| utils3d.numpy.utils.normals_edge | |
| def depth_aliasing(depth: numpy_.ndarray, atol: float = None, rtol: float = None, kernel_size: int = 3, mask: numpy_.ndarray = None) -> numpy_.ndarray: | |
| """Compute the map that indicates the aliasing of x depth map. The aliasing is defined as the pixels which neither close to the maximum nor the minimum of its neighbors. | |
| Args: | |
| depth (np.ndarray): shape (..., height, width), linear depth map | |
| atol (float): absolute tolerance | |
| rtol (float): relative tolerance | |
| Returns: | |
| edge (np.ndarray): shape (..., height, width) of dtype torch.bool""" | |
| utils3d.numpy.utils.depth_aliasing | |
| def interpolate(bary: numpy_.ndarray, tri_id: numpy_.ndarray, attr: numpy_.ndarray, faces: numpy_.ndarray) -> numpy_.ndarray: | |
| """Interpolate with given barycentric coordinates and triangle indices | |
| Args: | |
| bary (np.ndarray): shape (..., 3), barycentric coordinates | |
| tri_id (np.ndarray): int array of shape (...), triangle indices | |
| attr (np.ndarray): shape (N, M), vertices attributes | |
| faces (np.ndarray): int array of shape (T, 3), face vertex indices | |
| Returns: | |
| np.ndarray: shape (..., M) interpolated result""" | |
| utils3d.numpy.utils.interpolate | |
| def image_scrcoord(width: int, height: int) -> numpy_.ndarray: | |
| """Get OpenGL's screen space coordinates, ranging in [0, 1]. | |
| [0, 0] is the bottom-left corner of the image. | |
| Args: | |
| width (int): image width | |
| height (int): image height | |
| Returns: | |
| (np.ndarray): shape (height, width, 2)""" | |
| utils3d.numpy.utils.image_scrcoord | |
| def image_uv(height: int, width: int, left: int = None, top: int = None, right: int = None, bottom: int = None, dtype: numpy_.dtype = numpy_.float32) -> numpy_.ndarray: | |
| """Get image space UV grid, ranging in [0, 1]. | |
| image_uv(10, 10): | |
| [[[0.05, 0.05], [0.15, 0.05], ..., [0.95, 0.05]], | |
| [[0.05, 0.15], [0.15, 0.15], ..., [0.95, 0.15]], | |
| ... ... ... | |
| [[0.05, 0.95], [0.15, 0.95], ..., [0.95, 0.95]]] | |
| Args: | |
| width (int): image width | |
| height (int): image height | |
| Returns: | |
| np.ndarray: shape (height, width, 2)""" | |
| utils3d.numpy.utils.image_uv | |
| def image_pixel_center(height: int, width: int, left: int = None, top: int = None, right: int = None, bottom: int = None, dtype: numpy_.dtype = numpy_.float32) -> numpy_.ndarray: | |
| """Get image pixel center coordinates, ranging in [0, width] and [0, height]. | |
| `image[i, j]` has pixel center coordinates `(j + 0.5, i + 0.5)`. | |
| image_pixel_center(10, 10): | |
| [[[0.5, 0.5], [1.5, 0.5], ..., [9.5, 0.5]], | |
| [[0.5, 1.5], [1.5, 1.5], ..., [9.5, 1.5]], | |
| ... ... ... | |
| [[0.5, 9.5], [1.5, 9.5], ..., [9.5, 9.5]]] | |
| Args: | |
| width (int): image width | |
| height (int): image height | |
| Returns: | |
| np.ndarray: shape (height, width, 2)""" | |
| utils3d.numpy.utils.image_pixel_center | |
| def image_pixel(height: int, width: int, left: int = None, top: int = None, right: int = None, bottom: int = None, dtype: numpy_.dtype = numpy_.int32) -> numpy_.ndarray: | |
| """Get image pixel coordinates grid, ranging in [0, width - 1] and [0, height - 1]. | |
| `image[i, j]` has pixel center coordinates `(j, i)`. | |
| image_pixel_center(10, 10): | |
| [[[0, 0], [1, 0], ..., [9, 0]], | |
| [[0, 1.5], [1, 1], ..., [9, 1]], | |
| ... ... ... | |
| [[0, 9.5], [1, 9], ..., [9, 9 ]]] | |
| Args: | |
| width (int): image width | |
| height (int): image height | |
| Returns: | |
| np.ndarray: shape (height, width, 2)""" | |
| utils3d.numpy.utils.image_pixel | |
| def image_mesh(*image_attrs: numpy_.ndarray, mask: numpy_.ndarray = None, tri: bool = False, return_indices: bool = False) -> Tuple[numpy_.ndarray, ...]: | |
| """Get a mesh regarding image pixel uv coordinates as vertices and image grid as faces. | |
| Args: | |
| *image_attrs (np.ndarray): image attributes in shape (height, width, [channels]) | |
| mask (np.ndarray, optional): binary mask of shape (height, width), dtype=bool. Defaults to None. | |
| Returns: | |
| faces (np.ndarray): faces connecting neighboring pixels. shape (T, 4) if tri is False, else (T, 3) | |
| *vertex_attrs (np.ndarray): vertex attributes in corresponding order with input image_attrs | |
| indices (np.ndarray, optional): indices of vertices in the original mesh""" | |
| utils3d.numpy.utils.image_mesh | |
| def image_mesh_from_depth(depth: numpy_.ndarray, extrinsics: numpy_.ndarray = None, intrinsics: numpy_.ndarray = None, *vertice_attrs: numpy_.ndarray, atol: float = None, rtol: float = None, remove_by_depth: bool = False, return_uv: bool = False, return_indices: bool = False) -> Tuple[numpy_.ndarray, ...]: | |
| """Get x triangle mesh by lifting depth map to 3D. | |
| Args: | |
| depth (np.ndarray): [H, W] depth map | |
| extrinsics (np.ndarray, optional): [4, 4] extrinsics matrix. Defaults to None. | |
| intrinsics (np.ndarray, optional): [3, 3] intrinsics matrix. Defaults to None. | |
| *vertice_attrs (np.ndarray): [H, W, C] vertex attributes. Defaults to None. | |
| atol (float, optional): absolute tolerance. Defaults to None. | |
| rtol (float, optional): relative tolerance. Defaults to None. | |
| triangles with vertices having depth difference larger than atol + rtol * depth will be marked. | |
| remove_by_depth (bool, optional): whether to remove triangles with large depth difference. Defaults to True. | |
| return_uv (bool, optional): whether to return uv coordinates. Defaults to False. | |
| return_indices (bool, optional): whether to return indices of vertices in the original mesh. Defaults to False. | |
| Returns: | |
| vertices (np.ndarray): [N, 3] vertices | |
| faces (np.ndarray): [T, 3] faces | |
| *vertice_attrs (np.ndarray): [N, C] vertex attributes | |
| image_uv (np.ndarray, optional): [N, 2] uv coordinates | |
| ref_indices (np.ndarray, optional): [N] indices of vertices in the original mesh""" | |
| utils3d.numpy.utils.image_mesh_from_depth | |
| def depth_to_normals(depth: numpy_.ndarray, intrinsics: numpy_.ndarray, mask: numpy_.ndarray = None) -> numpy_.ndarray: | |
| """Calculate normal map from depth map. Value range is [-1, 1]. Normal direction in OpenGL identity camera's coordinate system. | |
| Args: | |
| depth (np.ndarray): shape (height, width), linear depth map | |
| intrinsics (np.ndarray): shape (3, 3), intrinsics matrix | |
| Returns: | |
| normal (np.ndarray): shape (height, width, 3), normal map. """ | |
| utils3d.numpy.utils.depth_to_normals | |
| def points_to_normals(point: numpy_.ndarray, mask: numpy_.ndarray = None) -> numpy_.ndarray: | |
| """Calculate normal map from point map. Value range is [-1, 1]. Normal direction in OpenGL identity camera's coordinate system. | |
| Args: | |
| point (np.ndarray): shape (height, width, 3), point map | |
| Returns: | |
| normal (np.ndarray): shape (height, width, 3), normal map. """ | |
| utils3d.numpy.utils.points_to_normals | |
| def chessboard(width: int, height: int, grid_size: int, color_a: numpy_.ndarray, color_b: numpy_.ndarray) -> numpy_.ndarray: | |
| """get x chessboard image | |
| Args: | |
| width (int): image width | |
| height (int): image height | |
| grid_size (int): size of chessboard grid | |
| color_a (np.ndarray): color of the grid at the top-left corner | |
| color_b (np.ndarray): color in complementary grid cells | |
| Returns: | |
| image (np.ndarray): shape (height, width, channels), chessboard image""" | |
| utils3d.numpy.utils.chessboard | |
| def cube(tri: bool = False) -> Tuple[numpy_.ndarray, numpy_.ndarray]: | |
| """Get x cube mesh of size 1 centered at origin. | |
| ### Parameters | |
| tri (bool, optional): return triangulated mesh. Defaults to False, which returns quad mesh. | |
| ### Returns | |
| vertices (np.ndarray): shape (8, 3) | |
| faces (np.ndarray): shape (12, 3)""" | |
| utils3d.numpy.utils.cube | |
| def icosahedron(): | |
| utils3d.numpy.utils.icosahedron | |
| def square(tri: bool = False) -> Tuple[numpy_.ndarray, numpy_.ndarray]: | |
| """Get a square mesh of area 1 centered at origin in the xy-plane. | |
| ### Returns | |
| vertices (np.ndarray): shape (4, 3) | |
| faces (np.ndarray): shape (1, 4)""" | |
| utils3d.numpy.utils.square | |
| def camera_frustum(extrinsics: numpy_.ndarray, intrinsics: numpy_.ndarray, depth: float = 1.0) -> Tuple[numpy_.ndarray, numpy_.ndarray, numpy_.ndarray]: | |
| """Get x triangle mesh of camera frustum.""" | |
| utils3d.numpy.utils.camera_frustum | |
| def perspective(fov_y: Union[float, numpy_.ndarray], aspect: Union[float, numpy_.ndarray], near: Union[float, numpy_.ndarray], far: Union[float, numpy_.ndarray]) -> numpy_.ndarray: | |
| """Get OpenGL perspective matrix | |
| Args: | |
| fov_y (float | np.ndarray): field of view in y axis | |
| aspect (float | np.ndarray): aspect ratio | |
| near (float | np.ndarray): near plane to clip | |
| far (float | np.ndarray): far plane to clip | |
| Returns: | |
| (np.ndarray): [..., 4, 4] perspective matrix""" | |
| utils3d.numpy.transforms.perspective | |
| def perspective_from_fov(fov: Union[float, numpy_.ndarray], width: Union[int, numpy_.ndarray], height: Union[int, numpy_.ndarray], near: Union[float, numpy_.ndarray], far: Union[float, numpy_.ndarray]) -> numpy_.ndarray: | |
| """Get OpenGL perspective matrix from field of view in largest dimension | |
| Args: | |
| fov (float | np.ndarray): field of view in largest dimension | |
| width (int | np.ndarray): image width | |
| height (int | np.ndarray): image height | |
| near (float | np.ndarray): near plane to clip | |
| far (float | np.ndarray): far plane to clip | |
| Returns: | |
| (np.ndarray): [..., 4, 4] perspective matrix""" | |
| utils3d.numpy.transforms.perspective_from_fov | |
| def perspective_from_fov_xy(fov_x: Union[float, numpy_.ndarray], fov_y: Union[float, numpy_.ndarray], near: Union[float, numpy_.ndarray], far: Union[float, numpy_.ndarray]) -> numpy_.ndarray: | |
| """Get OpenGL perspective matrix from field of view in x and y axis | |
| Args: | |
| fov_x (float | np.ndarray): field of view in x axis | |
| fov_y (float | np.ndarray): field of view in y axis | |
| near (float | np.ndarray): near plane to clip | |
| far (float | np.ndarray): far plane to clip | |
| Returns: | |
| (np.ndarray): [..., 4, 4] perspective matrix""" | |
| utils3d.numpy.transforms.perspective_from_fov_xy | |
| def intrinsics_from_focal_center(fx: Union[float, numpy_.ndarray], fy: Union[float, numpy_.ndarray], cx: Union[float, numpy_.ndarray], cy: Union[float, numpy_.ndarray], dtype: Optional[numpy_.dtype] = numpy_.float32) -> numpy_.ndarray: | |
| """Get OpenCV intrinsics matrix | |
| Returns: | |
| (np.ndarray): [..., 3, 3] OpenCV intrinsics matrix""" | |
| utils3d.numpy.transforms.intrinsics_from_focal_center | |
| def intrinsics_from_fov(fov_max: Union[float, numpy_.ndarray] = None, fov_min: Union[float, numpy_.ndarray] = None, fov_x: Union[float, numpy_.ndarray] = None, fov_y: Union[float, numpy_.ndarray] = None, width: Union[int, numpy_.ndarray] = None, height: Union[int, numpy_.ndarray] = None) -> numpy_.ndarray: | |
| """Get normalized OpenCV intrinsics matrix from given field of view. | |
| You can provide either fov_max, fov_min, fov_x or fov_y | |
| Args: | |
| width (int | np.ndarray): image width | |
| height (int | np.ndarray): image height | |
| fov_max (float | np.ndarray): field of view in largest dimension | |
| fov_min (float | np.ndarray): field of view in smallest dimension | |
| fov_x (float | np.ndarray): field of view in x axis | |
| fov_y (float | np.ndarray): field of view in y axis | |
| Returns: | |
| (np.ndarray): [..., 3, 3] OpenCV intrinsics matrix""" | |
| utils3d.numpy.transforms.intrinsics_from_fov | |
| def fov_to_focal(fov: numpy_.ndarray): | |
| utils3d.numpy.transforms.fov_to_focal | |
| def focal_to_fov(focal: numpy_.ndarray): | |
| utils3d.numpy.transforms.focal_to_fov | |
| def intrinsics_to_fov(intrinsics: numpy_.ndarray) -> Tuple[numpy_.ndarray, numpy_.ndarray]: | |
| utils3d.numpy.transforms.intrinsics_to_fov | |
| def view_look_at(eye: numpy_.ndarray, look_at: numpy_.ndarray, up: numpy_.ndarray) -> numpy_.ndarray: | |
| """Get OpenGL view matrix looking at something | |
| Args: | |
| eye (np.ndarray): [..., 3] the eye position | |
| look_at (np.ndarray): [..., 3] the position to look at | |
| up (np.ndarray): [..., 3] head up direction (y axis in screen space). Not necessarily othogonal to view direction | |
| Returns: | |
| (np.ndarray): [..., 4, 4], view matrix""" | |
| utils3d.numpy.transforms.view_look_at | |
| def extrinsics_look_at(eye: numpy_.ndarray, look_at: numpy_.ndarray, up: numpy_.ndarray) -> numpy_.ndarray: | |
| """Get OpenCV extrinsics matrix looking at something | |
| Args: | |
| eye (np.ndarray): [..., 3] the eye position | |
| look_at (np.ndarray): [..., 3] the position to look at | |
| up (np.ndarray): [..., 3] head up direction (-y axis in screen space). Not necessarily othogonal to view direction | |
| Returns: | |
| (np.ndarray): [..., 4, 4], extrinsics matrix""" | |
| utils3d.numpy.transforms.extrinsics_look_at | |
| def perspective_to_intrinsics(perspective: numpy_.ndarray) -> numpy_.ndarray: | |
| """OpenGL perspective matrix to OpenCV intrinsics | |
| Args: | |
| perspective (np.ndarray): [..., 4, 4] OpenGL perspective matrix | |
| Returns: | |
| (np.ndarray): shape [..., 3, 3] OpenCV intrinsics""" | |
| utils3d.numpy.transforms.perspective_to_intrinsics | |
| def perspective_to_near_far(perspective: numpy_.ndarray) -> Tuple[numpy_.ndarray, numpy_.ndarray]: | |
| """Get near and far planes from OpenGL perspective matrix | |
| Args:""" | |
| utils3d.numpy.transforms.perspective_to_near_far | |
| def intrinsics_to_perspective(intrinsics: numpy_.ndarray, near: Union[float, numpy_.ndarray], far: Union[float, numpy_.ndarray]) -> numpy_.ndarray: | |
| """OpenCV intrinsics to OpenGL perspective matrix | |
| NOTE: not work for tile-shifting intrinsics currently | |
| Args: | |
| intrinsics (np.ndarray): [..., 3, 3] OpenCV intrinsics matrix | |
| near (float | np.ndarray): [...] near plane to clip | |
| far (float | np.ndarray): [...] far plane to clip | |
| Returns: | |
| (np.ndarray): [..., 4, 4] OpenGL perspective matrix""" | |
| utils3d.numpy.transforms.intrinsics_to_perspective | |
| def extrinsics_to_view(extrinsics: numpy_.ndarray) -> numpy_.ndarray: | |
| """OpenCV camera extrinsics to OpenGL view matrix | |
| Args: | |
| extrinsics (np.ndarray): [..., 4, 4] OpenCV camera extrinsics matrix | |
| Returns: | |
| (np.ndarray): [..., 4, 4] OpenGL view matrix""" | |
| utils3d.numpy.transforms.extrinsics_to_view | |
| def view_to_extrinsics(view: numpy_.ndarray) -> numpy_.ndarray: | |
| """OpenGL view matrix to OpenCV camera extrinsics | |
| Args: | |
| view (np.ndarray): [..., 4, 4] OpenGL view matrix | |
| Returns: | |
| (np.ndarray): [..., 4, 4] OpenCV camera extrinsics matrix""" | |
| utils3d.numpy.transforms.view_to_extrinsics | |
| def normalize_intrinsics(intrinsics: numpy_.ndarray, width: Union[int, numpy_.ndarray], height: Union[int, numpy_.ndarray], integer_pixel_centers: bool = True) -> numpy_.ndarray: | |
| """Normalize intrinsics from pixel cooridnates to uv coordinates | |
| Args: | |
| intrinsics (np.ndarray): [..., 3, 3] camera intrinsics(s) to normalize | |
| width (int | np.ndarray): [...] image width(s) | |
| height (int | np.ndarray): [...] image height(s) | |
| integer_pixel_centers (bool): whether the integer pixel coordinates are at the center of the pixel. If False, the integer coordinates are at the left-top corner of the pixel. | |
| Returns: | |
| (np.ndarray): [..., 3, 3] normalized camera intrinsics(s)""" | |
| utils3d.numpy.transforms.normalize_intrinsics | |
| def crop_intrinsics(intrinsics: numpy_.ndarray, width: Union[int, numpy_.ndarray], height: Union[int, numpy_.ndarray], left: Union[int, numpy_.ndarray], top: Union[int, numpy_.ndarray], crop_width: Union[int, numpy_.ndarray], crop_height: Union[int, numpy_.ndarray]) -> numpy_.ndarray: | |
| """Evaluate the new intrinsics(s) after crop the image: cropped_img = img[top:top+crop_height, left:left+crop_width] | |
| Args: | |
| intrinsics (np.ndarray): [..., 3, 3] camera intrinsics(s) to crop | |
| width (int | np.ndarray): [...] image width(s) | |
| height (int | np.ndarray): [...] image height(s) | |
| left (int | np.ndarray): [...] left crop boundary | |
| top (int | np.ndarray): [...] top crop boundary | |
| crop_width (int | np.ndarray): [...] crop width | |
| crop_height (int | np.ndarray): [...] crop height | |
| Returns: | |
| (np.ndarray): [..., 3, 3] cropped camera intrinsics(s)""" | |
| utils3d.numpy.transforms.crop_intrinsics | |
| def pixel_to_uv(pixel: numpy_.ndarray, width: Union[int, numpy_.ndarray], height: Union[int, numpy_.ndarray]) -> numpy_.ndarray: | |
| """Args: | |
| pixel (np.ndarray): [..., 2] pixel coordinrates defined in image space, x range is (0, W - 1), y range is (0, H - 1) | |
| width (int | np.ndarray): [...] image width(s) | |
| height (int | np.ndarray): [...] image height(s) | |
| Returns: | |
| (np.ndarray): [..., 2] pixel coordinrates defined in uv space, the range is (0, 1)""" | |
| utils3d.numpy.transforms.pixel_to_uv | |
| def pixel_to_ndc(pixel: numpy_.ndarray, width: Union[int, numpy_.ndarray], height: Union[int, numpy_.ndarray]) -> numpy_.ndarray: | |
| """Args: | |
| pixel (np.ndarray): [..., 2] pixel coordinrates defined in image space, x range is (0, W - 1), y range is (0, H - 1) | |
| width (int | np.ndarray): [...] image width(s) | |
| height (int | np.ndarray): [...] image height(s) | |
| Returns: | |
| (np.ndarray): [..., 2] pixel coordinrates defined in ndc space, the range is (-1, 1)""" | |
| utils3d.numpy.transforms.pixel_to_ndc | |
| def uv_to_pixel(uv: numpy_.ndarray, width: Union[int, numpy_.ndarray], height: Union[int, numpy_.ndarray]) -> numpy_.ndarray: | |
| """Args: | |
| pixel (np.ndarray): [..., 2] pixel coordinrates defined in image space, x range is (0, W - 1), y range is (0, H - 1) | |
| width (int | np.ndarray): [...] image width(s) | |
| height (int | np.ndarray): [...] image height(s) | |
| Returns: | |
| (np.ndarray): [..., 2] pixel coordinrates defined in uv space, the range is (0, 1)""" | |
| utils3d.numpy.transforms.uv_to_pixel | |
| def project_depth(depth: numpy_.ndarray, near: Union[float, numpy_.ndarray], far: Union[float, numpy_.ndarray]) -> numpy_.ndarray: | |
| """Project linear depth to depth value in screen space | |
| Args: | |
| depth (np.ndarray): [...] depth value | |
| near (float | np.ndarray): [...] near plane to clip | |
| far (float | np.ndarray): [...] far plane to clip | |
| Returns: | |
| (np.ndarray): [..., 1] depth value in screen space, value ranging in [0, 1]""" | |
| utils3d.numpy.transforms.project_depth | |
| def depth_buffer_to_linear(depth_buffer: numpy_.ndarray, near: Union[float, numpy_.ndarray], far: Union[float, numpy_.ndarray]) -> numpy_.ndarray: | |
| """OpenGL depth buffer to linear depth | |
| Args: | |
| depth_buffer (np.ndarray): [...] depth value | |
| near (float | np.ndarray): [...] near plane to clip | |
| far (float | np.ndarray): [...] far plane to clip | |
| Returns: | |
| (np.ndarray): [..., 1] linear depth""" | |
| utils3d.numpy.transforms.depth_buffer_to_linear | |
| def unproject_cv(uv_coord: numpy_.ndarray, depth: numpy_.ndarray = None, extrinsics: numpy_.ndarray = None, intrinsics: numpy_.ndarray = None) -> numpy_.ndarray: | |
| """Unproject uv coordinates to 3D view space following the OpenCV convention | |
| Args: | |
| uv_coord (np.ndarray): [..., N, 2] uv coordinates, value ranging in [0, 1]. | |
| The origin (0., 0.) is corresponding to the left & top | |
| depth (np.ndarray): [..., N] depth value | |
| extrinsics (np.ndarray): [..., 4, 4] extrinsics matrix | |
| intrinsics (np.ndarray): [..., 3, 3] intrinsics matrix | |
| Returns: | |
| points (np.ndarray): [..., N, 3] 3d points""" | |
| utils3d.numpy.transforms.unproject_cv | |
| def unproject_gl(screen_coord: numpy_.ndarray, model: numpy_.ndarray = None, view: numpy_.ndarray = None, perspective: numpy_.ndarray = None) -> numpy_.ndarray: | |
| """Unproject screen space coordinates to 3D view space following the OpenGL convention (except for row major matrice) | |
| Args: | |
| screen_coord (np.ndarray): [..., N, 3] screen space coordinates, value ranging in [0, 1]. | |
| The origin (0., 0., 0.) is corresponding to the left & bottom & nearest | |
| model (np.ndarray): [..., 4, 4] model matrix | |
| view (np.ndarray): [..., 4, 4] view matrix | |
| perspective (np.ndarray): [..., 4, 4] perspective matrix | |
| Returns: | |
| points (np.ndarray): [..., N, 3] 3d points""" | |
| utils3d.numpy.transforms.unproject_gl | |
| def project_cv(points: numpy_.ndarray, extrinsics: numpy_.ndarray = None, intrinsics: numpy_.ndarray = None) -> Tuple[numpy_.ndarray, numpy_.ndarray]: | |
| """Project 3D points to 2D following the OpenCV convention | |
| Args: | |
| points (np.ndarray): [..., N, 3] or [..., N, 4] 3D points to project, if the last | |
| dimension is 4, the points are assumed to be in homogeneous coordinates | |
| extrinsics (np.ndarray): [..., 4, 4] extrinsics matrix | |
| intrinsics (np.ndarray): [..., 3, 3] intrinsics matrix | |
| Returns: | |
| uv_coord (np.ndarray): [..., N, 2] uv coordinates, value ranging in [0, 1]. | |
| The origin (0., 0.) is corresponding to the left & top | |
| linear_depth (np.ndarray): [..., N] linear depth""" | |
| utils3d.numpy.transforms.project_cv | |
| def project_gl(points: numpy_.ndarray, model: numpy_.ndarray = None, view: numpy_.ndarray = None, perspective: numpy_.ndarray = None) -> Tuple[numpy_.ndarray, numpy_.ndarray]: | |
| """Project 3D points to 2D following the OpenGL convention (except for row major matrice) | |
| Args: | |
| points (np.ndarray): [..., N, 3] or [..., N, 4] 3D points to project, if the last | |
| dimension is 4, the points are assumed to be in homogeneous coordinates | |
| model (np.ndarray): [..., 4, 4] model matrix | |
| view (np.ndarray): [..., 4, 4] view matrix | |
| perspective (np.ndarray): [..., 4, 4] perspective matrix | |
| Returns: | |
| scr_coord (np.ndarray): [..., N, 3] screen space coordinates, value ranging in [0, 1]. | |
| The origin (0., 0., 0.) is corresponding to the left & bottom & nearest | |
| linear_depth (np.ndarray): [..., N] linear depth""" | |
| utils3d.numpy.transforms.project_gl | |
| def quaternion_to_matrix(quaternion: numpy_.ndarray, eps: float = 1e-12) -> numpy_.ndarray: | |
| """Converts a batch of quaternions (w, x, y, z) to rotation matrices | |
| Args: | |
| quaternion (np.ndarray): shape (..., 4), the quaternions to convert | |
| Returns: | |
| np.ndarray: shape (..., 3, 3), the rotation matrices corresponding to the given quaternions""" | |
| utils3d.numpy.transforms.quaternion_to_matrix | |
| def axis_angle_to_matrix(axis_angle: numpy_.ndarray, eps: float = 1e-12) -> numpy_.ndarray: | |
| """Convert axis-angle representation (rotation vector) to rotation matrix, whose direction is the axis of rotation and length is the angle of rotation | |
| Args: | |
| axis_angle (np.ndarray): shape (..., 3), axis-angle vcetors | |
| Returns: | |
| np.ndarray: shape (..., 3, 3) The rotation matrices for the given axis-angle parameters""" | |
| utils3d.numpy.transforms.axis_angle_to_matrix | |
| def matrix_to_quaternion(rot_mat: numpy_.ndarray, eps: float = 1e-12) -> numpy_.ndarray: | |
| """Convert 3x3 rotation matrix to quaternion (w, x, y, z) | |
| Args: | |
| rot_mat (np.ndarray): shape (..., 3, 3), the rotation matrices to convert | |
| Returns: | |
| np.ndarray: shape (..., 4), the quaternions corresponding to the given rotation matrices""" | |
| utils3d.numpy.transforms.matrix_to_quaternion | |
| def extrinsics_to_essential(extrinsics: numpy_.ndarray): | |
| """extrinsics matrix `[[R, t] [0, 0, 0, 1]]` such that `x' = R (x - t)` to essential matrix such that `x' E x = 0` | |
| Args: | |
| extrinsics (np.ndaray): [..., 4, 4] extrinsics matrix | |
| Returns: | |
| (np.ndaray): [..., 3, 3] essential matrix""" | |
| utils3d.numpy.transforms.extrinsics_to_essential | |
| def euler_axis_angle_rotation(axis: str, angle: numpy_.ndarray) -> numpy_.ndarray: | |
| """Return the rotation matrices for one of the rotations about an axis | |
| of which Euler angles describe, for each value of the angle given. | |
| Args: | |
| axis: Axis label "X" or "Y or "Z". | |
| angle: any shape tensor of Euler angles in radians | |
| Returns: | |
| Rotation matrices as tensor of shape (..., 3, 3).""" | |
| utils3d.numpy.transforms.euler_axis_angle_rotation | |
| def euler_angles_to_matrix(euler_angles: numpy_.ndarray, convention: str = 'XYZ') -> numpy_.ndarray: | |
| """Convert rotations given as Euler angles in radians to rotation matrices. | |
| Args: | |
| euler_angles: Euler angles in radians as ndarray of shape (..., 3), XYZ | |
| convention: permutation of "X", "Y" or "Z", representing the order of Euler rotations to apply. | |
| Returns: | |
| Rotation matrices as ndarray of shape (..., 3, 3).""" | |
| utils3d.numpy.transforms.euler_angles_to_matrix | |
| def skew_symmetric(v: numpy_.ndarray): | |
| """Skew symmetric matrix from a 3D vector""" | |
| utils3d.numpy.transforms.skew_symmetric | |
| def rotation_matrix_from_vectors(v1: numpy_.ndarray, v2: numpy_.ndarray): | |
| """Rotation matrix that rotates v1 to v2""" | |
| utils3d.numpy.transforms.rotation_matrix_from_vectors | |
| def ray_intersection(p1: numpy_.ndarray, d1: numpy_.ndarray, p2: numpy_.ndarray, d2: numpy_.ndarray): | |
| """Compute the intersection/closest point of two D-dimensional rays | |
| If the rays are intersecting, the closest point is the intersection point. | |
| Args: | |
| p1 (np.ndarray): (..., D) origin of ray 1 | |
| d1 (np.ndarray): (..., D) direction of ray 1 | |
| p2 (np.ndarray): (..., D) origin of ray 2 | |
| d2 (np.ndarray): (..., D) direction of ray 2 | |
| Returns: | |
| (np.ndarray): (..., N) intersection point""" | |
| utils3d.numpy.transforms.ray_intersection | |
| def se3_matrix(R: numpy_.ndarray, t: numpy_.ndarray) -> numpy_.ndarray: | |
| """Convert rotation matrix and translation vector to 4x4 transformation matrix. | |
| Args: | |
| R (np.ndarray): [..., 3, 3] rotation matrix | |
| t (np.ndarray): [..., 3] translation vector | |
| Returns: | |
| np.ndarray: [..., 4, 4] transformation matrix""" | |
| utils3d.numpy.transforms.se3_matrix | |
| def slerp_quaternion(q1: numpy_.ndarray, q2: numpy_.ndarray, t: numpy_.ndarray) -> numpy_.ndarray: | |
| """Spherical linear interpolation between two unit quaternions. | |
| Args: | |
| q1 (np.ndarray): [..., d] unit vector 1 | |
| q2 (np.ndarray): [..., d] unit vector 2 | |
| t (np.ndarray): [...] interpolation parameter in [0, 1] | |
| Returns: | |
| np.ndarray: [..., 3] interpolated unit vector""" | |
| utils3d.numpy.transforms.slerp_quaternion | |
| def slerp_vector(v1: numpy_.ndarray, v2: numpy_.ndarray, t: numpy_.ndarray) -> numpy_.ndarray: | |
| """Spherical linear interpolation between two unit vectors. The vectors are assumed to be normalized. | |
| Args: | |
| v1 (np.ndarray): [..., d] unit vector 1 | |
| v2 (np.ndarray): [..., d] unit vector 2 | |
| t (np.ndarray): [...] interpolation parameter in [0, 1] | |
| Returns: | |
| np.ndarray: [..., d] interpolated unit vector""" | |
| utils3d.numpy.transforms.slerp_vector | |
| def lerp(x1: numpy_.ndarray, x2: numpy_.ndarray, t: numpy_.ndarray) -> numpy_.ndarray: | |
| """Linear interpolation between two vectors. | |
| Args: | |
| x1 (np.ndarray): [..., d] vector 1 | |
| x2 (np.ndarray): [..., d] vector 2 | |
| t (np.ndarray): [...] interpolation parameter. [0, 1] for interpolation between x1 and x2, otherwise for extrapolation. | |
| Returns: | |
| np.ndarray: [..., d] interpolated vector""" | |
| utils3d.numpy.transforms.lerp | |
| def lerp_se3_matrix(T1: numpy_.ndarray, T2: numpy_.ndarray, t: numpy_.ndarray) -> numpy_.ndarray: | |
| """Linear interpolation between two SE(3) matrices. | |
| Args: | |
| T1 (np.ndarray): [..., 4, 4] SE(3) matrix 1 | |
| T2 (np.ndarray): [..., 4, 4] SE(3) matrix 2 | |
| t (np.ndarray): [...] interpolation parameter in [0, 1] | |
| Returns: | |
| np.ndarray: [..., 4, 4] interpolated SE(3) matrix""" | |
| utils3d.numpy.transforms.lerp_se3_matrix | |
| def piecewise_lerp(x: numpy_.ndarray, t: numpy_.ndarray, s: numpy_.ndarray, extrapolation_mode: Literal['constant', 'linear'] = 'constant') -> numpy_.ndarray: | |
| """Linear spline interpolation. | |
| ### Parameters: | |
| - `x`: np.ndarray, shape (n, d): the values of data points. | |
| - `t`: np.ndarray, shape (n,): the times of the data points. | |
| - `s`: np.ndarray, shape (m,): the times to be interpolated. | |
| - `extrapolation_mode`: str, the mode of extrapolation. 'constant' means extrapolate the boundary values, 'linear' means extrapolate linearly. | |
| ### Returns: | |
| - `y`: np.ndarray, shape (..., m, d): the interpolated values.""" | |
| utils3d.numpy.transforms.piecewise_lerp | |
| def piecewise_lerp_se3_matrix(T: numpy_.ndarray, t: numpy_.ndarray, s: numpy_.ndarray, extrapolation_mode: Literal['constant', 'linear'] = 'constant') -> numpy_.ndarray: | |
| """Linear spline interpolation for SE(3) matrices. | |
| ### Parameters: | |
| - `T`: np.ndarray, shape (n, 4, 4): the SE(3) matrices. | |
| - `t`: np.ndarray, shape (n,): the times of the data points. | |
| - `s`: np.ndarray, shape (m,): the times to be interpolated. | |
| - `extrapolation_mode`: str, the mode of extrapolation. 'constant' means extrapolate the boundary values, 'linear' means extrapolate linearly. | |
| ### Returns: | |
| - `T_interp`: np.ndarray, shape (..., m, 4, 4): the interpolated SE(3) matrices.""" | |
| utils3d.numpy.transforms.piecewise_lerp_se3_matrix | |
| def apply_transform(T: numpy_.ndarray, x: numpy_.ndarray) -> numpy_.ndarray: | |
| """Apply SE(3) transformation to a point or a set of points. | |
| ### Parameters: | |
| - `T`: np.ndarray, shape (..., 4, 4): the SE(3) matrix. | |
| - `x`: np.ndarray, shape (..., 3): the point or a set of points to be transformed. | |
| ### Returns: | |
| - `x_transformed`: np.ndarray, shape (..., 3): the transformed point or a set of points.""" | |
| utils3d.numpy.transforms.apply_transform | |
| def linear_spline_interpolate(x: numpy_.ndarray, t: numpy_.ndarray, s: numpy_.ndarray, extrapolation_mode: Literal['constant', 'linear'] = 'constant') -> numpy_.ndarray: | |
| """Linear spline interpolation. | |
| ### Parameters: | |
| - `x`: np.ndarray, shape (n, d): the values of data points. | |
| - `t`: np.ndarray, shape (n,): the times of the data points. | |
| - `s`: np.ndarray, shape (m,): the times to be interpolated. | |
| - `extrapolation_mode`: str, the mode of extrapolation. 'constant' means extrapolate the boundary values, 'linear' means extrapolate linearly. | |
| ### Returns: | |
| - `y`: np.ndarray, shape (..., m, d): the interpolated values.""" | |
| utils3d.numpy.spline.linear_spline_interpolate | |
| def RastContext(*args, **kwargs): | |
| utils3d.numpy.rasterization.RastContext | |
| def rasterize_triangle_faces(ctx: utils3d.numpy.rasterization.RastContext, vertices: numpy_.ndarray, faces: numpy_.ndarray, attr: numpy_.ndarray, width: int, height: int, transform: numpy_.ndarray = None, cull_backface: bool = True, return_depth: bool = False, image: numpy_.ndarray = None, depth: numpy_.ndarray = None) -> Tuple[numpy_.ndarray, numpy_.ndarray]: | |
| """Rasterize vertex attribute. | |
| Args: | |
| vertices (np.ndarray): [N, 3] | |
| faces (np.ndarray): [T, 3] | |
| attr (np.ndarray): [N, C] | |
| width (int): width of rendered image | |
| height (int): height of rendered image | |
| transform (np.ndarray): [4, 4] model-view-projection transformation matrix. | |
| cull_backface (bool): whether to cull backface | |
| image: (np.ndarray): [H, W, C] background image | |
| depth: (np.ndarray): [H, W] background depth | |
| Returns: | |
| image (np.ndarray): [H, W, C] rendered image | |
| depth (np.ndarray): [H, W] screen space depth, ranging from 0 to 1. If return_depth is False, it is None.""" | |
| utils3d.numpy.rasterization.rasterize_triangle_faces | |
| def rasterize_edges(ctx: utils3d.numpy.rasterization.RastContext, vertices: numpy_.ndarray, edges: numpy_.ndarray, attr: numpy_.ndarray, width: int, height: int, transform: numpy_.ndarray = None, line_width: float = 1.0, return_depth: bool = False, image: numpy_.ndarray = None, depth: numpy_.ndarray = None) -> Tuple[numpy_.ndarray, ...]: | |
| """Rasterize vertex attribute. | |
| Args: | |
| vertices (np.ndarray): [N, 3] | |
| faces (np.ndarray): [T, 3] | |
| attr (np.ndarray): [N, C] | |
| width (int): width of rendered image | |
| height (int): height of rendered image | |
| transform (np.ndarray): [4, 4] model-view-projection matrix | |
| line_width (float): width of line. Defaults to 1.0. NOTE: Values other than 1.0 may not work across all platforms. | |
| cull_backface (bool): whether to cull backface | |
| Returns: | |
| image (np.ndarray): [H, W, C] rendered image | |
| depth (np.ndarray): [H, W] screen space depth, ranging from 0 to 1. If return_depth is False, it is None.""" | |
| utils3d.numpy.rasterization.rasterize_edges | |
| def texture(ctx: utils3d.numpy.rasterization.RastContext, uv: numpy_.ndarray, texture: numpy_.ndarray, interpolation: str = 'linear', wrap: str = 'clamp') -> numpy_.ndarray: | |
| """Given an UV image, texturing from the texture map""" | |
| utils3d.numpy.rasterization.texture | |
| def warp_image_by_depth(ctx: utils3d.numpy.rasterization.RastContext, src_depth: numpy_.ndarray, src_image: numpy_.ndarray = None, width: int = None, height: int = None, *, extrinsics_src: numpy_.ndarray = None, extrinsics_tgt: numpy_.ndarray = None, intrinsics_src: numpy_.ndarray = None, intrinsics_tgt: numpy_.ndarray = None, near: float = 0.1, far: float = 100.0, cull_backface: bool = True, ssaa: int = 1, return_depth: bool = False) -> Tuple[numpy_.ndarray, ...]: | |
| """Warp image by depth map. | |
| Args: | |
| ctx (RastContext): rasterizer context | |
| src_depth (np.ndarray): [H, W] | |
| src_image (np.ndarray, optional): [H, W, C]. The image to warp. Defaults to None (use uv coordinates). | |
| width (int, optional): width of the output image. None to use depth map width. Defaults to None. | |
| height (int, optional): height of the output image. None to use depth map height. Defaults to None. | |
| extrinsics_src (np.ndarray, optional): extrinsics matrix of the source camera. Defaults to None (identity). | |
| extrinsics_tgt (np.ndarray, optional): extrinsics matrix of the target camera. Defaults to None (identity). | |
| intrinsics_src (np.ndarray, optional): intrinsics matrix of the source camera. Defaults to None (use the same as intrinsics_tgt). | |
| intrinsics_tgt (np.ndarray, optional): intrinsics matrix of the target camera. Defaults to None (use the same as intrinsics_src). | |
| cull_backface (bool, optional): whether to cull backface. Defaults to True. | |
| ssaa (int, optional): super sampling anti-aliasing. Defaults to 1. | |
| Returns: | |
| tgt_image (np.ndarray): [H, W, C] warped image (or uv coordinates if image is None). | |
| tgt_depth (np.ndarray): [H, W] screen space depth, ranging from 0 to 1. If return_depth is False, it is None.""" | |
| utils3d.numpy.rasterization.warp_image_by_depth | |
| def test_rasterization(ctx: utils3d.numpy.rasterization.RastContext): | |
| """Test if rasterization works. It will render a cube with random colors and save it as a CHECKME.png file.""" | |
| utils3d.numpy.rasterization.test_rasterization | |
| def triangulate(faces: torch_.Tensor, vertices: torch_.Tensor = None, backslash: bool = None) -> torch_.Tensor: | |
| """Triangulate a polygonal mesh. | |
| Args: | |
| faces (torch.Tensor): [..., L, P] polygonal faces | |
| vertices (torch.Tensor, optional): [..., N, 3] 3-dimensional vertices. | |
| If given, the triangulation is performed according to the distance | |
| between vertices. Defaults to None. | |
| backslash (torch.Tensor, optional): [..., L] boolean array indicating | |
| how to triangulate the quad faces. Defaults to None. | |
| Returns: | |
| (torch.Tensor): [L * (P - 2), 3] triangular faces""" | |
| utils3d.torch.mesh.triangulate | |
| def compute_face_normal(vertices: torch_.Tensor, faces: torch_.Tensor) -> torch_.Tensor: | |
| """Compute face normals of a triangular mesh | |
| Args: | |
| vertices (torch.Tensor): [..., N, 3] 3-dimensional vertices | |
| faces (torch.Tensor): [..., T, 3] triangular face indices | |
| Returns: | |
| normals (torch.Tensor): [..., T, 3] face normals""" | |
| utils3d.torch.mesh.compute_face_normal | |
| def compute_face_angles(vertices: torch_.Tensor, faces: torch_.Tensor) -> torch_.Tensor: | |
| """Compute face angles of a triangular mesh | |
| Args: | |
| vertices (torch.Tensor): [..., N, 3] 3-dimensional vertices | |
| faces (torch.Tensor): [T, 3] triangular face indices | |
| Returns: | |
| angles (torch.Tensor): [..., T, 3] face angles""" | |
| utils3d.torch.mesh.compute_face_angles | |
| def compute_vertex_normal(vertices: torch_.Tensor, faces: torch_.Tensor, face_normal: torch_.Tensor = None) -> torch_.Tensor: | |
| """Compute vertex normals of a triangular mesh by averaging neightboring face normals | |
| Args: | |
| vertices (torch.Tensor): [..., N, 3] 3-dimensional vertices | |
| faces (torch.Tensor): [T, 3] triangular face indices | |
| face_normal (torch.Tensor, optional): [..., T, 3] face normals. | |
| None to compute face normals from vertices and faces. Defaults to None. | |
| Returns: | |
| normals (torch.Tensor): [..., N, 3] vertex normals""" | |
| utils3d.torch.mesh.compute_vertex_normal | |
| def compute_vertex_normal_weighted(vertices: torch_.Tensor, faces: torch_.Tensor, face_normal: torch_.Tensor = None) -> torch_.Tensor: | |
| """Compute vertex normals of a triangular mesh by weighted sum of neightboring face normals | |
| according to the angles | |
| Args: | |
| vertices (torch.Tensor): [..., N, 3] 3-dimensional vertices | |
| faces (torch.Tensor): [T, 3] triangular face indices | |
| face_normal (torch.Tensor, optional): [..., T, 3] face normals. | |
| None to compute face normals from vertices and faces. Defaults to None. | |
| Returns: | |
| normals (torch.Tensor): [..., N, 3] vertex normals""" | |
| utils3d.torch.mesh.compute_vertex_normal_weighted | |
| def remove_unreferenced_vertices(faces: torch_.Tensor, *vertice_attrs, return_indices: bool = False) -> Tuple[torch_.Tensor, ...]: | |
| """Remove unreferenced vertices of a mesh. | |
| Unreferenced vertices are removed, and the face indices are updated accordingly. | |
| Args: | |
| faces (torch.Tensor): [T, P] face indices | |
| *vertice_attrs: vertex attributes | |
| Returns: | |
| faces (torch.Tensor): [T, P] face indices | |
| *vertice_attrs: vertex attributes | |
| indices (torch.Tensor, optional): [N] indices of vertices that are kept. Defaults to None.""" | |
| utils3d.torch.mesh.remove_unreferenced_vertices | |
| def remove_corrupted_faces(faces: torch_.Tensor) -> torch_.Tensor: | |
| """Remove corrupted faces (faces with duplicated vertices) | |
| Args: | |
| faces (torch.Tensor): [T, 3] triangular face indices | |
| Returns: | |
| torch.Tensor: [T_, 3] triangular face indices""" | |
| utils3d.torch.mesh.remove_corrupted_faces | |
| def merge_duplicate_vertices(vertices: torch_.Tensor, faces: torch_.Tensor, tol: float = 1e-06) -> Tuple[torch_.Tensor, torch_.Tensor]: | |
| """Merge duplicate vertices of a triangular mesh. | |
| Duplicate vertices are merged by selecte one of them, and the face indices are updated accordingly. | |
| Args: | |
| vertices (torch.Tensor): [N, 3] 3-dimensional vertices | |
| faces (torch.Tensor): [T, 3] triangular face indices | |
| tol (float, optional): tolerance for merging. Defaults to 1e-6. | |
| Returns: | |
| vertices (torch.Tensor): [N_, 3] 3-dimensional vertices | |
| faces (torch.Tensor): [T, 3] triangular face indices""" | |
| utils3d.torch.mesh.merge_duplicate_vertices | |
| def subdivide_mesh_simple(vertices: torch_.Tensor, faces: torch_.Tensor, n: int = 1) -> Tuple[torch_.Tensor, torch_.Tensor]: | |
| """Subdivide a triangular mesh by splitting each triangle into 4 smaller triangles. | |
| NOTE: All original vertices are kept, and new vertices are appended to the end of the vertex list. | |
| Args: | |
| vertices (torch.Tensor): [N, 3] 3-dimensional vertices | |
| faces (torch.Tensor): [T, 3] triangular face indices | |
| n (int, optional): number of subdivisions. Defaults to 1. | |
| Returns: | |
| vertices (torch.Tensor): [N_, 3] subdivided 3-dimensional vertices | |
| faces (torch.Tensor): [4 * T, 3] subdivided triangular face indices""" | |
| utils3d.torch.mesh.subdivide_mesh_simple | |
| def compute_face_tbn(pos: torch_.Tensor, faces_pos: torch_.Tensor, uv: torch_.Tensor, faces_uv: torch_.Tensor, eps: float = 1e-07) -> torch_.Tensor: | |
| """compute TBN matrix for each face | |
| Args: | |
| pos (torch.Tensor): shape (..., N_pos, 3), positions | |
| faces_pos (torch.Tensor): shape(T, 3) | |
| uv (torch.Tensor): shape (..., N_uv, 3) uv coordinates, | |
| faces_uv (torch.Tensor): shape(T, 3) | |
| Returns: | |
| torch.Tensor: (..., T, 3, 3) TBN matrix for each face. Note TBN vectors are normalized but not necessarily orthognal""" | |
| utils3d.torch.mesh.compute_face_tbn | |
| def compute_vertex_tbn(faces_topo: torch_.Tensor, pos: torch_.Tensor, faces_pos: torch_.Tensor, uv: torch_.Tensor, faces_uv: torch_.Tensor) -> torch_.Tensor: | |
| """compute TBN matrix for each face | |
| Args: | |
| faces_topo (torch.Tensor): (T, 3), face indice of topology | |
| pos (torch.Tensor): shape (..., N_pos, 3), positions | |
| faces_pos (torch.Tensor): shape(T, 3) | |
| uv (torch.Tensor): shape (..., N_uv, 3) uv coordinates, | |
| faces_uv (torch.Tensor): shape(T, 3) | |
| Returns: | |
| torch.Tensor: (..., V, 3, 3) TBN matrix for each face. Note TBN vectors are normalized but not necessarily orthognal""" | |
| utils3d.torch.mesh.compute_vertex_tbn | |
| def laplacian(vertices: torch_.Tensor, faces: torch_.Tensor, weight: str = 'uniform') -> torch_.Tensor: | |
| """Laplacian smooth with cotangent weights | |
| Args: | |
| vertices (torch.Tensor): shape (..., N, 3) | |
| faces (torch.Tensor): shape (T, 3) | |
| weight (str): 'uniform' or 'cotangent'""" | |
| utils3d.torch.mesh.laplacian | |
| def laplacian_smooth_mesh(vertices: torch_.Tensor, faces: torch_.Tensor, weight: str = 'uniform', times: int = 5) -> torch_.Tensor: | |
| """Laplacian smooth with cotangent weights | |
| Args: | |
| vertices (torch.Tensor): shape (..., N, 3) | |
| faces (torch.Tensor): shape (T, 3) | |
| weight (str): 'uniform' or 'cotangent'""" | |
| utils3d.torch.mesh.laplacian_smooth_mesh | |
| def taubin_smooth_mesh(vertices: torch_.Tensor, faces: torch_.Tensor, lambda_: float = 0.5, mu_: float = -0.51) -> torch_.Tensor: | |
| """Taubin smooth mesh | |
| Args: | |
| vertices (torch.Tensor): _description_ | |
| faces (torch.Tensor): _description_ | |
| lambda_ (float, optional): _description_. Defaults to 0.5. | |
| mu_ (float, optional): _description_. Defaults to -0.51. | |
| Returns: | |
| torch.Tensor: _description_""" | |
| utils3d.torch.mesh.taubin_smooth_mesh | |
| def laplacian_hc_smooth_mesh(vertices: torch_.Tensor, faces: torch_.Tensor, times: int = 5, alpha: float = 0.5, beta: float = 0.5, weight: str = 'uniform'): | |
| """HC algorithm from Improved Laplacian Smoothing of Noisy Surface Meshes by J.Vollmer et al. | |
| """ | |
| utils3d.torch.mesh.laplacian_hc_smooth_mesh | |
| def get_rays(extrinsics: torch_.Tensor, intrinsics: torch_.Tensor, uv: torch_.Tensor) -> Tuple[torch_.Tensor, torch_.Tensor]: | |
| """Args: | |
| extrinsics: (..., 4, 4) extrinsics matrices. | |
| intrinsics: (..., 3, 3) intrinsics matrices. | |
| uv: (..., n_rays, 2) uv coordinates of the rays. | |
| Returns: | |
| rays_o: (..., 1, 3) ray origins | |
| rays_d: (..., n_rays, 3) ray directions. | |
| NOTE: ray directions are NOT normalized. They actuallys makes rays_o + rays_d * z = world coordinates, where z is the depth.""" | |
| utils3d.torch.nerf.get_rays | |
| def get_image_rays(extrinsics: torch_.Tensor, intrinsics: torch_.Tensor, width: int, height: int) -> Tuple[torch_.Tensor, torch_.Tensor]: | |
| """Args: | |
| extrinsics: (..., 4, 4) extrinsics matrices. | |
| intrinsics: (..., 3, 3) intrinsics matrices. | |
| width: width of the image. | |
| height: height of the image. | |
| Returns: | |
| rays_o: (..., 1, 1, 3) ray origins | |
| rays_d: (..., height, width, 3) ray directions. | |
| NOTE: ray directions are NOT normalized. They actuallys makes rays_o + rays_d * z = world coordinates, where z is the depth.""" | |
| utils3d.torch.nerf.get_image_rays | |
| def get_mipnerf_cones(rays_o: torch_.Tensor, rays_d: torch_.Tensor, z_vals: torch_.Tensor, pixel_width: torch_.Tensor) -> Tuple[torch_.Tensor, torch_.Tensor]: | |
| """Args: | |
| rays_o: (..., n_rays, 3) ray origins | |
| rays_d: (..., n_rays, 3) ray directions. | |
| z_vals: (..., n_rays, n_samples) z values. | |
| pixel_width: (...) pixel width. = 1 / (normalized focal length * width) | |
| Returns: | |
| mu: (..., n_rays, n_samples, 3) cone mu. | |
| sigma: (..., n_rays, n_samples, 3, 3) cone sigma.""" | |
| utils3d.torch.nerf.get_mipnerf_cones | |
| def volume_rendering(color: torch_.Tensor, sigma: torch_.Tensor, z_vals: torch_.Tensor, ray_length: torch_.Tensor, rgb: bool = True, depth: bool = True) -> Tuple[torch_.Tensor, torch_.Tensor, torch_.Tensor]: | |
| """Given color, sigma and z_vals (linear depth of the sampling points), render the volume. | |
| NOTE: By default, color and sigma should have one less sample than z_vals, in correspondence with the average value in intervals. | |
| If queried color are aligned with z_vals, we use trapezoidal rule to calculate the average values in intervals. | |
| Args: | |
| color: (..., n_samples or n_samples - 1, 3) color values. | |
| sigma: (..., n_samples or n_samples - 1) density values. | |
| z_vals: (..., n_samples) z values. | |
| ray_length: (...) length of the ray | |
| Returns: | |
| rgb: (..., 3) rendered color values. | |
| depth: (...) rendered depth values. | |
| weights (..., n_samples) weights.""" | |
| utils3d.torch.nerf.volume_rendering | |
| def bin_sample(size: Union[torch_.Size, Tuple[int, ...]], n_samples: int, min_value: numbers.Number, max_value: numbers.Number, spacing: Literal['linear', 'inverse_linear'], dtype: torch_.dtype = None, device: torch_.device = None) -> torch_.Tensor: | |
| """Uniformly (or uniformly in inverse space) sample z values in `n_samples` bins in range [min_value, max_value]. | |
| Args: | |
| size: size of the rays | |
| n_samples: number of samples to be sampled, also the number of bins | |
| min_value: minimum value of the range | |
| max_value: maximum value of the range | |
| space: 'linear' or 'inverse_linear'. If 'inverse_linear', the sampling is uniform in inverse space. | |
| Returns: | |
| z_rand: (*size, n_samples) sampled z values, sorted in ascending order.""" | |
| utils3d.torch.nerf.bin_sample | |
| def importance_sample(z_vals: torch_.Tensor, weights: torch_.Tensor, n_samples: int) -> Tuple[torch_.Tensor, torch_.Tensor]: | |
| """Importance sample z values. | |
| NOTE: By default, weights should have one less sample than z_vals, in correspondence with the intervals. | |
| If weights has the same number of samples as z_vals, we use trapezoidal rule to calculate the average weights in intervals. | |
| Args: | |
| z_vals: (..., n_rays, n_input_samples) z values, sorted in ascending order. | |
| weights: (..., n_rays, n_input_samples or n_input_samples - 1) weights. | |
| n_samples: number of output samples for importance sampling. | |
| Returns: | |
| z_importance: (..., n_rays, n_samples) importance sampled z values, unsorted.""" | |
| utils3d.torch.nerf.importance_sample | |
| def nerf_render_rays(nerf: Union[Callable[[torch_.Tensor, torch_.Tensor], Tuple[torch_.Tensor, torch_.Tensor]], Tuple[Callable[[torch_.Tensor], Tuple[torch_.Tensor, torch_.Tensor]], Callable[[torch_.Tensor], Tuple[torch_.Tensor, torch_.Tensor]]]], rays_o: torch_.Tensor, rays_d: torch_.Tensor, *, return_dict: bool = False, n_coarse: int = 64, n_fine: int = 64, near: float = 0.1, far: float = 100.0, z_spacing: Literal['linear', 'inverse_linear'] = 'linear'): | |
| """NeRF rendering of rays. Note that it supports arbitrary batch dimensions (denoted as `...`) | |
| Args: | |
| nerf: nerf model, which takes (points, directions) as input and returns (color, density) as output. | |
| If nerf is a tuple, it should be (nerf_coarse, nerf_fine), where nerf_coarse and nerf_fine are two nerf models for coarse and fine stages respectively. | |
| nerf args: | |
| points: (..., n_rays, n_samples, 3) | |
| directions: (..., n_rays, n_samples, 3) | |
| nerf returns: | |
| color: (..., n_rays, n_samples, 3) color values. | |
| density: (..., n_rays, n_samples) density values. | |
| rays_o: (..., n_rays, 3) ray origins | |
| rays_d: (..., n_rays, 3) ray directions. | |
| pixel_width: (..., n_rays) pixel width. How to compute? pixel_width = 1 / (normalized focal length * width) | |
| Returns | |
| if return_dict is False, return rendered rgb and depth for short cut. (If there are separate coarse and fine results, return fine results) | |
| rgb: (..., n_rays, 3) rendered color values. | |
| depth: (..., n_rays) rendered depth values. | |
| else, return a dict. If `n_fine == 0` or `nerf` is a single model, the dict only contains coarse results: | |
| ``` | |
| {'rgb': .., 'depth': .., 'weights': .., 'z_vals': .., 'color': .., 'density': ..} | |
| ``` | |
| If there are two models for coarse and fine stages, the dict contains both coarse and fine results: | |
| ``` | |
| { | |
| "coarse": {'rgb': .., 'depth': .., 'weights': .., 'z_vals': .., 'color': .., 'density': ..}, | |
| "fine": {'rgb': .., 'depth': .., 'weights': .., 'z_vals': .., 'color': .., 'density': ..} | |
| } | |
| ```""" | |
| utils3d.torch.nerf.nerf_render_rays | |
| def mipnerf_render_rays(mipnerf: Callable[[torch_.Tensor, torch_.Tensor, torch_.Tensor], Tuple[torch_.Tensor, torch_.Tensor]], rays_o: torch_.Tensor, rays_d: torch_.Tensor, pixel_width: torch_.Tensor, *, return_dict: bool = False, n_coarse: int = 64, n_fine: int = 64, uniform_ratio: float = 0.4, near: float = 0.1, far: float = 100.0, z_spacing: Literal['linear', 'inverse_linear'] = 'linear') -> Union[Tuple[torch_.Tensor, torch_.Tensor], Dict[str, torch_.Tensor]]: | |
| """MipNeRF rendering. | |
| Args: | |
| mipnerf: mipnerf model, which takes (points_mu, points_sigma) as input and returns (color, density) as output. | |
| mipnerf args: | |
| points_mu: (..., n_rays, n_samples, 3) cone mu. | |
| points_sigma: (..., n_rays, n_samples, 3, 3) cone sigma. | |
| directions: (..., n_rays, n_samples, 3) | |
| mipnerf returns: | |
| color: (..., n_rays, n_samples, 3) color values. | |
| density: (..., n_rays, n_samples) density values. | |
| rays_o: (..., n_rays, 3) ray origins | |
| rays_d: (..., n_rays, 3) ray directions. | |
| pixel_width: (..., n_rays) pixel width. How to compute? pixel_width = 1 / (normalized focal length * width) | |
| Returns | |
| if return_dict is False, return rendered results only: (If `n_fine == 0`, return coarse results, otherwise return fine results) | |
| rgb: (..., n_rays, 3) rendered color values. | |
| depth: (..., n_rays) rendered depth values. | |
| else, return a dict. If `n_fine == 0`, the dict only contains coarse results: | |
| ``` | |
| {'rgb': .., 'depth': .., 'weights': .., 'z_vals': .., 'color': .., 'density': ..} | |
| ``` | |
| If n_fine > 0, the dict contains both coarse and fine results : | |
| ``` | |
| { | |
| "coarse": {'rgb': .., 'depth': .., 'weights': .., 'z_vals': .., 'color': .., 'density': ..}, | |
| "fine": {'rgb': .., 'depth': .., 'weights': .., 'z_vals': .., 'color': .., 'density': ..} | |
| } | |
| ```""" | |
| utils3d.torch.nerf.mipnerf_render_rays | |
| def nerf_render_view(nerf: torch_.Tensor, extrinsics: torch_.Tensor, intrinsics: torch_.Tensor, width: int, height: int, *, patchify: bool = False, patch_size: Tuple[int, int] = (64, 64), **options: Dict[str, Any]) -> Tuple[torch_.Tensor, torch_.Tensor]: | |
| """NeRF rendering of views. Note that it supports arbitrary batch dimensions (denoted as `...`) | |
| Args: | |
| extrinsics: (..., 4, 4) extrinsics matrice of the rendered views | |
| intrinsics (optional): (..., 3, 3) intrinsics matrice of the rendered views. | |
| width (optional): image width of the rendered views. | |
| height (optional): image height of the rendered views. | |
| patchify (optional): If the image is too large, render it patch by patch | |
| **options: rendering options. | |
| Returns: | |
| rgb: (..., channels, height, width) rendered color values. | |
| depth: (..., height, width) rendered depth values.""" | |
| utils3d.torch.nerf.nerf_render_view | |
| def mipnerf_render_view(mipnerf: torch_.Tensor, extrinsics: torch_.Tensor, intrinsics: torch_.Tensor, width: int, height: int, *, patchify: bool = False, patch_size: Tuple[int, int] = (64, 64), **options: Dict[str, Any]) -> Tuple[torch_.Tensor, torch_.Tensor]: | |
| """MipNeRF rendering of views. Note that it supports arbitrary batch dimensions (denoted as `...`) | |
| Args: | |
| extrinsics: (..., 4, 4) extrinsics matrice of the rendered views | |
| intrinsics (optional): (..., 3, 3) intrinsics matrice of the rendered views. | |
| width (optional): image width of the rendered views. | |
| height (optional): image height of the rendered views. | |
| patchify (optional): If the image is too large, render it patch by patch | |
| **options: rendering options. | |
| Returns: | |
| rgb: (..., 3, height, width) rendered color values. | |
| depth: (..., height, width) rendered depth values.""" | |
| utils3d.torch.nerf.mipnerf_render_view | |
| def InstantNGP(view_dependent: bool = True, base_resolution: int = 16, finest_resolution: int = 2048, n_levels: int = 16, num_layers_density: int = 2, hidden_dim_density: int = 64, num_layers_color: int = 3, hidden_dim_color: int = 64, log2_hashmap_size: int = 19, bound: float = 1.0, color_channels: int = 3): | |
| """An implementation of InstantNGP, Müller et. al., https://nvlabs.github.io/instant-ngp/. | |
| Requires `tinycudann` package. | |
| Install it by: | |
| ``` | |
| pip install git+https://github.com/NVlabs/tiny-cuda-nn/#subdirectory=bindings/torch | |
| ```""" | |
| utils3d.torch.nerf.InstantNGP | |
| def sliding_window_1d(x: torch_.Tensor, window_size: int, stride: int = 1, dim: int = -1) -> torch_.Tensor: | |
| """Sliding window view of the input tensor. The dimension of the sliding window is appended to the end of the input tensor's shape. | |
| NOTE: Since Pytorch has `unfold` function, 1D sliding window view is just a wrapper of it.""" | |
| utils3d.torch.utils.sliding_window_1d | |
| def sliding_window_2d(x: torch_.Tensor, window_size: Union[int, Tuple[int, int]], stride: Union[int, Tuple[int, int]], dim: Union[int, Tuple[int, int]] = (-2, -1)) -> torch_.Tensor: | |
| utils3d.torch.utils.sliding_window_2d | |
| def sliding_window_nd(x: torch_.Tensor, window_size: Tuple[int, ...], stride: Tuple[int, ...], dim: Tuple[int, ...]) -> torch_.Tensor: | |
| utils3d.torch.utils.sliding_window_nd | |
| def image_uv(height: int, width: int, left: int = None, top: int = None, right: int = None, bottom: int = None, device: torch_.device = None, dtype: torch_.dtype = None) -> torch_.Tensor: | |
| """Get image space UV grid, ranging in [0, 1]. | |
| image_uv(10, 10): | |
| [[[0.05, 0.05], [0.15, 0.05], ..., [0.95, 0.05]], | |
| [[0.05, 0.15], [0.15, 0.15], ..., [0.95, 0.15]], | |
| ... ... ... | |
| [[0.05, 0.95], [0.15, 0.95], ..., [0.95, 0.95]]] | |
| Args: | |
| width (int): image width | |
| height (int): image height | |
| Returns: | |
| np.ndarray: shape (height, width, 2)""" | |
| utils3d.torch.utils.image_uv | |
| def image_pixel_center(height: int, width: int, left: int = None, top: int = None, right: int = None, bottom: int = None, dtype: torch_.dtype = None, device: torch_.device = None) -> torch_.Tensor: | |
| """Get image pixel center coordinates, ranging in [0, width] and [0, height]. | |
| `image[i, j]` has pixel center coordinates `(j + 0.5, i + 0.5)`. | |
| image_pixel_center(10, 10): | |
| [[[0.5, 0.5], [1.5, 0.5], ..., [9.5, 0.5]], | |
| [[0.5, 1.5], [1.5, 1.5], ..., [9.5, 1.5]], | |
| ... ... ... | |
| [[0.5, 9.5], [1.5, 9.5], ..., [9.5, 9.5]]] | |
| Args: | |
| width (int): image width | |
| height (int): image height | |
| Returns: | |
| np.ndarray: shape (height, width, 2)""" | |
| utils3d.torch.utils.image_pixel_center | |
| def image_mesh(height: int, width: int, mask: torch_.Tensor = None, device: torch_.device = None, dtype: torch_.dtype = None) -> Tuple[torch_.Tensor, torch_.Tensor]: | |
| """Get a quad mesh regarding image pixel uv coordinates as vertices and image grid as faces. | |
| Args: | |
| width (int): image width | |
| height (int): image height | |
| mask (np.ndarray, optional): binary mask of shape (height, width), dtype=bool. Defaults to None. | |
| Returns: | |
| uv (np.ndarray): uv corresponding to pixels as described in image_uv() | |
| faces (np.ndarray): quad faces connecting neighboring pixels | |
| indices (np.ndarray, optional): indices of vertices in the original mesh""" | |
| utils3d.torch.utils.image_mesh | |
| def chessboard(width: int, height: int, grid_size: int, color_a: torch_.Tensor, color_b: torch_.Tensor) -> torch_.Tensor: | |
| """get a chessboard image | |
| Args: | |
| width (int): image width | |
| height (int): image height | |
| grid_size (int): size of chessboard grid | |
| color_a (torch.Tensor): shape (chanenls,), color of the grid at the top-left corner | |
| color_b (torch.Tensor): shape (chanenls,), color in complementary grids | |
| Returns: | |
| image (torch.Tensor): shape (height, width, channels), chessboard image""" | |
| utils3d.torch.utils.chessboard | |
| def depth_edge(depth: torch_.Tensor, atol: float = None, rtol: float = None, kernel_size: int = 3, mask: torch_.Tensor = None) -> torch_.BoolTensor: | |
| """Compute the edge mask of a depth map. The edge is defined as the pixels whose neighbors have a large difference in depth. | |
| Args: | |
| depth (torch.Tensor): shape (..., height, width), linear depth map | |
| atol (float): absolute tolerance | |
| rtol (float): relative tolerance | |
| Returns: | |
| edge (torch.Tensor): shape (..., height, width) of dtype torch.bool""" | |
| utils3d.torch.utils.depth_edge | |
| def depth_aliasing(depth: torch_.Tensor, atol: float = None, rtol: float = None, kernel_size: int = 3, mask: torch_.Tensor = None) -> torch_.BoolTensor: | |
| """Compute the map that indicates the aliasing of a depth map. The aliasing is defined as the pixels which neither close to the maximum nor the minimum of its neighbors. | |
| Args: | |
| depth (torch.Tensor): shape (..., height, width), linear depth map | |
| atol (float): absolute tolerance | |
| rtol (float): relative tolerance | |
| Returns: | |
| edge (torch.Tensor): shape (..., height, width) of dtype torch.bool""" | |
| utils3d.torch.utils.depth_aliasing | |
| def image_mesh_from_depth(depth: torch_.Tensor, extrinsics: torch_.Tensor = None, intrinsics: torch_.Tensor = None) -> Tuple[torch_.Tensor, torch_.Tensor]: | |
| utils3d.torch.utils.image_mesh_from_depth | |
| def point_to_normal(point: torch_.Tensor, mask: torch_.Tensor = None) -> torch_.Tensor: | |
| """Calculate normal map from point map. Value range is [-1, 1]. Normal direction in OpenGL identity camera's coordinate system. | |
| Args: | |
| point (torch.Tensor): shape (..., height, width, 3), point map | |
| Returns: | |
| normal (torch.Tensor): shape (..., height, width, 3), normal map. """ | |
| utils3d.torch.utils.point_to_normal | |
| def depth_to_normal(depth: torch_.Tensor, intrinsics: torch_.Tensor, mask: torch_.Tensor = None) -> torch_.Tensor: | |
| """Calculate normal map from depth map. Value range is [-1, 1]. Normal direction in OpenGL identity camera's coordinate system. | |
| Args: | |
| depth (torch.Tensor): shape (..., height, width), linear depth map | |
| intrinsics (torch.Tensor): shape (..., 3, 3), intrinsics matrix | |
| Returns: | |
| normal (torch.Tensor): shape (..., 3, height, width), normal map. """ | |
| utils3d.torch.utils.depth_to_normal | |
| def masked_min(input: torch_.Tensor, mask: torch_.BoolTensor, dim: int = None, keepdim: bool = False) -> Union[torch_.Tensor, Tuple[torch_.Tensor, torch_.Tensor]]: | |
| """Similar to torch.min, but with mask | |
| """ | |
| utils3d.torch.utils.masked_min | |
| def masked_max(input: torch_.Tensor, mask: torch_.BoolTensor, dim: int = None, keepdim: bool = False) -> Union[torch_.Tensor, Tuple[torch_.Tensor, torch_.Tensor]]: | |
| """Similar to torch.max, but with mask | |
| """ | |
| utils3d.torch.utils.masked_max | |
| def bounding_rect(mask: torch_.BoolTensor): | |
| """get bounding rectangle of a mask | |
| Args: | |
| mask (torch.Tensor): shape (..., height, width), mask | |
| Returns: | |
| rect (torch.Tensor): shape (..., 4), bounding rectangle (left, top, right, bottom)""" | |
| utils3d.torch.utils.bounding_rect | |
| def perspective(fov_y: Union[float, torch_.Tensor], aspect: Union[float, torch_.Tensor], near: Union[float, torch_.Tensor], far: Union[float, torch_.Tensor]) -> torch_.Tensor: | |
| """Get OpenGL perspective matrix | |
| Args: | |
| fov_y (float | torch.Tensor): field of view in y axis | |
| aspect (float | torch.Tensor): aspect ratio | |
| near (float | torch.Tensor): near plane to clip | |
| far (float | torch.Tensor): far plane to clip | |
| Returns: | |
| (torch.Tensor): [..., 4, 4] perspective matrix""" | |
| utils3d.torch.transforms.perspective | |
| def perspective_from_fov(fov: Union[float, torch_.Tensor], width: Union[int, torch_.Tensor], height: Union[int, torch_.Tensor], near: Union[float, torch_.Tensor], far: Union[float, torch_.Tensor]) -> torch_.Tensor: | |
| """Get OpenGL perspective matrix from field of view in largest dimension | |
| Args: | |
| fov (float | torch.Tensor): field of view in largest dimension | |
| width (int | torch.Tensor): image width | |
| height (int | torch.Tensor): image height | |
| near (float | torch.Tensor): near plane to clip | |
| far (float | torch.Tensor): far plane to clip | |
| Returns: | |
| (torch.Tensor): [..., 4, 4] perspective matrix""" | |
| utils3d.torch.transforms.perspective_from_fov | |
| def perspective_from_fov_xy(fov_x: Union[float, torch_.Tensor], fov_y: Union[float, torch_.Tensor], near: Union[float, torch_.Tensor], far: Union[float, torch_.Tensor]) -> torch_.Tensor: | |
| """Get OpenGL perspective matrix from field of view in x and y axis | |
| Args: | |
| fov_x (float | torch.Tensor): field of view in x axis | |
| fov_y (float | torch.Tensor): field of view in y axis | |
| near (float | torch.Tensor): near plane to clip | |
| far (float | torch.Tensor): far plane to clip | |
| Returns: | |
| (torch.Tensor): [..., 4, 4] perspective matrix""" | |
| utils3d.torch.transforms.perspective_from_fov_xy | |
| def intrinsics_from_focal_center(fx: Union[float, torch_.Tensor], fy: Union[float, torch_.Tensor], cx: Union[float, torch_.Tensor], cy: Union[float, torch_.Tensor]) -> torch_.Tensor: | |
| """Get OpenCV intrinsics matrix | |
| Args: | |
| focal_x (float | torch.Tensor): focal length in x axis | |
| focal_y (float | torch.Tensor): focal length in y axis | |
| cx (float | torch.Tensor): principal point in x axis | |
| cy (float | torch.Tensor): principal point in y axis | |
| Returns: | |
| (torch.Tensor): [..., 3, 3] OpenCV intrinsics matrix""" | |
| utils3d.torch.transforms.intrinsics_from_focal_center | |
| def intrinsics_from_fov(fov_max: Union[float, torch_.Tensor] = None, fov_min: Union[float, torch_.Tensor] = None, fov_x: Union[float, torch_.Tensor] = None, fov_y: Union[float, torch_.Tensor] = None, width: Union[int, torch_.Tensor] = None, height: Union[int, torch_.Tensor] = None) -> torch_.Tensor: | |
| """Get normalized OpenCV intrinsics matrix from given field of view. | |
| You can provide either fov_max, fov_min, fov_x or fov_y | |
| Args: | |
| width (int | torch.Tensor): image width | |
| height (int | torch.Tensor): image height | |
| fov_max (float | torch.Tensor): field of view in largest dimension | |
| fov_min (float | torch.Tensor): field of view in smallest dimension | |
| fov_x (float | torch.Tensor): field of view in x axis | |
| fov_y (float | torch.Tensor): field of view in y axis | |
| Returns: | |
| (torch.Tensor): [..., 3, 3] OpenCV intrinsics matrix""" | |
| utils3d.torch.transforms.intrinsics_from_fov | |
| def intrinsics_from_fov_xy(fov_x: Union[float, torch_.Tensor], fov_y: Union[float, torch_.Tensor]) -> torch_.Tensor: | |
| """Get OpenCV intrinsics matrix from field of view in x and y axis | |
| Args: | |
| fov_x (float | torch.Tensor): field of view in x axis | |
| fov_y (float | torch.Tensor): field of view in y axis | |
| Returns: | |
| (torch.Tensor): [..., 3, 3] OpenCV intrinsics matrix""" | |
| utils3d.torch.transforms.intrinsics_from_fov_xy | |
| def view_look_at(eye: torch_.Tensor, look_at: torch_.Tensor, up: torch_.Tensor) -> torch_.Tensor: | |
| """Get OpenGL view matrix looking at something | |
| Args: | |
| eye (torch.Tensor): [..., 3] the eye position | |
| look_at (torch.Tensor): [..., 3] the position to look at | |
| up (torch.Tensor): [..., 3] head up direction (y axis in screen space). Not necessarily othogonal to view direction | |
| Returns: | |
| (torch.Tensor): [..., 4, 4], view matrix""" | |
| utils3d.torch.transforms.view_look_at | |
| def extrinsics_look_at(eye: torch_.Tensor, look_at: torch_.Tensor, up: torch_.Tensor) -> torch_.Tensor: | |
| """Get OpenCV extrinsics matrix looking at something | |
| Args: | |
| eye (torch.Tensor): [..., 3] the eye position | |
| look_at (torch.Tensor): [..., 3] the position to look at | |
| up (torch.Tensor): [..., 3] head up direction (-y axis in screen space). Not necessarily othogonal to view direction | |
| Returns: | |
| (torch.Tensor): [..., 4, 4], extrinsics matrix""" | |
| utils3d.torch.transforms.extrinsics_look_at | |
| def perspective_to_intrinsics(perspective: torch_.Tensor) -> torch_.Tensor: | |
| """OpenGL perspective matrix to OpenCV intrinsics | |
| Args: | |
| perspective (torch.Tensor): [..., 4, 4] OpenGL perspective matrix | |
| Returns: | |
| (torch.Tensor): shape [..., 3, 3] OpenCV intrinsics""" | |
| utils3d.torch.transforms.perspective_to_intrinsics | |
| def intrinsics_to_perspective(intrinsics: torch_.Tensor, near: Union[float, torch_.Tensor], far: Union[float, torch_.Tensor]) -> torch_.Tensor: | |
| """OpenCV intrinsics to OpenGL perspective matrix | |
| Args: | |
| intrinsics (torch.Tensor): [..., 3, 3] OpenCV intrinsics matrix | |
| near (float | torch.Tensor): [...] near plane to clip | |
| far (float | torch.Tensor): [...] far plane to clip | |
| Returns: | |
| (torch.Tensor): [..., 4, 4] OpenGL perspective matrix""" | |
| utils3d.torch.transforms.intrinsics_to_perspective | |
| def extrinsics_to_view(extrinsics: torch_.Tensor) -> torch_.Tensor: | |
| """OpenCV camera extrinsics to OpenGL view matrix | |
| Args: | |
| extrinsics (torch.Tensor): [..., 4, 4] OpenCV camera extrinsics matrix | |
| Returns: | |
| (torch.Tensor): [..., 4, 4] OpenGL view matrix""" | |
| utils3d.torch.transforms.extrinsics_to_view | |
| def view_to_extrinsics(view: torch_.Tensor) -> torch_.Tensor: | |
| """OpenGL view matrix to OpenCV camera extrinsics | |
| Args: | |
| view (torch.Tensor): [..., 4, 4] OpenGL view matrix | |
| Returns: | |
| (torch.Tensor): [..., 4, 4] OpenCV camera extrinsics matrix""" | |
| utils3d.torch.transforms.view_to_extrinsics | |
| def normalize_intrinsics(intrinsics: torch_.Tensor, width: Union[int, torch_.Tensor], height: Union[int, torch_.Tensor]) -> torch_.Tensor: | |
| """Normalize camera intrinsics(s) to uv space | |
| Args: | |
| intrinsics (torch.Tensor): [..., 3, 3] camera intrinsics(s) to normalize | |
| width (int | torch.Tensor): [...] image width(s) | |
| height (int | torch.Tensor): [...] image height(s) | |
| Returns: | |
| (torch.Tensor): [..., 3, 3] normalized camera intrinsics(s)""" | |
| utils3d.torch.transforms.normalize_intrinsics | |
| def crop_intrinsics(intrinsics: torch_.Tensor, width: Union[int, torch_.Tensor], height: Union[int, torch_.Tensor], left: Union[int, torch_.Tensor], top: Union[int, torch_.Tensor], crop_width: Union[int, torch_.Tensor], crop_height: Union[int, torch_.Tensor]) -> torch_.Tensor: | |
| """Evaluate the new intrinsics(s) after crop the image: cropped_img = img[top:top+crop_height, left:left+crop_width] | |
| Args: | |
| intrinsics (torch.Tensor): [..., 3, 3] camera intrinsics(s) to crop | |
| width (int | torch.Tensor): [...] image width(s) | |
| height (int | torch.Tensor): [...] image height(s) | |
| left (int | torch.Tensor): [...] left crop boundary | |
| top (int | torch.Tensor): [...] top crop boundary | |
| crop_width (int | torch.Tensor): [...] crop width | |
| crop_height (int | torch.Tensor): [...] crop height | |
| Returns: | |
| (torch.Tensor): [..., 3, 3] cropped camera intrinsics(s)""" | |
| utils3d.torch.transforms.crop_intrinsics | |
| def pixel_to_uv(pixel: torch_.Tensor, width: Union[int, torch_.Tensor], height: Union[int, torch_.Tensor]) -> torch_.Tensor: | |
| """Args: | |
| pixel (torch.Tensor): [..., 2] pixel coordinrates defined in image space, x range is (0, W - 1), y range is (0, H - 1) | |
| width (int | torch.Tensor): [...] image width(s) | |
| height (int | torch.Tensor): [...] image height(s) | |
| Returns: | |
| (torch.Tensor): [..., 2] pixel coordinrates defined in uv space, the range is (0, 1)""" | |
| utils3d.torch.transforms.pixel_to_uv | |
| def pixel_to_ndc(pixel: torch_.Tensor, width: Union[int, torch_.Tensor], height: Union[int, torch_.Tensor]) -> torch_.Tensor: | |
| """Args: | |
| pixel (torch.Tensor): [..., 2] pixel coordinrates defined in image space, x range is (0, W - 1), y range is (0, H - 1) | |
| width (int | torch.Tensor): [...] image width(s) | |
| height (int | torch.Tensor): [...] image height(s) | |
| Returns: | |
| (torch.Tensor): [..., 2] pixel coordinrates defined in ndc space, the range is (-1, 1)""" | |
| utils3d.torch.transforms.pixel_to_ndc | |
| def uv_to_pixel(uv: torch_.Tensor, width: Union[int, torch_.Tensor], height: Union[int, torch_.Tensor]) -> torch_.Tensor: | |
| """Args: | |
| uv (torch.Tensor): [..., 2] pixel coordinrates defined in uv space, the range is (0, 1) | |
| width (int | torch.Tensor): [...] image width(s) | |
| height (int | torch.Tensor): [...] image height(s) | |
| Returns: | |
| (torch.Tensor): [..., 2] pixel coordinrates defined in uv space, the range is (0, 1)""" | |
| utils3d.torch.transforms.uv_to_pixel | |
| def project_depth(depth: torch_.Tensor, near: Union[float, torch_.Tensor], far: Union[float, torch_.Tensor]) -> torch_.Tensor: | |
| """Project linear depth to depth value in screen space | |
| Args: | |
| depth (torch.Tensor): [...] depth value | |
| near (float | torch.Tensor): [...] near plane to clip | |
| far (float | torch.Tensor): [...] far plane to clip | |
| Returns: | |
| (torch.Tensor): [..., 1] depth value in screen space, value ranging in [0, 1]""" | |
| utils3d.torch.transforms.project_depth | |
| def depth_buffer_to_linear(depth: torch_.Tensor, near: Union[float, torch_.Tensor], far: Union[float, torch_.Tensor]) -> torch_.Tensor: | |
| """Linearize depth value to linear depth | |
| Args: | |
| depth (torch.Tensor): [...] screen depth value, ranging in [0, 1] | |
| near (float | torch.Tensor): [...] near plane to clip | |
| far (float | torch.Tensor): [...] far plane to clip | |
| Returns: | |
| (torch.Tensor): [...] linear depth""" | |
| utils3d.torch.transforms.depth_buffer_to_linear | |
| def project_gl(points: torch_.Tensor, model: torch_.Tensor = None, view: torch_.Tensor = None, perspective: torch_.Tensor = None) -> Tuple[torch_.Tensor, torch_.Tensor]: | |
| """Project 3D points to 2D following the OpenGL convention (except for row major matrice) | |
| Args: | |
| points (torch.Tensor): [..., N, 3 or 4] 3D points to project, if the last | |
| dimension is 4, the points are assumed to be in homogeneous coordinates | |
| model (torch.Tensor): [..., 4, 4] model matrix | |
| view (torch.Tensor): [..., 4, 4] view matrix | |
| perspective (torch.Tensor): [..., 4, 4] perspective matrix | |
| Returns: | |
| scr_coord (torch.Tensor): [..., N, 3] screen space coordinates, value ranging in [0, 1]. | |
| The origin (0., 0., 0.) is corresponding to the left & bottom & nearest | |
| linear_depth (torch.Tensor): [..., N] linear depth""" | |
| utils3d.torch.transforms.project_gl | |
| def project_cv(points: torch_.Tensor, extrinsics: torch_.Tensor = None, intrinsics: torch_.Tensor = None) -> Tuple[torch_.Tensor, torch_.Tensor]: | |
| """Project 3D points to 2D following the OpenCV convention | |
| Args: | |
| points (torch.Tensor): [..., N, 3] or [..., N, 4] 3D points to project, if the last | |
| dimension is 4, the points are assumed to be in homogeneous coordinates | |
| extrinsics (torch.Tensor): [..., 4, 4] extrinsics matrix | |
| intrinsics (torch.Tensor): [..., 3, 3] intrinsics matrix | |
| Returns: | |
| uv_coord (torch.Tensor): [..., N, 2] uv coordinates, value ranging in [0, 1]. | |
| The origin (0., 0.) is corresponding to the left & top | |
| linear_depth (torch.Tensor): [..., N] linear depth""" | |
| utils3d.torch.transforms.project_cv | |
| def unproject_gl(screen_coord: torch_.Tensor, model: torch_.Tensor = None, view: torch_.Tensor = None, perspective: torch_.Tensor = None) -> torch_.Tensor: | |
| """Unproject screen space coordinates to 3D view space following the OpenGL convention (except for row major matrice) | |
| Args: | |
| screen_coord (torch.Tensor): [... N, 3] screen space coordinates, value ranging in [0, 1]. | |
| The origin (0., 0., 0.) is corresponding to the left & bottom & nearest | |
| model (torch.Tensor): [..., 4, 4] model matrix | |
| view (torch.Tensor): [..., 4, 4] view matrix | |
| perspective (torch.Tensor): [..., 4, 4] perspective matrix | |
| Returns: | |
| points (torch.Tensor): [..., N, 3] 3d points""" | |
| utils3d.torch.transforms.unproject_gl | |
| def unproject_cv(uv_coord: torch_.Tensor, depth: torch_.Tensor, extrinsics: torch_.Tensor = None, intrinsics: torch_.Tensor = None) -> torch_.Tensor: | |
| """Unproject uv coordinates to 3D view space following the OpenCV convention | |
| Args: | |
| uv_coord (torch.Tensor): [..., N, 2] uv coordinates, value ranging in [0, 1]. | |
| The origin (0., 0.) is corresponding to the left & top | |
| depth (torch.Tensor): [..., N] depth value | |
| extrinsics (torch.Tensor): [..., 4, 4] extrinsics matrix | |
| intrinsics (torch.Tensor): [..., 3, 3] intrinsics matrix | |
| Returns: | |
| points (torch.Tensor): [..., N, 3] 3d points""" | |
| utils3d.torch.transforms.unproject_cv | |
| def skew_symmetric(v: torch_.Tensor): | |
| """Skew symmetric matrix from a 3D vector""" | |
| utils3d.torch.transforms.skew_symmetric | |
| def rotation_matrix_from_vectors(v1: torch_.Tensor, v2: torch_.Tensor): | |
| """Rotation matrix that rotates v1 to v2""" | |
| utils3d.torch.transforms.rotation_matrix_from_vectors | |
| def euler_axis_angle_rotation(axis: str, angle: torch_.Tensor) -> torch_.Tensor: | |
| """Return the rotation matrices for one of the rotations about an axis | |
| of which Euler angles describe, for each value of the angle given. | |
| Args: | |
| axis: Axis label "X" or "Y or "Z". | |
| angle: any shape tensor of Euler angles in radians | |
| Returns: | |
| Rotation matrices as tensor of shape (..., 3, 3).""" | |
| utils3d.torch.transforms.euler_axis_angle_rotation | |
| def euler_angles_to_matrix(euler_angles: torch_.Tensor, convention: str = 'XYZ') -> torch_.Tensor: | |
| """Convert rotations given as Euler angles in radians to rotation matrices. | |
| Args: | |
| euler_angles: Euler angles in radians as tensor of shape (..., 3), XYZ | |
| convention: permutation of "X", "Y" or "Z", representing the order of Euler rotations to apply. | |
| Returns: | |
| Rotation matrices as tensor of shape (..., 3, 3).""" | |
| utils3d.torch.transforms.euler_angles_to_matrix | |
| def matrix_to_euler_angles(matrix: torch_.Tensor, convention: str) -> torch_.Tensor: | |
| """Convert rotations given as rotation matrices to Euler angles in radians. | |
| NOTE: The composition order eg. `XYZ` means `Rz * Ry * Rx` (like blender), instead of `Rx * Ry * Rz` (like pytorch3d) | |
| Args: | |
| matrix: Rotation matrices as tensor of shape (..., 3, 3). | |
| convention: Convention string of three uppercase letters. | |
| Returns: | |
| Euler angles in radians as tensor of shape (..., 3), in the order of XYZ (like blender), instead of convention (like pytorch3d)""" | |
| utils3d.torch.transforms.matrix_to_euler_angles | |
| def matrix_to_quaternion(rot_mat: torch_.Tensor, eps: float = 1e-12) -> torch_.Tensor: | |
| """Convert 3x3 rotation matrix to quaternion (w, x, y, z) | |
| Args: | |
| rot_mat (torch.Tensor): shape (..., 3, 3), the rotation matrices to convert | |
| Returns: | |
| torch.Tensor: shape (..., 4), the quaternions corresponding to the given rotation matrices""" | |
| utils3d.torch.transforms.matrix_to_quaternion | |
| def quaternion_to_matrix(quaternion: torch_.Tensor, eps: float = 1e-12) -> torch_.Tensor: | |
| """Converts a batch of quaternions (w, x, y, z) to rotation matrices | |
| Args: | |
| quaternion (torch.Tensor): shape (..., 4), the quaternions to convert | |
| Returns: | |
| torch.Tensor: shape (..., 3, 3), the rotation matrices corresponding to the given quaternions""" | |
| utils3d.torch.transforms.quaternion_to_matrix | |
| def matrix_to_axis_angle(rot_mat: torch_.Tensor, eps: float = 1e-12) -> torch_.Tensor: | |
| """Convert a batch of 3x3 rotation matrices to axis-angle representation (rotation vector) | |
| Args: | |
| rot_mat (torch.Tensor): shape (..., 3, 3), the rotation matrices to convert | |
| Returns: | |
| torch.Tensor: shape (..., 3), the axis-angle vectors corresponding to the given rotation matrices""" | |
| utils3d.torch.transforms.matrix_to_axis_angle | |
| def axis_angle_to_matrix(axis_angle: torch_.Tensor, eps: float = 1e-12) -> torch_.Tensor: | |
| """Convert axis-angle representation (rotation vector) to rotation matrix, whose direction is the axis of rotation and length is the angle of rotation | |
| Args: | |
| axis_angle (torch.Tensor): shape (..., 3), axis-angle vcetors | |
| Returns: | |
| torch.Tensor: shape (..., 3, 3) The rotation matrices for the given axis-angle parameters""" | |
| utils3d.torch.transforms.axis_angle_to_matrix | |
| def axis_angle_to_quaternion(axis_angle: torch_.Tensor, eps: float = 1e-12) -> torch_.Tensor: | |
| """Convert axis-angle representation (rotation vector) to quaternion (w, x, y, z) | |
| Args: | |
| axis_angle (torch.Tensor): shape (..., 3), axis-angle vcetors | |
| Returns: | |
| torch.Tensor: shape (..., 4) The quaternions for the given axis-angle parameters""" | |
| utils3d.torch.transforms.axis_angle_to_quaternion | |
| def quaternion_to_axis_angle(quaternion: torch_.Tensor, eps: float = 1e-12) -> torch_.Tensor: | |
| """Convert a batch of quaternions (w, x, y, z) to axis-angle representation (rotation vector) | |
| Args: | |
| quaternion (torch.Tensor): shape (..., 4), the quaternions to convert | |
| Returns: | |
| torch.Tensor: shape (..., 3), the axis-angle vectors corresponding to the given quaternions""" | |
| utils3d.torch.transforms.quaternion_to_axis_angle | |
| def slerp(rot_mat_1: torch_.Tensor, rot_mat_2: torch_.Tensor, t: Union[numbers.Number, torch_.Tensor]) -> torch_.Tensor: | |
| """Spherical linear interpolation between two rotation matrices | |
| Args: | |
| rot_mat_1 (torch.Tensor): shape (..., 3, 3), the first rotation matrix | |
| rot_mat_2 (torch.Tensor): shape (..., 3, 3), the second rotation matrix | |
| t (torch.Tensor): scalar or shape (...,), the interpolation factor | |
| Returns: | |
| torch.Tensor: shape (..., 3, 3), the interpolated rotation matrix""" | |
| utils3d.torch.transforms.slerp | |
| def interpolate_extrinsics(ext1: torch_.Tensor, ext2: torch_.Tensor, t: Union[numbers.Number, torch_.Tensor]) -> torch_.Tensor: | |
| """Interpolate extrinsics between two camera poses. Linear interpolation for translation, spherical linear interpolation for rotation. | |
| Args: | |
| ext1 (torch.Tensor): shape (..., 4, 4), the first camera pose | |
| ext2 (torch.Tensor): shape (..., 4, 4), the second camera pose | |
| t (torch.Tensor): scalar or shape (...,), the interpolation factor | |
| Returns: | |
| torch.Tensor: shape (..., 4, 4), the interpolated camera pose""" | |
| utils3d.torch.transforms.interpolate_extrinsics | |
| def interpolate_view(view1: torch_.Tensor, view2: torch_.Tensor, t: Union[numbers.Number, torch_.Tensor]): | |
| """Interpolate view matrices between two camera poses. Linear interpolation for translation, spherical linear interpolation for rotation. | |
| Args: | |
| ext1 (torch.Tensor): shape (..., 4, 4), the first camera pose | |
| ext2 (torch.Tensor): shape (..., 4, 4), the second camera pose | |
| t (torch.Tensor): scalar or shape (...,), the interpolation factor | |
| Returns: | |
| torch.Tensor: shape (..., 4, 4), the interpolated camera pose""" | |
| utils3d.torch.transforms.interpolate_view | |
| def extrinsics_to_essential(extrinsics: torch_.Tensor): | |
| """extrinsics matrix `[[R, t] [0, 0, 0, 1]]` such that `x' = R (x - t)` to essential matrix such that `x' E x = 0` | |
| Args: | |
| extrinsics (torch.Tensor): [..., 4, 4] extrinsics matrix | |
| Returns: | |
| (torch.Tensor): [..., 3, 3] essential matrix""" | |
| utils3d.torch.transforms.extrinsics_to_essential | |
| def to4x4(R: torch_.Tensor, t: torch_.Tensor): | |
| """Compose rotation matrix and translation vector to 4x4 transformation matrix | |
| Args: | |
| R (torch.Tensor): [..., 3, 3] rotation matrix | |
| t (torch.Tensor): [..., 3] translation vector | |
| Returns: | |
| (torch.Tensor): [..., 4, 4] transformation matrix""" | |
| utils3d.torch.transforms.to4x4 | |
| def rotation_matrix_2d(theta: Union[float, torch_.Tensor]): | |
| """2x2 matrix for 2D rotation | |
| Args: | |
| theta (float | torch.Tensor): rotation angle in radians, arbitrary shape (...,) | |
| Returns: | |
| (torch.Tensor): (..., 2, 2) rotation matrix""" | |
| utils3d.torch.transforms.rotation_matrix_2d | |
| def rotate_2d(theta: Union[float, torch_.Tensor], center: torch_.Tensor = None): | |
| """3x3 matrix for 2D rotation around a center | |
| ``` | |
| [[Rxx, Rxy, tx], | |
| [Ryx, Ryy, ty], | |
| [0, 0, 1]] | |
| ``` | |
| Args: | |
| theta (float | torch.Tensor): rotation angle in radians, arbitrary shape (...,) | |
| center (torch.Tensor): rotation center, arbitrary shape (..., 2). Default to (0, 0) | |
| Returns: | |
| (torch.Tensor): (..., 3, 3) transformation matrix""" | |
| utils3d.torch.transforms.rotate_2d | |
| def translate_2d(translation: torch_.Tensor): | |
| """Translation matrix for 2D translation | |
| ``` | |
| [[1, 0, tx], | |
| [0, 1, ty], | |
| [0, 0, 1]] | |
| ``` | |
| Args: | |
| translation (torch.Tensor): translation vector, arbitrary shape (..., 2) | |
| Returns: | |
| (torch.Tensor): (..., 3, 3) transformation matrix""" | |
| utils3d.torch.transforms.translate_2d | |
| def scale_2d(scale: Union[float, torch_.Tensor], center: torch_.Tensor = None): | |
| """Scale matrix for 2D scaling | |
| ``` | |
| [[s, 0, tx], | |
| [0, s, ty], | |
| [0, 0, 1]] | |
| ``` | |
| Args: | |
| scale (float | torch.Tensor): scale factor, arbitrary shape (...,) | |
| center (torch.Tensor): scale center, arbitrary shape (..., 2). Default to (0, 0) | |
| Returns: | |
| (torch.Tensor): (..., 3, 3) transformation matrix""" | |
| utils3d.torch.transforms.scale_2d | |
| def apply_2d(transform: torch_.Tensor, points: torch_.Tensor): | |
| """Apply (3x3 or 2x3) 2D affine transformation to points | |
| ``` | |
| p = R @ p + t | |
| ``` | |
| Args: | |
| transform (torch.Tensor): (..., 2 or 3, 3) transformation matrix | |
| points (torch.Tensor): (..., N, 2) points to transform | |
| Returns: | |
| (torch.Tensor): (..., N, 2) transformed points""" | |
| utils3d.torch.transforms.apply_2d | |
| def RastContext(nvd_ctx: Union[nvdiffrast.torch.ops.RasterizeCudaContext, nvdiffrast.torch.ops.RasterizeGLContext] = None, *, backend: Literal['cuda', 'gl'] = 'gl', device: Union[str, torch_.device] = None): | |
| """Create a rasterization context. Nothing but a wrapper of nvdiffrast.torch.RasterizeCudaContext or nvdiffrast.torch.RasterizeGLContext.""" | |
| utils3d.torch.rasterization.RastContext | |
| def rasterize_triangle_faces(ctx: utils3d.torch.rasterization.RastContext, vertices: torch_.Tensor, faces: torch_.Tensor, attr: torch_.Tensor, width: int, height: int, model: torch_.Tensor = None, view: torch_.Tensor = None, projection: torch_.Tensor = None, antialiasing: Union[bool, List[int]] = True, diff_attrs: Optional[List[int]] = None) -> Tuple[torch_.Tensor, torch_.Tensor, Optional[torch_.Tensor]]: | |
| """Rasterize a mesh with vertex attributes. | |
| Args: | |
| ctx (GLContext): rasterizer context | |
| vertices (np.ndarray): (B, N, 2 or 3 or 4) | |
| faces (torch.Tensor): (T, 3) | |
| attr (torch.Tensor): (B, N, C) | |
| width (int): width of the output image | |
| height (int): height of the output image | |
| model (torch.Tensor, optional): ([B,] 4, 4) model matrix. Defaults to None (identity). | |
| view (torch.Tensor, optional): ([B,] 4, 4) view matrix. Defaults to None (identity). | |
| projection (torch.Tensor, optional): ([B,] 4, 4) projection matrix. Defaults to None (identity). | |
| antialiasing (Union[bool, List[int]], optional): whether to perform antialiasing. Defaults to True. If a list of indices is provided, only those channels will be antialiased. | |
| diff_attrs (Union[None, List[int]], optional): indices of attributes to compute screen-space derivatives. Defaults to None. | |
| Returns: | |
| image: (torch.Tensor): (B, C, H, W) | |
| depth: (torch.Tensor): (B, H, W) screen space depth, ranging from 0 (near) to 1. (far) | |
| NOTE: Empty pixels will have depth 1., i.e. far plane.""" | |
| utils3d.torch.rasterization.rasterize_triangle_faces | |
| def warp_image_by_depth(ctx: utils3d.torch.rasterization.RastContext, depth: torch_.FloatTensor, image: torch_.FloatTensor = None, mask: torch_.BoolTensor = None, width: int = None, height: int = None, *, extrinsics_src: torch_.FloatTensor = None, extrinsics_tgt: torch_.FloatTensor = None, intrinsics_src: torch_.FloatTensor = None, intrinsics_tgt: torch_.FloatTensor = None, near: float = 0.1, far: float = 100.0, antialiasing: bool = True, backslash: bool = False, padding: int = 0, return_uv: bool = False, return_dr: bool = False) -> Tuple[torch_.FloatTensor, torch_.FloatTensor, torch_.BoolTensor, Optional[torch_.FloatTensor], Optional[torch_.FloatTensor]]: | |
| """Warp image by depth. | |
| NOTE: if batch size is 1, image mesh will be triangulated aware of the depth, yielding less distorted results. | |
| Otherwise, image mesh will be triangulated simply for batch rendering. | |
| Args: | |
| ctx (Union[dr.RasterizeCudaContext, dr.RasterizeGLContext]): rasterization context | |
| depth (torch.Tensor): (B, H, W) linear depth | |
| image (torch.Tensor): (B, C, H, W). None to use image space uv. Defaults to None. | |
| width (int, optional): width of the output image. None to use the same as depth. Defaults to None. | |
| height (int, optional): height of the output image. Defaults the same as depth.. | |
| extrinsics_src (torch.Tensor, optional): (B, 4, 4) extrinsics matrix for source. None to use identity. Defaults to None. | |
| extrinsics_tgt (torch.Tensor, optional): (B, 4, 4) extrinsics matrix for target. None to use identity. Defaults to None. | |
| intrinsics_src (torch.Tensor, optional): (B, 3, 3) intrinsics matrix for source. None to use the same as target. Defaults to None. | |
| intrinsics_tgt (torch.Tensor, optional): (B, 3, 3) intrinsics matrix for target. None to use the same as source. Defaults to None. | |
| near (float, optional): near plane. Defaults to 0.1. | |
| far (float, optional): far plane. Defaults to 100.0. | |
| antialiasing (bool, optional): whether to perform antialiasing. Defaults to True. | |
| backslash (bool, optional): whether to use backslash triangulation. Defaults to False. | |
| padding (int, optional): padding of the image. Defaults to 0. | |
| return_uv (bool, optional): whether to return the uv. Defaults to False. | |
| return_dr (bool, optional): whether to return the image-space derivatives of uv. Defaults to False. | |
| Returns: | |
| image: (torch.FloatTensor): (B, C, H, W) rendered image | |
| depth: (torch.FloatTensor): (B, H, W) linear depth, ranging from 0 to inf | |
| mask: (torch.BoolTensor): (B, H, W) mask of valid pixels | |
| uv: (torch.FloatTensor): (B, 2, H, W) image-space uv | |
| dr: (torch.FloatTensor): (B, 4, H, W) image-space derivatives of uv""" | |
| utils3d.torch.rasterization.warp_image_by_depth | |
| def warp_image_by_forward_flow(ctx: utils3d.torch.rasterization.RastContext, image: torch_.FloatTensor, flow: torch_.FloatTensor, depth: torch_.FloatTensor = None, *, antialiasing: bool = True, backslash: bool = False) -> Tuple[torch_.FloatTensor, torch_.BoolTensor]: | |
| """Warp image by forward flow. | |
| NOTE: if batch size is 1, image mesh will be triangulated aware of the depth, yielding less distorted results. | |
| Otherwise, image mesh will be triangulated simply for batch rendering. | |
| Args: | |
| ctx (Union[dr.RasterizeCudaContext, dr.RasterizeGLContext]): rasterization context | |
| image (torch.Tensor): (B, C, H, W) image | |
| flow (torch.Tensor): (B, 2, H, W) forward flow | |
| depth (torch.Tensor, optional): (B, H, W) linear depth. If None, will use the same for all pixels. Defaults to None. | |
| antialiasing (bool, optional): whether to perform antialiasing. Defaults to True. | |
| backslash (bool, optional): whether to use backslash triangulation. Defaults to False. | |
| Returns: | |
| image: (torch.FloatTensor): (B, C, H, W) rendered image | |
| mask: (torch.BoolTensor): (B, H, W) mask of valid pixels""" | |
| utils3d.torch.rasterization.warp_image_by_forward_flow | |