Transforms¶
Transforms adopt a dict-based API heavily inspired by MONAI's API.
A transform takes one sample dict and returns a new one. Compose chains them, and a dataset applies the chain to every sample it loads. The API follows MONAI's dict transforms and
PyTorch Geometric's Data conventions.
Why a dict-based API?
The dict-based API allows for flexible composition of transforms and what the inputs/outputs.
PyTorch Geometric transforms, in contrast, require a Data object as input. This can be limiting if we want to forward more keys (intensity, color, etc.) and make it easier to compose when we don't want to forward all these values (using a Data object will required each transform to take care of all the attributes it carries, and defaults to None if we don't have them).
Transforms are designed to manipulate specific keys of the input data, which makes the operations explicit and easier to compose.
import torch
import torch_pointcloud.transforms as T
pos = torch.randn(2048, 3)
color = torch.rand(2048, 3)
pipeline = T.Compose([
T.Rescale(keys="pos", method="centroid"),
T.Shift(keys="pos", method="bbox", axes=[0, 1]),
T.RandomSample(keys=("pos", "color"), num_samples=1024),
])
scene = pipeline({"pos": pos, "color": color})
Atomic operations
Each transform is designed as an atomic operation to make it easier to compose and reuse.
Pretrained checkpoints
A pretrained checkpoint carries its own preprocessing in info["transform"] used for inference on the specified dataset.
Sampling and downsampling¶
| Transform | Description | |
|---|---|---|
RandomSample |
Uniform random subsample with shared indices across keys | |
FarthestPointSample |
FPS subsample (well-distributed) | |
RandomSampleFaceVertices |
Sample points on a mesh's faces | |
Voxelize |
Voxel-grid downsample with per-voxel reduction |
Sampling keys¶
Any transform that changes the number of points keeps pos, x, segment and batch aligned at the new resolution and records how to get back:
| Key | Shape | Written by | Meaning |
|---|---|---|---|
origin_pos |
\((N_\text{origin}, 3)\) | a CopyItems step in every registered pipeline |
the source cloud, in the same frame as pos |
origin_segment |
\((N_\text{origin},)\) | the same step, when the pipeline carries labels | the source labels, in the model's label space |
inverse |
\((N_\text{origin},)\) | Voxelize, DivisiblePad through dst_inverse_key |
source row to predictor row: preds[inverse] scores at full resolution |
index |
\((N,)\) | the selection samplers (FarthestPointSample, RandomSample, SphereCrop, ...) through dst_index_key |
predictor row to source row: origin_pos[index] is pos |
Chained steps compose these maps, so they always address the outermost source. Registered pipelines set the keys; set them on your own samplers to get the maps.
Geometry / shifting¶
| Transform | Description | |
|---|---|---|
Shift |
Subtract a computed offset (bbox, centroid, or min) |
|
AlignAxis |
Shift one axis so its min is zero | |
AxisMinOffset |
Per-point offset from axis minimum (height feature) |
Scaling / normalization¶
| Transform | Description | |
|---|---|---|
Rescale |
Center and rescale to unit extent (centroid / bbox / centroid_extent / min_sphere) |
|
Normalize |
Per-channel \((x - \mu) / \sigma\) standardization | |
Scale |
Multiply by a scalar | |
Divide |
Divide by a scalar |
Masking and filtering¶
| Transform | Geometry | |
|---|---|---|
BoxMask |
Axis-aligned bounding box (AABB) | |
CubeMask |
Lā / Chebyshev ball (hypercube) | |
SphereMask |
L2 / Euclidean ball | |
ApplyMask |
Apply any precomputed mask to one or more keys | |
RemoveNearOrigin |
One-shot L2 filter around origin |
Key / dict manipulation¶
| Transform | Description | |
|---|---|---|
Cat |
Concatenate multiple keys' tensors along a dim | |
CopyItems |
Clone a key's value under a new name | |
RenameItems |
Move a key to a new name | |
KeepItems |
Drop everything not in a whitelist | |
SetValue |
Set keys to literal values | |
SubtractKey |
data[k] - data[sub_k] element-wise |
|
DivideKey |
data[k] / data[div_k] element-wise |
|
Reduce |
Reduce a tensor along a dim (min/max/mean/sum) |
|
OneHot |
One-hot encode integer labels | |
Relabel |
Remap integer labels via a lookup table | |
Abs |
Element-wise absolute value |
Type / device¶
| Transform | Description | |
|---|---|---|
ToFloat |
Cast tensors to float32 | |
ToTensor |
Convert lists / arrays to tensors | |
ToDevice |
Move to a device | |
OnesLike |
Add a key whose tensor is torch.ones_like(...) |
Octree (optional, requires ocnn)¶
| Transform | Description | |
|---|---|---|
BuildOctree |
Build an octree from positions | |
OctreeFeatures |
Extract per-node features from an octree |