Skip to content

functional

Functional API of the transforms: the tensor functions of every themed module.

Functions:

  • color_auto_contrast –

    Stretch per-cloud color range to the full [0, max] interval, then blend.

  • color_drop –

    Replace colors with a constant gray value (drops chromatic information).

  • color_grayscale –

    Convert RGB colors to grayscale using the BT.601 luminance weights.

  • color_jitter –

    Apply brightness, contrast, and saturation factors to colors, in that order.

  • color_shift –

    Add a per-channel offset to colors, clamped to the valid color range.

  • flip_boxes –

    Flip oriented 3D boxes along a spatial axis.

  • flip_vectors –

    Flip a packed field of 3D vectors along a spatial axis.

  • random_color_jitter –

    Jitter colors by brightness, contrast, and saturation, in that order.

  • random_elastic_distortion –

    Apply a smooth random displacement field to pos.

  • random_jitter –

    Add Gaussian noise to x, optionally clipped.

  • rotate_boxes –

    Rotate oriented 3D boxes about the up axis.

  • scale_boxes –

    Scale oriented 3D boxes by an isotropic factor.

  • translate_boxes –

    Translate oriented 3D boxes by a fixed offset.

  • cut_boxes –

    Cut the annotated objects of a scene out by their boxes, one dict per object.

  • points_in_oriented_box –

    Test which points lie inside a single oriented 3D box.

  • axis_min_offset –

    Per-point offset from a floor reference along a chosen coordinate axis.

  • estimate_normals –

    Estimate per-point unit surface normals by local PCA.

  • quantize –

    Integer voxel-grid coordinates of every point, without reducing the cloud.

  • rotate_vectors –

    Rotate a packed field of 3D vectors by a rotation matrix.

  • rotation_matrix –

    \(3 \times 3\) rotation matrix for angle radians around an axis-aligned axis.

  • shift –

    Subtract a data-driven offset from x.

  • apply_mask –

    Apply a mask to a tensor.

  • bounding_box –

    Returns the min and max values along a given dimension.

  • box_mask –

    Create a boolean mask for points inside an axis-aligned bounding box (AABB).

  • cube_mask –

    Create a boolean mask for points inside an axis-aligned cube (L∞ / Chebyshev ball).

  • remove_near_origin –

    Remove points that are within a given radius (L2) of the origin.

  • sphere_mask –

    Create a boolean mask for points inside an L2 (Euclidean) ball.

  • laser_mix_masks –

    Return keep-masks that swap alternating inclination (pitch) bands between two LiDAR scans.

  • polar_mix_masks –

    Return keep-masks that swap a random azimuth half-sector between two LiDAR scans.

  • farthest_point_sample –

    Farthest-point sampling (FPS) from a tensor of positions.

  • random_dropout_mask –

    Return a boolean keep-mask of length n where each entry is kept with probability 1 - drop_ratio.

  • random_sample –

    Randomly sample a fixed number of values from a tensor.

  • random_sample_face_vertices –

    Randomly sample a fixed number of vertices from a 3D mesh (vertices, face),

  • shuffle_indices –

    Return a random permutation of [0, n).

  • maxabs_scale –

    Scale a tensor by its largest absolute value, per channel: \(x' = x / \max(\max_i |x_i|, \epsilon)\).

  • minimal_enclosing_ball –

    Compute the smallest ball enclosing a point set (Welzl's move-to-front algorithm).

  • normalize –

    Per-channel standardization: \(x' = (x - \mu) / \max(\sigma, \epsilon)\).

  • rescale –

    Center a point set and rescale it to a unit extent.

  • absolute –

    Make the input tensor absolute.

  • relabel –

    Remap integer labels via a lookup table.

  • divisible_pad –

    Pad the batch indices of a tensor to make them divisible by a given integer.

color_auto_contrast [source] ΒΆ

color_auto_contrast(
    color: Tensor,
    blend: float = 0.5,
    int_color: bool = False,
) -> Tensor

Stretch per-cloud color range to the full [0, max] interval, then blend.

For each channel, the min becomes 0 and the max becomes max_val. The output is then linearly blended with the original by blend (blend=1.0 is the fully stretched version, blend=0.0 is the input).

Parameters:

  • color (Tensor) –

    Color tensor of shape \((N, 3)\).

  • blend (float, default: 0.5 ) –

    Blend weight in [0, 1].

  • int_color (bool, default: False ) –

    If True, treat float colors as [0, 255] values; otherwise [0, 1]. uint8 colors are always treated as [0, 255] regardless of the flag.

Returns:

  • Tensor –

    Auto-contrast tensor with the same shape and dtype as color.

Raises:

  • ValueError –

    If color is a float tensor with values above 1 while int_color=False.

color_drop [source] ΒΆ

color_drop(
    color: Tensor,
    fill: float = 0.5,
    int_color: bool = False,
) -> Tensor

Replace colors with a constant gray value (drops chromatic information).

Parameters:

  • color (Tensor) –

    Color tensor of shape \((N, 3)\).

  • fill (float, default: 0.5 ) –

    Replacement value, expressed in the range implied by int_color ([0, 1] when False, [0, 255] when True). It is rescaled to the input's actual range when that differs, so the default 0.5 fills 127 on uint8 colors.

  • int_color (bool, default: False ) –

    If True, treat float colors as [0, 255] values; otherwise [0, 1]. uint8 colors are always treated as [0, 255] regardless of the flag.

Returns:

  • Tensor –

    Tensor of the same shape and dtype as color, filled with the rescaled fill.

Raises:

  • ValueError –

    If color is a float tensor with values above 1 while int_color=False.

color_grayscale [source] ΒΆ

color_grayscale(
    color: Tensor, int_color: bool = False
) -> Tensor

Convert RGB colors to grayscale using the BT.601 luminance weights.

Parameters:

  • color (Tensor) –

    Color tensor of shape \((N, 3)\).

  • int_color (bool, default: False ) –

    If True, treat colors as [0, 255] ints; otherwise [0, 1] floats.

Returns:

  • Tensor –

    Tensor with the same shape and dtype as color, with R=G=B = luminance.

color_jitter [source] ΒΆ

color_jitter(
    color: Tensor,
    brightness: Optional[float] = None,
    contrast: Optional[float] = None,
    saturation: Optional[float] = None,
    int_color: bool = False,
) -> Tensor

Apply brightness, contrast, and saturation factors to colors, in that order.

Each factor multiplies its component directly (1.0 is identity); None skips the component entirely.

Parameters:

  • color (Tensor) –

    Color tensor of shape \((N, 3)\).

  • brightness (Optional[float], default: None ) –

    Multiplicative brightness factor (e.g. 1.2 brightens by 20%).

  • contrast (Optional[float], default: None ) –

    Contrast factor, scaling the deviation from the per-channel mean.

  • saturation (Optional[float], default: None ) –

    Saturation factor, scaling the deviation from the per-point grayscale luminance.

  • int_color (bool, default: False ) –

    If True, treat float colors as [0, 255] values; otherwise [0, 1]. uint8 colors are always treated as [0, 255] regardless of the flag.

Returns:

  • Tensor –

    Jittered colors with the same shape and dtype as color.

Raises:

  • ValueError –

    If color is a float tensor with values above 1 while int_color=False.

color_shift [source] ΒΆ

color_shift(
    color: Tensor, shift: Tensor, int_color: bool = False
) -> Tensor

Add a per-channel offset to colors, clamped to the valid color range.

Parameters:

  • color (Tensor) –

    Color tensor of shape \((N, 3)\).

  • shift (Tensor) –

    Per-channel offset of shape \((3,)\), in the same range as the colors.

  • int_color (bool, default: False ) –

    If True, treat float colors as [0, 255] values; otherwise [0, 1]. uint8 colors are always treated as [0, 255] regardless of the flag.

Returns:

  • Tensor –

    Shifted colors with the same shape and dtype as color.

Raises:

  • ValueError –

    If color is a float tensor with values above 1 while int_color=False.

flip_boxes [source] ΒΆ

flip_boxes(boxes: Tensor, axis: int) -> Tensor

Flip oriented 3D boxes along a spatial axis.

Boxes are stored as \((K, 7)\) rows \([c_x, c_y, c_z, d_x, d_y, d_z, \theta]\) with full extents and heading in radians counterclockwise about \(+z\) from \(+x\). A flip negates the center component along axis. A flip along axis \(0\) (the \(yz\) plane) maps the heading to \(\pi - \theta\); a flip along axis \(1\) (the \(xz\) plane) maps the heading to \(-\theta\). Sizes are unchanged. Boxes with a planar velocity \((v_x, v_y)\) in columns \(7{:}9\) have its axis component negated too; further columns are kept as they are.

Parameters:

  • boxes (Tensor) –

    Box tensor of shape \((K, 7)\) or \((K, 7 + C)\).

  • axis (int) –

    Center axis index to negate (0=X, 1=Y).

Returns:

  • Tensor –

    The flipped box tensor, same shape as boxes.

flip_vectors [source] ΒΆ

flip_vectors(x: Tensor, axis: int) -> Tensor

Flip a packed field of 3D vectors along a spatial axis.

Negates component axis of every contiguous triple of the last dimension, so it handles both a plain \((N, 3)\) field (e.g. coordinates or normals) and a \((N, 3 G)\) field of \(G\) tiled offsets (e.g. vote offsets \((\text{center} - \text{point})\)) alike.

Parameters:

  • x (Tensor) –

    Vector field of shape \((N, 3)\) or \((N, 3 G)\).

  • axis (int) –

    Axis index within each triple to negate.

Returns:

  • Tensor –

    The flipped tensor with the same shape as x.

random_color_jitter [source] ΒΆ

random_color_jitter(
    color: Tensor,
    brightness: float = 0.0,
    contrast: float = 0.0,
    saturation: float = 0.0,
    int_color: bool = False,
    generator: Optional[Generator] = None,
) -> Tensor

Jitter colors by brightness, contrast, and saturation, in that order.

Each strength is a relative delta sampled uniformly from [-x, x] and applied multiplicatively (out = x * factor) via color_jitter.

Parameters:

  • color (Tensor) –

    Color tensor of shape \((N, 3)\).

  • brightness (float, default: 0.0 ) –

    Max relative brightness change. 0.2 means Β±20%.

  • contrast (float, default: 0.0 ) –

    Max relative contrast change.

  • saturation (float, default: 0.0 ) –

    Max relative saturation change. Saturation moves toward (or away from) the per-channel grayscale luminance.

  • int_color (bool, default: False ) –

    If True, treat float colors as [0, 255] values; otherwise [0, 1]. uint8 colors are always treated as [0, 255] regardless of the flag.

  • generator (Optional[Generator], default: None ) –

    Random generator for reproducibility.

Returns:

  • Tensor –

    Jittered colors with the same shape and dtype as color.

Raises:

  • ValueError –

    If color is a float tensor with values above 1 while int_color=False.

random_elastic_distortion [source] ΒΆ

random_elastic_distortion(
    pos: Tensor,
    granularity: float = 0.2,
    magnitude: float = 0.4,
    generator: Optional[Generator] = None,
) -> Tensor

Apply a smooth random displacement field to pos.

Implements the elastic distortion recipe common in sparse-voxel indoor segmentation pipelines: sample Gaussian noise on a coarse 3D grid (cells of side granularity), smooth it with two passes of a \(3 \times 3 \times 3\) mean filter, trilinear-interpolate the smoothed displacement at each point, and add it to the position. Net effect is a locally-coherent, low-frequency deformation that preserves nearby-point relationships.

Parameters:

  • pos (Tensor) –

    Input positions of shape \((N, 3)\).

  • granularity (float, default: 0.2 ) –

    Size of the noise grid cells (in the same units as pos). Smaller values give higher-frequency distortion.

  • magnitude (float, default: 0.4 ) –

    Standard deviation of the per-cell Gaussian noise (in the same units as pos). Larger values give stronger deformation.

  • generator (Optional[Generator], default: None ) –

    Random generator for reproducibility.

Returns:

  • Tensor –

    Distorted positions of shape \((N, 3)\).

random_jitter [source] ΒΆ

random_jitter(
    x: Tensor,
    sigma: float = 0.01,
    clip: Optional[float] = 0.05,
    generator: Optional[Generator] = None,
) -> Tensor

Add Gaussian noise to x, optionally clipped.

Parameters:

  • x (Tensor) –

    Input tensor.

  • sigma (float, default: 0.01 ) –

    Standard deviation of the Gaussian noise.

  • clip (Optional[float], default: 0.05 ) –

    If not None, clip the noise to [-clip, clip].

  • generator (Optional[Generator], default: None ) –

    Random generator for reproducibility.

Returns:

  • Tensor –

    Jittered tensor with the same shape as x.

rotate_boxes [source] ΒΆ

rotate_boxes(
    boxes: Tensor, rotation: Tensor, angle: float
) -> Tensor

Rotate oriented 3D boxes about the up axis.

Box centers are rotated by rotation (centers @ rotation.transpose(-1, -2)) and the heading is incremented by angle, so a counterclockwise rotation about \(+z\) keeps the counterclockwise heading aligned with the jointly rotated points. Sizes are unchanged. Boxes with a planar velocity \((v_x, v_y)\) in columns \(7{:}9\) have it rotated in the plane; further columns are kept as they are.

Parameters:

  • boxes (Tensor) –

    Box tensor of shape \((K, 7)\) as \([c_x, c_y, c_z, d_x, d_y, d_z, \theta]\), or \((K, 7 + C)\).

  • rotation (Tensor) –

    A \(3 \times 3\) rotation matrix rotating by angle counterclockwise about the \(z\) axis.

  • angle (float) –

    Rotation angle in radians, added to the heading.

Returns:

  • Tensor –

    The rotated box tensor, same shape as boxes.

scale_boxes [source] ΒΆ

scale_boxes(
    boxes: Tensor, scale: Union[float, Tensor]
) -> Tensor

Scale oriented 3D boxes by an isotropic factor.

Both centers and extents (columns \(0\) to \(6\)) are multiplied by scale, and so is a planar velocity \((v_x, v_y)\) in columns \(7{:}9\). Heading and further columns are unchanged.

Parameters:

  • boxes (Tensor) –

    Box tensor of shape \((K, 7)\) or \((K, 7 + C)\).

  • scale (Union[float, Tensor]) –

    Isotropic scalar factor applied to centers, sizes and velocity.

Returns:

  • Tensor –

    The scaled box tensor, same shape as boxes.

translate_boxes [source] ΒΆ

translate_boxes(
    boxes: Tensor, translation: Tensor
) -> Tensor

Translate oriented 3D boxes by a fixed offset.

Centers (columns \(0\) to \(3\)) are offset by translation. Sizes, heading and any further column (such as a velocity) are unchanged.

Parameters:

  • boxes (Tensor) –

    Box tensor of shape \((K, 7)\) as \([c_x, c_y, c_z, d_x, d_y, d_z, \theta]\), or \((K, 7 + C)\).

  • translation (Tensor) –

    Translation vector of shape \((3,)\).

Returns:

  • Tensor –

    The shifted box tensor, same shape as boxes.

cut_boxes [source] ΒΆ

cut_boxes(
    data: Mapping[str, Any],
    keys: KeyCollection = POS,
    box_key: str = BOX,
    label_key: str = LABEL,
    attribute_keys: Optional[KeyCollection] = None,
) -> List[Dict[str, Tensor]]

Cut the annotated objects of a scene out by their boxes, one dict per object.

An object holds the points inside its box under keys, the coordinates relative to the box center under the first key, its box under box_key, its label under label_key and its value of every attribute_keys. A point inside several boxes belongs to each of them. The keys are plain strings, so a list of objects saves with torch.save and loads back with weights_only=True. PasteBoxes pastes such objects into other scenes.

Parameters:

  • data (Mapping[str, Any]) –

    Scene holding the packed points under keys, the boxes \((K, 7)\) or wider under box_key, the labels \((K,)\) under label_key and one row per box under each of attribute_keys.

  • keys (KeyCollection, default: POS ) –

    Point keys cut out with the objects, the coordinates first.

  • box_key (str, default: BOX ) –

    Key of the boxes, whose first seven columns are read.

  • label_key (str, default: LABEL ) –

    Key of the labels.

  • attribute_keys (Optional[KeyCollection], default: None ) –

    Per-box keys cut out with the objects (e.g. a velocity).

Returns:

  • List[Dict[str, Tensor]] –

    The objects of the scene, in the order of its boxes.

Example
import torch
import torch_pointcloud.transforms.functional as F
from torch_pointcloud.datasets import KITTI

objects = []
for data in KITTI(root="data"):
    objects.extend(F.cut_boxes(data, keys=["pos", "intensity"]))
objects = [obj for obj in objects if len(obj["pos"]) >= 5]
torch.save(objects, "objects.pt")

points_in_oriented_box [source] ΒΆ

points_in_oriented_box(pos: Tensor, box: Tensor) -> Tensor

Test which points lie inside a single oriented 3D box.

The point offsets relative to the box center are rotated into the box frame by \(-\theta\) about \(+z\), then compared against the half-extents with an axis-aligned bounding-box test. The heading \(\theta\) is in radians counterclockwise about \(+z\). For a box with zero heading this reduces to a plain axis-aligned test.

Parameters:

  • pos (Tensor) –

    Coordinate tensor of shape \((N, 3)\).

  • box (Tensor) –

    A single box of shape \((7,)\) as \([c_x, c_y, c_z, h_x, h_y, h_z, \theta]\) with half-extents.

Returns:

  • Tensor –

    A boolean mask of shape \((N,)\) that is True for points inside the box.

axis_min_offset [source] ΒΆ

axis_min_offset(
    x: Tensor, axis: int, quantile: Optional[float] = None
) -> Tensor

Per-point offset from a floor reference along a chosen coordinate axis.

For positions of shape \((N, D)\) and an axis \(a \in [0, D)\), returns a tensor of shape \((N, 1)\) whose entries are \(x_{i, a} - r\) where the floor reference \(r\) is either the strict minimum \(\min_j x_{j, a}\) (default) or, when quantile is given, the empirical quantile \(Q_{q}(x_{\cdot, a})\). A small positive quantile (e.g. \(q = 0.0099\)) yields an outlier-robust floor estimate. Useful for extracting "height above the local floor" as a per-point feature.

Parameters:

  • x (Tensor) –

    Input tensor of shape \((N, D)\).

  • axis (int) –

    Axis index in the last dimension.

  • quantile (Optional[float], default: None ) –

    Optional quantile \(q \in [0, 1]\) for the floor reference. When None, the strict per-axis minimum is used (equivalent to \(q = 0\)).

Returns:

  • Tensor –

    Tensor of shape \((N, 1)\) with the same dtype as x. Returns an empty

  • Tensor –

    \((0, 1)\) tensor when x is empty.

estimate_normals [source] ΒΆ

estimate_normals(
    pos: Tensor,
    k: int = 16,
    batch: Optional[Tensor] = None,
    orient_to_centroid: bool = False,
) -> Tensor

Estimate per-point unit surface normals by local PCA.

For each point the normal is the eigenvector of the smallest eigenvalue of the covariance of its \(k\) nearest neighbors, i.e. the direction of least variance (the local tangent-plane normal).

PCA gives no canonical orientation. By default the sign is the arbitrary-but-deterministic sign returned by torch.linalg.eigh. With orient_to_centroid, each normal is flipped to point towards its cloud's centroid, which approximates the inward-facing orientation of meshes scanned from inside a room (S3DIS, ScanNet) and matters when the consuming model was trained on oriented normals.

Parameters:

  • pos (Tensor) –

    Point coordinates of shape \((N, 3)\).

  • k (int, default: 16 ) –

    Number of nearest neighbors (the point itself included) used per local PCA. Must not exceed the number of points in the smallest cloud.

  • batch (Optional[Tensor], default: None ) –

    Optional \((N,)\) batch index so neighbors never cross cloud boundaries.

  • orient_to_centroid (bool, default: False ) –

    If True, flip each normal to point towards its cloud's centroid.

Returns:

  • Tensor –

    Unit normals of shape \((N, 3)\).

Raises:

  • ValueError –

    If pos has fewer than k points.

Shape
  • Input: \((N, 3)\)
  • Output: \((N, 3)\)

quantize [source] ΒΆ

quantize(pos: Tensor, size: float) -> Tensor

Integer voxel-grid coordinates of every point, without reducing the cloud.

Each point maps to \(\lfloor p / s \rfloor\) shifted so the per-axis minimum is \(0\); points sharing a voxel get equal coordinates and every input row is kept. This is the coordinate a voxel-partition protocol feeds to a sparse model for each raw point (Voxelize(pos_reduce="grid") produces the same coordinates for the one representative it keeps per voxel).

Parameters:

  • pos (Tensor) –

    Point positions of shape \((N, D)\).

  • size (float) –

    Voxel side length in the units of pos.

Returns:

  • Tensor –

    Long tensor of shape \((N, D)\) (empty input returns an empty \((0, D)\) tensor).

Example
import torch
from torch_pointcloud.transforms import functional as F

pos = torch.tensor([[0.0, 0.0, 0.0], [0.03, 0.0, 0.0], [0.05, 0.0, 0.0]])
F.quantize(pos, size=0.02)  # tensor([[0, 0, 0], [1, 0, 0], [2, 0, 0]])

rotate_vectors [source] ΒΆ

rotate_vectors(x: Tensor, rotation: Tensor) -> Tensor

Rotate a packed field of 3D vectors by a rotation matrix.

Each contiguous triple of the last dimension rotates as a vector, so it handles both a plain \((N, 3)\) field (e.g. coordinates or normals) and a \((N, 3 G)\) field of \(G\) tiled offsets (e.g. vote offsets) alike.

Parameters:

  • x (Tensor) –

    Vector field of shape \((N, 3)\) or \((N, 3 G)\).

  • rotation (Tensor) –

    A \(3 \times 3\) rotation matrix.

Returns:

  • Tensor –

    The rotated tensor with the same shape as x.

rotation_matrix [source] ΒΆ

rotation_matrix(
    angle: float,
    axis: int = 2,
    device: Optional[device] = None,
) -> Tensor

\(3 \times 3\) rotation matrix for angle radians around an axis-aligned axis.

Parameters:

  • angle (float) –

    Rotation angle in radians.

  • axis (int, default: 2 ) –

    Axis index to rotate around (0=X, 1=Y, 2=Z).

  • device (Optional[device], default: None ) –

    Output device. Defaults to CPU.

Returns:

  • Tensor –

    Rotation matrix of shape \((3, 3)\).

Raises:

  • ValueError –

    If axis is not in {0, 1, 2}.

shift [source] ΒΆ

shift(
    x: Tensor,
    method: ShiftMethod,
    dim: int = 0,
    axes: Optional[Sequence[int]] = None,
) -> Tensor

Subtract a data-driven offset from x.

The offset is computed from x itself along the reduction dimension dim:

method Offset
"bbox" Midrange: (min + max) / 2
"centroid" Mean across the reduced dimension
"min" Per-axis minimum (shifts to the positive octant)

When axes is given, only those axis-indices of the offset are non-zero, so axes not listed are left untouched. This is the composable knob for mixed-method shifts:

import torch

import torch_pointcloud.transforms.functional as F

x = torch.rand(100, 3)
# Center XY at the bbox midpoint and Z at the minimum
x = F.shift(x, method="bbox", axes=[0, 1])
x = F.shift(x, method="min", axes=[2])

The two calls touch disjoint axes, so they commute.

Parameters:

  • x (Tensor) –

    Input tensor.

  • method (ShiftMethod) –

    How the offset is computed. See the table.

  • dim (int, default: 0 ) –

    The dimension to reduce over when computing the offset.

  • axes (Optional[Sequence[int]], default: None ) –

    Last-dim axis indices to shift. None (default) shifts every axis.

Returns:

  • Tensor –

    The shifted tensor, same shape as x. Returns x unchanged when

  • Tensor –

    x.size(dim) == 0.

Raises:

  • ValueError –

    If method is not one of "bbox", "centroid", "min".

apply_mask [source] ΒΆ

apply_mask(x: Tensor, mask: Tensor) -> Tensor

Apply a mask to a tensor.

Parameters:

  • x (Tensor) –

    The input tensor.

  • mask (Tensor) –

    The mask.

Returns:

  • Tensor –

    The tensor with the mask applied.

Examples:

>>> import torch
>>> import torch_pointcloud.transforms.functional as F
>>> x = torch.tensor([1.0, 2.0, 3.0])
>>> mask = torch.tensor([True, False, True])
>>> F.apply_mask(x, mask)
tensor([1., 3.])

bounding_box [source] ΒΆ

bounding_box(x: Tensor, dim: int = 0) -> tuple[float, ...]

Returns the min and max values along a given dimension.

Parameters:

  • x (Tensor) –

    The input tensor of shape (..., D, ...).

  • dim (int, default: 0 ) –

    The dimension to compute bounds over.

Returns:

  • tuple[float, ...] –

    A tuple of (*min, *max) values.

box_mask [source] ΒΆ

box_mask(
    x: Tensor,
    bbox: tuple[float, ...],
    dim: int = -1,
    strict: bool = False,
) -> Tensor

Create a boolean mask for points inside an axis-aligned bounding box (AABB).

Membership condition along dim (default, boundary points included):

\[ \text{bbmin}_j \leq x_j \leq \text{bbmax}_j \quad \forall j \]

With strict=True the inequalities are strict, so boundary points are excluded.

Parameters:

  • x (Tensor) –

    The input tensor of shape \((\ldots, D)\) along dim.

  • bbox (tuple[float, ...]) –

    AABB as a flat tuple (*bbmin, *bbmax) of length \(2 \cdot D\); a row longer than \(D\) is tested by its first \(D\) coordinates, so a box row \((c_x, c_y, c_z, \ldots)\) is tested by its center.

  • dim (int, default: -1 ) –

    The dimension to compute the mask over.

  • strict (bool, default: False ) –

    If True, use strict inequalities (points exactly on the boundary are excluded).

Returns:

  • Tensor –

    The boolean mask, with dim reduced.

Raises:

  • ValueError –

    If len(bbox) is odd or larger than 2 * x.shape[dim].

cube_mask [source] ΒΆ

cube_mask(
    x: Tensor,
    center: Union[Tensor, Sequence[float], float],
    radius: float,
    dim: int = -1,
) -> Tensor

Create a boolean mask for points inside an axis-aligned cube (L∞ / Chebyshev ball).

Membership condition along dim:

\[ \| x - c \|_{\infty} \leq r \]

Geometrically, the L∞ ball of radius \(r\) centered at \(c\) is a hypercube with edge \(2r\) aligned to the axes. Pair with sphere_mask (L2) and box_mask (explicit AABB).

Parameters:

  • x (Tensor) –

    The input tensor of shape \((\ldots, D)\) along dim.

  • center (Union[Tensor, Sequence[float], float]) –

    The center of the cube, shape \((D,)\) or broadcastable.

  • radius (float) –

    The half-edge (radius) of the cube.

  • dim (int, default: -1 ) –

    The dimension to reduce the per-axis comparison over.

Returns:

  • Tensor –

    The boolean mask, with dim reduced.

remove_near_origin [source] ΒΆ

remove_near_origin(
    pos: Tensor, radius: float, return_mask: Literal[True]
) -> Tuple[Tensor, Tensor]
remove_near_origin(
    pos: Tensor,
    radius: float,
    return_mask: Literal[False] = False,
) -> Tensor
remove_near_origin(
    pos: Tensor, radius: float, return_mask: bool
) -> Union[Tensor, Tuple[Tensor, Tensor]]
remove_near_origin(
    pos: Tensor,
    radius: float = 0.001,
    return_mask: bool = False,
) -> Any

Remove points that are within a given radius (L2) of the origin.

Equivalent to inverting sphere_mask(pos, center=0, radius=r) and indexing.

Parameters:

  • pos (Tensor) –

    The input tensor of shape \((N, D)\).

  • radius (float, default: 0.001 ) –

    The L2 radius (Euclidean distance) below which points are removed.

  • return_mask (bool, default: False ) –

    If True, also return the keep-mask.

Returns:

  • Any –

    The filtered tensor; or (filtered, mask) if return_mask=True.

sphere_mask [source] ΒΆ

sphere_mask(
    x: Tensor,
    center: Union[Tensor, Sequence[float], float],
    radius: float,
    dim: int = -1,
) -> Tensor

Create a boolean mask for points inside an L2 (Euclidean) ball.

Membership condition along dim:

\[ \| x - c \|_2 \leq r \]

Pair with cube_mask (L∞) and box_mask (explicit AABB).

Parameters:

  • x (Tensor) –

    The input tensor of shape \((\ldots, D)\) along dim.

  • center (Union[Tensor, Sequence[float], float]) –

    The center of the sphere, shape \((D,)\) or broadcastable.

  • radius (float) –

    The radius of the sphere.

  • dim (int, default: -1 ) –

    The dimension to compute the Euclidean norm over.

Returns:

  • Tensor –

    The boolean mask, with dim reduced.

laser_mix_masks [source] ΒΆ

laser_mix_masks(
    pos: Tensor,
    other_pos: Tensor,
    num_areas: int,
    pitch_range: Tuple[float, float],
    generator: Optional[Generator] = None,
) -> Tuple[Tensor, Tensor]

Return keep-masks that swap alternating inclination (pitch) bands between two LiDAR scans.

Each point's inclination is \(\phi = \arctan2(z, \sqrt{x^2 + y^2})\) in degrees. The range pitch_range is split into num_areas equal bands; a random parity picks whether the even or odd bands are kept from the first scan, with the complementary bands kept from the second. The mixed scene is torch.cat([pos[mask], other_pos[other_mask]]), so the two masks tile the sky.

Parameters:

  • pos (Tensor) –

    Coordinates of the first scan of shape \((N, 3)\).

  • other_pos (Tensor) –

    Coordinates of the second scan of shape \((M, 3)\).

  • num_areas (int) –

    Number of inclination bands to split pitch_range into.

  • pitch_range (Tuple[float, float]) –

    Inclination range (min, max) in degrees.

  • generator (Optional[Generator], default: None ) –

    Random generator for reproducibility.

Returns:

  • Tensor –

    A tuple (mask, other_mask) of boolean tensors of shape \((N,)\) and \((M,)\) that select the

  • Tensor –

    points kept from pos and from other_pos respectively.

Shape
  • pos: \((N, 3)\)
  • other_pos: \((M, 3)\)
  • output: \((N,)\) and \((M,)\)

Raises:

  • ValueError –

    If num_areas is not positive.

Example
import torch
from torch_pointcloud.transforms.functional import laser_mix_masks

pos = torch.randn(100, 3)
other = torch.randn(120, 3)
g = torch.Generator().manual_seed(0)
mask, other_mask = laser_mix_masks(pos, other, num_areas=4, pitch_range=(-25.0, 3.0), generator=g)
mixed = torch.cat([pos[mask], other[other_mask]], dim=0)

polar_mix_masks [source] ΒΆ

polar_mix_masks(
    pos: Tensor,
    other_pos: Tensor,
    generator: Optional[Generator] = None,
) -> Tuple[Tensor, Tensor]

Return keep-masks that swap a random azimuth half-sector between two LiDAR scans.

Each point's azimuth is \(\theta = \arctan2(y, x)\). A random start angle in \([-\pi, \pi)\) defines a half-circle sector \([\theta_0, \theta_0 + \pi)\) that wraps around the \(\pm\pi\) seam, so half of the azimuth range is swapped regardless of the start angle. Points of the first scan outside the sector are kept, and points of the second scan inside the sector are added, so the mixed scene is torch.cat([pos[mask], other_pos[other_mask]]).

Parameters:

  • pos (Tensor) –

    Coordinates of the first scan of shape \((N, 3)\).

  • other_pos (Tensor) –

    Coordinates of the second scan of shape \((M, 3)\).

  • generator (Optional[Generator], default: None ) –

    Random generator for reproducibility.

Returns:

  • Tensor –

    A tuple (mask, other_mask) of boolean tensors of shape \((N,)\) and \((M,)\) that select the

  • Tensor –

    points kept from pos and pasted from other_pos respectively.

Shape
  • pos: \((N, 3)\)
  • other_pos: \((M, 3)\)
  • output: \((N,)\) and \((M,)\)
Example
import torch
from torch_pointcloud.transforms.functional import polar_mix_masks

pos = torch.randn(100, 3)
other = torch.randn(120, 3)
g = torch.Generator().manual_seed(0)
mask, other_mask = polar_mix_masks(pos, other, generator=g)
mixed = torch.cat([pos[mask], other[other_mask]], dim=0)

farthest_point_sample [source] ΒΆ

farthest_point_sample(
    pos: Tensor,
    num_samples: Optional[int] = None,
    ratio: Optional[float] = None,
    random_start: bool = False,
) -> Tensor

Farthest-point sampling (FPS) from a tensor of positions.

Thin wrapper around torch_pointcloud.ops.cluster.fps, provided for convenience and naming symmetry with random_sample.

See Also

torch_pointcloud.ops.cluster.fps for more details and advanced usage.

Parameters:

  • pos (Tensor) –

    The input tensor of shape \((N, D)\).

  • num_samples (Optional[int], default: None ) –

    The number of points to sample.

  • ratio (Optional[float], default: None ) –

    The ratio of points to sample.

  • random_start (bool, default: False ) –

    Whether to start the sampling from a random point.

Returns:

  • Tensor –

    The indices of the sampled points, always num_samples of them when num_samples is given. A cloud with at

  • Tensor –

    most num_samples points keeps its original order instead of being reordered by farthest-point rank, and a

  • Tensor –

    smaller one is completed by cycling through its points, the repetition fps applies too. ratio >= 1

  • Tensor –

    returns torch.arange(N).

Examples:

>>> import torch
>>> from torch_pointcloud.transforms.functional import farthest_point_sample
>>> pos = torch.randn(100, 3)
>>> idx = farthest_point_sample(pos, num_samples=10)  # doctest: +SKIP
>>> print(idx.shape)  # doctest: +SKIP
torch.Size([10])

random_dropout_mask [source] ΒΆ

random_dropout_mask(
    n: int,
    drop_ratio: float,
    device: Optional[device] = None,
    generator: Optional[Generator] = None,
) -> Tensor

Return a boolean keep-mask of length n where each entry is kept with probability 1 - drop_ratio.

Parameters:

  • n (int) –

    Number of points.

  • drop_ratio (float) –

    Probability of dropping a point. Must be in \([0, 1)\).

  • device (Optional[device], default: None ) –

    Output device.

  • generator (Optional[Generator], default: None ) –

    Random generator for reproducibility.

Returns:

  • Tensor –

    Boolean tensor of shape \((n,)\).

Raises:

  • ValueError –

    If drop_ratio is not in [0, 1).

random_sample [source] ΒΆ

random_sample(
    tensor: Tensor,
    num_samples: int,
    return_indices: Literal[True],
    replace: bool = False,
    generator: Optional[Generator] = None,
) -> Tuple[Tensor, Tensor]
random_sample(
    tensor: Tensor,
    num_samples: int,
    return_indices: Literal[False] = False,
    replace: bool = False,
    generator: Optional[Generator] = None,
) -> Tensor
random_sample(
    tensor: Tensor,
    num_samples: int,
    return_indices: bool = False,
    replace: bool = False,
    generator: Optional[Generator] = None,
) -> Union[Tensor, Tuple[Tensor, Tensor]]

Randomly sample a fixed number of values from a tensor.

Note

The data is sampled uniformly along dim=0.

Parameters:

  • tensor (Tensor) –

    The input tensor of shape \((N, \ldots)\).

  • num_samples (int) –

    The number of values to sample.

  • return_indices (bool, default: False ) –

    Whether to return the indices of the sampled values.

  • replace (bool, default: False ) –

    If True, sample with replacement (duplicates allowed). If False, sample without replacement when \(N \geq \text{num\_samples}\); when \(\text{num\_samples} > N\) the draw falls back to replacement so the output always has num_samples rows.

  • generator (Optional[Generator], default: None ) –

    The generator for the random number generator.

Returns:

  • Union[Tensor, Tuple[Tensor, Tensor]] –

    If return_indices is True, the function returns a tuple of the sampled values and their indices.

  • Union[Tensor, Tuple[Tensor, Tensor]] –

    Otherwise, it returns the sampled values.

Raises:

  • ValueError –

    If num_samples > 0 and the input is empty.

random_sample_face_vertices [source] ΒΆ

random_sample_face_vertices(
    vertices: Tensor,
    face: Tensor,
    num_samples: int,
    return_normals: Literal[True],
    generator: Optional[Generator] = None,
) -> Tuple[Tensor, Tensor]
random_sample_face_vertices(
    vertices: Tensor,
    face: Tensor,
    num_samples: int,
    return_normals: Literal[False] = False,
    generator: Optional[Generator] = None,
) -> Tensor
random_sample_face_vertices(
    vertices: Tensor,
    face: Tensor,
    num_samples: int,
    return_normals: bool,
    generator: Optional[Generator] = None,
) -> Union[Tensor, Tuple[Tensor, Tensor]]
random_sample_face_vertices(
    vertices: Tensor,
    face: Tensor,
    num_samples: int,
    return_normals: bool = False,
    generator: Optional[Generator] = None,
) -> Union[Tensor, Tuple[Tensor, Tensor]]

Randomly sample a fixed number of vertices from a 3D mesh (vertices, face), using:

Note

The data is sampled uniformly from the mesh.

Parameters:

  • vertices (Tensor) –

    The input tensor.

  • face (Tensor) –

    The input tensor.

  • num_samples (int) –

    The number of vertices to sample.

  • return_normals (bool, default: False ) –

    Whether to return the normal of the sampled vertices.

  • generator (Optional[Generator], default: None ) –

    The generator for the random number generator.

Returns:

  • Union[Tensor, Tuple[Tensor, Tensor]] –

    If return_normals is True, the function returns a tuple of the sampled vertices and their normal.

  • Union[Tensor, Tuple[Tensor, Tensor]] –

    Otherwise, it returns the sampled vertices.

shuffle_indices [source] ΒΆ

shuffle_indices(
    n: int,
    device: Optional[device] = None,
    generator: Optional[Generator] = None,
) -> Tensor

Return a random permutation of [0, n).

Parameters:

  • n (int) –

    Sequence length.

  • device (Optional[device], default: None ) –

    Output device.

  • generator (Optional[Generator], default: None ) –

    Random generator for reproducibility.

Returns:

  • Tensor –

    Long tensor of shape \((n,)\).

maxabs_scale [source] ΒΆ

maxabs_scale(x: Tensor, eps: float = 1e-07) -> Tensor

Scale a tensor by its largest absolute value, per channel: \(x' = x / \max(\max_i |x_i|, \epsilon)\).

The maximum is taken over every dimension but the last (the channel dimension), so the input is treated as one point cloud: scale packed batches per sample (pre-collate), never on concatenated clouds.

Parameters:

  • x (Tensor) –

    Input tensor. Integer tensors are cast to float32.

  • eps (float, default: 1e-07 ) –

    Lower bound on the divisor to prevent division by zero.

Returns:

  • Tensor –

    The scaled tensor, same shape as x, with values in \([-1, 1]\).

minimal_enclosing_ball [source] ΒΆ

minimal_enclosing_ball(
    points: Tensor,
) -> Tuple[Tensor, Tensor]

Compute the smallest ball enclosing a point set (Welzl's move-to-front algorithm).

The recursion only descends on the support set (at most \(C + 1\) points), so the depth is bounded by the dimension while the point loop stays iterative; points already known to be inside are moved to the front so that later checks succeed early.

Parameters:

  • points (Tensor) –

    Tensor of shape \((N, C)\) with \(N \geq 1\).

Returns:

  • Tuple[Tensor, Tensor] –

    The ball center \((C,)\) and its radius (a scalar), in the dtype and on the device of points.

Shape
  • Input: \((N, C)\)
  • Output: \((C,)\) and \(()\)
Example
import torch
from torch_pointcloud.transforms import functional as F

points = torch.tensor([[1.0, 0.0, 0.0], [-1.0, 0.0, 0.0], [0.0, 0.5, 0.0]])
center, radius = F.minimal_enclosing_ball(points)  # tensor([0., 0., 0.]), tensor(1.)

normalize [source] ΒΆ

normalize(
    x: Tensor,
    mean: Union[Tensor, Sequence[float], float],
    std: Union[Tensor, Sequence[float], float],
    eps: float = 1e-07,
) -> Tensor

Per-channel standardization: \(x' = (x - \mu) / \max(\sigma, \epsilon)\).

Parameters:

  • x (Tensor) –

    Input tensor. The last dimension is treated as the channel dim.

  • mean (Union[Tensor, Sequence[float], float]) –

    Per-channel mean(s). Broadcast against the last dimension.

  • std (Union[Tensor, Sequence[float], float]) –

    Per-channel standard deviation(s).

  • eps (float, default: 1e-07 ) –

    Lower bound on \(\sigma\) to prevent division by zero.

Returns:

  • Tensor –

    Standardized tensor, same shape as x.

rescale [source] ΒΆ

rescale(
    points: Tensor,
    eps: float = 1e-06,
    method: RescaleMethod = "centroid",
) -> Tensor

Center a point set and rescale it to a unit extent.

Operates along the point dimension dim=-2. Pairs a centering step with a scale-by-extent step that share the same statistics. The scale denominator is a single statistic over all leading dimensions, so the input is treated as one point cloud: rescale packed batches per sample (pre-collate), never on concatenated clouds.

Parameters:

  • points (Tensor) –

    Tensor of shape \((\ldots, N, C)\) with \(C \geq 1\); min/max and means are over \(N\).

  • eps (float, default: 1e-06 ) –

    Small constant added to the scale denominator for numerical stability.

  • method (RescaleMethod, default: 'centroid' ) –
    • "centroid": subtract the mean over points, then divide by the max Euclidean distance from the centroid plus \(\epsilon\):

    $$ \mathbf{x} \leftarrow \frac{\mathbf{x} - \boldsymbol{\mu}}{\max_i |\mathbf{x}_i - \boldsymbol{\mu}|_2 + \epsilon} $$

    • "bbox": subtract the axis-aligned bounding-box midpoint (midrange center), then divide by half the longest edge of that box plus \(\epsilon\) (matches common ModelNet-style normalization):

    $$ \mathbf{c} = \frac{\mathbf{x}{\min} + \mathbf{x}, \quad r = \frac{1}{2}\max_j (x_{\max,j} - x_{\min,j}) + \epsilon, \quad \mathbf{x} \leftarrow \frac{\mathbf{x} - \mathbf{c}}{r} $$}}{2

    • "centroid_extent": subtract the centroid then divide by the longest axis-aligned span (the convention used by the published RandLA-Net Toronto-3D / Semantic3D checkpoints):

    $$ \mathbf{x} \leftarrow \frac{\mathbf{x} - \boldsymbol{\mu}}{\max_j (x_{\max,j} - x_{\min,j}) + \epsilon} $$

    • "min_sphere": subtract the center of the minimal enclosing sphere of all points and divide by its radius plus \(\epsilon\) (see minimal_enclosing_ball; the OctFormer ModelNet40 normalization).

Returns:

  • Tensor –

    Normalized tensor, same shape as points.

Raises:

  • ValueError –

    If method is not "centroid", "bbox", "centroid_extent", or "min_sphere".

absolute [source] ΒΆ

absolute(x: Tensor, inplace: bool = False) -> Tensor

Make the input tensor absolute.

Parameters:

  • x (Tensor) –

    The input tensor.

Returns:

  • Tensor –

    The absolute tensor.

Examples:

>>> import torch
>>> import torch_pointcloud.transforms.functional as F
>>> x = torch.tensor([-1.0, 2.0, -3.0])
>>> F.absolute(x)
tensor([1., 2., 3.])

relabel [source] ΒΆ

relabel(
    labels: Tensor,
    mapping: Union[Sequence[int], Dict[int, int]],
    default: int = 0,
) -> Tensor

Remap integer labels via a lookup table.

mapping can be either:

  • a sequence of source values (1:1): each value at index \(i\) is mapped to \(i\);
  • a dict[int, int] (general source β†’ target): supports N-to-1 merges (e.g. SemanticKITTI's moving-car and car both β†’ 0).

Source values not listed in mapping are set to default.

Parameters:

  • labels (Tensor) –

    Integer label tensor (any integer dtype). Output preserves dtype.

  • mapping (Union[Sequence[int], Dict[int, int]]) –

    Source-value listing (1:1) or explicit {source: target} dict (N:1).

  • default (int, default: 0 ) –

    Value assigned to source values not listed in mapping.

Returns:

  • Tensor –

    Remapped tensor with the same shape and dtype as labels.

Raises:

  • ValueError –

    If mapping is empty.

divisible_pad [source] ΒΆ

divisible_pad(
    batch: Tensor,
    k: int,
    mode: PadMode = "all",
    pad_fill: PadFill = "cycle",
    return_inverse: Literal[False] = False,
    generator: Optional[Generator] = None,
) -> Tuple[Tensor, Tensor]
divisible_pad(
    batch: Tensor,
    k: int,
    mode: PadMode = "all",
    pad_fill: PadFill = "cycle",
    return_inverse: Literal[True] = ...,
    generator: Optional[Generator] = None,
) -> Tuple[Tensor, Tensor, Tensor]
divisible_pad(
    batch: Tensor,
    k: int,
    mode: PadMode = "all",
    pad_fill: PadFill = "cycle",
    return_inverse: bool = False,
    generator: Optional[Generator] = None,
) -> Union[
    Tuple[Tensor, Tensor], Tuple[Tensor, Tensor, Tensor]
]

Pad the batch indices of a tensor to make them divisible by a given integer.

Consider a batch with three samples of sizes 2, 7, and 4, and k=4:

batch:  [0 0 | 1 1 1 1 1 1 1 | 2 2 2 2]
size:     2          7            4

Mode controls which batches get padded (Β· = padded slot):

mode="all"    [0 0 Β· Β· | 1 1 1 1 1 1 1 Β· | 2 2 2 2]
                 2β†’4          7β†’8             4 (ok)

mode="below"  [0 0 Β· Β· | 1 1 1 1 1 1 1 | 2 2 2 2]
                 2β†’4  ↑        7 (β‰₯k)       4 (ok)
                only <k

mode="above"  [0 0 | 1 1 1 1 1 1 1 Β· | 2 2 2 2]
                2        7β†’8  ↑           4 (ok)
              (<k)      only β‰₯k

Pad fill controls how padded slots are filled. Given batch 1 with 7 elements (A B C D E F G) and k=4:

Original patches:  [A B C D] [E F G Β·]
                    patchβ‚€    patch₁ (incomplete)

pad_fill="cycle"      β†’ [A B C D] [E F G A]
  Cycles from the start                  ↑ wraps to A

pad_fill="replicate"  β†’ [A B C D] [E F G D]
  Copies from previous patch             ↑ same position as D
  at same offset

pad_fill="random"     β†’ [A B C D] [E F G ?]
  Random sample from the batch           ↑ uniform over {A..G}

When batch_size < k there is no previous patch, so "replicate" falls back to "cycle":

batch 0 (size 2, k=4):  [A B Β· Β·]
pad_fill="cycle"      β†’ [A B A B]
pad_fill="replicate"  β†’ [A B A B]   (same, no prior patch)
pad_fill="random"     β†’ [A B ? ?]

Parameters:

  • batch (Tensor) –

    The batch indices of the tensor. Rows of the same batch must be contiguous (grouped, as produced by packed-batch collation); the batch values themselves may be non-consecutive. Interleaved orderings (e.g. [0, 1, 0, 1]) are not supported and silently mix samples.

  • k (int) –

    The integer to make the batch indices divisible by.

  • mode (PadMode, default: 'all' ) –

    The mode to use for padding. - "below": Pad only batches with fewer than k elements. - "above": Pad only batches with k or more elements. - "all": Pad all batches to be divisible by k.

  • pad_fill (PadFill, default: 'cycle' ) –

    Strategy for filling padding slots. - "cycle": Cycle through original indices from the start of the batch (indices[0], indices[1], ...). - "replicate": Copy indices from the previous patch at the same relative offset. When the last group of k elements is incomplete, the missing positions are filled with the corresponding positions from the preceding full group. Falls back to "cycle" when there is no preceding group (i.e. the batch has fewer than k elements). - "random": Sample padded indices uniformly with replacement from within the batch's original indices. Consumes generator if given.

  • return_inverse (bool, default: False ) –

    Whether to return the inverse of the padded indices.

  • generator (Optional[Generator], default: None ) –

    Optional torch.Generator for reproducibility (used only by pad_fill="random").

Returns:

  • Union[Tuple[Tensor, Tensor], Tuple[Tensor, Tensor, Tensor]] –

    Returns a tuple of (indices, padded_batch).

  • Union[Tuple[Tensor, Tensor], Tuple[Tensor, Tensor, Tensor]] –

    If return_inverse is True, returns (indices, inverse_indices, padded_batch).