From 6dfa32692277735b369a5c7a28aceb47263d451a Mon Sep 17 00:00:00 2001 From: Nikhila Ravi Date: Thu, 7 Oct 2021 18:40:56 -0700 Subject: [PATCH] IOU box3d epsilon fix Summary: The epsilon value is important for determining whether vertices are inside/outside a plane. Reviewed By: gkioxari Differential Revision: D31485247 fbshipit-source-id: 5517575de7c02f1afa277d00e0190a81f44f5761 --- pytorch3d/csrc/iou_box3d/iou_utils.cuh | 3 ++- pytorch3d/csrc/iou_box3d/iou_utils.h | 2 +- tests/data/real_boxes.pkl | Bin 0 -> 1428 bytes tests/test_iou_box3d.py | 32 +++++++++++++++++++------ 4 files changed, 28 insertions(+), 9 deletions(-) create mode 100644 tests/data/real_boxes.pkl diff --git a/pytorch3d/csrc/iou_box3d/iou_utils.cuh b/pytorch3d/csrc/iou_box3d/iou_utils.cuh index 452cf7dc..243174a0 100644 --- a/pytorch3d/csrc/iou_box3d/iou_utils.cuh +++ b/pytorch3d/csrc/iou_box3d/iou_utils.cuh @@ -11,7 +11,8 @@ #include #include #include "utils/float_math.cuh" -#include "utils/geometry_utils.cuh" + +const auto kEpsilon = 1e-4; /* _PLANES and _TRIS define the 4- and 3-connectivity diff --git a/pytorch3d/csrc/iou_box3d/iou_utils.h b/pytorch3d/csrc/iou_box3d/iou_utils.h index fd5b37eb..d602eb3e 100644 --- a/pytorch3d/csrc/iou_box3d/iou_utils.h +++ b/pytorch3d/csrc/iou_box3d/iou_utils.h @@ -16,9 +16,9 @@ #include #include #include -#include "utils/geometry_utils.h" #include "utils/vec3.h" +const auto kEpsilon = 1e-4; /* _PLANES and _TRIS define the 4- and 3-connectivity of the 8 box corners. diff --git a/tests/data/real_boxes.pkl b/tests/data/real_boxes.pkl new file mode 100644 index 0000000000000000000000000000000000000000..e8b8117aab87fa8d8e730b88f8b5f5dfb3b7c6af GIT binary patch literal 1428 zcmaizT}TvB6vxHgm24}GN+NOq{+2_?4`-6Y9idaw*E z3hdb_qz!}WA%a5K>5F=Z#0M*>Xe2FKm3*+wTB~!;9bHXj_vQZX|9{W_+&SFUomVfo zlIVA)HM7NeGZmu zBZF-LJi+B~-Z})4^f^2z)b|C$77&;F+G|t*VSnt5F;ctK4LU+3dNZH`K%eP3k%9-LVfpyXzxxz?Iy{%dVO2tM5yZT9( zk(#!Z3s9O@8=wfgFxDW{MawQ)phCF&oCm!VPEXMz>C&6dZ;%K7^@pn|bvn9g#;f7T^(h9FJC@BBJv8IBvK+Q0=x5 zm~_Z#00?_iWgTv~Jm#AqVAAuI7AV5@O$?c^fdLf%MU}IHoGb)8JQyNX9>2brfJynk zjJVzV+k_35M|Qdi*!J$P1}Jv#BbmTp#~wR$1SYXRsMx)KT*D1#j-|;afz+|Y0)UsW zT)c#`W3|CRSyhF0B2*P>z&{JVK+}IqWmMpJbq7|6P||7*01@op(ZNVfV5g6_S#)k@ z^<;PgJ07m)s}M79?>X&w_zZh?Z`+<6N$xx&@%4Q2;J3*AO^p@;lX6;g0DIQSE)~@T lHggo;z@q=F?eGNlwD9ipkTQSox$J4-Gwj*DZCg8;{ST!Cs8|31 literal 0 HcmV?d00001 diff --git a/tests/test_iou_box3d.py b/tests/test_iou_box3d.py index f98e6582..f40ae3a3 100644 --- a/tests/test_iou_box3d.py +++ b/tests/test_iou_box3d.py @@ -4,6 +4,7 @@ # This source code is licensed under the BSD-style license found in the # LICENSE file in the root directory of this source tree. +import pickle import random import unittest from typing import List, Tuple, Union @@ -15,7 +16,6 @@ from pytorch3d.io import save_obj from pytorch3d.ops.iou_box3d import _box_planes, _box_triangles, box3d_overlap from pytorch3d.transforms.rotation_conversions import random_rotation - OBJECTRON_TO_PYTORCH3D_FACE_IDX = [0, 4, 6, 2, 1, 5, 7, 3] DATA_DIR = get_tests_dir() / "data" DEBUG = False @@ -167,6 +167,7 @@ class TestIoU3D(TestCaseMixin, unittest.TestCase): device=vol.device, dtype=vol.dtype, ), + atol=1e-7, ) # 7th test: hand coded example and test with meshlab output @@ -283,20 +284,36 @@ class TestIoU3D(TestCaseMixin, unittest.TestCase): self.assertClose(vols, torch.tensor([[vol_inters]], device=device), atol=1e-1) self.assertClose(ious, torch.tensor([[iou]], device=device), atol=1e-1) + def _test_real_boxes(self, overlap_fn, device): + data_filename = "./real_boxes.pkl" + with open(DATA_DIR / data_filename, "rb") as f: + example = pickle.load(f) + + verts1 = torch.FloatTensor(example["verts1"]) + verts2 = torch.FloatTensor(example["verts2"]) + boxes = torch.stack((verts1, verts2)).to(device) + + iou_expected = torch.eye(2).to(device) + vol, iou = overlap_fn(boxes, boxes) + self.assertClose(iou, iou_expected) + def test_iou_naive(self): device = get_random_cuda_device() self._test_iou(self._box3d_overlap_naive_batched, device) self._test_compare_objectron(self._box3d_overlap_naive_batched, device) + self._test_real_boxes(self._box3d_overlap_naive_batched, device) def test_iou_cpu(self): device = torch.device("cpu") self._test_iou(box3d_overlap, device) self._test_compare_objectron(box3d_overlap, device) + self._test_real_boxes(box3d_overlap, device) def test_iou_cuda(self): device = torch.device("cuda:0") self._test_iou(box3d_overlap, device) self._test_compare_objectron(box3d_overlap, device) + self._test_real_boxes(box3d_overlap, device) def _test_compare_objectron(self, overlap_fn, device): # Load saved objectron data @@ -656,7 +673,7 @@ def is_inside( n: torch.Tensor, points: torch.Tensor, return_proj: bool = True, - eps: float = 1e-6, + eps: float = 1e-4, ): """ Computes whether point is "inside" the plane. @@ -778,17 +795,17 @@ def clip_tri_by_plane_oneout( vout is "outside" the plane and vin1, vin2 are "inside" Returns: verts: tensor of shape (4, 3) containing the new vertices formed after clipping the - original intersectiong triangle (vout, vin1, vin2) + original intersecting triangle (vout, vin1, vin2) faces: tensor of shape (2, 3) defining the vertex indices forming the two new triangles which are "inside" the plane formed after clipping """ device = plane.device # point of intersection between plane and (vin1, vout) pint1, a1 = plane_edge_point_of_intersection(plane, n, vin1, vout) - assert a1 >= eps and a1 <= 1.0, a1 + assert a1 >= -eps and a1 <= 1.0 + eps, a1 # point of intersection between plane and (vin2, vout) pint2, a2 = plane_edge_point_of_intersection(plane, n, vin2, vout) - assert a2 >= 0.0 and a2 <= 1.0, a2 + assert a2 >= -eps and a2 <= 1.0 + eps, a2 verts = torch.stack((vin1, pint1, pint2, vin2), dim=0) # 4x3 faces = torch.tensor( @@ -823,10 +840,10 @@ def clip_tri_by_plane_twoout( device = plane.device # point of intersection between plane and (vin, vout1) pint1, a1 = plane_edge_point_of_intersection(plane, n, vin, vout1) - assert a1 >= eps and a1 <= 1.0, a1 + assert a1 >= -eps and a1 <= 1.0 + eps, a1 # point of intersection between plane and (vin, vout2) pint2, a2 = plane_edge_point_of_intersection(plane, n, vin, vout2) - assert a2 >= eps and a2 <= 1.0, a2 + assert a2 >= -eps and a2 <= 1.0 + eps, a2 verts = torch.stack((vin, pint1, pint2), dim=0) # 3x3 faces = torch.tensor( @@ -917,6 +934,7 @@ def box3d_overlap_naive(box1: torch.Tensor, box2: torch.Tensor): `iou = vol / (vol1 + vol2 - vol)` """ device = box1.device + # For boxes1 we compute the unit directions n1 corresponding to quad_faces n1 = box_planar_dir(box1) # (6, 3) # For boxes2 we compute the unit directions n2 corresponding to quad_faces