9
9
from common_testing import TestCaseMixin
10
10
from pytorch3d .loss import chamfer_distance
11
11
from pytorch3d .structures .pointclouds import Pointclouds
12
- from pytorch3d .structures .utils import list_to_padded
13
12
14
13
15
14
# Output of init_pointclouds
@@ -24,38 +23,39 @@ def setUp(self) -> None:
24
23
torch .manual_seed (1 )
25
24
26
25
@staticmethod
27
- def init_pointclouds (N , P1 , P2 , device , requires_grad : bool = True ):
26
+ def init_pointclouds (
27
+ N , P1 , P2 , device , requires_grad : bool = True , allow_empty : bool = True
28
+ ):
28
29
"""
29
30
Create 2 pointclouds object and associated padded points/normals tensors by
30
31
starting from lists. The clouds and tensors have the same data. The
31
32
leaf nodes for the clouds are a list of tensors. The padded tensor can be
32
33
used directly as a leaf node.
33
34
"""
34
- p1_lengths = torch .randint (P1 , size = (N ,), dtype = torch .int64 , device = device )
35
- p2_lengths = torch .randint (P2 , size = (N ,), dtype = torch .int64 , device = device )
35
+ low = 0 if allow_empty else 1
36
+ p1_lengths = torch .randint (low , P1 , size = (N ,), dtype = torch .int64 , device = device )
37
+ p2_lengths = torch .randint (low , P2 , size = (N ,), dtype = torch .int64 , device = device )
36
38
weights = torch .rand ((N ,), dtype = torch .float32 , device = device )
37
39
38
40
# list of points and normals tensors
41
+ p1 = torch .rand ((N , P1 , 3 ), dtype = torch .float32 , device = device )
42
+ p2 = torch .rand ((N , P2 , 3 ), dtype = torch .float32 , device = device )
43
+ n1 = torch .rand ((N , P1 , 3 ), dtype = torch .float32 , device = device )
44
+ n2 = torch .rand ((N , P2 , 3 ), dtype = torch .float32 , device = device )
45
+ n1 /= n1 .norm (dim = - 1 , p = 2 , keepdim = True )
46
+ n2 /= n2 .norm (dim = - 1 , p = 2 , keepdim = True )
47
+
39
48
p1_list = []
40
49
p2_list = []
41
50
n1_list = []
42
51
n2_list = []
43
52
for i in range (N ):
44
53
l1 = p1_lengths [i ]
45
54
l2 = p2_lengths [i ]
46
- p1_list .append (torch .rand ((l1 , 3 ), dtype = torch .float32 , device = device ))
47
- p2_list .append (torch .rand ((l2 , 3 ), dtype = torch .float32 , device = device ))
48
- n1_list .append (torch .rand ((l1 , 3 ), dtype = torch .float32 , device = device ))
49
- n2_list .append (torch .rand ((l2 , 3 ), dtype = torch .float32 , device = device ))
50
-
51
- n1_list = [n / n .norm (dim = - 1 , p = 2 , keepdim = True ) for n in n1_list ]
52
- n2_list = [n / n .norm (dim = - 1 , p = 2 , keepdim = True ) for n in n2_list ]
53
-
54
- # Clone the lists and initialize padded tensors.
55
- p1 = list_to_padded ([p .clone () for p in p1_list ])
56
- p2 = list_to_padded ([p .clone () for p in p2_list ])
57
- n1 = list_to_padded ([p .clone () for p in n1_list ])
58
- n2 = list_to_padded ([p .clone () for p in n2_list ])
55
+ p1_list .append (p1 [i , :l1 ].clone ())
56
+ p2_list .append (p2 [i , :l2 ].clone ())
57
+ n1_list .append (n1 [i , :l1 ].clone ())
58
+ n2_list .append (n2 [i , :l2 ].clone ())
59
59
60
60
# Set requires_grad for all tensors in the lists and
61
61
# padded tensors.
@@ -313,7 +313,9 @@ def test_chamfer_pointcloud_object_withnormals(self):
313
313
314
314
# Reinitialize all the tensors so that the
315
315
# backward pass can be computed.
316
- points_normals = TestChamfer .init_pointclouds (N , P1 , P2 , device )
316
+ points_normals = TestChamfer .init_pointclouds (
317
+ N , P1 , P2 , device , allow_empty = False
318
+ )
317
319
318
320
# Chamfer with pointclouds as input.
319
321
cham_cloud , norm_cloud = chamfer_distance (
@@ -371,7 +373,9 @@ def test_chamfer_pointcloud_object_nonormals(self):
371
373
372
374
# Reinitialize all the tensors so that the
373
375
# backward pass can be computed.
374
- points_normals = TestChamfer .init_pointclouds (N , P1 , P2 , device )
376
+ points_normals = TestChamfer .init_pointclouds (
377
+ N , P1 , P2 , device , allow_empty = False
378
+ )
375
379
376
380
# Chamfer with pointclouds as input.
377
381
cham_cloud , _ = chamfer_distance (
@@ -560,7 +564,7 @@ def _check_grad_by_type(self, x1, x2, lengths=None):
560
564
561
565
# List of tensors vs padded tensor
562
566
for i in range (len (x1 )):
563
- self .assertClose (x1 [i ].grad , x2 .grad [i , : lengths [i ]])
567
+ self .assertClose (x1 [i ].grad , x2 .grad [i , : lengths [i ]], atol = 1e-7 )
564
568
self .assertTrue (x2 .grad [i , lengths [i ] :].sum ().item () == 0.0 )
565
569
elif all (torch .is_tensor (p ) for p in [x1 , x2 ]):
566
570
# Two tensors
0 commit comments