@@ -192,6 +192,7 @@ def add_pointclouds_to_volumes(
192
192
initial_volumes : "Volumes" ,
193
193
mode : str = "trilinear" ,
194
194
min_weight : float = 1e-4 ,
195
+ _python : bool = False ,
195
196
) -> "Volumes" :
196
197
"""
197
198
Add a batch of point clouds represented with a `Pointclouds` structure
@@ -249,6 +250,8 @@ def add_pointclouds_to_volumes(
249
250
min_weight: A scalar controlling the lowest possible total per-voxel
250
251
weight used to normalize the features accumulated in a voxel.
251
252
Only active for `mode==trilinear`.
253
+ _python: Set to True to use a pure Python implementation, e.g. for test
254
+ purposes, which requires more memory and may be slower.
252
255
253
256
Returns:
254
257
updated_volumes: Output `Volumes` structure containing the conversion result.
@@ -283,6 +286,7 @@ def add_pointclouds_to_volumes(
283
286
grid_sizes = initial_volumes .get_grid_sizes (),
284
287
mask = mask ,
285
288
mode = mode ,
289
+ _python = _python ,
286
290
)
287
291
288
292
return initial_volumes .update_padded (
@@ -299,6 +303,7 @@ def add_points_features_to_volume_densities_features(
299
303
min_weight : float = 1e-4 ,
300
304
mask : Optional [torch .Tensor ] = None ,
301
305
grid_sizes : Optional [torch .LongTensor ] = None ,
306
+ _python : bool = False ,
302
307
) -> Tuple [torch .Tensor , torch .Tensor ]:
303
308
"""
304
309
Convert a batch of point clouds represented with tensors of per-point
@@ -340,6 +345,7 @@ def add_points_features_to_volume_densities_features(
340
345
grid_sizes: `LongTensor` of shape (minibatch, 3) representing the
341
346
spatial resolutions of each of the the non-flattened `volumes` tensors,
342
347
or None to indicate the whole volume is used for every batch element.
348
+ _python: Set to True to use a pure Python implementation.
343
349
Returns:
344
350
volume_features: Output volume of shape `(minibatch, feature_dim, D, H, W)`
345
351
volume_densities: Occupancy volume of shape `(minibatch, 1, D, H, W)`
@@ -362,6 +368,66 @@ def add_points_features_to_volume_densities_features(
362
368
.expand (volume_densities .shape [0 ], 3 )
363
369
)
364
370
371
+ if _python :
372
+ return _add_points_features_to_volume_densities_features_python (
373
+ points_3d = points_3d ,
374
+ points_features = points_features ,
375
+ volume_densities = volume_densities ,
376
+ volume_features = volume_features ,
377
+ mode = mode ,
378
+ min_weight = min_weight ,
379
+ mask = mask ,
380
+ grid_sizes = grid_sizes ,
381
+ )
382
+
383
+ if mode == "trilinear" :
384
+ splat = True
385
+ elif mode == "nearest" :
386
+ splat = False
387
+ else :
388
+ raise ValueError ('No such interpolation mode "%s"' % mode )
389
+ volume_densities , volume_features = _points_to_volumes (
390
+ points_3d ,
391
+ points_features ,
392
+ volume_densities ,
393
+ volume_features ,
394
+ grid_sizes ,
395
+ 1.0 , # point_weight
396
+ mask ,
397
+ True , # align_corners
398
+ splat ,
399
+ )
400
+ if splat :
401
+ # divide each feature by the total weight of the votes
402
+ volume_features = volume_features / volume_densities .clamp (min_weight )
403
+ else :
404
+ # divide each feature by the total weight of the votes
405
+ volume_features = volume_features / volume_densities .clamp (1.0 )
406
+
407
+ return volume_features , volume_densities
408
+
409
+
410
+ def _add_points_features_to_volume_densities_features_python (
411
+ * ,
412
+ points_3d : torch .Tensor ,
413
+ points_features : torch .Tensor ,
414
+ volume_densities : torch .Tensor ,
415
+ volume_features : Optional [torch .Tensor ],
416
+ mode : str ,
417
+ min_weight : float ,
418
+ mask : Optional [torch .Tensor ],
419
+ grid_sizes : torch .LongTensor ,
420
+ ) -> Tuple [torch .Tensor , torch .Tensor ]:
421
+ """
422
+ Python implementation for add_points_features_to_volume_densities_features.
423
+
424
+ Returns:
425
+ volume_features: Output volume of shape `(minibatch, feature_dim, D, H, W)`
426
+ volume_densities: Occupancy volume of shape `(minibatch, 1, D, H, W)`
427
+ containing the total amount of votes cast to each of the voxels.
428
+ """
429
+ ba , n_points , feature_dim = points_features .shape
430
+
365
431
# flatten densities and features
366
432
v_shape = volume_densities .shape [2 :]
367
433
volume_densities_flatten = volume_densities .view (ba , - 1 , 1 )
@@ -376,7 +442,7 @@ def add_points_features_to_volume_densities_features(
376
442
volume_features_flatten = volume_features .view (ba , feature_dim , n_voxels )
377
443
378
444
if mode == "trilinear" : # do the splatting (trilinear interp)
379
- volume_features , volume_densities = splat_points_to_volumes (
445
+ volume_features , volume_densities = _splat_points_to_volumes (
380
446
points_3d ,
381
447
points_features ,
382
448
volume_densities_flatten ,
@@ -386,7 +452,7 @@ def add_points_features_to_volume_densities_features(
386
452
min_weight = min_weight ,
387
453
)
388
454
elif mode == "nearest" : # nearest neighbor interp
389
- volume_features , volume_densities = round_points_to_volumes (
455
+ volume_features , volume_densities = _round_points_to_volumes (
390
456
points_3d ,
391
457
points_features ,
392
458
volume_densities_flatten ,
@@ -400,7 +466,6 @@ def add_points_features_to_volume_densities_features(
400
466
# reshape into the volume shape
401
467
volume_features = volume_features .view (ba , feature_dim , * v_shape )
402
468
volume_densities = volume_densities .view (ba , 1 , * v_shape )
403
-
404
469
return volume_features , volume_densities
405
470
406
471
@@ -441,7 +506,7 @@ def _check_points_to_volumes_inputs(
441
506
)
442
507
443
508
444
- def splat_points_to_volumes (
509
+ def _splat_points_to_volumes (
445
510
points_3d : torch .Tensor ,
446
511
points_features : torch .Tensor ,
447
512
volume_densities : torch .Tensor ,
@@ -574,7 +639,7 @@ def splat_points_to_volumes(
574
639
return volume_features , volume_densities
575
640
576
641
577
- def round_points_to_volumes (
642
+ def _round_points_to_volumes (
578
643
points_3d : torch .Tensor ,
579
644
points_features : torch .Tensor ,
580
645
volume_densities : torch .Tensor ,
0 commit comments