Skip to content

transforms

Dict-based transforms and their tensor-level functional equivalents.

Modules:

  • functional –

    Pure tensor functions backing the dict transforms: sampling, masking, normalization, padding, and rotation.

  • transforms –

    Dict transforms.

Classes:

  • Transform –

    Base class for all point cloud transforms.

  • Compose –

    Compose multiple transforms into a single transform.

  • DictTransform –

    Base class for dictionary transforms.

  • RandomSample –

    Randomly sample a fixed number of points from dict entries.

  • DivisiblePad –

    Pad per-point tensors so each batch is divisible by num_samples.

  • RandomSampleFaceVertices –

    Randomly sample a fixed number of vertices from a 3D mesh stored in a dictionary.

  • EstimateNormals –

    Estimate per-point surface normals from coordinates via local PCA.

  • FarthestPointSample –

    Farthest-point sampling (FPS) of a dictionary entry.

  • Rescale –

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

  • RemoveNearOrigin –

    Remove points that are within a given radius of the origin from dictionary entries.

  • Abs –

    Make dictionary tensor entries absolute.

  • BoxMask –

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

  • ApplyMask –

    Apply a mask stored in a dictionary to other dictionary entries.

  • SetValue –

    Set values for keys in the dictionary, creating or overwriting them.

  • Scale –

    Multiply dictionary tensor entries by a scale factor.

  • Divide –

    Divide dictionary tensor entries by a divisor.

  • ToFloat –

    Cast dictionary tensor entries to float32.

  • Normalize –

    Normalize dictionary tensor entries: \(x' = (x - \mu) / \max(\sigma, \epsilon)\).

  • Shift –

    Shift dictionary tensor entries by subtracting a computed offset.

  • AlignAxis –

    Shift dictionary tensor entries so that the minimum along a chosen axis is zero.

  • CubeMask –

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

  • SphereMask –

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

  • ToDevice –

    Convert dictionary tensor entries to the given device.

  • BuildOctree –

    Build an octree from positions stored in a dictionary.

  • HardVoxelize –

    Hard-voxelize a single scene into the per-voxel point stack consumed by voxel detectors.

  • OctreeFeatures –

    Extract per-node features from an octree via octree.get_input_feature.

  • Relabel –

    Remap integer labels in dictionary entries via a lookup table.

  • RelabelBoxes –

    Map raw box labels to a detection class set and flag don't-care boxes for the AP metric.

  • RenameItems –

    Rename keys in the dictionary.

  • CopyItems –

    Copy values from source keys to new destination keys.

  • SubtractKey –

    Subtract the value of a reference key from target keys element-wise.

  • BBoxCenter –

    Derive the center of an axis-aligned bbox stored as a flat tensor.

  • DivideKey –

    Divide target keys by the value of a reference key element-wise.

  • ToTensor –

    Convert dictionary entries to tensors.

  • Voxelize –

    Voxelize a point cloud by grid-binning and per-voxel reduction.

  • Quantize –

    Integer voxel-grid coordinates of every point, keeping the cloud at full resolution.

  • OnesLike –

    Adds a tensor of ones shaped like existing dictionary entries.

  • AxisMinOffset –

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

  • Cat –

    Concatenates tensors from multiple keys into a single feature tensor.

  • OneHot –

    One-hot encode integer-class tensors.

  • Reduce –

    Reduce a tensor along a dimension and store the scalar/vector result.

  • KeepItems –

    Keep only items in the data dictionary that are in the keys list.

  • RandomRotate –

    Rotate one or more keys (and optionally oriented boxes) by a uniformly random angle around an axis.

  • RandomScale –

    Scale one or more keys (and optionally oriented boxes) by a uniformly random factor.

  • RandomFlip –

    Flip listed axes (and optionally oriented boxes) with probability p each.

  • RandomJitter –

    Add Gaussian noise to listed keys, optionally clipped.

  • RandomShift –

    Translate listed keys (and optionally oriented boxes) by a uniformly random vector.

  • RandomDropout –

    Randomly drop a fraction of points across all listed keys.

  • RandomColorJitter –

    Jitter colors by brightness, contrast, and saturation strengths.

  • RandomColorDrop –

    Replace colors with a constant gray value with probability p.

  • RandomColorGrayScale –

    Convert listed color keys to grayscale (BT.601 luminance) with probability p.

  • RandomColorAutoContrast –

    Stretch per-cloud color range to the full extent, then blend back, with probability p.

  • SphereCrop –

    Keep only points inside an L2 sphere of given radius.

  • Slice –

    Slice each listed tensor along a chosen dimension via standard Python slicing.

  • ShufflePoint –

    Randomly permute the order of points across listed keys.

  • Clamp –

    Clamp tensor entries to a range (a thin wrapper over torch.clamp).

  • RandomRotateChoice –

    Rotate one or more keys by an angle chosen uniformly from a discrete list.

  • RandomColorShift –

    Additive per-channel color shift sampled uniformly per channel.

  • RandomElasticDistortion –

    Apply a smooth random displacement field (elastic distortion).

  • InstanceToBox –

    Axis-aligned bounding boxes from per-point instance ids (e.g. ScanNet detection targets).

  • GenerateVoteLabels –

    Generate per-point vote offsets and a vote mask from oriented GT boxes.

  • EncodeVoteNetTargets –

    Encode oriented GT boxes into the padded label tensors the VoteNet loss consumes.

  • Mix3D –

    Concatenate two scenes into one, offsetting the second scene's instance ids.

  • LaserMix –

    Mix two LiDAR scans by swapping alternating inclination (pitch) bands.

  • PolarMix –

    Mix two LiDAR scans by swapping an azimuth sector and rotate-pasting instance-class points.

Attributes:

  • ReduceOp –

    Allowed values for Reduce.op (per-key reduction operator).

  • VoxelMethod –

    Allowed values for Voxelize.method (voxel-id hashing scheme).

  • VoxelReduce –

    Allowed values for Voxelize.reduce (per-key per-voxel reduction).

  • VoxelPosReduce –

    Allowed values for Voxelize.pos_reduce (per-voxel reduction for positions; "grid" keeps integer voxel coords).

ReduceOp module-attribute

ReduceOp = Literal['min', 'max', 'mean', 'sum']

Allowed values for Reduce.op (per-key reduction operator).

VoxelMethod module-attribute

VoxelMethod = Literal['fnv', 'pyg']

Allowed values for Voxelize.method (voxel-id hashing scheme).

VoxelReduce module-attribute

VoxelReduce = Literal['mean', 'min', 'max', 'sum', 'first']

Allowed values for Voxelize.reduce (per-key per-voxel reduction).

VoxelPosReduce module-attribute

VoxelPosReduce = Literal[
    "mean", "min", "max", "sum", "first", "grid"
]

Allowed values for Voxelize.pos_reduce (per-voxel reduction for positions; "grid" keeps integer voxel coords).

Transform

Base class for all point cloud transforms.

A transform is a callable that takes an arbitrary data object and returns a transformed version of it.

While any callable can be used as a transform, this class provides a common interface and some convenience features, such as:

  • a torch_pointcloud.transforms.transforms.Transform.transform method, which implements the actual transformation logic. It will be called by the __call__ method to apply the transform.
  • a torch_pointcloud.transforms.transforms.Transform.extra_repr method, which returns a string that describes the transform. This will be used by the __repr__ method to represent the transform as a string.
Note

A transform should avoid modifying the input data in place. Instead, it should return a new object with the transformed data.

If the transform is in-place, it should be clearly stated in its documentation.

Warning

Transforms that accept a generator keep a reference to it. Under a multi-worker DataLoader, every worker receives an identical copy of that generator, so all workers replay the same "random" augmentations (and with persistent_workers=False, so does every epoch). Leave generator=None for multi-worker training: the global generator is seeded per worker by PyTorch (base_seed + worker_id), which stays random across workers and reproducible under torch.manual_seed. Reserve a stored generator for num_workers=0, or re-seed it per worker in a worker_init_fn:

def worker_init_fn(worker_id: int) -> None:
    info = torch.utils.data.get_worker_info()
    info.dataset.transform.generator = torch.Generator().manual_seed(info.seed)
See Also

torch_pointcloud.transforms.DictTransform for a version of this class that operates on dictionaries.

Example

For example, to create a transform that scales the points in a point cloud, we can subclass the torch_pointcloud.transforms.Transform class and implement the torch_pointcloud.transforms.Transform.transform method as follows:

from torch import Tensor

from torch_pointcloud.transforms import Transform

# 1. Subclass the Transform class
class MyScale(Transform):
    def __init__(self, factor: float = 1.0):
        self.factor = factor

    def extra_repr(self) -> str:
        return f"factor={self.factor}"

    def transform(self, tensor: Tensor) -> Tensor:
        return tensor * self.factor

# 2. Initialize the transform
transform = MyScale()
# 3. Apply the transform
tensor = torch.randn(4096, 3)
tensor = transform(tensor)

Methods:

  • transform –

    Apply the transform to the input data.

transform abstractmethod

transform(*args: Any, **kwargs: Any) -> Any

Apply the transform to the input data.

This method should be implemented by all subclasses, and do not have any constraints on the input data.

Compose

Compose(
    transforms: Sequence[Transform],
    allow_missing_keys: Optional[bool] = None,
)

Bases: Transform

Compose multiple transforms into a single transform.

This class allows for chaining multiple transforms together.

Note

The order of the transforms is important, as each transform will be applied in the order they are added to the Compose object.

Parameters:

  • transforms (Sequence[Transform]) –

    The transforms to apply, in order.

  • allow_missing_keys (Optional[bool], default: None ) –

    When set, assigned to every DictTransform child, recursively through nested Compose objects, overriding what each child was built with (assigning the attribute later does the same). Registered pipelines are shared objects, so setting it on one mutates its children for every user. None leaves the children as built.

Example

For example, to chain a random sample and a normalization transform, we can do the following:

from torch import Tensor

from torch_pointcloud.transforms import Compose, RandomSample, Rescale

# 1. Initialize the transforms
transform = Compose([
    RandomSample(keys="pos", num_samples=1024),
    Rescale(keys="pos"),
])

# 2. Apply the transform
data = {"pos": torch.randn(4096, 3)}
data = transform(data)

Methods:

  • transform –

    Apply the transforms to the input data.

transform

transform(data: Any) -> Any

Apply the transforms to the input data.

This method will apply each transform in the order they were added to the torch_pointcloud.transforms.Compose object.

DictTransform

DictTransform(
    keys: Optional[KeyCollection] = None,
    allow_missing_keys: bool = False,
)

Bases: Transform

Base class for dictionary transforms.

This class is used to define transforms that operate on a dictionary of data, and implements utility methods for key iteration and error handling.

Note

allow_missing_keys controls the iteration over self.keys performed by iter_keys. Auxiliary keys read by individual transforms (e.g. mask_key in ApplyMask, pos_key in RemoveNearOrigin / FarthestPointSample, face_key in RandomSampleFaceVertices) document their own missing-key behavior in their respective docstrings.

Parameters:

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

    The keys to apply the transform to.

  • allow_missing_keys (bool, default: False ) –

    If True, the transform will not raise an error if keys listed in self.keys are missing from the input dict.

Methods:

  • transform –

    Apply the transform to the dictionary data.

  • iter_keys –

    Iterate over self.keys present in the data, honoring allow_missing_keys.

transform abstractmethod

transform(data: Dict[str, Any]) -> Dict[str, Any]

Apply the transform to the dictionary data.

Parameters:

  • data (Dict[str, Any]) –

    The dictionary data to apply the transform to.

Returns:

  • Dict[str, Any] –

    The transformed dictionary data.

iter_keys

iter_keys(
    data: Dict[str, Any],
    *extra_iterables: Iterable[Any],
    extra_msg: str = "",
) -> Generator[Any, None, None]

Iterate over self.keys present in the data, honoring allow_missing_keys.

Parameters:

  • data (Dict[str, Any]) –

    The dictionary data the transform is applied to.

  • *extra_iterables (Iterable[Any], default: () ) –

    Per-key values (e.g. one output key per input key) zipped with self.keys.

  • extra_msg (str, default: '' ) –

    Message appended to the KeyError raised on a missing key.

Returns:

  • None –

    A generator yielding each present key, or a tuple of the key and its values from

  • None –

    extra_iterables when any is given.

RandomSample

RandomSample(
    keys: KeyCollection,
    num_samples: int,
    replace: bool = False,
    generator: Optional[Generator] = None,
    dst_index_key: Optional[str] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Randomly sample a fixed number of points from dict entries.

If multiple keys are provided, the same indices are used for all keys, ensuring correspondence between the sampled values.

RandomSample on an object

RandomSample on a room

See Also

torch_pointcloud.transforms.functional.random_sample

Parameters:

  • keys (KeyCollection) –

    The keys to sample from.

  • num_samples (int) –

    The number of values to sample.

  • replace (bool, default: False ) –

    If True, sample with replacement (duplicates allowed). If False (default), sample without replacement when the first sampled key has at least num_samples points; when num_samples exceeds that count 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.

  • dst_index_key (Optional[str], default: None ) –

    Key for the output-to-input row map (see the module docs on sampling keys); None (the default) disables it.

  • allow_missing_keys (bool, default: False ) –

    If True, the transform will not raise an error if the keys are not present in the data.

Raises:

  • ValueError –

    If the first sampled tensor is empty and num_samples > 0.

DivisiblePad

DivisiblePad(
    num_samples: int,
    pad_fill: PadFill = "cycle",
    ref_key: str = POS,
    batch_key: str = BATCH,
    generator: Optional[Generator] = None,
    dst_inverse_key: Optional[str] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Pad per-point tensors so each batch is divisible by num_samples.

Thin dict wrapper around divisible_pad; see its docstring for the full behavior of each pad_fill strategy ("cycle", "replicate", "random"). The tensor at ref_key defines the packed count \(n\) and the device. If a batch index tensor lives at batch_key, padding is done per-batch; otherwise a single zero batch is synthesized. Every tensor in the dict whose first dim equals \(n\) (positions, features, labels, ...) is re-indexed by the same gather map, so per-point correspondence is preserved.

When dst_inverse_key is set, the transform also records a source-to-padded index map under that dict key: a 1-D long tensor of length \(n\) with values in \([0, n_\text{padded})\) giving the canonical padded row for each source row. If the key already holds a prior inverse map (from an earlier invertible transform), the new map composes with it via gather, so the stored tensor always maps from the outermost source space to the current predictor space. Consumers such as SlidingWindowInferer read this key once and gather predictions back to the source rows.

DivisiblePad on an object

DivisiblePad on a room

Parameters:

  • num_samples (int) –

    Target chunk size \(k\) for divisibility.

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

    Fill strategy passed through to divisible_pad.

  • ref_key (str, default: POS ) –

    Key whose tensor defines \(n\) and the device.

  • batch_key (str, default: BATCH ) –

    Key for an optional batch index tensor. When present in the data, padding runs per-batch; otherwise a single zero batch is synthesized for the whole scene.

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

    Optional torch.Generator. Only consumed when pad_fill="random". See Transform for the multi-worker caveat.

  • dst_inverse_key (Optional[str], default: None ) –

    Key for the source-to-padded row map (see the module docs on sampling keys); composes with any prior value at the same key. None (the default) disables it.

  • allow_missing_keys (bool, default: False ) –

    If True, return the data unchanged when ref_key is missing instead of raising.

Example
from torch_pointcloud.transforms import DivisiblePad

# Pad a 5000-point block to 8192 (= 2 * 4096) before sliding-window
# sub-chunking. Random fill duplicates points uniformly at random.
transform = DivisiblePad(num_samples=4096, pad_fill="random")

RandomSampleFaceVertices

RandomSampleFaceVertices(
    *,
    keys: KeyCollection,
    face_key: KeyCollection,
    normal_key: Optional[KeyCollection] = "normal",
    num_samples: int,
    generator: Optional[Generator] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Randomly sample a fixed number of vertices from a 3D mesh stored in a dictionary.

RandomSampleFaceVertices before / after

See Also

torch_pointcloud.transforms.functional.random_sample_face_vertices

Parameters:

  • keys (KeyCollection) –

    The keys holding vertex positions.

  • face_key (KeyCollection) –

    The keys holding the face indices.

  • normal_key (Optional[KeyCollection], default: 'normal' ) –

    The key to store the computed normals in.

  • num_samples (int) –

    The number of vertices to sample.

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

    The generator for the random number generator.

  • allow_missing_keys (bool, default: False ) –

    If True, the transform will not raise an error if the keys are not present in the data.

EstimateNormals

EstimateNormals(
    keys: KeyCollection,
    normal_key: KeyCollection = "normal",
    k: int = 16,
    orient_to_centroid: bool = False,
    batch_key: Optional[str] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Estimate per-point surface normals from coordinates via local PCA.

Computes unit normals (see torch_pointcloud.transforms.functional.estimate_normals) for clouds that ship without them (e.g. S3DIS). Each normal is the least-variance direction of a point's \(k\) nearest neighbors. With orient_to_centroid, normals are flipped to face the cloud centroid.

See Also

torch_pointcloud.transforms.functional.estimate_normals

EstimateNormals on an object

EstimateNormals on a room

Parameters:

  • keys (KeyCollection) –

    Coordinate keys to estimate normals from.

  • normal_key (KeyCollection, default: 'normal' ) –

    Keys under which to store the normals (one per coordinate key). Defaults to normal.

  • k (int, default: 16 ) –

    Number of nearest neighbors (the point itself included) per local PCA.

  • orient_to_centroid (bool, default: False ) –

    If True, flip each normal to point towards its cloud's centroid (approximates the inward-facing normals of meshes scanned from inside a room).

  • batch_key (Optional[str], default: None ) –

    Optional key holding a per-point batch index so neighbors stay within a cloud.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

FarthestPointSample

FarthestPointSample(
    pos_key: str,
    keys: Optional[KeyCollection] = None,
    num_samples: Optional[int] = None,
    ratio: Optional[float] = None,
    random_start: bool = False,
    dst_index_key: Optional[str] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Farthest-point sampling (FPS) of a dictionary entry.

Iteratively picks the point that maximizes the minimum distance to the already-selected set, producing a well-distributed subset. Matches the FPS convention used by PointNet++, PointNeXt, KPConv, and others.

FarthestPointSample on an object

FarthestPointSample on a room

See Also

torch_pointcloud.transforms.functional.farthest_point_sample

Note

The underlying fps does not accept a torch.Generator. To make random_start=True reproducible, seed PyTorch globally via torch.manual_seed(...) before applying this transform.

Parameters:

  • pos_key (str) –

    The key holding the positions used for FPS.

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

    Extra keys to subsample with the same indices.

  • 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.

  • dst_index_key (Optional[str], default: None ) –

    Key for the output-to-input row map (see the module docs on sampling keys); None (the default) disables it.

  • allow_missing_keys (bool, default: False ) –

    If True, the transform will not raise an error if the keys are not present in the data.

Rescale

Rescale(
    keys: KeyCollection,
    eps: float = 1e-06,
    method: RescaleMethod = "centroid",
    allow_missing_keys: bool = False,
)

Bases: DictTransform

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

Bundles a centering step and a divide-by-extent step that depend on the same statistics. Four methods, each pairing a center and a denominator:

method Center on Divide by
"centroid" centroid (mean) max Euclidean distance to center
"bbox" bbox midpoint half of the longest axis extent
"centroid_extent" centroid (mean) longest axis extent
"min_sphere" min-sphere center min-sphere radius

Empty inputs (N=0) are returned unchanged.

Rescale method=centroid on an object

Rescale method=bbox on an object

Rescale method=centroid_extent on an object

See Also

torch_pointcloud.transforms.functional.rescale

Parameters:

  • keys (KeyCollection) –

    The keys to rescale.

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

    Small constant added to the denominator for numerical stability.

  • method (RescaleMethod, default: 'centroid' ) –

    "centroid", "bbox", "centroid_extent", or "min_sphere".

  • allow_missing_keys (bool, default: False ) –

    If True, the transform will not raise an error if the keys are not present in the data.

RemoveNearOrigin

RemoveNearOrigin(
    pos_key: str,
    keys: Optional[KeyCollection] = None,
    radius: float = 0.001,
    dst_index_key: Optional[str] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Remove points that are within a given radius of the origin from dictionary entries.

RemoveNearOrigin on an object

RemoveNearOrigin on a room

See Also

torch_pointcloud.transforms.functional.remove_near_origin

Parameters:

  • pos_key (str) –

    The key containing the positions / coordinates, used to compute the distance from the origin.

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

    Extra keys to filter with the same mask.

  • radius (float, default: 0.001 ) –

    The radius of the sphere.

  • dst_index_key (Optional[str], default: None ) –

    Key for the output-to-input row map (see the module docs on sampling keys); None (the default) disables it.

  • allow_missing_keys (bool, default: False ) –

    If True, the transform will not raise an error if the keys are not present in the data.

Abs

Abs(
    keys: KeyCollection,
    inplace: bool = False,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Make dictionary tensor entries absolute.

See Also

torch_pointcloud.transforms.functional.abs

Abs on an object

Abs on a room

Parameters:

  • keys (KeyCollection) –

    The keys to make absolute.

  • inplace (bool, default: False ) –

    Whether to perform the operation in place.

  • allow_missing_keys (bool, default: False ) –

    If True, the transform will not raise an error if the keys are not present in the data.

BoxMask

BoxMask(
    keys: KeyCollection,
    bbox: tuple[float, ...],
    dst_keys: Optional[KeyCollection] = None,
    dim: int = -1,
    strict: bool = False,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

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 \]

where bbox = (*bbmin, *bbmax) is the AABB. With strict=True the inequalities are strict, so boundary points are excluded.

Sibling masks:

  • CubeMask - L∞ ball (center + radius)
  • SphereMask - L2 ball (center + radius)

BoxMask on an object

BoxMask on a room

See Also

torch_pointcloud.transforms.functional.box_mask

Parameters:

  • keys (KeyCollection) –

    The keys to create the mask for.

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

    The bounding box used to mask input tensors, as (*bbmin, *bbmax).

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

    The keys to store the mask in.

  • dim (int, default: -1 ) –

    The dimension to create the mask over.

  • strict (bool, default: False ) –

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

  • allow_missing_keys (bool, default: False ) –

    If True, the transform will not raise an error if the keys are not present in the data.

ApplyMask

ApplyMask(
    keys: KeyCollection,
    mask_key: str,
    dst_keys: Optional[KeyCollection] = None,
    dst_index_key: Optional[str] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Apply a mask stored in a dictionary to other dictionary entries.

See Also

torch_pointcloud.transforms.functional.apply_mask

ApplyMask on an object

ApplyMask on a room

Parameters:

  • keys (KeyCollection) –

    The keys to apply the mask to.

  • mask_key (str) –

    The key containing the mask.

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

    The keys to store the transformed data in.

  • dst_index_key (Optional[str], default: None ) –

    Key for the output-to-input row map (see the module docs on sampling keys); None (the default) disables it. Leave it unset when dst_keys differ from keys, since the map would describe the dst_keys rows.

  • allow_missing_keys (bool, default: False ) –

    If True, the transform will not raise an error if the keys are not present in the data.

SetValue

SetValue(keys: KeyCollection, values: Any)

Bases: DictTransform

Set values for keys in the dictionary, creating or overwriting them.

Unlike most DictTransform subclasses, SetValue does not read existing values, so allow_missing_keys has no meaning and is not accepted.

SetValue diagram

Parameters:

  • keys (KeyCollection) –

    The keys to set.

  • values (Any) –

    The values to set. Either a single value broadcast to every key, or a sequence of values the same length as keys.

Scale

Scale(
    keys: KeyCollection,
    scale: float | Sequence[float],
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Multiply dictionary tensor entries by a scale factor.

Scale on an object

Scale on a room

Parameters:

  • keys (KeyCollection) –

    The keys to scale.

  • scale (float | Sequence[float]) –

    The scale factor(s).

  • allow_missing_keys (bool, default: False ) –

    If True, the transform will not raise an error if the keys are not present in the data.

Divide

Divide(
    keys: KeyCollection,
    divisor: float | Sequence[float],
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Divide dictionary tensor entries by a divisor.

Divide on an object

Divide on a room

Parameters:

  • keys (KeyCollection) –

    The keys to divide.

  • divisor (float | Sequence[float]) –

    The divisor(s).

  • allow_missing_keys (bool, default: False ) –

    If True, the transform will not raise an error if the keys are not present in the data.

ToFloat

ToFloat(
    keys: KeyCollection, allow_missing_keys: bool = False
)

Bases: DictTransform

Cast dictionary tensor entries to float32.

Useful when tensors are stored in integer formats (e.g. uint8 for colors) and need to be promoted to floating point before arithmetic transforms like Divide or Normalize.

ToFloat diagram

Parameters:

  • keys (KeyCollection) –

    The keys to cast.

  • allow_missing_keys (bool, default: False ) –

    If True, missing keys are silently ignored.

Normalize

Normalize(
    keys: KeyCollection,
    mean: Sequence[float],
    std: Sequence[float],
    eps: float = 1e-07,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Normalize dictionary tensor entries: \(x' = (x - \mu) / \max(\sigma, \epsilon)\).

Normalize before / after

Parameters:

  • keys (KeyCollection) –

    The keys to standardize.

  • mean (Sequence[float]) –

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

  • std (Sequence[float]) –

    Per-channel standard deviation(s).

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

    Lower bound on \(\sigma\) to prevent division by zero. Defaults to \(10^{-7}\).

  • allow_missing_keys (bool, default: False ) –

    If True, missing keys are silently ignored.

Shift

Shift(
    keys: KeyCollection,
    method: ValueCollection[ShiftMethod],
    dim: int = 0,
    axes: Optional[Sequence[int]] = None,
    dst_keys: Optional[KeyCollection] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Shift dictionary tensor entries by subtracting a computed offset.

Each key is offset independently. The offset is determined by method:

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

On empty inputs (size \(0\) along dim) the tensor is returned unchanged.

Shift method=centroid on an object

Shift method=bbox on an object

Shift method=min on an object

Shift restricted to a subset of axes, on an object

Parameters:

  • keys (KeyCollection) –

    The keys to shift.

  • method (ValueCollection[ShiftMethod]) –

    "bbox" (midrange), "centroid" (mean), or "min" (shift to origin).

  • dim (int, default: 0 ) –

    The dimension to reduce over.

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

    Which axes (last-dim indices) to shift. None (default) shifts every axis; pass e.g. axes=[0, 1] to recenter only XY. Axes outside this list are left unchanged - this is the composable knob for mixed-method shifts.

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

    The keys to store the shifted data in.

  • allow_missing_keys (bool, default: False ) –

    If True, skip missing keys silently.

Example

XY shifted by the bbox midpoint, Z shifted by its minimum (equivalent to the old CenterShift(apply_z=True)):

from torch_pointcloud.transforms import Compose, Shift

center_shift = Compose([
    Shift(keys="pos", method="bbox", axes=[0, 1]),  # XY: bbox midrange
    Shift(keys="pos", method="min",  axes=[2]),     # Z:  min
])

Without the Z step (equivalent to the old CenterShift(apply_z=False)), a single Shift suffices:

Shift(keys="pos", method="bbox", axes=[0, 1])

AlignAxis

AlignAxis(
    keys: KeyCollection,
    dim: int = -1,
    inplace: bool = False,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Shift dictionary tensor entries so that the minimum along a chosen axis is zero.

Empty inputs (N=0) are returned unchanged.

AlignAxis on an object

AlignAxis on a room

Parameters:

  • keys (KeyCollection) –

    The keys to align.

  • dim (int, default: -1 ) –

    The coordinate axis to align.

  • inplace (bool, default: False ) –

    Whether to modify the tensor in place. Non-contiguous inputs are materialized to contiguous via .contiguous() before the in-place op, so the caller's original tensor may not be mutated in that case.

  • allow_missing_keys (bool, default: False ) –

    If True, the transform will not raise an error if the keys are not present in the data.

CubeMask

CubeMask(
    keys: KeyCollection,
    center: ValueCollection[float],
    radius: float,
    dim: int = -1,
    dst_keys: Optional[KeyCollection] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

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 SphereMask (L2) and BoxMask (AABB) for the mask family.

CubeMask on an object

CubeMask on a room

See Also

torch_pointcloud.transforms.functional.cube_mask

Parameters:

  • keys (KeyCollection) –

    The keys to create the mask for.

  • center (ValueCollection[float]) –

    The center of the cube.

  • radius (float) –

    The radius (half-edge) of the cube.

  • dim (int, default: -1 ) –

    The dimension to create the mask over.

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

    The keys to store the mask in.

  • allow_missing_keys (bool, default: False ) –

    If True, the transform will not raise an error if the keys are not present in the data.

SphereMask

SphereMask(
    keys: KeyCollection,
    center: ValueCollection[float],
    radius: float,
    dim: int = -1,
    dst_keys: Optional[KeyCollection] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

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

Membership condition along dim:

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

Pair with CubeMask (L∞) and BoxMask (AABB) for the mask family. RemoveNearOrigin(radius=r) is equivalent to Compose([SphereMask(center=(0,0,0), radius=r, invert=True), ApplyMask(...)]).

SphereMask on an object

SphereMask on a room

See Also

torch_pointcloud.transforms.functional.sphere_mask

Parameters:

  • keys (KeyCollection) –

    The keys to create the mask for.

  • center (ValueCollection[float]) –

    The center of the sphere.

  • radius (float) –

    The radius of the sphere.

  • dim (int, default: -1 ) –

    The dimension to compute the Euclidean norm over.

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

    The keys to store the mask in.

  • allow_missing_keys (bool, default: False ) –

    If True, the transform will not raise an error if the keys are not present in the data.

ToDevice

ToDevice(
    keys: KeyCollection,
    device: ValueCollection[str | device],
    non_blocking: ValueCollection[bool] = False,
    copy: ValueCollection[bool] = True,
    memory_format: ValueCollection[
        memory_format | None
    ] = None,
    dst_keys: Optional[KeyCollection] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Convert dictionary tensor entries to the given device.

ToDevice diagram

Parameters:

  • keys (KeyCollection) –

    The keys to convert the tensors to the given device.

  • device (ValueCollection[str | device]) –

    The device to convert the tensors to.

  • non_blocking (ValueCollection[bool], default: False ) –

    If True, the transfer will be done asynchronously.

  • copy (ValueCollection[bool], default: True ) –

    If True, the tensor will be copied to the new device.

  • memory_format (ValueCollection[memory_format | None], default: None ) –

    The memory format to use for the tensor.

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

    The keys to store the converted tensors in.

  • allow_missing_keys (bool, default: False ) –

    If True, the transform will not raise an error if the keys are not present in the data.

BuildOctree

BuildOctree(
    *,
    pos_key: str,
    octree_key: str,
    depth: int,
    full_depth: int = 2,
    batch_size: int = 1,
    normal_key: str | None = None,
    feature_key: str | None = None,
    label_key: str | None = None,
    batch_key: str | None = None,
    points_key: str | None = None,
)

Bases: DictTransform

Build an octree from positions stored in a dictionary.

BuildOctree on an object

BuildOctree on a room

Parameters:

  • pos_key (str) –

    Key holding the point positions.

  • octree_key (str) –

    Key under which the octree is stored.

  • depth (int) –

    Octree depth.

  • full_depth (int, default: 2 ) –

    Full depth of the octree.

  • batch_size (int, default: 1 ) –

    Batch size.

  • normal_key (str | None, default: None ) –

    Key holding surface normals.

  • feature_key (str | None, default: None ) –

    Key holding point features.

  • label_key (str | None, default: None ) –

    Key holding per-point labels.

  • batch_key (str | None, default: None ) –

    Key holding batch indices.

  • points_key (str | None, default: None ) –

    Key under which the octree points are stored.

HardVoxelize

HardVoxelize(
    pos_key: str,
    voxel_size: Sequence[float],
    point_cloud_range: Sequence[float],
    max_num_points: int,
    max_num_voxels: int,
    feat_key: Optional[str] = None,
    voxel_key: str = VOXEL,
    pos_voxel_key: str = POS_VOXEL,
    num_points_key: str = VOXEL_NUM_POINTS,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Hard-voxelize a single scene into the per-voxel point stack consumed by voxel detectors.

Moves the transform_points_to_voxels step of voxel detectors (PointPillars, SECOND) out of the model and into the data pipeline, mirroring how BuildOctree produces an octree for OctFormer. The model then receives already-voxelized input and focuses on the network math.

Reads pos_key (and optionally feat_key), runs hard_voxelize on the single sample (the batch index is all zeros), and adds three keys while keeping pos / x:

  • voxel_key: the per-voxel point stack.
  • pos_voxel_key: integer voxel grid indices \((z, y, x)\) (the single-sample batch column is dropped; the per-voxel scene index is synthesized at collation).
  • num_points_key: the per-voxel point counts.

HardVoxelize on an object

HardVoxelize on a room

Parameters:

  • pos_key (str) –

    Key holding the point positions \((N, 3)\).

  • voxel_size (Sequence[float]) –

    Voxel size \((v_x, v_y, v_z)\).

  • point_cloud_range (Sequence[float]) –

    Range \((x_\min, y_\min, z_\min, x_\max, y_\max, z_\max)\).

  • max_num_points (int) –

    Maximum number of points kept per voxel.

  • max_num_voxels (int) –

    Maximum number of voxels kept per scene.

  • feat_key (Optional[str], default: None ) –

    Optional key holding extra point features \((N, C)\) concatenated after \(xyz\).

  • voxel_key (str, default: VOXEL ) –

    Output key for the per-voxel point stack.

  • pos_voxel_key (str, default: POS_VOXEL ) –

    Output key for the integer voxel grid indices.

  • num_points_key (str, default: VOXEL_NUM_POINTS ) –

    Output key for the per-voxel point counts.

  • allow_missing_keys (bool, default: False ) –

    Unused (pos_key is always required); kept for interface parity.

Shape
  • voxel_key: \((V, \text{max\_num\_points}, 3 + C)\).
  • pos_voxel_key: \((V, 3)\) with columns \((z, y, x)\).
  • num_points_key: \((V,)\).
Example
import torch
import torch_pointcloud.transforms as T

data = {"pos": torch.rand(1000, 3) * 50.0, "x": torch.rand(1000, 1)}
transform = T.HardVoxelize(
    pos_key="pos",
    feat_key="x",
    voxel_size=(0.16, 0.16, 4.0),
    point_cloud_range=(0.0, -39.68, -3.0, 69.12, 39.68, 1.0),
    max_num_points=32,
    max_num_voxels=40000,
)
data = transform(data)
print(data["voxel"].shape, data["pos_voxel"].shape, data["voxel_num_points"].shape)

OctreeFeatures

OctreeFeatures(
    keys: KeyCollection,
    features_type: str,
    nempty: bool = False,
    dst_keys: Optional[KeyCollection] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Extract per-node features from an octree via octree.get_input_feature.

OctreeFeatures on an object

OctreeFeatures on a room

Parameters:

  • keys (KeyCollection) –

    Keys holding Octree instances to extract features from.

  • features_type (str) –

    Feature spec passed to octree.get_input_feature (e.g. "ND" for normals + depth, "NDFP" for normals + depth + features + position).

  • nempty (bool, default: False ) –

    If True, return features only for non-empty nodes; otherwise include empty-node padding.

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

    Where to store the extracted feature tensors. Defaults to keys.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

Relabel

Relabel(
    keys: KeyCollection,
    labels: Sequence[int] | Dict[int, int],
    default: int = 0,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Remap integer labels in dictionary entries via a lookup table.

labels 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 labels are set to default.

Relabel before / after

Parameters:

  • keys (KeyCollection) –

    Keys holding label tensors to remap.

  • labels (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 labels.

  • allow_missing_keys (bool, default: False ) –

    If True, skip missing keys instead of raising.

Example
# 1:1 - keep raw NYU40 ids 1, 2, 3, 4, 5 and remap them to 0..4
T.Relabel(keys="segment", labels=[1, 2, 3, 4, 5])

# N:1 - SemanticKITTI 19-class benchmark (merges moving-* into static)
T.Relabel(
    keys="segment",
    labels={
        10: 0, 252: 0,    # car        (+ moving-car)
        11: 1,             # bicycle
        15: 2,             # motorcycle
        18: 3, 258: 3,    # truck      (+ moving-truck)
        # ...
    },
    default=255,
)

RelabelBoxes

RelabelBoxes(
    keys: KeyCollection,
    mapping: Dict[int, int],
    *,
    label_key: str = LABEL,
    ignore_mapping: Optional[Dict[int, int]] = None,
    ignore_fields: Optional[
        Dict[str, Tuple[Optional[float], Optional[float]]]
    ] = None,
    ignore_mask_key: str = "ignore_mask",
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Map raw box labels to a detection class set and flag don't-care boxes for the AP metric.

A detection dataset (e.g. KITTI) returns the raw annotated boxes: every labeled class plus per-box attributes such as occlusion / truncation. This transform turns those into the inputs the 3D AP metric expects, the way Relabel turns raw segmentation ids into a benchmark label set:

  • boxes whose raw label is a key of mapping are kept as ground truth, relabeled to mapping[raw];
  • boxes whose raw label is a key of ignore_mapping (neighboring classes, e.g. KITTI Van for Car) are kept as ignore regions (ignore_mask = True), labeled ignore_mapping[raw]: the evaluated class they excuse. They suppress false positives of that class but are not scored;
  • a kept foreground box that falls outside any range in ignore_fields (e.g. KITTI's moderate rule: occlusion \(\le 1\), truncation \(\le 0.3\), 2D height \(\ge 25\) px) is downgraded to an ignore region attributed to its mapped class;
  • every other box is dropped.

All keys in keys (the box tensor and every per-box attribute, including those named in ignore_fields) are filtered together by the keep mask so they stay row-aligned. The output adds the boolean ignore_mask_key consumed by average_precision3d / mean_average_precision3d, which excuse an unmatched prediction only on ignore boxes labeled with the evaluated class.

RelabelBoxes before / after

Parameters:

  • keys (KeyCollection) –

    Per-box tensors to filter together (e.g. DataKeys.BOX, DataKeys.LABEL, DataKeys.TRUNCATION, DataKeys.OCCLUSION). Must include label_key and every key referenced by ignore_fields.

  • mapping (Dict[int, int]) –

    Raw-label to detection-label dict; raw labels absent from it (and from ignore_mapping) are dropped.

  • label_key (str, default: LABEL ) –

    Key holding the raw integer labels (must be one of keys).

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

    Raw labels kept as ignore regions rather than scored ground truth, mapped to the detection class they excuse (e.g. KITTI Van to the Car class index).

  • ignore_fields (Optional[Dict[str, Tuple[Optional[float], Optional[float]]]], default: None ) –

    Per-attribute inclusive ranges {key: (low, high)} (use None for an open side); a foreground box outside any range becomes an ignore region.

  • ignore_mask_key (str, default: 'ignore_mask' ) –

    Output key for the written boolean ignore mask.

  • allow_missing_keys (bool, default: False ) –

    If True, skip missing keys instead of raising.

Example
import torch_pointcloud.transforms as T

# KITTI: raw 8-class boxes -> 3 detection classes, Van / Person_sitting as ignore regions
# for Car / Pedestrian, moderate difficulty (occlusion <= 1, truncation <= 0.3,
# height >= 25 px) as ignore.
T.RelabelBoxes(
    keys=("box", "label", "truncation", "occlusion", "bbox_height"),
    mapping={0: 0, 3: 1, 5: 2},
    ignore_mapping={1: 0, 4: 1},
    ignore_fields={
        "occlusion": (None, 1),
        "truncation": (None, 0.3),
        "bbox_height": (25, None),
    },
)

RenameItems

RenameItems(
    keys: KeyCollection,
    names: KeyCollection,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Rename keys in the dictionary.

RenameItems diagram

Parameters:

  • keys (KeyCollection) –

    Source keys to rename.

  • names (KeyCollection) –

    New key names (same length as keys).

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent source keys.

CopyItems

CopyItems(
    keys: KeyCollection,
    names: KeyCollection,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Copy values from source keys to new destination keys.

CopyItems diagram

Parameters:

  • keys (KeyCollection) –

    Source keys to copy from.

  • names (KeyCollection) –

    Destination keys to copy to (same length as keys).

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent source keys.

SubtractKey

SubtractKey(
    keys: KeyCollection,
    sub_keys: KeyCollection,
    dst_keys: Optional[KeyCollection] = None,
    axes: Optional[Sequence[int]] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Subtract the value of a reference key from target keys element-wise.

Computes data[key] = data[key] - data[sub_key] for each key. With axes set, only the listed last-dim indices are subtracted; the other components pass through unchanged (useful to shift only XY while keeping Z absolute).

SubtractKey on an object

SubtractKey on a room

Parameters:

  • keys (KeyCollection) –

    Keys whose tensors are modified (subtracted from).

  • sub_keys (KeyCollection) –

    Keys whose values are subtracted from each target key.

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

    Where to store results. Defaults to keys.

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

    Optional indices into the last dim restricting which components are subtracted. None (default) subtracts every component.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent target keys.

BBoxCenter

BBoxCenter(
    keys: KeyCollection,
    dst_keys: Optional[KeyCollection] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Derive the center of an axis-aligned bbox stored as a flat tensor.

Reads a bbox at each source key, laid out as a \((2D,)\) vector \([\,\min_0, \ldots, \min_{D-1},\, \max_0, \ldots, \max_{D-1}\,]\), and writes the per-axis midpoint \((\min + \max) / 2\) (shape \((D,)\)) at the matching destination key.

BBoxCenter on an object

BBoxCenter on a room

Parameters:

  • keys (KeyCollection) –

    Source keys holding flat bbox tensors of shape \((2D,)\).

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

    Destination keys for the centers. Defaults to overwriting the source keys.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent source keys.

Example
from torch_pointcloud.transforms import BBoxCenter

data = {"block_bbox": torch.tensor([0.0, 0.0, 0.0, 1.5, 1.5, 2.8])}
BBoxCenter(keys="block_bbox", dst_keys="block_center")(data)
# data["block_center"] == tensor([0.75, 0.75, 1.40])

DivideKey

DivideKey(
    keys: KeyCollection,
    div_keys: KeyCollection,
    dst_keys: Optional[KeyCollection] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Divide target keys by the value of a reference key element-wise.

Computes data[key] = data[key] / data[div_key] for each key.

DivideKey diagram

Parameters:

  • keys (KeyCollection) –

    Keys whose tensors are divided.

  • div_keys (KeyCollection) –

    Keys whose values are used as the divisors.

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

    Where to store results. Defaults to keys.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent target keys.

ToTensor

ToTensor(
    keys: KeyCollection,
    dtype: ValueCollection[str | dtype] | None = None,
    device: ValueCollection[str | device] | None = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Convert dictionary entries to tensors.

ToTensor diagram

Parameters:

  • keys (KeyCollection) –

    The keys to convert.

  • dtype (ValueCollection[str | dtype] | None, default: None ) –

    Target dtype(s).

  • device (ValueCollection[str | device] | None, default: None ) –

    Target device(s).

  • allow_missing_keys (bool, default: False ) –

    If True, the transform will not raise an error if the keys are not present in the data.

Voxelize

Voxelize(
    pos_key: str,
    pos_reduce: VoxelPosReduce,
    size: float,
    method: VoxelMethod = "pyg",
    reduce: Optional[ValueCollection[VoxelReduce]] = None,
    keys: Optional[KeyCollection] = None,
    dst_inverse_key: Optional[str] = None,
    dst_pos_grid_key: Optional[str] = None,
    random_sample: bool = False,
    generator: Optional[Generator] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Voxelize a point cloud by grid-binning and per-voxel reduction.

Sub-samples a point cloud to one representative point per occupied voxel, and optionally records a source-to-voxel index map for full-resolution back-projection.

Operates on a single sample (pre-collate). With dst_inverse_key set, the stored tensor has shape \((N_\text{full},)\) with values in \([0, N_\text{voxel})\): for each original point \(i\), the voxel it belongs to. Downstream code can recover full-resolution predictions with preds_full = preds_voxel[inverse].

If the key already holds a prior inverse map (e.g. from an earlier invertible transform), the new map composes with it via gather, so the stored tensor always maps from the outermost source space to the current predictor space.

Voxelize on an object

Voxelize on a room

Parameters:

  • pos_key (str) –

    Key holding the positions to sub-sample.

  • pos_reduce (VoxelPosReduce) –

    How to reduce positions per voxel (mean/min/max/sum/first/grid).

  • size (float) –

    Voxel edge length in the same units as the positions. Must be positive.

  • method (VoxelMethod, default: 'pyg' ) –

    Voxel-id hashing scheme (fnv matches FNV-1a-based reference pipelines; pyg is the default).

  • reduce (Optional[ValueCollection[VoxelReduce]], default: None ) –

    Per-key reduction for keys. None (the default) resolves per key to mean for floating-point tensors and first for integer tensors (e.g. segment). Integer keys keep their dtype: non-first reductions compute in float and cast back. The first representative is the first point of each voxel in input order, deterministic across devices (unless random_sample=True).

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

    Additional per-point keys to sub-sample (e.g. color, segment).

  • dst_inverse_key (Optional[str], default: None ) –

    Key for the source-to-voxel row map (see the module docs on sampling keys); composes with any prior value at the same key. None (the default) disables it.

  • dst_pos_grid_key (Optional[str], default: None ) –

    When set, also store the integer voxel-grid coordinates under this key. Useful when a model needs both real-valued positions (e.g. for rotary position embedding) and integer grid coordinates (for serialization / sparse-conv stems); with pos_reduce="grid" it holds the same grid as pos_key.

  • random_sample (bool, default: False ) –

    If True, the per-voxel representative used by reduce="first" (and the pos/grid_pos derivations) is chosen randomly within each voxel on every call. Per-voxel random sampling is a meaningful training augmentation; leave False (default) for deterministic validation.

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

    Optional torch.Generator for random_sample reproducibility. See Transform for the multi-worker caveat.

  • allow_missing_keys (bool, default: False ) –

    If True, return the data unchanged when pos_key is missing and skip absent keys.

Raises:

  • ValueError –

    If size is not positive, or pos_reduce / method / any reduce entry is not one of its allowed values.

Quantize

Quantize(
    keys: KeyCollection,
    size: float,
    dst_keys: Optional[KeyCollection] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Integer voxel-grid coordinates of every point, keeping the cloud at full resolution.

Stores \(\lfloor p / s \rfloor\) (shifted so the per-axis minimum is \(0\)) for each point of keys under dst_keys. Unlike Voxelize, no reduction happens: points sharing a voxel keep their own rows and get equal coordinates. This is how a voxel-partition evaluation feeds sparse models with every raw point (each sub-cloud holds one point per voxel, so its rows are exactly the voxels), and how test-time views recompute grid coordinates after rotating or scaling the positions.

Quantize on an object

Quantize on a room

Parameters:

  • keys (KeyCollection) –

    Keys holding point positions of shape \((N, D)\).

  • size (float) –

    Voxel side length in the units of the positions.

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

    Keys under which the grid coordinates are stored. Defaults to keys (in-place overwrite).

  • allow_missing_keys (bool, default: False ) –

    If True, missing keys are skipped.

Example
import torch
from torch_pointcloud.transforms import Quantize

transform = Quantize(keys="pos", size=0.02, dst_keys="pos_grid")
data = transform({"pos": torch.tensor([[0.0, 0.0, 0.0], [0.03, 0.0, 0.0], [0.05, 0.0, 0.0]])})
data["pos_grid"]  # tensor([[0, 0, 0], [1, 0, 0], [2, 0, 0]])

OnesLike

OnesLike(
    keys: KeyCollection,
    memory_format: ValueCollection[memory_format]
    | None = None,
    dtype: ValueCollection[dtype] | None = None,
    layout: ValueCollection[layout] | None = None,
    device: ValueCollection[device] | None = None,
    pin_memory: ValueCollection[bool] | None = False,
    requires_grad: ValueCollection[bool] | None = False,
    dst_keys: KeyCollection | None = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Adds a tensor of ones shaped like existing dictionary entries.

OnesLike diagram

Parameters:

  • keys (KeyCollection) –

    Reference keys used to determine tensor shape.

  • dst_keys (KeyCollection | None, default: None ) –

    Keys under which the ones tensors are stored.

AxisMinOffset

AxisMinOffset(
    keys: KeyCollection,
    axis: ValueCollection[int],
    quantile: Optional[float] = None,
    dst_keys: KeyCollection | None = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

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

For each point and a given axis \(a\) along tensor dimension \(d\), computes:

\[ o_i = p_{i,a} - r \]

where the floor reference \(r\) is either the strict minimum \(\min_j p_{j,a}\) (default) or, when quantile is set, the empirical quantile \(Q_q(p_{\cdot,a})\). A small positive quantile gives an outlier-robust floor estimate: quantile=0.0099 reproduces VoteNet's np.percentile(z, 0.99) height feature.

The result has the same shape as the input with the coordinate dimension reduced to size 1 (e.g. \((N, 3) \to (N, 1)\) or \((B, N, 3) \to (B, N, 1)\)). For batched inputs, the minimum is computed per-sample.

AxisMinOffset on an object

AxisMinOffset on a room

Parameters:

  • keys (KeyCollection) –

    Keys holding point positions of shape \((N, D)\).

  • axis (ValueCollection[int]) –

    Coordinate axis \(a\) along which to compute the offset.

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

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

  • dst_keys (KeyCollection | None, default: None ) –

    Keys under which the offset tensors are stored. Defaults to keys (in-place overwrite).

  • allow_missing_keys (bool, default: False ) –

    If True, skip missing keys instead of raising.

Example

Let's say you have a point cloud with positions \((N, 3)\) in XYZ order and you want to compute the offset from the minimum along the z-axis, i.e. computing the height above the local floor.

from torch_pointcloud.transforms import AxisMinOffset

data = {
    "pos": torch.randn(10, 3),
}
transform = AxisMinOffset(keys="pos", dst_keys="pos_offset", axis=2)
data = transform(data)

Now, the data dictionary will contain the key pos_offset with the shape \((N, 1)\).

Cat

Cat(
    keys: KeyCollection,
    dst_key: str,
    dim: int = -1,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Concatenates tensors from multiple keys into a single feature tensor.

Note

This transform is mostly used to concatenate multiple features into a single tensor to feed into your model.

Integer inputs are cast to float32; floating inputs keep their dtype. When the inputs mix floating dtypes, the result uses the widest one (so float64 is preserved, never downcast).

Cat diagram

Parameters:

  • keys (KeyCollection) –

    Keys whose tensors are concatenated (in order).

  • dst_key (str) –

    Key under which the result is stored.

  • dim (int, default: -1 ) –

    Dimension along which to concatenate.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

Example

If you have a point cloud data containing position, color and normal and want to concatenate them into a single feature tensor (to feed into your model), you can do the following:

from torch_pointcloud.transforms import Cat

data = {
    "pos": torch.randn(10, 3),
    "color": torch.randn(10, 3),
    "normal": torch.randn(10, 3),
}
transform = Cat(keys=["pos", "color", "normal"], dst_key="x", dim=1)
data = transform(data)

Now, the data dictionary will contain the key x with the shape \((10, 9)\).

OneHot

OneHot(
    keys: KeyCollection,
    num_classes: ValueCollection[int],
    dst_keys: Optional[KeyCollection] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

One-hot encode integer-class tensors.

Wraps torch.nn.functional.one_hot and casts the result to float so the output is ready to feed into a model.

OneHot diagram

Parameters:

  • keys (KeyCollection) –

    Keys holding integer (long) class indices.

  • num_classes (ValueCollection[int]) –

    Number of classes \(C\) in the one-hot encoding.

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

    Where to store the one-hot tensors. Defaults to keys.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

Shape

Input class tensor of shape \((N,)\) becomes \((N, C)\). A scalar input becomes shape \((C,)\), which after batched collate stacks to \((B, C)\).

Reduce

Reduce(
    keys: KeyCollection,
    op: ValueCollection[ReduceOp],
    dim: ValueCollection[int] = 0,
    keepdim: bool = False,
    dst_keys: Optional[KeyCollection] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Reduce a tensor along a dimension and store the scalar/vector result.

Useful for capturing per-sample statistics (e.g. axis-wise scene maxima or centroids) as standalone keys that downstream transforms can reference.

Reduce diagram

Parameters:

  • keys (KeyCollection) –

    Keys to reduce.

  • op (ValueCollection[ReduceOp]) –

    Reduction operator: "min", "max", "mean", or "sum" (matches the vocabulary used by Voxelize). "mean" keeps the input's floating dtype (float64 included); integer inputs are cast to float32.

  • dim (ValueCollection[int], default: 0 ) –

    Dimension to reduce. Defaults to 0.

  • keepdim (bool, default: False ) –

    Pass keepdim=True to keep the reduced axis as size \(1\). This is helpful when the result is meant to broadcast against a \((N, D)\) tensor (e.g. per-sample bbox stats) and to survive the packed-batch collate - a \((1, D)\) tensor collates to \((B, D)\) via torch.cat, whereas a \((D,)\) tensor would concatenate to \((B \cdot D,)\).

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

    Output keys. Defaults to keys (in-place overwrite).

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

KeepItems

KeepItems(
    keys: KeyCollection, allow_missing_keys: bool = False
)

Bases: DictTransform

Keep only items in the data dictionary that are in the keys list.

Note

This transform is useful if during augmentation process you constructed multiple tensors and want to drop intermediate tensors for memory efficiency.

KeepItems diagram

Parameters:

  • keys (KeyCollection) –

    The keys to keep in the data dictionary.

  • allow_missing_keys (bool, default: False ) –

    If True, the transform will not raise an error if the keys are not present in the data.

Example

If you have a data dictionary containing position, color and normal and want to keep only the position and color, you can do the following:

from torch_pointcloud.transforms import KeepItems

data = {
    "pos": torch.randn(10, 3),
    "color": torch.randn(10, 3),
    "normal": torch.randn(10, 3),
}
transform = KeepItems(keys=["pos", "color"])
data = transform(data)

Now, the data dictionary will contain only the keys pos and color. The key normal will be removed.

RandomRotate

RandomRotate(
    keys: KeyCollection,
    angle_range: Tuple[float, float] = (-180.0, 180.0),
    axis: int = 2,
    p: float = 1.0,
    box_key: Optional[str] = None,
    dst_keys: Optional[KeyCollection] = None,
    dst_box_key: Optional[str] = None,
    generator: Optional[Generator] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Rotate one or more keys (and optionally oriented boxes) by a uniformly random angle around an axis.

Sampling is done once per call: every listed key and the optional box get the same rotation. Each key is a \((\ldots, 3)\) field or a packed \((N, 3G)\) field of tiled 3D offsets (e.g. VoteNet votes). Pair keys=("pos", "normal") to keep positions and normals consistent, or pass box_key to also rotate a \((K, 7)\) oriented-box tensor (centers rotated, heading incremented). Box headings are counterclockwise yaw about the up axis, so box_key requires axis=2.

RandomRotate on an object

RandomRotate on a room

RandomRotate around each axis on an object

See Also

torch_pointcloud.transforms.functional.rotate_vectors, torch_pointcloud.transforms.functional.rotate_boxes, torch_pointcloud.transforms.functional.rotation_matrix

Parameters:

  • keys (KeyCollection) –

    Keys to rotate. Each must be a \((\ldots, 3)\) or \((N, 3G)\) vector field.

  • angle_range (Tuple[float, float], default: (-180.0, 180.0) ) –

    Min and max rotation angle, in degrees.

  • axis (int, default: 2 ) –

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

  • p (float, default: 1.0 ) –

    Probability of applying the transform.

  • box_key (Optional[str], default: None ) –

    Optional key of a \((K, 7)\) oriented-box tensor to rotate jointly (requires axis=2).

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

    Where to store the rotated tensors. Defaults to keys (in-place).

  • dst_box_key (Optional[str], default: None ) –

    Where to store the rotated boxes. Defaults to box_key (in-place).

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

    Optional torch.Generator for reproducibility. See Transform for the multi-worker caveat.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

RandomScale

RandomScale(
    keys: KeyCollection,
    scale_range: Tuple[float, float] = (0.8, 1.25),
    anisotropic: bool = False,
    p: float = 1.0,
    box_key: Optional[str] = None,
    dst_keys: Optional[KeyCollection] = None,
    dst_box_key: Optional[str] = None,
    generator: Optional[Generator] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Scale one or more keys (and optionally oriented boxes) by a uniformly random factor.

Sampling is done once per call: every listed key and the optional box are scaled by the same factor (or per-axis factor vector when anisotropic=True). Pass box_key to also scale a \((K, 7)\) oriented-box tensor (centers and sizes). An oriented box has no per-axis scale, so box_key is incompatible with anisotropic=True.

List only point-like keys. Do not list direction vectors such as normal: a scaled normal is no longer unit length, while a true surface normal is unchanged by an isotropic scale (and an anisotropic scale would require the inverse-transpose rule). Simply omit normal keys.

RandomScale on an object

RandomScale on a room

See Also

torch_pointcloud.transforms.functional.scale_boxes

Parameters:

  • keys (KeyCollection) –

    Keys to scale. Point-like keys only; do not list direction vectors such as normal.

  • scale_range (Tuple[float, float], default: (0.8, 1.25) ) –

    Min and max scaling factor.

  • anisotropic (bool, default: False ) –

    If True, sample a separate scale per axis of the last dim (incompatible with box_key).

  • p (float, default: 1.0 ) –

    Probability of applying the transform.

  • box_key (Optional[str], default: None ) –

    Optional key of a \((K, 7)\) oriented-box tensor to scale jointly.

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

    Where to store the scaled tensors.

  • dst_box_key (Optional[str], default: None ) –

    Where to store the scaled boxes. Defaults to box_key (in-place).

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

    Optional torch.Generator for reproducibility. See Transform for the multi-worker caveat.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

RandomFlip

RandomFlip(
    keys: KeyCollection,
    axes: Sequence[int] = (0, 1),
    p: float = 0.5,
    box_key: Optional[str] = None,
    dst_keys: Optional[KeyCollection] = None,
    dst_box_key: Optional[str] = None,
    generator: Optional[Generator] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Flip listed axes (and optionally oriented boxes) with probability p each.

Sampling is done once per call: every listed key and the optional box are flipped on the same axes. Each key is a \((\ldots, 3)\) field or a packed \((N, 3G)\) field of tiled 3D offsets (e.g. VoteNet votes). Pass box_key to also flip a \((K, 7)\) oriented-box tensor (centers negated, heading remapped).

RandomFlip on an object

RandomFlip on a room

RandomFlip across each axis on an object

See Also

torch_pointcloud.transforms.functional.flip_vectors, torch_pointcloud.transforms.functional.flip_boxes

Parameters:

  • keys (KeyCollection) –

    Keys to flip. Each must be a \((\ldots, 3)\) or \((N, 3G)\) vector field.

  • axes (Sequence[int], default: (0, 1) ) –

    Axis indices (into each 3D triple) to consider for flipping.

  • p (float, default: 0.5 ) –

    Per-axis flip probability.

  • box_key (Optional[str], default: None ) –

    Optional key of a \((K, 7)\) oriented-box tensor to flip jointly.

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

    Where to store the flipped tensors.

  • dst_box_key (Optional[str], default: None ) –

    Where to store the flipped boxes. Defaults to box_key (in-place).

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

    Optional torch.Generator for reproducibility. See Transform for the multi-worker caveat.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

RandomJitter

RandomJitter(
    keys: KeyCollection,
    sigma: float = 0.01,
    clip: Optional[float] = 0.05,
    p: float = 1.0,
    dst_keys: Optional[KeyCollection] = None,
    generator: Optional[Generator] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Add Gaussian noise to listed keys, optionally clipped.

Each key gets its own independent noise tensor (because the noise shape matches the key shape). Pair-rotation-style consistency does not apply here.

RandomJitter on an object

RandomJitter on a room

See Also

torch_pointcloud.transforms.functional.random_jitter

Parameters:

  • keys (KeyCollection) –

    Keys to jitter.

  • 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].

  • p (float, default: 1.0 ) –

    Probability of applying the transform.

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

    Where to store the jittered tensors.

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

    Optional torch.Generator for reproducibility. See Transform for the multi-worker caveat.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

RandomShift

RandomShift(
    keys: KeyCollection,
    shift_range: Tuple[float, float] = (-0.2, 0.2),
    p: float = 1.0,
    box_key: Optional[str] = None,
    dst_keys: Optional[KeyCollection] = None,
    dst_box_key: Optional[str] = None,
    generator: Optional[Generator] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Translate listed keys (and optionally oriented boxes) by a uniformly random vector.

Sampling is done once per call: all listed keys and the optional box are shifted by the same translation vector. Pass box_key to also shift a \((K, 7)\) oriented-box tensor (centers only; sizes and heading unchanged).

List only point-like keys. Do not list direction vectors such as normal: directions are translation-invariant, so a shifted normal is wrong. Simply omit normal keys.

RandomShift on an object

RandomShift on a room

See Also

torch_pointcloud.transforms.functional.shift_boxes

Parameters:

  • keys (KeyCollection) –

    Keys to shift. Point-like keys only; do not list direction vectors such as normal.

  • shift_range (Tuple[float, float], default: (-0.2, 0.2) ) –

    Min and max per-axis translation.

  • p (float, default: 1.0 ) –

    Probability of applying the transform.

  • box_key (Optional[str], default: None ) –

    Optional key of a \((K, 7)\) oriented-box tensor to shift jointly.

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

    Where to store the shifted tensors.

  • dst_box_key (Optional[str], default: None ) –

    Where to store the shifted boxes. Defaults to box_key (in-place).

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

    Optional torch.Generator for reproducibility. See Transform for the multi-worker caveat.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

RandomDropout

RandomDropout(
    keys: KeyCollection,
    p_drop: float = 0.1,
    p: float = 1.0,
    generator: Optional[Generator] = None,
    dst_index_key: Optional[str] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Randomly drop a fraction of points across all listed keys.

The same boolean keep-mask is applied to every key so per-point correspondence is preserved. Sampling is once per call.

RandomDropout on an object

RandomDropout on a room

See Also

torch_pointcloud.transforms.functional.random_dropout_mask

Parameters:

  • keys (KeyCollection) –

    Keys to subset. All must share the same leading dimension \(N\).

  • p_drop (float, default: 0.1 ) –

    Fraction of points to drop per call (uniform across points). Must lie in \([0, 1)\).

  • p (float, default: 1.0 ) –

    Probability of applying the transform.

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

    Optional torch.Generator for reproducibility. See Transform for the multi-worker caveat.

  • dst_index_key (Optional[str], default: None ) –

    Key for the output-to-input row map (see the module docs on sampling keys); None (the default) disables it.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

RandomColorJitter

RandomColorJitter(
    keys: KeyCollection,
    brightness: float = 0.4,
    contrast: float = 0.4,
    saturation: float = 0.2,
    int_color: bool = False,
    p: float = 1.0,
    dst_keys: Optional[KeyCollection] = None,
    generator: Optional[Generator] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Jitter colors by brightness, contrast, and saturation strengths.

Each strength is a relative delta uniformly sampled from [-x, x]. Sampling is once per call, so the same factors are applied to every listed key.

RandomColorJitter before / after

See Also

torch_pointcloud.transforms.functional.color_jitter

Parameters:

  • keys (KeyCollection) –

    Color keys to jitter, shape \((N, 3)\).

  • brightness (float, default: 0.4 ) –

    Max relative brightness change in \([0, 1]\).

  • contrast (float, default: 0.4 ) –

    Max relative contrast change in \([0, 1]\).

  • saturation (float, default: 0.2 ) –

    Max relative saturation change 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; float colors above 1 with int_color=False raise a ValueError.

  • p (float, default: 1.0 ) –

    Probability of applying the transform.

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

    Where to store the jittered tensors.

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

    Optional torch.Generator for reproducibility. See Transform for the multi-worker caveat.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

RandomColorDrop

RandomColorDrop(
    keys: KeyCollection,
    fill: float = 0.5,
    int_color: bool = False,
    p: float = 0.2,
    dst_keys: Optional[KeyCollection] = None,
    generator: Optional[Generator] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Replace colors with a constant gray value with probability p.

RandomColorDrop before / after

See Also

torch_pointcloud.transforms.functional.random_color_drop

Parameters:

  • keys (KeyCollection) –

    Color keys to drop.

  • fill (float, default: 0.5 ) –

    Replacement value in the range implied by int_color ([0, 1] when False, [0, 255] when True); 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; float colors above 1 with int_color=False raise a ValueError.

  • p (float, default: 0.2 ) –

    Probability of dropping colors.

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

    Where to store the result.

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

    Optional torch.Generator for reproducibility. See Transform for the multi-worker caveat.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

RandomColorGrayScale

RandomColorGrayScale(
    keys: KeyCollection,
    int_color: bool = False,
    p: float = 0.2,
    dst_keys: Optional[KeyCollection] = None,
    generator: Optional[Generator] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Convert listed color keys to grayscale (BT.601 luminance) with probability p.

RandomColorGrayScale before / after

See Also

torch_pointcloud.transforms.functional.color_grayscale

Parameters:

  • keys (KeyCollection) –

    Color keys, shape \((N, 3)\).

  • int_color (bool, default: False ) –

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

  • p (float, default: 0.2 ) –

    Probability of converting to grayscale.

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

    Where to store the result.

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

    Optional torch.Generator for reproducibility. See Transform for the multi-worker caveat.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

RandomColorAutoContrast

RandomColorAutoContrast(
    keys: KeyCollection,
    blend: float = 0.5,
    int_color: bool = False,
    p: float = 0.2,
    dst_keys: Optional[KeyCollection] = None,
    generator: Optional[Generator] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Stretch per-cloud color range to the full extent, then blend back, with probability p.

RandomColorAutoContrast before / after

See Also

torch_pointcloud.transforms.functional.color_auto_contrast

Parameters:

  • keys (KeyCollection) –

    Color keys, shape \((N, 3)\).

  • blend (float, default: 0.5 ) –

    Blend weight in [0, 1]. 1.0 is fully auto-contrasted; 0.0 is the input.

  • 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; float colors above 1 with int_color=False raise a ValueError.

  • p (float, default: 0.2 ) –

    Probability of applying the transform.

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

    Where to store the result.

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

    Optional torch.Generator for reproducibility. See Transform for the multi-worker caveat.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

SphereCrop

SphereCrop(
    pos_key: str,
    radius: float,
    max_nodes: Optional[int] = None,
    keys: Optional[KeyCollection] = None,
    center: Any = "centroid",
    p: float = 1.0,
    generator: Optional[Generator] = None,
    dst_index_key: Optional[str] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Keep only points inside an L2 sphere of given radius.

The mask is computed from pos_key and applied to every listed keys. Equivalent to Compose([SphereMask(...), ApplyMask(...)]), kept as a convenience preset (the dual of RemoveNearOrigin).

When max_nodes is set and the sphere holds more than max_nodes points, only the max_nodes nearest the center are kept, bounding memory on large scenes.

SphereCrop on an object

SphereCrop on a room

Parameters:

  • pos_key (str) –

    Key with positions used to compute the mask.

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

    Extra keys to filter with the same mask.

  • center (Any, default: 'centroid' ) –

    Center of the sphere. If "centroid", uses the per-cloud centroid; if "random_point", picks a random point as the center; otherwise treat as a 3-vector.

  • radius (float) –

    Radius of the sphere (Euclidean).

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

    Optional cap on the number of kept points. If None (default), no cap is applied; otherwise the max_nodes points nearest the center are kept.

  • p (float, default: 1.0 ) –

    Probability of applying the transform.

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

    Optional torch.Generator for reproducibility (used when center="random_point"). See Transform for the multi-worker caveat.

  • dst_index_key (Optional[str], default: None ) –

    Key for the output-to-input row map (see the module docs on sampling keys); None (the default) disables it.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

Slice

Slice(
    keys: KeyCollection,
    start: Optional[int] = None,
    stop: Optional[int] = None,
    step: Optional[int] = None,
    dim: int = 0,
    dst_keys: Optional[KeyCollection] = None,
    dst_index_key: Optional[str] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Slice each listed tensor along a chosen dimension via standard Python slicing.

Useful for taking the first \(N\) rows (e.g. on FPS-sorted point clouds), or extracting a single column of pos into a separate key (set dim=1 with start=axis, stop=axis+1).

Slice diagram

Parameters:

  • keys (KeyCollection) –

    Keys to slice.

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

    Start index (inclusive). None is equivalent to 0.

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

    Stop index (exclusive). None means "to the end".

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

    Stride between selected positions. None is equivalent to 1.

  • dim (int, default: 0 ) –

    Dimension along which to slice. Defaults to 0 (the row axis).

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

    Where to store results. Defaults to keys.

  • dst_index_key (Optional[str], default: None ) –

    Key for the output-to-input row map (see the module docs on sampling keys), written only when dim == 0; None (the default) disables it. Leave it unset when dst_keys differ from keys, since the map would describe the dst_keys rows.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

Example
from torch_pointcloud.transforms import Slice

# First 1024 rows of `pos` (e.g. an FPS-sorted ModelNet sample).
Slice(keys="pos", stop=1024)

# Extract the gravity axis (z=2) into a `(N, 1)` `height` key.
Slice(keys="pos", start=2, stop=3, dim=1, dst_keys="height")

ShufflePoint

ShufflePoint(
    keys: KeyCollection,
    p: float = 1.0,
    generator: Optional[Generator] = None,
    dst_index_key: Optional[str] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Randomly permute the order of points across listed keys.

The same permutation is applied to every key so per-point correspondence is preserved. Useful before RandomSample when you want to break any structural ordering in the input.

See Also

torch_pointcloud.transforms.functional.shuffle_indices

ShufflePoint on an object

ShufflePoint on a room

Parameters:

  • keys (KeyCollection) –

    Keys to permute. All must share the same leading dimension \(N\).

  • p (float, default: 1.0 ) –

    Probability of applying the transform.

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

    Optional torch.Generator for reproducibility. See Transform for the multi-worker caveat.

  • dst_index_key (Optional[str], default: None ) –

    Key for the output-to-input row map (see the module docs on sampling keys); None (the default) disables it.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

Clamp

Clamp(
    keys: KeyCollection,
    min: Optional[float] = None,
    max: Optional[float] = None,
    dst_keys: Optional[KeyCollection] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Clamp tensor entries to a range (a thin wrapper over torch.clamp).

Clamp on an object

Clamp on a room

Parameters:

  • keys (KeyCollection) –

    Keys to clamp.

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

    Lower bound. None disables the lower clamp.

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

    Upper bound. None disables the upper clamp.

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

    Where to store the result. Defaults to keys (in-place overwrite).

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

RandomRotateChoice

RandomRotateChoice(
    keys: KeyCollection,
    angles: Sequence[float],
    axis: int = 2,
    p: float = 1.0,
    dst_keys: Optional[KeyCollection] = None,
    generator: Optional[Generator] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Rotate one or more keys by an angle chosen uniformly from a discrete list.

Common use: ModelNet / ScanObjectNN augmentation with angles=[0, 90, 180, 270] around the z-axis. Sampling is done once per call: every listed key gets the same rotation matrix.

See Also

torch_pointcloud.transforms.functional.rotation_matrix, torch_pointcloud.transforms.functional.rotate_vectors

RandomRotateChoice on an object

RandomRotateChoice on a room

Parameters:

  • keys (KeyCollection) –

    Keys to rotate. Each must have shape (..., 3).

  • angles (Sequence[float]) –

    Candidate rotation angles, in degrees. Must be non-empty.

  • axis (int, default: 2 ) –

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

  • p (float, default: 1.0 ) –

    Probability of applying the transform.

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

    Where to store the rotated tensors. Defaults to keys (in-place).

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

    Optional torch.Generator for reproducibility. See Transform for the multi-worker caveat.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

RandomColorShift

RandomColorShift(
    keys: KeyCollection,
    shift_range: Tuple[float, float] = (-0.05, 0.05),
    int_color: bool = False,
    p: float = 1.0,
    dst_keys: Optional[KeyCollection] = None,
    generator: Optional[Generator] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Additive per-channel color shift sampled uniformly per channel.

For each of the 3 channels, sample one offset uniformly from shift_range and add it to every point's value. Sampling is once per call (same shift across all listed keys). Result is clamped to the valid color range.

RandomColorShift before / after

See Also

torch_pointcloud.transforms.functional.color_shift

Parameters:

  • keys (KeyCollection) –

    Color keys to shift, shape \((N, 3)\).

  • shift_range (Tuple[float, float], default: (-0.05, 0.05) ) –

    Min and max per-channel offset (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; float colors above 1 with int_color=False raise a ValueError.

  • p (float, default: 1.0 ) –

    Probability of applying the transform.

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

    Where to store the shifted tensors.

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

    Optional torch.Generator for reproducibility. See Transform for the multi-worker caveat.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

RandomElasticDistortion

RandomElasticDistortion(
    keys: KeyCollection,
    granularity: float = 0.2,
    magnitude: float = 0.4,
    p: float = 1.0,
    dst_keys: Optional[KeyCollection] = None,
    generator: Optional[Generator] = None,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Apply a smooth random displacement field (elastic distortion).

Used in sparse-voxel indoor segmentation recipes. Sampling is done once per call so multi-key consistency is preserved (the same displacement field is applied to every listed key).

For multi-scale distortion (the common default), compose two RandomElasticDistortion calls with different granularity / magnitude.

RandomElasticDistortion on an object

RandomElasticDistortion on a room

See Also

torch_pointcloud.transforms.functional.random_elastic_distortion

Parameters:

  • keys (KeyCollection) –

    Position keys to distort, shape \((N, 3)\). All listed keys must share the same leading dimension \(N\): the per-point displacement is computed once from the first present key and added to every key.

  • granularity (float, default: 0.2 ) –

    Size of the displacement-field grid cells. Smaller values give higher-frequency distortion.

  • magnitude (float, default: 0.4 ) –

    Standard deviation of the per-cell Gaussian noise. Larger values give stronger deformation.

  • p (float, default: 1.0 ) –

    Probability of applying the transform.

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

    Where to store the distorted tensors.

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

    Optional torch.Generator for reproducibility. See Transform for the multi-worker caveat.

  • allow_missing_keys (bool, default: False ) –

    If True, silently skip absent keys.

InstanceToBox

InstanceToBox(
    instance_key: str = "instance",
    semantic_key: str = "segment",
    pos_key: str = "pos",
    dst_box_key: str = "box",
    dst_class_key: str = "label",
    ignore_index: int = -1,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Axis-aligned bounding boxes from per-point instance ids (e.g. ScanNet detection targets).

Each distinct non-negative instance id in instance_key becomes one axis-aligned box covering its pos_key points: the center and full extents with heading \(0\), written to dst_box_key as \((K, 7)\) rows \([c_x, c_y, c_z, d_x, d_y, d_z, 0]\). The box class (the instance's most common semantic_key value) is written separately to dst_class_key as a \((K,)\) long tensor. Negative instance ids mark unlabeled points and never form a box. Instances whose class equals ignore_index are dropped, so mapping the stuff / non-target semantics to ignore_index with a Relabel upstream filters the boxes down to the detection classes.

InstanceToBox before / after

Parameters:

  • instance_key (str, default: 'instance' ) –

    Key of the \((N,)\) per-point instance ids.

  • semantic_key (str, default: 'segment' ) –

    Key of the \((N,)\) per-point class labels the box class is read from.

  • pos_key (str, default: 'pos' ) –

    Key of the \((N, 3)\) coordinates.

  • dst_box_key (str, default: 'box' ) –

    Key to write the \((K, 7)\) boxes to.

  • dst_class_key (str, default: 'label' ) –

    Key to write the \((K,)\) per-box classes to.

  • ignore_index (int, default: -1 ) –

    Class value whose instances are dropped (e.g. unlabeled / stuff).

  • allow_missing_keys (bool, default: False ) –

    If True, return the data unchanged when an input key is missing instead of raising.

GenerateVoteLabels

GenerateVoteLabels(
    pos_key: str = "pos",
    box_key: str = "box",
    vote_key: str = "vote_label",
    mask_key: str = "vote_label_mask",
    oriented: bool = True,
    gt_vote_factor: int = 3,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Generate per-point vote offsets and a vote mask from oriented GT boxes.

Each point collects the offsets to the centers of the first gt_vote_factor boxes containing it, in box order, matching the VoteNet ScanNet and SUN RGB-D vote layout: a point inside fewer boxes repeats its first offset in the unfilled slots, so the min-over-votes loss can credit either center on overlapping objects. Points inside no box receive zero offsets and a zero mask. Boxes are \((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\). When oriented is True containment is yaw-aware, otherwise an axis-aligned test is used.

See Also

torch_pointcloud.transforms.functional.points_in_oriented_box

GenerateVoteLabels before / after

Parameters:

  • pos_key (str, default: 'pos' ) –

    Key of the \((N, 3)\) coordinate tensor.

  • box_key (str, default: 'box' ) –

    Key of the \((K, 7)\) box tensor (full extents, counterclockwise heading).

  • vote_key (str, default: 'vote_label' ) –

    Key to write the \((N, 3 G)\) vote offsets to.

  • mask_key (str, default: 'vote_label_mask' ) –

    Key to write the \((N,)\) vote mask to.

  • oriented (bool, default: True ) –

    If True, use yaw-aware containment, otherwise an axis-aligned test.

  • gt_vote_factor (int, default: 3 ) –

    Number \(G\) of vote slots per point.

  • allow_missing_keys (bool, default: False ) –

    If True, return the data unchanged when pos_key or box_key is missing instead of raising.

EncodeVoteNetTargets

EncodeVoteNetTargets(
    box_key: str = "box",
    class_key: str = "label",
    center_key: str = "center_label",
    heading_class_key: str = "heading_class_label",
    heading_residual_key: str = "heading_residual_label",
    size_class_key: str = "size_class_label",
    size_residual_key: str = "size_residual_label",
    sem_cls_key: str = "sem_cls_label",
    box_mask_key: str = "box_label_mask",
    num_heading_bin: int = 12,
    mean_sizes: Optional[
        Union[Tensor, Sequence[Sequence[float]]]
    ] = None,
    max_num_obj: int = 64,
    allow_missing_keys: bool = False,
)

Bases: DictTransform

Encode oriented GT boxes into the padded label tensors the VoteNet loss consumes.

Each \((K, 7)\) box row \([c_x, c_y, c_z, d_x, d_y, d_z, \theta]\) (full extents) and its class from class_key are converted to fixed-size \((M, \ldots)\) targets where \(M\) is max_num_obj. Headings are binned with angle_to_class. The size class is the semantic class and the size residual is computed against mean_sizes (full edge lengths).

See Also

torch_pointcloud.transforms.functional.angle_to_class, torch_pointcloud.transforms.functional.class_to_size

EncodeVoteNetTargets before / after

Parameters:

  • box_key (str, default: 'box' ) –

    Key of the \((K, 7)\) box tensor (full extents).

  • class_key (str, default: 'label' ) –

    Key of the \((K,)\) per-box class tensor.

  • center_key (str, default: 'center_label' ) –

    Key to write the \((M, 3)\) center labels to.

  • heading_class_key (str, default: 'heading_class_label' ) –

    Key to write the \((M,)\) heading class labels to.

  • heading_residual_key (str, default: 'heading_residual_label' ) –

    Key to write the \((M,)\) heading residual labels to.

  • size_class_key (str, default: 'size_class_label' ) –

    Key to write the \((M,)\) size class labels to.

  • size_residual_key (str, default: 'size_residual_label' ) –

    Key to write the \((M, 3)\) size residual labels to.

  • sem_cls_key (str, default: 'sem_cls_label' ) –

    Key to write the \((M,)\) semantic class labels to.

  • box_mask_key (str, default: 'box_label_mask' ) –

    Key to write the \((M,)\) box mask to.

  • num_heading_bin (int, default: 12 ) –

    Number of heading bins.

  • mean_sizes (Optional[Union[Tensor, Sequence[Sequence[float]]]], default: None ) –

    Template sizes of shape \((C, 3)\) holding full edge lengths per class.

  • max_num_obj (int, default: 64 ) –

    Padded number of objects \(M\).

  • allow_missing_keys (bool, default: False ) –

    If True, return the data unchanged when box_key or class_key is missing instead of raising.

Raises:

  • ValueError –

    If mean_sizes is not provided.

Mix3D

Mix3D(
    keys: KeyCollection,
    instance_key: Optional[str] = "instance",
    ignore_index: int = -1,
    p: float = 1.0,
    generator: Optional[Generator] = None,
)

Bases: Transform

Concatenate two scenes into one, offsetting the second scene's instance ids.

Mix3D: Out-of-Context Data Augmentation for 3D Scenes

Every point-aligned key in keys is concatenated along the point dimension, so the mixed scene holds all points of both inputs. When instance_key is present in both scenes, the second scene's instance ids are shifted past the first scene's maximum id so the merged instances stay disjoint; points labeled ignore_index keep that label and are excluded from the offset.

Unlike the other pairwise mixes, Mix3D keeps all points of both scenes, so the mixed scene has roughly twice as many points as either input.

Mix3D before / after

Parameters:

  • keys (KeyCollection) –

    Point-aligned keys concatenated jointly (e.g. pos, color, normal, segment).

  • instance_key (Optional[str], default: 'instance' ) –

    Key of per-point instance ids to offset, or None to skip instance handling.

  • ignore_index (int, default: -1 ) –

    Instance id treated as "no instance" (kept as-is, ignored by the offset).

  • p (float, default: 1.0 ) –

    Probability of applying the mix; below it the first scene is returned unchanged.

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

    Optional torch.Generator for the probability draw. See Transform for the multi-worker caveat.

Shape
  • each key in keys: \((N, \ldots)\) and \((M, \ldots)\) inputs, \((N + M, \ldots)\) output.
Example
import torch
import torch_pointcloud.transforms as T

a = {"pos": torch.randn(100, 3), "segment": torch.randint(0, 10, (100,))}
b = {"pos": torch.randn(120, 3), "segment": torch.randint(0, 10, (120,))}
mix = T.Mix3D(keys=("pos", "segment"), instance_key=None)
out = mix(a, b)
print(out["pos"].shape)

LaserMix

LaserMix(
    keys: KeyCollection,
    num_areas: Sequence[int],
    pitch_range: Tuple[float, float],
    pos_key: str = "pos",
    p: float = 1.0,
    generator: Optional[Generator] = None,
)

Bases: Transform

Mix two LiDAR scans by swapping alternating inclination (pitch) bands.

LaserMix for Semi-Supervised LiDAR Semantic Segmentation

Both scans are partitioned into num_areas inclination bands (one count is drawn per call), and alternating bands are taken from each scan so the mixed scene tiles the full field of view. Every key in keys is masked with the same per-scan selection, keeping per-point correspondence.

See Also

torch_pointcloud.transforms.functional.laser_mix_masks

LaserMix before / after

Parameters:

  • keys (KeyCollection) –

    Point-aligned keys masked jointly (must include pos_key).

  • num_areas (Sequence[int]) –

    Candidate band counts; one is sampled uniformly per call.

  • pitch_range (Tuple[float, float]) –

    Inclination range (min, max) in degrees.

  • pos_key (str, default: 'pos' ) –

    Key of the coordinates used to compute inclination bands.

  • p (float, default: 1.0 ) –

    Probability of applying the mix; below it the first scene is returned unchanged.

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

    Optional torch.Generator for the band count, parity, and probability draws. See Transform for the multi-worker caveat.

Shape
  • each key in keys: \((N, \ldots)\) and \((M, \ldots)\) inputs, \((N' + M', \ldots)\) output.
Example
import torch
import torch_pointcloud.transforms as T

a = {"pos": torch.randn(100, 3), "segment": torch.randint(0, 10, (100,))}
b = {"pos": torch.randn(120, 3), "segment": torch.randint(0, 10, (120,))}
mix = T.LaserMix(keys=("pos", "segment"), num_areas=(3, 4, 5, 6), pitch_range=(-25.0, 3.0))
out = mix(a, b)

PolarMix

PolarMix(
    keys: KeyCollection,
    instance_classes: Sequence[int],
    swap_ratio: float = 0.5,
    rotate_paste_ratio: float = 1.0,
    pos_key: str = "pos",
    segment_key: str = "segment",
    p: float = 1.0,
    generator: Optional[Generator] = None,
)

Bases: Transform

Mix two LiDAR scans by swapping an azimuth sector and rotate-pasting instance-class points.

PolarMix: A General Data Augmentation Technique for LiDAR Point Clouds

Two independent sub-augmentations run per call. With probability swap_ratio, a random azimuth half-sector of the first scan is replaced by the same sector of the second scan. With probability rotate_paste_ratio, points of the second scan whose segment_key label is in instance_classes are rotated by a random angle about the up axis and appended. Only pos_key is rotated for the pasted points; the other keys are copied unchanged.

See Also

torch_pointcloud.transforms.functional.polar_mix_masks

PolarMix before / after

Parameters:

  • keys (KeyCollection) –

    Point-aligned keys masked and concatenated jointly (must include pos_key).

  • instance_classes (Sequence[int]) –

    Semantic labels whose points are rotate-pasted from the second scan.

  • swap_ratio (float, default: 0.5 ) –

    Probability of swapping the azimuth sector.

  • rotate_paste_ratio (float, default: 1.0 ) –

    Probability of rotate-pasting the instance-class points.

  • pos_key (str, default: 'pos' ) –

    Key of the coordinates used to compute azimuth sectors and to rotate pasted points.

  • segment_key (str, default: 'segment' ) –

    Key of per-point semantic labels used to select the instance classes.

  • p (float, default: 1.0 ) –

    Probability of applying the mix; below it the first scene is returned unchanged.

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

    Optional torch.Generator for the sector, rotation, and probability draws. See Transform for the multi-worker caveat.

Shape
  • each key in keys: \((N, \ldots)\) and \((M, \ldots)\) inputs, \((K, \ldots)\) output.
Example
import torch
import torch_pointcloud.transforms as T

a = {"pos": torch.randn(100, 3), "segment": torch.randint(0, 10, (100,))}
b = {"pos": torch.randn(120, 3), "segment": torch.randint(0, 10, (120,))}
mix = T.PolarMix(keys=("pos", "segment"), instance_classes=(1, 2, 3))
out = mix(a, b)