|
4 | 4 | # This source code is licensed under the BSD-style license found in the
|
5 | 5 | # LICENSE file in the root directory of this source tree.
|
6 | 6 |
|
| 7 | +import pickle |
7 | 8 | import random
|
8 | 9 | import unittest
|
9 | 10 | from typing import List, Tuple, Union
|
|
15 | 16 | from pytorch3d.ops.iou_box3d import _box_planes, _box_triangles, box3d_overlap
|
16 | 17 | from pytorch3d.transforms.rotation_conversions import random_rotation
|
17 | 18 |
|
18 |
| - |
19 | 19 | OBJECTRON_TO_PYTORCH3D_FACE_IDX = [0, 4, 6, 2, 1, 5, 7, 3]
|
20 | 20 | DATA_DIR = get_tests_dir() / "data"
|
21 | 21 | DEBUG = False
|
@@ -167,6 +167,7 @@ def _test_iou(self, overlap_fn, device):
|
167 | 167 | device=vol.device,
|
168 | 168 | dtype=vol.dtype,
|
169 | 169 | ),
|
| 170 | + atol=1e-7, |
170 | 171 | )
|
171 | 172 |
|
172 | 173 | # 7th test: hand coded example and test with meshlab output
|
@@ -283,20 +284,36 @@ def _test_iou(self, overlap_fn, device):
|
283 | 284 | self.assertClose(vols, torch.tensor([[vol_inters]], device=device), atol=1e-1)
|
284 | 285 | self.assertClose(ious, torch.tensor([[iou]], device=device), atol=1e-1)
|
285 | 286 |
|
| 287 | + def _test_real_boxes(self, overlap_fn, device): |
| 288 | + data_filename = "./real_boxes.pkl" |
| 289 | + with open(DATA_DIR / data_filename, "rb") as f: |
| 290 | + example = pickle.load(f) |
| 291 | + |
| 292 | + verts1 = torch.FloatTensor(example["verts1"]) |
| 293 | + verts2 = torch.FloatTensor(example["verts2"]) |
| 294 | + boxes = torch.stack((verts1, verts2)).to(device) |
| 295 | + |
| 296 | + iou_expected = torch.eye(2).to(device) |
| 297 | + vol, iou = overlap_fn(boxes, boxes) |
| 298 | + self.assertClose(iou, iou_expected) |
| 299 | + |
286 | 300 | def test_iou_naive(self):
|
287 | 301 | device = get_random_cuda_device()
|
288 | 302 | self._test_iou(self._box3d_overlap_naive_batched, device)
|
289 | 303 | self._test_compare_objectron(self._box3d_overlap_naive_batched, device)
|
| 304 | + self._test_real_boxes(self._box3d_overlap_naive_batched, device) |
290 | 305 |
|
291 | 306 | def test_iou_cpu(self):
|
292 | 307 | device = torch.device("cpu")
|
293 | 308 | self._test_iou(box3d_overlap, device)
|
294 | 309 | self._test_compare_objectron(box3d_overlap, device)
|
| 310 | + self._test_real_boxes(box3d_overlap, device) |
295 | 311 |
|
296 | 312 | def test_iou_cuda(self):
|
297 | 313 | device = torch.device("cuda:0")
|
298 | 314 | self._test_iou(box3d_overlap, device)
|
299 | 315 | self._test_compare_objectron(box3d_overlap, device)
|
| 316 | + self._test_real_boxes(box3d_overlap, device) |
300 | 317 |
|
301 | 318 | def _test_compare_objectron(self, overlap_fn, device):
|
302 | 319 | # Load saved objectron data
|
@@ -656,7 +673,7 @@ def is_inside(
|
656 | 673 | n: torch.Tensor,
|
657 | 674 | points: torch.Tensor,
|
658 | 675 | return_proj: bool = True,
|
659 |
| - eps: float = 1e-6, |
| 676 | + eps: float = 1e-4, |
660 | 677 | ):
|
661 | 678 | """
|
662 | 679 | Computes whether point is "inside" the plane.
|
@@ -778,17 +795,17 @@ def clip_tri_by_plane_oneout(
|
778 | 795 | vout is "outside" the plane and vin1, vin2 are "inside"
|
779 | 796 | Returns:
|
780 | 797 | verts: tensor of shape (4, 3) containing the new vertices formed after clipping the
|
781 |
| - original intersectiong triangle (vout, vin1, vin2) |
| 798 | + original intersecting triangle (vout, vin1, vin2) |
782 | 799 | faces: tensor of shape (2, 3) defining the vertex indices forming the two new triangles
|
783 | 800 | which are "inside" the plane formed after clipping
|
784 | 801 | """
|
785 | 802 | device = plane.device
|
786 | 803 | # point of intersection between plane and (vin1, vout)
|
787 | 804 | pint1, a1 = plane_edge_point_of_intersection(plane, n, vin1, vout)
|
788 |
| - assert a1 >= eps and a1 <= 1.0, a1 |
| 805 | + assert a1 >= -eps and a1 <= 1.0 + eps, a1 |
789 | 806 | # point of intersection between plane and (vin2, vout)
|
790 | 807 | pint2, a2 = plane_edge_point_of_intersection(plane, n, vin2, vout)
|
791 |
| - assert a2 >= 0.0 and a2 <= 1.0, a2 |
| 808 | + assert a2 >= -eps and a2 <= 1.0 + eps, a2 |
792 | 809 |
|
793 | 810 | verts = torch.stack((vin1, pint1, pint2, vin2), dim=0) # 4x3
|
794 | 811 | faces = torch.tensor(
|
@@ -823,10 +840,10 @@ def clip_tri_by_plane_twoout(
|
823 | 840 | device = plane.device
|
824 | 841 | # point of intersection between plane and (vin, vout1)
|
825 | 842 | pint1, a1 = plane_edge_point_of_intersection(plane, n, vin, vout1)
|
826 |
| - assert a1 >= eps and a1 <= 1.0, a1 |
| 843 | + assert a1 >= -eps and a1 <= 1.0 + eps, a1 |
827 | 844 | # point of intersection between plane and (vin, vout2)
|
828 | 845 | pint2, a2 = plane_edge_point_of_intersection(plane, n, vin, vout2)
|
829 |
| - assert a2 >= eps and a2 <= 1.0, a2 |
| 846 | + assert a2 >= -eps and a2 <= 1.0 + eps, a2 |
830 | 847 |
|
831 | 848 | verts = torch.stack((vin, pint1, pint2), dim=0) # 3x3
|
832 | 849 | faces = torch.tensor(
|
@@ -917,6 +934,7 @@ def box3d_overlap_naive(box1: torch.Tensor, box2: torch.Tensor):
|
917 | 934 | `iou = vol / (vol1 + vol2 - vol)`
|
918 | 935 | """
|
919 | 936 | device = box1.device
|
| 937 | + |
920 | 938 | # For boxes1 we compute the unit directions n1 corresponding to quad_faces
|
921 | 939 | n1 = box_planar_dir(box1) # (6, 3)
|
922 | 940 | # For boxes2 we compute the unit directions n2 corresponding to quad_faces
|
|
0 commit comments