Skip to content

Commit b0515e1

Browse files
davidsonicfacebook-github-bot
authored andcommitted
Amend D38407094: Fisheye Camera for PyTorch3D
Summary: Amend FisheyeCamera by adding tests for all combination of params and for different batch_sizes. Reviewed By: kjchalup Differential Revision: D39176747 fbshipit-source-id: 830d30da24beeb2f0df52db0b17a4303ed53b59c
1 parent d4a1051 commit b0515e1

File tree

2 files changed

+162
-56
lines changed

2 files changed

+162
-56
lines changed

pytorch3d/renderer/fisheyecameras.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ def _compute_xr_yr_from_uv_distorted(
425425
# do Newton iterations to find xr_yr
426426
for _ in range(self.num_distortion_iters):
427427
# compute the estimated uvDistorted
428-
uv_distorted_est = xr_yr
428+
uv_distorted_est = xr_yr.clone()
429429
xr_yr_squared_norm = torch.pow(xr_yr, 2).sum(dim=-1, keepdim=True)
430430

431431
if self.use_tangential:
@@ -479,7 +479,6 @@ def _get_theta_from_norm_xr_yr(
479479
th: angle theta (in radians) of shape (...), E.g., (P), (1, P), (M, P)
480480
"""
481481
sh = list(th_radial_desired.shape)
482-
# th = th_radial_desired.clone()
483482
th = th_radial_desired
484483
c = torch.tensor(
485484
[2.0 * i + 3 for i in range(self.num_radial)], device=self.device
@@ -552,7 +551,7 @@ def _compute_duv_distorted_dxryr(
552551
+ 2.0 * xr_yr[..., 0] * tangential_params[..., 0]
553552
)
554553
else:
555-
duv_distorted_dxryr = torch.eye(2).view(*sh, 2, 2).expand(*sh, 1, 1)
554+
duv_distorted_dxryr = torch.eye(2).repeat(*sh, 1, 1)
556555

557556
if self.use_thin_prism:
558557
temp1 = 2.0 * (

tests/test_cameras.py

+160-53
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import math
3434
import typing
3535
import unittest
36+
from itertools import product
3637

3738
import numpy as np
3839
import torch
@@ -1389,7 +1390,7 @@ def setUpAriaCase(self) -> None:
13891390
thin_prism_params,
13901391
)
13911392

1392-
def setUpBatchCameras(self) -> None:
1393+
def setUpBatchCameras(self, combination: None) -> None:
13931394
super().setUp()
13941395
focal, principal_point, p_3d = self.setUpSimpleCase()
13951396
radial_params = torch.tensor(
@@ -1412,8 +1413,12 @@ def setUpBatchCameras(self) -> None:
14121413
radial_params = torch.cat([radial_params, radial_params1], dim=0)
14131414
tangential_params = torch.cat([tangential_params, tangential_params1], dim=0)
14141415
thin_prism_params = torch.cat([thin_prism_params, thin_prism_params1], dim=0)
1415-
1416+
if combination is None:
1417+
combination = [True, True, True]
14161418
cameras = FishEyeCameras(
1419+
use_radial=combination[0],
1420+
use_tangential=combination[1],
1421+
use_thin_prism=combination[2],
14171422
focal_length=focal,
14181423
principal_point=principal_point,
14191424
radial_params=radial_params,
@@ -1474,21 +1479,31 @@ def test_fisheye_against_perspective_cameras(self):
14741479

14751480
def test_project_shape_broadcasts(self):
14761481
focal, principal_point, p_3d = self.setUpSimpleCase()
1477-
# test case 1:
1478-
# 1 transform with points of shape (P, 3) -> (P, 3)
1479-
# 1 transform with points of shape (1, P, 3) -> (1, P, 3)
1480-
# 1 transform with points of shape (M, P, 3) -> (M, P, 3)
1481-
points = p_3d.repeat(1, 1, 1)
1482-
cameras = FishEyeCameras(
1483-
focal_length=focal,
1484-
principal_point=principal_point,
1485-
use_radial=False,
1486-
use_tangential=False,
1487-
use_thin_prism=False,
1488-
)
1489-
uv = cameras.transform_points(p_3d)
1490-
uv_point_batch = cameras.transform_points(points)
1491-
self.assertClose(uv_point_batch, uv.repeat(1, 1, 1))
1482+
torch.set_printoptions(precision=6)
1483+
combinations = product([0, 1], repeat=3)
1484+
for combination in combinations:
1485+
cameras = FishEyeCameras(
1486+
use_radial=combination[0],
1487+
use_tangential=combination[1],
1488+
use_thin_prism=combination[2],
1489+
focal_length=focal,
1490+
principal_point=principal_point,
1491+
)
1492+
# test case 1:
1493+
# 1 transform with points of shape (P, 3) -> (P, 3)
1494+
# 1 transform with points of shape (1, P, 3) -> (1, P, 3)
1495+
# 1 transform with points of shape (M, P, 3) -> (M, P, 3)
1496+
points = p_3d.repeat(1, 1, 1)
1497+
cameras = FishEyeCameras(
1498+
focal_length=focal,
1499+
principal_point=principal_point,
1500+
use_radial=False,
1501+
use_tangential=False,
1502+
use_thin_prism=False,
1503+
)
1504+
uv = cameras.transform_points(p_3d)
1505+
uv_point_batch = cameras.transform_points(points)
1506+
self.assertClose(uv_point_batch, uv.repeat(1, 1, 1))
14921507

14931508
points = p_3d.repeat(3, 1, 1)
14941509
uv_point_batch = cameras.transform_points(points)
@@ -1497,35 +1512,105 @@ def test_project_shape_broadcasts(self):
14971512
# test case 2
14981513
# test with N transforms and points of shape (P, 3) -> (N, P, 3)
14991514
# test with N transforms and points of shape (1, P, 3) -> (N, P, 3)
1500-
1501-
# first camera transform params
1502-
cameras = self.setUpBatchCameras()
1515+
torch.set_printoptions(sci_mode=False)
15031516
p_3d = torch.tensor(
15041517
[
1505-
[2.0, 3.0, 1.0],
15061518
[2.0, 3.0, 1.0],
15071519
[3.0, 2.0, 1.0],
15081520
]
15091521
)
15101522
expected_res = torch.tensor(
15111523
[
15121524
[
1513-
[493.0993, 499.6489, 1.0],
1514-
[493.0993, 499.6489, 1.0],
1515-
[579.6489, 413.0993, 1.0],
1525+
[
1526+
[800.000000, 960.000000, 1.000000],
1527+
[1040.000000, 720.000000, 1.000000],
1528+
],
1529+
[
1530+
[1929.862549, 2533.643311, 1.000000],
1531+
[2538.788086, 1924.717773, 1.000000],
1532+
],
1533+
],
1534+
[
1535+
[
1536+
[800.000000, 960.000000, 1.000000],
1537+
[1040.000000, 720.000000, 1.000000],
1538+
],
1539+
[
1540+
[1927.272095, 2524.220459, 1.000000],
1541+
[2536.197754, 1915.295166, 1.000000],
1542+
],
1543+
],
1544+
[
1545+
[
1546+
[800.000000, 960.000000, 1.000000],
1547+
[1040.000000, 720.000000, 1.000000],
1548+
],
1549+
[
1550+
[1930.050293, 2538.434814, 1.000000],
1551+
[2537.956543, 1927.569092, 1.000000],
1552+
],
1553+
],
1554+
[
1555+
[
1556+
[800.000000, 960.000000, 1.000000],
1557+
[1040.000000, 720.000000, 1.000000],
1558+
],
1559+
[
1560+
[1927.459839, 2529.011963, 1.000000],
1561+
[2535.366211, 1918.146484, 1.000000],
1562+
],
1563+
],
1564+
[
1565+
[
1566+
[493.099304, 499.648926, 1.000000],
1567+
[579.648926, 413.099304, 1.000000],
1568+
],
1569+
[
1570+
[1662.673950, 2132.860352, 1.000000],
1571+
[2138.005127, 1657.529053, 1.000000],
1572+
],
1573+
],
1574+
[
1575+
[
1576+
[493.099304, 499.648926, 1.000000],
1577+
[579.648926, 413.099304, 1.000000],
1578+
],
1579+
[
1580+
[1660.083496, 2123.437744, 1.000000],
1581+
[2135.414795, 1648.106445, 1.000000],
1582+
],
1583+
],
1584+
[
1585+
[
1586+
[493.099304, 499.648926, 1.000000],
1587+
[579.648926, 413.099304, 1.000000],
1588+
],
1589+
[
1590+
[1662.861816, 2137.651855, 1.000000],
1591+
[2137.173828, 1660.380371, 1.000000],
1592+
],
15161593
],
15171594
[
1518-
[1660.2700, 2128.2273, 1.0],
1519-
[1660.2700, 2128.2273, 1.0],
1520-
[2134.5815, 1650.9565, 1.0],
1595+
[
1596+
[493.099304, 499.648926, 1.000000],
1597+
[579.648926, 413.099304, 1.000000],
1598+
],
1599+
[
1600+
[1660.271240, 2128.229248, 1.000000],
1601+
[2134.583496, 1650.957764, 1.000000],
1602+
],
15211603
],
15221604
]
15231605
)
1524-
uv_point_batch = cameras.transform_points(p_3d)
1525-
self.assertClose(uv_point_batch, expected_res)
1606+
combinations = product([0, 1], repeat=3)
1607+
for i, combination in enumerate(combinations):
1608+
cameras = self.setUpBatchCameras(combination)
1609+
uv_point_batch = cameras.transform_points(p_3d)
1610+
self.assertClose(uv_point_batch, expected_res[i])
15261611

1527-
uv_point_batch = cameras.transform_points(p_3d.repeat(1, 1, 1))
1528-
self.assertClose(uv_point_batch, expected_res)
1612+
uv_point_batch = cameras.transform_points(p_3d.repeat(1, 1, 1))
1613+
self.assertClose(uv_point_batch, expected_res[i].repeat(1, 1, 1))
15291614

15301615
def test_cuda(self):
15311616
"""
@@ -1573,42 +1658,64 @@ def test_unproject_shape_broadcasts(self):
15731658
rep_3d = cameras.unproject_points(xy_depth)
15741659
expected_res = torch.tensor(
15751660
[
1576-
[3.0000, 2.0000, 1.0000],
1577-
[0.666667, 0.833333, 1.0000],
1578-
],
1579-
)
1580-
self.assertClose(rep_3d, expected_res)
1581-
1582-
rep_3d = cameras.unproject_points(xy_depth.repeat(3, 1, 1))
1583-
self.assertClose(rep_3d, expected_res.repeat(3, 1, 1))
1584-
1585-
# test case 2:
1586-
# N transforms with points of (P, 3) -> (N, P, 3)
1587-
# N transforms with points of (1, P, 3) -> (N, P, 3)
1588-
cameras = FishEyeCameras(
1589-
focal_length=focal.repeat(2, 1),
1590-
principal_point=principal_point.repeat(2, 1),
1591-
radial_params=radial_params.repeat(2, 1),
1592-
tangential_params=tangential_params.repeat(2, 1),
1593-
thin_prism_params=thin_prism_params.repeat(2, 1),
1661+
[[2.999442, 1.990583, 1.000000], [0.666728, 0.833142, 1.000000]],
1662+
[[2.997338, 2.005411, 1.000000], [0.666859, 0.834456, 1.000000]],
1663+
[[3.002090, 1.985229, 1.000000], [0.666537, 0.832025, 1.000000]],
1664+
[[2.999999, 2.000000, 1.000000], [0.666667, 0.833333, 1.000000]],
1665+
[[2.999442, 1.990583, 1.000000], [0.666728, 0.833142, 1.000000]],
1666+
[[2.997338, 2.005411, 1.000000], [0.666859, 0.834456, 1.000000]],
1667+
[[3.002090, 1.985229, 1.000000], [0.666537, 0.832025, 1.000000]],
1668+
[[2.999999, 2.000000, 1.000000], [0.666667, 0.833333, 1.000000]],
1669+
]
15941670
)
1595-
rep_3d = cameras.unproject_points(xy_depth)
1596-
self.assertClose(rep_3d, expected_res.repeat(2, 1, 1))
1671+
torch.set_printoptions(precision=6)
1672+
combinations = product([0, 1], repeat=3)
1673+
for i, combination in enumerate(combinations):
1674+
cameras = FishEyeCameras(
1675+
use_radial=combination[0],
1676+
use_tangential=combination[1],
1677+
use_thin_prism=combination[2],
1678+
focal_length=focal,
1679+
principal_point=principal_point,
1680+
radial_params=radial_params,
1681+
tangential_params=tangential_params,
1682+
thin_prism_params=thin_prism_params,
1683+
)
1684+
rep_3d = cameras.unproject_points(xy_depth)
1685+
self.assertClose(rep_3d, expected_res[i])
1686+
rep_3d = cameras.unproject_points(xy_depth.repeat(3, 1, 1))
1687+
self.assertClose(rep_3d, expected_res[i].repeat(3, 1, 1))
1688+
1689+
# test case 2:
1690+
# N transforms with points of (P, 3) -> (N, P, 3)
1691+
# N transforms with points of (1, P, 3) -> (N, P, 3)
1692+
cameras = FishEyeCameras(
1693+
use_radial=combination[0],
1694+
use_tangential=combination[1],
1695+
use_thin_prism=combination[2],
1696+
focal_length=focal.repeat(2, 1),
1697+
principal_point=principal_point.repeat(2, 1),
1698+
radial_params=radial_params.repeat(2, 1),
1699+
tangential_params=tangential_params.repeat(2, 1),
1700+
thin_prism_params=thin_prism_params.repeat(2, 1),
1701+
)
1702+
rep_3d = cameras.unproject_points(xy_depth)
1703+
self.assertClose(rep_3d, expected_res[i].repeat(2, 1, 1))
15971704

15981705
def test_unhandled_shape(self):
15991706
"""
16001707
Test error handling when shape of transforms
16011708
and points are not expected.
16021709
"""
1603-
cameras = self.setUpBatchCameras()
1710+
cameras = self.setUpBatchCameras(None)
16041711
points = torch.rand(3, 3, 1)
16051712
with self.assertRaises(ValueError):
16061713
cameras.transform_points(points)
16071714

16081715
def test_getitem(self):
16091716
# Check get item returns an instance of the same class
16101717
# with all the same keys
1611-
cam = self.setUpBatchCameras()
1718+
cam = self.setUpBatchCameras(None)
16121719
c0 = cam[0]
16131720
self.assertTrue(isinstance(c0, FishEyeCameras))
16141721
self.assertEqual(cam.__dict__.keys(), c0.__dict__.keys())

0 commit comments

Comments
 (0)