s3dis
S3DIS indoor scene segmentation datasets with room loading, alignment, and tiling helpers.

Classes:
-
S3DISRoomDataβPer-point arrays of one S3DIS room, as returned by
load_s3dis_room. -
S3DISβThe Stanford 3D Indoor Spaces Dataset (S3DIS) dataset, as described in the original paper
-
S3DISHdf5βPre-processed HDF5 version of the S3DIS dataset used by multiple SOTA reference implementations.
Functions:
-
load_s3dis_roomβLoad the full S3DIS room from a given directory and (optionally) apply an alignment angle.
-
load_s3dis_alignment_anglesβLoad the alignment angles for a given area from a text file.
-
tile_s3dis_roomβSplit a single room dict into fixed-size spatial blocks.
S3DISRoomData [source] ΒΆ
Bases: TypedDict
Per-point arrays of one S3DIS room, as returned by load_s3dis_room.
S3DIS [source] ΒΆ
S3DIS(
root: PathLike,
*,
areas: Union[
ValueCollection[S3DISArea], Literal["all"]
] = "all",
classes: Union[
ValueCollection[S3DISClass], Literal["all"]
] = "all",
aligned: bool = True,
block_size: Optional[float] = None,
block_stride: float = 1.0,
num_nodes: Optional[int] = 4096,
min_num_nodes: int = 100,
transform: Optional[Callable] = None,
download: bool = False,
force_download: bool = False,
force_process: bool = False,
show_progress: bool = True,
num_workers: Optional[int] = None,
accept_terms: bool = False,
)
Bases: PointCloudDataset
The Stanford 3D Indoor Spaces Dataset (S3DIS) dataset, as described in the original paper 3D Indoor Spaces Dataset: Collection, Annotations, and Methods.
You can download the raw dataset from https://cvg-data.inf.ethz.ch/s3dis/ official website. The dataset is released under a terms-of-use agreement (terms_url): accept it, then pass download=True, accept_terms=True (or answer the prompt download=True alone raises on the terminal), or place the archive under raw by hand.
The S3DIS dataset contains 6 diverse areas (one used for testing) covering a total of 6020 square meters. Each area contains multiple rooms (e.g. office, conference room, etc.), and each room contains multiple segment regions (e.g. wall, floor, ceiling, etc.) with instance-level annotations.
The dataset will be processed automatically and saved in the S3DIS/processed directory. Each room is stored as its own folder: <processed_dir>/<Area_i>/<room_name>/{coord,color,segment,instance}.npy. If the processed data already exists, it will be loaded from the S3DIS/processed directory and processing will be skipped.
Tip
If you change the preprocessing parameters, you can delete the processed data to reprocess the dataset or use the force_process argument to force the processing of the raw data.
Parameters:
-
root(PathLike) βThe root directory of the dataset, where the raw and processed data will be stored.
-
areas(Union[ValueCollection[S3DISArea], Literal['all']], default:'all') βThe areas to load, either a list of area names or "all".
-
classes(Union[ValueCollection[S3DISClass], Literal['all']], default:'all') βThe classes to load, either a list of class names or "all".
-
aligned(bool, default:True) βWhether to apply each room's global alignment rotation during processing. The raw
Stanford3dDataset_v1.2_Aligned_Versiondownload ships the same (non-aligned) coordinates as V1.2 plus per-roomArea_{i}_alignmentAngle.txtfiles. Whenaligned=True(default) the rotation is applied so the stored coordinates are globally aligned. WhenFalsethe original V1.2 coordinate frame is kept: this is required when benchmarking pretrained weights that were trained on non-aligned data (e.g. the DGCNN reference weights whose HDF5 blocks use non-aligned coordinates). Aligned and unaligned data are stored in separate processed directories so they can coexist. -
block_size(Optional[float], default:None) βIf set, each room is split into ground-plane blocks of this size (meters) at load time. Changing this only affects loading, not on-disk processed data.
-
block_stride(float, default:1.0) βStride between blocks when
block_sizeis set. -
num_nodes(Optional[int], default:4096) βNumber of points kept per block when tiling, drawn at random (
Nonekeeps every point). -
min_num_nodes(int, default:100) βSkip blocks with fewer than this many points.
-
transform(Optional[Callable], default:None) βA callable that transforms the data when retrieved from the dataset.
-
download(bool, default:False) βWhether to download the raw data.
-
force_download(bool, default:False) βWhether to force the download of the raw data.
-
force_process(bool, default:False) βWhether to force the processing of the raw data.
-
show_progress(bool, default:True) βWhether to show a progress bar during processing.
-
num_workers(Optional[int], default:None) βNumber of worker processes for parallel room processing. If
None, rooms are processed sequentially. -
accept_terms(bool, default:False) βConfirm that you have accepted the S3DIS terms of use (
terms_url). When leftFalse,downloadasks for the confirmation on the terminal, once in every process that triggers the download.
Example
Assuming you have downloaded the raw dataset from https://cvg-data.inf.ethz.ch/s3dis/, and extracted it under data/S3DIS/raw, you can load the dataset as follows:
from torch_pointcloud.datasets import S3DIS
dataset = S3DIS(
root="data",
areas=["Area_1", "Area_2", "Area_3", "Area_4", "Area_6"],
)
To split rooms into 1m x 1m blocks (matching the DGCNN evaluation protocol):
Methods:
-
is_area_processedβCheck whether an area is fully packed in the processed cache.
-
processβProcess the raw dataset for easier loading.
-
loadβLoad the processed dataset into memory.
Attributes:
-
processed_dir(str) βPath to the processed cache directory, suffixed
_alignedwhen the rooms are axis-aligned. -
class_to_idx(dict[str, int]) βMapping from class name to label index.
-
name(str) βName of the dataset directory.
-
data_dir(str) βPath to the dataset directory
<root>/<name>. -
raw_dir(str) βPath to the raw download directory.
processed_dir property ΒΆ
Path to the processed cache directory, suffixed _aligned when the rooms are axis-aligned.
class_to_idx cached property ΒΆ
Mapping from class name to label index.
is_area_processed [source] ΒΆ
Check whether an area is fully packed in the processed cache.
Parameters:
-
area(str) βName of the area (e.g.
Area_1).
Returns:
-
boolβTrue if every packed file of the area exists, False otherwise.
process [source] ΒΆ
process(
force: bool = False,
num_workers: Optional[int] = None,
show_progress: bool = True,
) -> None
Process the raw dataset for easier loading.
When aligned=True, applies the per-room alignment rotation so that the stored coordinates are in the globally-aligned frame (the s3disfull convention). When aligned=False, coordinates are kept in the raw scan frame.
load [source] ΒΆ
load(
block_size: Optional[float] = None,
block_stride: float = 1.0,
num_nodes: Optional[int] = 4096,
min_num_nodes: int = 100,
show_progress: bool = True,
) -> None
Load the processed dataset into memory. If the provided block_size is not None and greater than 0, the rooms will be split into fixed-size spatial blocks.
Parameters:
-
block_size(Optional[float], default:None) βSide length of each square block in meters.
-
block_stride(float, default:1.0) βStep size for the sliding window in meters. Must be \(\leq\)
block_size. -
num_nodes(Optional[int], default:4096) βFixed number of nodes per block. Nodes are randomly subsampled (or duplicated if the block has fewer nodes);
Nonekeeps every node. -
min_num_nodes(int, default:100) βMinimum number of raw nodes for a block to be kept.
-
show_progress(bool, default:True) βWhether to show a progress bar during loading.
S3DISHdf5 [source] ΒΆ
S3DISHdf5(
root: PathLike,
*,
areas: Union[
Sequence[S3DISArea], Literal["all"]
] = "all",
classes: Union[
ValueCollection[S3DISClass], Literal["all"]
] = "all",
transform: Optional[Callable] = None,
download: bool = False,
force_download: bool = False,
force_process: bool = False,
show_progress: bool = True,
accept_terms: bool = False,
)
Bases: PointCloudDataset
Pre-processed HDF5 version of the S3DIS dataset used by multiple SOTA reference implementations.
Unlike S3DIS, which loads from the raw annotated rooms, this class loads the pre-tiled 4096-point blocks distributed as HDF5 files. The blocks are already spatially tiled and fixed-size, so no additional tiling step is needed.
Each sample is a dict with the following keys:
| Key | Shape | Dtype | Description |
|---|---|---|---|
pos | \((4096, 3)\) | float32 | XYZ coordinates |
color | \((4096, 3)\) | float32 | RGB values |
norm_pos | \((4096, 3)\) | float32 | Room-normalized XYZ coordinates (range \([0,1]\)) |
segment | \((4096,)\) | int64 | Per-point semantic label (13 classes) |
Labels are emitted in S3DIS_CLASSES order (the archive itself stores them in S3DIS_HDF5_CLASSES order, which swaps table / chair and sofa / bookcase).
Important
This dataset is already processed and the HDF5 files are used directly. They are stored in the S3DIS/indoor3d_sem_seg_hdf5_data directory, meaning that they are co-located with the S3DIS dataset.
Parameters:
-
root(PathLike) βRoot directory where
S3DIS/indoor3d_sem_seg_hdf5_data/is stored. -
areas(Union[Sequence[S3DISArea], Literal['all']], default:'all') βAreas to load, either a sequence of area names or
"all". -
classes(Union[ValueCollection[S3DISClass], Literal['all']], default:'all') βClasses to load, either a sequence of class names or
"all". When a subset is selected, labels are remapped to contiguous indices in the given order; unselected classes fall back to the new index ofclutterwhen it is selected, else to the ignore index -1 (matchingS3DIS). -
transform(Optional[Callable], default:None) βOptional callable applied to each sample dict at
__getitem__time. -
download(bool, default:False) βWhether to download the HDF5 archive if not already present.
-
force_download(bool, default:False) βWhether to re-download even if the archive already exists.
-
force_process(bool, default:False) βWhether to force re-processing (no-op for this variant since the HDF5 files are used directly).
-
show_progress(bool, default:True) βWhether to show progress bars during download and loading.
-
accept_terms(bool, default:False) βConfirm that you have accepted the S3DIS terms of use (
terms_url). When leftFalse,downloadasks for the confirmation on the terminal, once in every process that triggers the download.
Example
Assuming you have downloaded the HDF5 files from https://shapenet.cs.stanford.edu/media/, and extracted it under data/S3DIS/indoor3d_sem_seg_hdf5_data, you can load the dataset as follows:
Attributes:
-
name(str) βName of the dataset directory (shared with
S3DIS). -
class_to_idx(dict[str, int]) βMapping from class name to label index.
-
raw_dir(str) βPath to the raw download directory.
-
processed_dir(str) βPath to the processed cache directory, which aliases
raw_dirsince the HDF5 blocks are read as-is. -
data_dir(str) βPath to the dataset directory
<root>/<name>.
load_s3dis_room [source] ΒΆ
load_s3dis_room(
room_dir: PathLike, alignment_angle: float | None = None
) -> S3DISRoomData
Load the full S3DIS room from a given directory and (optionally) apply an alignment angle.
Parameters:
-
room_dir(PathLike) βPath to the room directory.
-
alignment_angle(float | None, default:None) βAlignment angle to apply to the room. Defaults to None.
Returns:
-
S3DISRoomDataβA dictionary containing the room data.
load_s3dis_alignment_angles [source] ΒΆ
Load the alignment angles for a given area from a text file. In S3DIS dataset, one file is provided for each area, containing the alignment angles for each room in the area. The file is a text file with the following format:
## Global alignment angle per disjoint space in Area_1 ##
## Disjoint Space Name Global Alignment Angle ##
conferenceRoom_1 0
conferenceRoom_2 180
Example
Assuming you have downloaded the raw dataset and extracted it under data/S3DIS/raw, you can load the alignment angles for the Area_1 as follows:
tile_s3dis_room [source] ΒΆ
tile_s3dis_room(
room: dict[str, Any],
block_size: float = 1.0,
block_stride: float = 1.0,
num_nodes: Optional[int] = 4096,
min_num_nodes: int = 100,
) -> list[dict[str, Any]]
Split a single room dict into fixed-size spatial blocks.
The algorithm shifts the room so that the minimum point is at the origin, then sweeps a \(\text{block\_size} \times \text{block\_size}\) window (full Z extent) over the room with the given stride. This matches the procedure in multiple SOTA reference implementations (KPFCNN, ...).
Parameters:
-
room(dict[str, Any]) βDict with at least
DataKeys.POS(float32, \((N, 3)\)). All other tensors with a leading dimension of \(N\) are sliced in parallel. -
block_size(float, default:1.0) βSide length of each square block in meters.
-
block_stride(float, default:1.0) βStep size for the sliding window in meters. Must be \(\leq\)
block_size. -
num_nodes(Optional[int], default:4096) βFixed number of nodes per block. Nodes are randomly subsampled (or duplicated if the block has fewer nodes);
Nonekeeps every node of the block. -
min_num_nodes(int, default:100) βMinimum number of raw nodes for a block to be kept.
Returns:
-
list[dict[str, Any]]βList of dicts, one per retained block. Each block has exactly
-
list[dict[str, Any]]βnum_nodesnodes (randomly subsampled or oversampled), or all of its nodes withnum_nodes=None. -
list[dict[str, Any]]βPositions are origin-shifted (room minimum at origin).
Example
Tile a room into 1m x 1m blocks of 4096 nodes:
import torch
from torch_pointcloud.datasets.s3dis import tile_s3dis_room
room = {
"pos": torch.rand(20_000, 3) * torch.tensor([4.0, 3.0, 2.5]),
"segment": torch.randint(0, 13, (20_000,)),
}
blocks = tile_s3dis_room(room, block_size=1.0, block_stride=1.0, num_nodes=4096)
len(blocks), blocks[0]["pos"].shape # (12, torch.Size([4096, 3]))