Skip to content

Commit

Permalink
Changes related to google-research#13: Adds focal, fov
Browse files Browse the repository at this point in the history
  • Loading branch information
Achint08 committed May 30, 2022
1 parent cad21f4 commit fb9909b
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 7 deletions.
54 changes: 50 additions & 4 deletions visu3d/dc_arrays/camera_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ class implementation.
repr=False,
init=False,
)
focal_length: Tuple[float, float]

@property
def h(self) -> int:
Expand All @@ -118,14 +119,60 @@ def w(self) -> int:

@property
def hw(self) -> tuple[int, int]:
"""`(Height, Width)` in pixel (for usage in `(i, j)` coordinates)."""
"""`(Height, Width)` in pixel (for usage in `(u, v)` coordinates)."""
return (self.h, self.w)

@property
def wh(self) -> tuple[int, int]:
"""`(Width, Height)` in pixel (for usage in `(u, v)` coordinates)."""
"""`(Width, Height)` in pixel (for usage in `(i, j)` coordinates)."""
return (self.w, self.h)

@property
def fw(self) -> float:
"""Focal length (along x-axis) in pixels (for usage in `(i, j)` coordinates)."""
return self.focal_length[0]

@property
def fh(self) -> float:
"""Focal length (along y-axis) in pixels (for usage in `(i, j)` coordinates)."""
return self.focal_length[1]

@property
def focal_px_wh(self) -> tuple[float, float]:
"""Focal length in pixel (`(fw, fh)`)."""
return (self.fw, self.fh)

@property
def focal_px(self) -> float:
"""Unique Focal length in pixels (when fw == fh)."""

def _err_msg():
return (
'Cannot get `CameraSpec.focal_px` when fw and fh are '
f'different: {self.focal_px_wh}'
)

if self.fw != self.fh:
raise ValueError(_err_msg())

return self.fw

@property
def fov_w(self) -> float:
"""Field of view (horizontal) in radians (for usage in `(i, j)` coordinates)."""
return 2 * self.xnp.arctan(self.w / (2 * self.fw))

@property
def fov_h(self) -> float:
"""Field of view (vertical) in radians (for usage in `(i, j)` coordinates)."""
return 2 * self.xnp.arctan(self.h / (2 * self.fh))

@property
def fov(self) -> float:
"""Field of view in radians (`(fov_w, fov_h)`)."""

return (self.fov_w, self.fov_h)

# @abc.abstractmethod
@property
def px_from_cam(self) -> transformation.TransformBase:
Expand Down Expand Up @@ -300,8 +347,7 @@ def from_focal(
[0, 0, 1],
])
return cls(
K=K,
resolution=resolution,
K=K, resolution=resolution, focal_length=(focal_in_px, focal_in_px)
)

@property
Expand Down
14 changes: 13 additions & 1 deletion visu3d/dc_arrays/camera_spec_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@

H, W = 640, 480

FOCAL_PX = 35.

FIELD_OF_VIEW_W_RADIANS = 2 * np.arctan(W / (2 * FOCAL_PX))
FIELD_OF_VIEW_H_RADIANS = 2 * np.arctan(H / (2 * FOCAL_PX))


def make_camera_spec(
*,
Expand All @@ -34,7 +39,7 @@ def make_camera_spec(
) -> v3d.PinholeCamera:
spec = v3d.PinholeCamera.from_focal(
resolution=(H, W),
focal_in_px=35.,
focal_in_px=FOCAL_PX,
xnp=xnp,
)
spec = spec.broadcast_to(shape)
Expand All @@ -58,6 +63,13 @@ def test_camera_spec_init(
assert spec.hw == (H, W)
assert spec.shape == spec_shape
assert spec.K.shape == spec_shape + (3, 3)
assert spec.fw == FOCAL_PX
assert spec.fh == FOCAL_PX
assert spec.focal_px_wh == (FOCAL_PX, FOCAL_PX)
assert spec.focal_px == FOCAL_PX
assert spec.fov_w == FIELD_OF_VIEW_W_RADIANS
assert spec.fov_h == FIELD_OF_VIEW_H_RADIANS
assert spec.fov == (FIELD_OF_VIEW_W_RADIANS, FIELD_OF_VIEW_H_RADIANS)

if xnp is None:
xnp = np
Expand Down
14 changes: 12 additions & 2 deletions visu3d/dc_arrays/camera_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@
# Activate the fixture
set_tnp = enp.testing.set_tnp


H, W = 64, 128
FOCAL_PX = 34.

FIELD_OF_VIEW_W_RADIANS = 2 * np.arctan(W / (2 * FOCAL_PX))
FIELD_OF_VIEW_H_RADIANS = 2 * np.arctan(H / (2 * FOCAL_PX))


def _make_cam(
Expand All @@ -34,7 +37,7 @@ def _make_cam(
shape: v3d.typing.Shape,
) -> v3d.Camera:
"""Create a camera at (0, 4, 0) looking at the center."""
spec = v3d.PinholeCamera.from_focal(resolution=(H, W), focal_in_px=34.)
spec = v3d.PinholeCamera.from_focal(resolution=(H, W), focal_in_px=FOCAL_PX)
cam = v3d.Camera.from_look_at(
spec=spec.as_xnp(xnp),
pos=[0, 4, 0], # Camera on the `y` axis
Expand All @@ -59,6 +62,13 @@ def test_camera_properties(xnp: enp.NpModule, shape: v3d.typing.Shape):
assert cam.w == W
assert cam.wh == (W, H)
assert cam.hw == (H, W)
assert cam.spec.fw == FOCAL_PX
assert cam.spec.fh == FOCAL_PX
assert cam.spec.focal_px_wh == (FOCAL_PX, FOCAL_PX)
assert cam.spec.focal_px == FOCAL_PX
assert cam.spec.fov_w == FIELD_OF_VIEW_W_RADIANS
assert cam.spec.fov_h == FIELD_OF_VIEW_H_RADIANS
assert cam.spec.fov == (FIELD_OF_VIEW_W_RADIANS, FIELD_OF_VIEW_H_RADIANS)


@enp.testing.parametrize_xnp()
Expand Down

0 comments on commit fb9909b

Please sign in to comment.