mixing
Transforms that mix two samples into one.
Classes:
-
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.
Mix3D [source] ΒΆ
Mix3D(
keys: KeyCollection,
instance_key: Optional[str] = "instance",
ignore_index: int = -1,
p: float = 1.0,
seed: Optional[int] = None,
)
Bases: Transform, Randomizable
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.

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
Noneto 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.
-
seed(Optional[int], default:None) βSeed for the probability draw;
Nonedraws from the global generator (seeRandomizable).
Shape
- each key in
keys: \((N, \ldots)\) and \((M, \ldots)\) inputs, \((N + M, \ldots)\) output.
Example
LaserMix [source] ΒΆ
LaserMix(
keys: KeyCollection,
num_areas: Sequence[int],
pitch_range: Tuple[float, float],
pos_key: str = "pos",
p: float = 1.0,
seed: Optional[int] = None,
)
Bases: Transform, Randomizable
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

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.
-
seed(Optional[int], default:None) βSeed for the band count, parity and probability draws;
Nonedraws from the global generator (seeRandomizable).
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 [source] ΒΆ
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,
seed: Optional[int] = None,
)
Bases: Transform, Randomizable
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

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.
-
seed(Optional[int], default:None) βSeed for the sector, rotation and probability draws;
Nonedraws from the global generator (seeRandomizable).
Shape
- each key in
keys: \((N, \ldots)\) and \((M, \ldots)\) inputs, \((K, \ldots)\) output.
Example
laser_mix_masks [source] ΒΆ
laser_mix_masks(
pos: Tensor,
other_pos: Tensor,
num_areas: int,
pitch_range: Tuple[float, float],
generator: Optional[Generator] = None,
) -> Tuple[Tensor, Tensor]
Return keep-masks that swap alternating inclination (pitch) bands between two LiDAR scans.
Each point's inclination is \(\phi = \arctan2(z, \sqrt{x^2 + y^2})\) in degrees. The range pitch_range is split into num_areas equal bands; a random parity picks whether the even or odd bands are kept from the first scan, with the complementary bands kept from the second. The mixed scene is torch.cat([pos[mask], other_pos[other_mask]]), so the two masks tile the sky.
Parameters:
-
pos(Tensor) βCoordinates of the first scan of shape \((N, 3)\).
-
other_pos(Tensor) βCoordinates of the second scan of shape \((M, 3)\).
-
num_areas(int) βNumber of inclination bands to split
pitch_rangeinto. -
pitch_range(Tuple[float, float]) βInclination range
(min, max)in degrees. -
generator(Optional[Generator], default:None) βRandom generator for reproducibility.
Returns:
-
TensorβA tuple
(mask, other_mask)of boolean tensors of shape \((N,)\) and \((M,)\) that select the -
Tensorβpoints kept from
posand fromother_posrespectively.
Shape
pos: \((N, 3)\)other_pos: \((M, 3)\)- output: \((N,)\) and \((M,)\)
Raises:
-
ValueErrorβIf
num_areasis not positive.
Example
import torch
from torch_pointcloud.transforms.functional import laser_mix_masks
pos = torch.randn(100, 3)
other = torch.randn(120, 3)
g = torch.Generator().manual_seed(0)
mask, other_mask = laser_mix_masks(pos, other, num_areas=4, pitch_range=(-25.0, 3.0), generator=g)
mixed = torch.cat([pos[mask], other[other_mask]], dim=0)
polar_mix_masks [source] ΒΆ
polar_mix_masks(
pos: Tensor,
other_pos: Tensor,
generator: Optional[Generator] = None,
) -> Tuple[Tensor, Tensor]
Return keep-masks that swap a random azimuth half-sector between two LiDAR scans.
Each point's azimuth is \(\theta = \arctan2(y, x)\). A random start angle in \([-\pi, \pi)\) defines a half-circle sector \([\theta_0, \theta_0 + \pi)\) that wraps around the \(\pm\pi\) seam, so half of the azimuth range is swapped regardless of the start angle. Points of the first scan outside the sector are kept, and points of the second scan inside the sector are added, so the mixed scene is torch.cat([pos[mask], other_pos[other_mask]]).
Parameters:
-
pos(Tensor) βCoordinates of the first scan of shape \((N, 3)\).
-
other_pos(Tensor) βCoordinates of the second scan of shape \((M, 3)\).
-
generator(Optional[Generator], default:None) βRandom generator for reproducibility.
Returns:
-
TensorβA tuple
(mask, other_mask)of boolean tensors of shape \((N,)\) and \((M,)\) that select the -
Tensorβpoints kept from
posand pasted fromother_posrespectively.
Shape
pos: \((N, 3)\)other_pos: \((M, 3)\)- output: \((N,)\) and \((M,)\)