torch-pointcloud 0.0.2__tar.gz → 0.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/.gitignore +1 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/PKG-INFO +2 -2
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/README.md +1 -1
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/pyproject.toml +1 -1
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/inferers/sliding_window.py +99 -50
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/serialized_attention.py +57 -18
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/_base.py +10 -4
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/concerto.py +8 -4
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/dgcnn.py +1 -8
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/kpconv.py +13 -14
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/octformer.py +13 -12
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/point_bert.py +10 -4
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/point_m2ae.py +2 -9
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/point_mae.py +2 -7
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/point_transformer.py +9 -9
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/point_transformer_v2.py +11 -12
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/point_transformer_v3.py +42 -19
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/pointcnn.py +12 -22
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/pointconv.py +9 -17
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/pointmlp.py +12 -22
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/pointnet2.py +7 -7
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/pointnext.py +23 -34
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/pvcnn.py +16 -12
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/pvcnn2.py +17 -11
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/randlanet.py +14 -20
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/sonata.py +8 -4
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/spformer_unet.py +41 -14
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/spunet.py +40 -16
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/spvcnn.py +29 -8
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/utonia.py +4 -4
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/types.py +26 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/LICENSE +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/THIRD_PARTY_NOTICES.md +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/__init__.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/config.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/datasets/__init__.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/datasets/concat.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/datasets/kitti.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/datasets/mix.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/datasets/modelnet.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/datasets/nuscenes.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/datasets/parislille3d.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/datasets/pointcloud.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/datasets/repeat.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/datasets/s3dis.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/datasets/scannet.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/datasets/scanobjectnn.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/datasets/semantic3d.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/datasets/semantickitti.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/datasets/shapenetpart.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/datasets/sunrgbd.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/datasets/toronto3d.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/datasets/utils.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/inferers/__init__.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/inferers/_utils.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/inferers/inferer.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/inferers/knn_window.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/inferers/part_refinement.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/inferers/potential_sphere.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/inferers/simple.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/inferers/tta.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/inferers/voxel_partition.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/__init__.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/_modules.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/act.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/affine.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/anchors.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/bev_backbone.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/conv2d_blocks.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/conv3d_blocks.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/dropouts.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/fps.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/geometric_affine.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/grid_pool.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/linear_blocks.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/norms.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/octree_attention.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/octree_blocks.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/pdnorm.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/point_patch_embed.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/pointconv.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/pointconv_sa.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/pointnet2_blocks.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/pointnext_blocks.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/pools.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/pvcnn_blocks.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/rope.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/serialized_pool.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/spconv_blocks.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/tnet.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/transformer.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/vfe.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/view.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/layers/xconv.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/lightning/__init__.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/lightning/callbacks.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/lightning/datamodule.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/lightning/metrics.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/lightning/module.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/losses/__init__.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/losses/_utils.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/losses/anchor.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/losses/center.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/losses/chamfer.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/losses/detr3d.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/losses/lovasz.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/losses/pointrcnn.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/losses/sum.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/losses/transfusion.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/losses/votenet.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/__init__.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/_registry.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/detr3d.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/lion.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/point_mamba.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/pointgpt.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/pointnet.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/pointpillars.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/pointrcnn.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/second.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/sphereformer.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/votenet.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/voxel_mamba.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/models/voxelnext.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/py.typed +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/transforms/__init__.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/transforms/functional.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/transforms/transforms.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/__init__.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/box3d.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/cluster.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/conversion.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/data.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/diffusion.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/ensemble.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/geometry.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/heatmap.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/hilbert.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/imports.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/io.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/metrics.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/misc.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/neighbors.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/octree.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/ops.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/optim.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/random.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/serialization.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/state_dict.py +0 -0
- {torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/utils/voxelization.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: torch-pointcloud
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.3
|
|
4
4
|
Summary: PyTorch Point Cloud models, scripts, pretrained weights and more
|
|
5
5
|
Project-URL: Homepage, https://github.com/arthurdjn/pytorch-pointcloud
|
|
6
6
|
Project-URL: Repository, https://github.com/arthurdjn/pytorch-pointcloud
|
|
@@ -158,7 +158,7 @@ Every checkpoint ships the transform that turns a raw point cloud into what the
|
|
|
158
158
|
# Requires torch-scatter, torch-cluster, spconv
|
|
159
159
|
model, info = tp.create_model("ptv3-base.scannet20.pointcept", task="segmentation", pretrained=True, return_info=True)
|
|
160
160
|
info["transform"] # the preprocessing pipeline of that checkpoint
|
|
161
|
-
info["weights"]["metrics"] # {"mIoU":
|
|
161
|
+
info["weights"]["metrics"] # {"mIoU": 77.40}
|
|
162
162
|
|
|
163
163
|
tp.list_models("pointnext*") # every registered PointNeXt config
|
|
164
164
|
tp.list_models(task="detection", pretrained=True) # all detection checkpoints
|
|
@@ -115,7 +115,7 @@ Every checkpoint ships the transform that turns a raw point cloud into what the
|
|
|
115
115
|
# Requires torch-scatter, torch-cluster, spconv
|
|
116
116
|
model, info = tp.create_model("ptv3-base.scannet20.pointcept", task="segmentation", pretrained=True, return_info=True)
|
|
117
117
|
info["transform"] # the preprocessing pipeline of that checkpoint
|
|
118
|
-
info["weights"]["metrics"] # {"mIoU":
|
|
118
|
+
info["weights"]["metrics"] # {"mIoU": 77.40}
|
|
119
119
|
|
|
120
120
|
tp.list_models("pointnext*") # every registered PointNeXt config
|
|
121
121
|
tp.list_models(task="detection", pretrained=True) # all detection checkpoints
|
{torch_pointcloud-0.0.2 → torch_pointcloud-0.0.3}/src/torch_pointcloud/inferers/sliding_window.py
RENAMED
|
@@ -27,7 +27,7 @@ import torch
|
|
|
27
27
|
from torch import Tensor
|
|
28
28
|
from tqdm import tqdm
|
|
29
29
|
|
|
30
|
-
from torch_pointcloud.utils.data import DataKeys
|
|
30
|
+
from torch_pointcloud.utils.data import DataKeys, collate
|
|
31
31
|
|
|
32
32
|
from ._utils import check_batch_alignment, gaussian_weights, index_select_dict, split_chunks
|
|
33
33
|
from .inferer import Inferer
|
|
@@ -194,6 +194,7 @@ def sliding_window_inference(
|
|
|
194
194
|
mode: WindowMode = "constant",
|
|
195
195
|
sigma_scale: float = 0.125,
|
|
196
196
|
roi_num_points: Optional[int] = None,
|
|
197
|
+
sw_batch_size: int = 1,
|
|
197
198
|
softmax: bool = True,
|
|
198
199
|
aggregate: AggregateMode = "mean",
|
|
199
200
|
transform: Optional[Callable[[Dict[str, Any]], Dict[str, Any]]] = None,
|
|
@@ -239,13 +240,18 @@ def sliding_window_inference(
|
|
|
239
240
|
$D_\text{tiled}$ the number of tiled axes.
|
|
240
241
|
sigma_scale: Gaussian sigma scale factor. Only used when
|
|
241
242
|
`mode="gaussian"`.
|
|
242
|
-
roi_num_points: Optional cap on points per
|
|
243
|
+
roi_num_points: Optional cap on points per batch element. Blocks
|
|
243
244
|
exceeding this are split into random sub-batches and every point is
|
|
244
245
|
predicted exactly once per block pass. `None` passes the whole block
|
|
245
|
-
in one
|
|
246
|
+
in one element. At the default `sw_batch_size=1` an element is a call,
|
|
247
|
+
so this also caps the points per `predictor` call. To enforce a fixed-N predictor input, pair the inferer
|
|
246
248
|
with a `DivisiblePad`-style `transform` that pads each block to a
|
|
247
249
|
multiple of `roi_num_points` and writes its source-to-padded index
|
|
248
250
|
map under `inverse_key`.
|
|
251
|
+
sw_batch_size: Number of batch elements packed into a single `predictor` call. Blocks are
|
|
252
|
+
independent, so they are collated along the batch index and their predictions are
|
|
253
|
+
accumulated in block order: only the number of calls changes. Small blocks are
|
|
254
|
+
dominated by per-call overhead, where a larger value is several times faster.
|
|
249
255
|
softmax: If `True`, softmax each block's logits before accumulating.
|
|
250
256
|
Use `True` when averaging predictions across multiple blocks or
|
|
251
257
|
TTA passes. Set `False` to accumulate raw logits. `"max"` and
|
|
@@ -307,6 +313,8 @@ def sliding_window_inference(
|
|
|
307
313
|
raise ValueError(f"`aggregate` must be 'mean', 'max' or 'vote', got {aggregate!r}.")
|
|
308
314
|
if roi_num_points is not None and roi_num_points < 1:
|
|
309
315
|
raise ValueError(f"`roi_num_points` must be >= 1 or None, got {roi_num_points}.")
|
|
316
|
+
if sw_batch_size < 1:
|
|
317
|
+
raise ValueError(f"`sw_batch_size` must be >= 1, got {sw_batch_size}.")
|
|
310
318
|
if padding < 0.0:
|
|
311
319
|
raise ValueError(f"`padding` must be >= 0, got {padding}.")
|
|
312
320
|
|
|
@@ -343,59 +351,97 @@ def sliding_window_inference(
|
|
|
343
351
|
weights_b = torch.zeros(n_b, device=device, dtype=torch.float32)
|
|
344
352
|
confidence_b = torch.full((n_b,), -1.0, device=device, dtype=torch.float32)
|
|
345
353
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
354
|
+
blocks = list(zip(point_groups, weight_groups, bbox_groups))
|
|
355
|
+
for start in tqdm(
|
|
356
|
+
range(0, len(blocks), sw_batch_size),
|
|
357
|
+
total=math.ceil(len(blocks) / sw_batch_size),
|
|
349
358
|
desc=f"batch {int(b)}",
|
|
350
359
|
leave=False,
|
|
351
360
|
disable=not progress,
|
|
352
361
|
):
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
window =
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
if
|
|
362
|
+
windows: List[Dict[str, Any]] = []
|
|
363
|
+
inverse_maps: List[Optional[Tensor]] = []
|
|
364
|
+
samples: List[Dict[str, Any]] = []
|
|
365
|
+
owners: List[Tuple[int, Tensor]] = []
|
|
366
|
+
|
|
367
|
+
for point_ids, _, bbox in blocks[start : start + sw_batch_size]:
|
|
368
|
+
n_block = int(point_ids.numel())
|
|
369
|
+
window = index_select_dict(data_b, point_ids, n_b)
|
|
370
|
+
window[batch_key] = torch.zeros(n_block, device=device, dtype=torch.long)
|
|
371
|
+
window[block_bbox_key] = bbox
|
|
372
|
+
if inverse_key is not None:
|
|
373
|
+
window.pop(inverse_key, None)
|
|
374
|
+
if transform is not None:
|
|
375
|
+
window = transform(window)
|
|
376
|
+
|
|
377
|
+
n_window = int(window[pos_key].size(0))
|
|
378
|
+
inverse_maps.append(window.pop(inverse_key, None) if inverse_key is not None else None)
|
|
379
|
+
windows.append(window)
|
|
380
|
+
|
|
381
|
+
for chunk_local in split_chunks(n_window, roi_num_points, rng):
|
|
382
|
+
sub_window = index_select_dict(window, chunk_local, n_window)
|
|
383
|
+
samples.append(sub_window)
|
|
384
|
+
owners.append((len(windows) - 1, chunk_local))
|
|
385
|
+
|
|
386
|
+
if not samples:
|
|
378
387
|
continue
|
|
379
388
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
389
|
+
parts: List[Tensor] = []
|
|
390
|
+
for pack_start in range(0, len(samples), sw_batch_size):
|
|
391
|
+
packed = collate(
|
|
392
|
+
samples[pack_start : pack_start + sw_batch_size],
|
|
393
|
+
batch_from=pos_key,
|
|
394
|
+
batch_key=batch_key,
|
|
395
|
+
)
|
|
396
|
+
logits = predictor(packed)
|
|
397
|
+
parts.append(torch.softmax(logits, dim=-1) if softmax or aggregate != "mean" else logits)
|
|
398
|
+
preds = torch.cat(parts)
|
|
399
|
+
|
|
400
|
+
window_preds: List[Optional[Tensor]] = [None] * len(windows)
|
|
401
|
+
offset = 0
|
|
402
|
+
for (index, chunk_local), sample in zip(owners, samples):
|
|
403
|
+
count = int(sample[pos_key].size(0))
|
|
404
|
+
chunk_preds = preds[offset : offset + count]
|
|
405
|
+
offset += count
|
|
406
|
+
preds_at_window = window_preds[index]
|
|
407
|
+
if preds_at_window is None:
|
|
408
|
+
n_window = int(windows[index][pos_key].size(0))
|
|
409
|
+
preds_at_window = torch.zeros(
|
|
410
|
+
n_window,
|
|
411
|
+
int(chunk_preds.size(-1)),
|
|
412
|
+
device=device,
|
|
413
|
+
dtype=torch.float32,
|
|
414
|
+
)
|
|
415
|
+
window_preds[index] = preds_at_window
|
|
416
|
+
preds_at_window[chunk_local] = chunk_preds.to(preds_at_window)
|
|
417
|
+
|
|
418
|
+
for (point_ids, w, _), block_preds, inverse_map in zip(
|
|
419
|
+
blocks[start : start + sw_batch_size],
|
|
420
|
+
window_preds,
|
|
421
|
+
inverse_maps,
|
|
422
|
+
):
|
|
423
|
+
if block_preds is None:
|
|
424
|
+
continue
|
|
425
|
+
|
|
426
|
+
preds_at_block = block_preds if inverse_map is None else block_preds[inverse_map]
|
|
427
|
+
if scores_b is None:
|
|
428
|
+
scores_b = torch.zeros(n_b, int(block_preds.size(-1)), device=device, dtype=torch.float32)
|
|
429
|
+
|
|
430
|
+
if aggregate == "max":
|
|
431
|
+
confidence, _ = preds_at_block.max(dim=-1)
|
|
432
|
+
better = confidence > confidence_b[point_ids]
|
|
433
|
+
scores_b[point_ids[better]] = preds_at_block[better]
|
|
434
|
+
confidence_b[point_ids[better]] = confidence[better]
|
|
435
|
+
weights_b[point_ids] = 1.0
|
|
436
|
+
continue
|
|
437
|
+
|
|
438
|
+
if aggregate == "vote":
|
|
439
|
+
preds_at_block = torch.nn.functional.one_hot(
|
|
440
|
+
preds_at_block.argmax(dim=-1), num_classes=int(preds_at_block.size(-1))
|
|
441
|
+
).to(scores_b.dtype)
|
|
442
|
+
|
|
443
|
+
scores_b.index_add_(0, point_ids, preds_at_block * w.unsqueeze(-1))
|
|
444
|
+
weights_b.index_add_(0, point_ids, w)
|
|
399
445
|
|
|
400
446
|
if scores_b is None:
|
|
401
447
|
continue
|
|
@@ -442,6 +488,7 @@ class SlidingWindowInferer(Inferer):
|
|
|
442
488
|
mode: WindowMode = "constant",
|
|
443
489
|
sigma_scale: float = 0.125,
|
|
444
490
|
roi_num_points: Optional[int] = None,
|
|
491
|
+
sw_batch_size: int = 1,
|
|
445
492
|
softmax: bool = True,
|
|
446
493
|
aggregate: AggregateMode = "mean",
|
|
447
494
|
transform: Optional[Callable[[Dict[str, Any]], Dict[str, Any]]] = None,
|
|
@@ -459,6 +506,7 @@ class SlidingWindowInferer(Inferer):
|
|
|
459
506
|
self.mode = mode
|
|
460
507
|
self.sigma_scale = sigma_scale
|
|
461
508
|
self.roi_num_points = roi_num_points
|
|
509
|
+
self.sw_batch_size = sw_batch_size
|
|
462
510
|
self.softmax = softmax
|
|
463
511
|
self.aggregate = aggregate
|
|
464
512
|
self.transform = transform
|
|
@@ -484,6 +532,7 @@ class SlidingWindowInferer(Inferer):
|
|
|
484
532
|
mode=self.mode,
|
|
485
533
|
sigma_scale=self.sigma_scale,
|
|
486
534
|
roi_num_points=self.roi_num_points,
|
|
535
|
+
sw_batch_size=self.sw_batch_size,
|
|
487
536
|
softmax=self.softmax,
|
|
488
537
|
aggregate=self.aggregate,
|
|
489
538
|
transform=self.transform,
|
|
@@ -25,11 +25,25 @@ class RelativePositionalEncoding(nn.Module):
|
|
|
25
25
|
r"""Table-based relative position bias added to the attention logits of a serialized patch.
|
|
26
26
|
|
|
27
27
|
Each axis of the clamped relative grid coordinates indexes its own slice of a shared table, and the three
|
|
28
|
-
per-head biases are summed.
|
|
28
|
+
per-head biases are summed. Clamping leaves $\text{rpe\_num}^3$ distinct offsets, so the three rows are
|
|
29
|
+
summed once per *combination* into a lookup table and the bias is a single gather. Summing them per point
|
|
30
|
+
pair instead would hold $(\text{pairs}, 3)$ offsets and $(\text{pairs}, 3, H)$ gathered rows, which on a
|
|
31
|
+
large cloud is the peak allocation of the whole model.
|
|
29
32
|
|
|
30
33
|
Args:
|
|
31
34
|
patch_size: Number of points attending to each other, setting the clamping boundary.
|
|
32
35
|
num_heads: Number of attention heads.
|
|
36
|
+
|
|
37
|
+
Shape:
|
|
38
|
+
- Input: $(P, K, 3)$ integer grid coordinates, $K$ points per patch.
|
|
39
|
+
- Output: $(P, H, K, K)$ bias, aligned with the attention logits.
|
|
40
|
+
|
|
41
|
+
Example:
|
|
42
|
+
```python
|
|
43
|
+
rpe = RelativePositionalEncoding(patch_size=8, num_heads=4)
|
|
44
|
+
bias = rpe(torch.randint(0, 16, (2, 8, 3)))
|
|
45
|
+
bias.shape # (2, 4, 8, 8)
|
|
46
|
+
```
|
|
33
47
|
"""
|
|
34
48
|
|
|
35
49
|
def __init__(self, patch_size: int, num_heads: int) -> None:
|
|
@@ -41,18 +55,24 @@ class RelativePositionalEncoding(nn.Module):
|
|
|
41
55
|
self.rpe_table = nn.Parameter(torch.zeros(3 * self.rpe_num, num_heads))
|
|
42
56
|
nn.init.trunc_normal_(self.rpe_table, std=0.02)
|
|
43
57
|
|
|
44
|
-
def
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
58
|
+
def _relative_index(self, coord: Tensor) -> Tensor:
|
|
59
|
+
r"""Clamped relative offset of every point pair along one axis. $(P, K) \to (P, K, K)$."""
|
|
60
|
+
relative = coord.unsqueeze(2) - coord.unsqueeze(1)
|
|
61
|
+
return relative.clamp(-self.coords_boundary, self.coords_boundary) + self.coords_boundary
|
|
48
62
|
|
|
49
|
-
|
|
63
|
+
def forward(self, pos_grid: Tensor) -> Tensor:
|
|
64
|
+
table = self.rpe_table.view(3, self.rpe_num, self.num_heads)
|
|
65
|
+
combined = table[0].view(-1, 1, 1, self.num_heads) + table[1].view(1, -1, 1, self.num_heads)
|
|
66
|
+
combined = combined + table[2].view(1, 1, -1, self.num_heads)
|
|
50
67
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
68
|
+
x, y, z = pos_grid.unbind(dim=-1)
|
|
69
|
+
idx = self._relative_index(x) * self.rpe_num + self._relative_index(y)
|
|
70
|
+
idx = idx * self.rpe_num + self._relative_index(z)
|
|
54
71
|
|
|
55
|
-
|
|
72
|
+
encodings = combined.view(-1, self.num_heads).index_select(0, idx.reshape(-1))
|
|
73
|
+
encodings = encodings.view(idx.shape + (self.num_heads,))
|
|
74
|
+
|
|
75
|
+
return encodings.permute(0, 3, 1, 2)
|
|
56
76
|
|
|
57
77
|
def extra_repr(self) -> str:
|
|
58
78
|
return f"patch_size={self.patch_size}, num_heads={self.num_heads}"
|
|
@@ -124,6 +144,7 @@ class SerializedAttention(nn.Module):
|
|
|
124
144
|
raise ValueError("Upcasting attention is not supported with Flash Attention.")
|
|
125
145
|
if upcast_softmax:
|
|
126
146
|
raise ValueError("Upcasting softmax is not supported with Flash Attention.")
|
|
147
|
+
|
|
127
148
|
self.channels = channels
|
|
128
149
|
self.num_heads = num_heads
|
|
129
150
|
self.patch_size = patch_size
|
|
@@ -155,8 +176,13 @@ class SerializedAttention(nn.Module):
|
|
|
155
176
|
pad_mode: PadMode = "above" if self.use_flash_attn else "all"
|
|
156
177
|
|
|
157
178
|
padded_indices, unpadded_indices, padded_batch = divisible_pad(
|
|
158
|
-
batch,
|
|
179
|
+
batch,
|
|
180
|
+
patch_size,
|
|
181
|
+
mode=pad_mode,
|
|
182
|
+
pad_fill="replicate",
|
|
183
|
+
return_inverse=True,
|
|
159
184
|
)
|
|
185
|
+
|
|
160
186
|
order = serialized_order[padded_indices] if serialized_order is not None else padded_indices
|
|
161
187
|
inverse = unpadded_indices[serialized_inverse] if serialized_inverse is not None else unpadded_indices
|
|
162
188
|
qkv = self.qkv(x)[order]
|
|
@@ -171,9 +197,11 @@ class SerializedAttention(nn.Module):
|
|
|
171
197
|
if self.upcast_attn:
|
|
172
198
|
q = q.float()
|
|
173
199
|
k = k.float()
|
|
200
|
+
|
|
174
201
|
attn = (q * self.scale) @ k.transpose(-2, -1)
|
|
175
202
|
if self.upcast_softmax:
|
|
176
203
|
attn = attn.float()
|
|
204
|
+
|
|
177
205
|
attn = attn.softmax(dim=-1)
|
|
178
206
|
attn = F.dropout(attn, p=self.attn_drop, training=self.training).to(qkv.dtype)
|
|
179
207
|
feat = (attn @ v).transpose(1, 2).reshape(-1, C)
|
|
@@ -243,8 +271,13 @@ class SerializedAttentionRPE(nn.Module):
|
|
|
243
271
|
patch_size = self.patch_size
|
|
244
272
|
|
|
245
273
|
padded_indices, unpadded_indices, _ = divisible_pad(
|
|
246
|
-
batch,
|
|
274
|
+
batch,
|
|
275
|
+
patch_size,
|
|
276
|
+
mode="all",
|
|
277
|
+
pad_fill="replicate",
|
|
278
|
+
return_inverse=True,
|
|
247
279
|
)
|
|
280
|
+
|
|
248
281
|
order = serialized_order[padded_indices] if serialized_order is not None else padded_indices
|
|
249
282
|
inverse = unpadded_indices[serialized_inverse] if serialized_inverse is not None else unpadded_indices
|
|
250
283
|
qkv = self.qkv(x)[order]
|
|
@@ -255,14 +288,12 @@ class SerializedAttentionRPE(nn.Module):
|
|
|
255
288
|
if self.upcast_attn:
|
|
256
289
|
q = q.float()
|
|
257
290
|
k = k.float()
|
|
258
|
-
attn = (q * self.scale) @ k.transpose(-2, -1)
|
|
259
|
-
|
|
260
|
-
pos_grid_ordered = pos_grid_ordered.reshape(-1, K, 3)
|
|
261
|
-
relative_pos = pos_grid_ordered.unsqueeze(2) - pos_grid_ordered.unsqueeze(1)
|
|
262
|
-
attn = attn + self.rpe(relative_pos)
|
|
263
291
|
|
|
292
|
+
attn = (q * self.scale) @ k.transpose(-2, -1)
|
|
293
|
+
attn = attn + self.rpe(pos_grid_ordered.reshape(-1, K, 3))
|
|
264
294
|
if self.upcast_softmax:
|
|
265
295
|
attn = attn.float()
|
|
296
|
+
|
|
266
297
|
attn = attn.softmax(dim=-1)
|
|
267
298
|
attn = F.dropout(attn, p=self.attn_drop, training=self.training).to(qkv.dtype)
|
|
268
299
|
feat = (attn @ v).transpose(1, 2).reshape(-1, C)
|
|
@@ -313,6 +344,7 @@ class SerializedAttentionRoPE(nn.Module):
|
|
|
313
344
|
raise ValueError("Upcasting attention is not supported with Flash Attention.")
|
|
314
345
|
if upcast_softmax:
|
|
315
346
|
raise ValueError("Upcasting softmax is not supported with Flash Attention.")
|
|
347
|
+
|
|
316
348
|
self.channels = channels
|
|
317
349
|
self.num_heads = num_heads
|
|
318
350
|
self.patch_size = patch_size
|
|
@@ -344,8 +376,13 @@ class SerializedAttentionRoPE(nn.Module):
|
|
|
344
376
|
pad_mode: PadMode = "above" if self.use_flash_attn else "all"
|
|
345
377
|
|
|
346
378
|
padded_indices, unpadded_indices, padded_batch = divisible_pad(
|
|
347
|
-
batch,
|
|
379
|
+
batch,
|
|
380
|
+
patch_size,
|
|
381
|
+
mode=pad_mode,
|
|
382
|
+
pad_fill="replicate",
|
|
383
|
+
return_inverse=True,
|
|
348
384
|
)
|
|
385
|
+
|
|
349
386
|
order = serialized_order[padded_indices] if serialized_order is not None else padded_indices
|
|
350
387
|
inverse = unpadded_indices[serialized_inverse] if serialized_inverse is not None else unpadded_indices
|
|
351
388
|
qkv = self.qkv(x)[order]
|
|
@@ -366,9 +403,11 @@ class SerializedAttentionRoPE(nn.Module):
|
|
|
366
403
|
if self.upcast_attn:
|
|
367
404
|
q = q.float()
|
|
368
405
|
k = k.float()
|
|
406
|
+
|
|
369
407
|
attn = (q * self.scale) @ k.transpose(-2, -1)
|
|
370
408
|
if self.upcast_softmax:
|
|
371
409
|
attn = attn.float()
|
|
410
|
+
|
|
372
411
|
attn = attn.softmax(dim=-1)
|
|
373
412
|
attn = F.dropout(attn, p=self.attn_drop, training=self.training).to(qkv.dtype)
|
|
374
413
|
feat = (attn @ v).transpose(1, 2).reshape(-1, C)
|
|
@@ -87,8 +87,11 @@ class ClassificationModel(nn.Module, metaclass=ABCMeta):
|
|
|
87
87
|
def forward_features(self, *args: Any, **kwargs: Any) -> Any:
|
|
88
88
|
r"""Encode a packed point cloud into features for `forward_head`.
|
|
89
89
|
|
|
90
|
-
Canonical signature: `forward_features(x, pos, batch)`, returning the encoded
|
|
91
|
-
the downsampled `pos` / `batch`).
|
|
90
|
+
Canonical signature: `forward_features(x, pos, batch, return_intermediates=False)`, returning the encoded
|
|
91
|
+
features (often with the downsampled `pos` / `batch`). With `return_intermediates=True`, the finer encoder
|
|
92
|
+
stages are appended as the last element of the return: a `List[FeaturesDict]` in fine-to-coarse order, each
|
|
93
|
+
entry holding `x`, `batch` and the stage's `pos` or `pos_grid`. Models add the keys their decoder needs or use
|
|
94
|
+
their own container when a stage is not a packed point set (dense tokens, voxel-point pairs).
|
|
92
95
|
"""
|
|
93
96
|
|
|
94
97
|
@abstractmethod
|
|
@@ -157,8 +160,11 @@ class SegmentationModel(nn.Module, metaclass=ABCMeta):
|
|
|
157
160
|
def forward_features(self, *args: Any, **kwargs: Any) -> Any:
|
|
158
161
|
r"""Encode a packed point cloud, keeping what `forward_decoder` needs for the skip connections.
|
|
159
162
|
|
|
160
|
-
Canonical signature: `forward_features(x, pos, batch)`, returning the encoder
|
|
161
|
-
the
|
|
163
|
+
Canonical signature: `forward_features(x, pos, batch, return_intermediates=False)`, returning the encoder
|
|
164
|
+
output. With `return_intermediates=True`, the finer encoder stages are appended as the last element of the
|
|
165
|
+
return: a `List[FeaturesDict]` in fine-to-coarse order, each entry holding `x`, `batch` and the stage's `pos`
|
|
166
|
+
or `pos_grid`. Models add the keys their decoder needs (e.g. `pooling_inverse`) or use their own container
|
|
167
|
+
when a stage is not a packed point set (dense tokens, voxel-point pairs).
|
|
162
168
|
"""
|
|
163
169
|
|
|
164
170
|
def forward_decoder(self, *args: Any, **kwargs: Any) -> Any:
|
|
@@ -14,7 +14,11 @@ import torch_pointcloud.transforms as T
|
|
|
14
14
|
from torch_pointcloud.datasets.scannet import SCANNET20_CLASSES
|
|
15
15
|
from torch_pointcloud.models._base import SegmentationModel
|
|
16
16
|
from torch_pointcloud.models._registry import WeightsDict, register_model
|
|
17
|
-
from torch_pointcloud.models.point_transformer_v3 import
|
|
17
|
+
from torch_pointcloud.models.point_transformer_v3 import (
|
|
18
|
+
AttentionKind,
|
|
19
|
+
PointTransformerV3Encoder,
|
|
20
|
+
SerializedFeaturesDict,
|
|
21
|
+
)
|
|
18
22
|
from torch_pointcloud.utils.data import DataKeys
|
|
19
23
|
from torch_pointcloud.utils.serialization import SerializationOrder
|
|
20
24
|
from torch_pointcloud.utils.types import OptTensor
|
|
@@ -154,7 +158,7 @@ class ConcertoSegmentation(SegmentationModel):
|
|
|
154
158
|
pos_grid: Tensor,
|
|
155
159
|
batch: Tensor,
|
|
156
160
|
return_intermediates: Literal[True],
|
|
157
|
-
) -> Tuple[Tensor, Tensor, Tensor, List[
|
|
161
|
+
) -> Tuple[Tensor, Tensor, Tensor, List[SerializedFeaturesDict]]: ...
|
|
158
162
|
|
|
159
163
|
@overload
|
|
160
164
|
def forward_features(
|
|
@@ -176,10 +180,10 @@ class ConcertoSegmentation(SegmentationModel):
|
|
|
176
180
|
return self.encoder.forward(x, pos_grid, batch, return_intermediates=True)
|
|
177
181
|
return self.encoder.forward(x, pos_grid, batch, return_intermediates=False)
|
|
178
182
|
|
|
179
|
-
def forward_decoder(self, x: Tensor, intermediates: List[
|
|
183
|
+
def forward_decoder(self, x: Tensor, intermediates: List[SerializedFeaturesDict]) -> Tuple[Tensor, Tensor, Tensor]:
|
|
180
184
|
pos_grid = batch = None
|
|
181
185
|
for intermediate in reversed(intermediates):
|
|
182
|
-
inverse = intermediate["
|
|
186
|
+
inverse = intermediate["pooling_inverse"]
|
|
183
187
|
x = torch.cat([intermediate["x"], x[inverse]], dim=-1)
|
|
184
188
|
pos_grid = intermediate["pos_grid"]
|
|
185
189
|
batch = intermediate["batch"]
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
{{ paper("1801.07829") }}
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
from typing import Any, Callable, Dict,
|
|
6
|
+
from typing import Any, Callable, Dict, Optional, Sequence, Tuple, Union
|
|
7
7
|
|
|
8
8
|
import torch
|
|
9
9
|
import torch.nn as nn
|
|
@@ -26,13 +26,6 @@ from ._base import ClassificationModel, SegmentationModel
|
|
|
26
26
|
from ._registry import WeightsDict, register_model
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
class DGCNNIntermediate(NamedTuple):
|
|
30
|
-
"""Per-block encoder features and their batch index."""
|
|
31
|
-
|
|
32
|
-
x: Tensor
|
|
33
|
-
batch: Tensor
|
|
34
|
-
|
|
35
|
-
|
|
36
29
|
class DGCNNEncoderBlock(nn.Module):
|
|
37
30
|
"""EdgeConv block: rebuilds a $k$-nearest-neighbor graph in feature space and runs an MLP over the edges.
|
|
38
31
|
|
|
@@ -27,7 +27,7 @@ from torch_pointcloud.utils.conversion import ensure_tuple, ensure_tuple_size
|
|
|
27
27
|
from torch_pointcloud.utils.data import DataKeys
|
|
28
28
|
from torch_pointcloud.utils.geometry import rodrigues_rotation_matrix, spherical_points_gradient, spherical_points_lloyd
|
|
29
29
|
from torch_pointcloud.utils.imports import _TORCH_CLUSTER_GITHUB_URL, _TORCH_SCATTER_GITHUB_URL, optional_import
|
|
30
|
-
from torch_pointcloud.utils.types import OptTensor
|
|
30
|
+
from torch_pointcloud.utils.types import OptTensor, PooledFeaturesDict
|
|
31
31
|
|
|
32
32
|
from ._base import ClassificationModel, SegmentationModel
|
|
33
33
|
from ._registry import WeightsDict, register_model
|
|
@@ -770,7 +770,7 @@ class KPFCNNEncoder(nn.Module):
|
|
|
770
770
|
pos: Tensor,
|
|
771
771
|
batch: Tensor,
|
|
772
772
|
return_intermediates: Literal[True],
|
|
773
|
-
) -> Tuple[Tensor, Tensor, Tensor, List[
|
|
773
|
+
) -> Tuple[Tensor, Tensor, Tensor, List[PooledFeaturesDict]]: ...
|
|
774
774
|
|
|
775
775
|
@overload
|
|
776
776
|
def forward(
|
|
@@ -788,12 +788,12 @@ class KPFCNNEncoder(nn.Module):
|
|
|
788
788
|
batch: Tensor,
|
|
789
789
|
return_intermediates: bool = False,
|
|
790
790
|
) -> Any:
|
|
791
|
-
intermediates = []
|
|
791
|
+
intermediates: List[PooledFeaturesDict] = []
|
|
792
792
|
for i, block in enumerate(self.blocks):
|
|
793
|
-
intermediate = {"x": x, "pos": pos, "batch": batch}
|
|
793
|
+
intermediate: PooledFeaturesDict = {"x": x, "pos": pos, "batch": batch}
|
|
794
794
|
x, pos, batch, inv = block(x, pos, batch, return_inverse=True)
|
|
795
795
|
|
|
796
|
-
if i > 0:
|
|
796
|
+
if return_intermediates and i > 0:
|
|
797
797
|
intermediate["pooling_inverse"] = inv
|
|
798
798
|
intermediates.append(intermediate)
|
|
799
799
|
|
|
@@ -994,7 +994,7 @@ class KPFCNNClassification(ClassificationModel):
|
|
|
994
994
|
pos: Tensor,
|
|
995
995
|
batch: Tensor,
|
|
996
996
|
return_intermediates: Literal[True],
|
|
997
|
-
) -> Tuple[Tensor, Tensor, Tensor, List[
|
|
997
|
+
) -> Tuple[Tensor, Tensor, Tensor, List[PooledFeaturesDict]]: ...
|
|
998
998
|
|
|
999
999
|
@overload
|
|
1000
1000
|
def forward_features(
|
|
@@ -1291,7 +1291,7 @@ class KPFCNNSegmentation(SegmentationModel):
|
|
|
1291
1291
|
pos: Tensor,
|
|
1292
1292
|
batch: Tensor,
|
|
1293
1293
|
return_intermediates: Literal[True],
|
|
1294
|
-
) -> Tuple[Tensor, Tensor, Tensor, List[
|
|
1294
|
+
) -> Tuple[Tensor, Tensor, Tensor, List[PooledFeaturesDict]]: ...
|
|
1295
1295
|
|
|
1296
1296
|
@overload
|
|
1297
1297
|
def forward_features(
|
|
@@ -1331,20 +1331,19 @@ class KPFCNNSegmentation(SegmentationModel):
|
|
|
1331
1331
|
else:
|
|
1332
1332
|
x = self.stem(x)
|
|
1333
1333
|
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
intermediates.extend(encoder_intermediates)
|
|
1334
|
+
if not return_intermediates:
|
|
1335
|
+
return self.encoder(x, pos, batch)
|
|
1337
1336
|
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
return x, pos, batch
|
|
1337
|
+
skip: PooledFeaturesDict = {"x": x, "pos": pos, "batch": batch}
|
|
1338
|
+
x, pos, batch, intermediates = self.encoder(x, pos, batch, return_intermediates=True)
|
|
1339
|
+
return x, pos, batch, [skip, *intermediates]
|
|
1341
1340
|
|
|
1342
1341
|
def forward_decoder(
|
|
1343
1342
|
self,
|
|
1344
1343
|
x: Tensor,
|
|
1345
1344
|
pos: Tensor,
|
|
1346
1345
|
batch: Tensor,
|
|
1347
|
-
intermediates: List[
|
|
1346
|
+
intermediates: List[PooledFeaturesDict],
|
|
1348
1347
|
) -> Tensor:
|
|
1349
1348
|
x, _, _ = self.decoder(x, pos, batch, intermediates)
|
|
1350
1349
|
return x
|