Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more interpolation modes up to order 5. #31

Merged
merged 2 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions py360convert/__main__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import argparse
import sys
from pathlib import Path
from typing import get_args

import numpy as np
from PIL import Image

import py360convert
from py360convert.utils import InterpolationMode


def _assert_height_width(args):
Expand Down Expand Up @@ -46,7 +48,7 @@ def main():
c2e_parser.add_argument("--height", "-h", type=int, required=True, help="Output image height in pixels.")
c2e_parser.add_argument("--width", "-w", type=int, required=True, help="Output image width in pixels.")
c2e_parser.add_argument(
"--mode", "-m", default="bilinear", choices=["bilinear", "nearest"], help="Resampling method."
"--mode", "-m", default="bilinear", choices=get_args(InterpolationMode), help="Resampling method."
)

e2c_parser = subparsers.add_parser("e2c", help="Convert equirectangular to cubemap.", add_help=False)
Expand All @@ -58,7 +60,7 @@ def main():
e2c_parser.add_argument("--width", "-w", type=int, help="Output image width in pixels.")
e2c_parser.add_argument("--size", "-s", type=int, help="Side length of each cube face. Overrides height/width.")
e2c_parser.add_argument(
"--mode", "-m", default="bilinear", choices=["bilinear", "nearest"], help="Resampling method."
"--mode", "-m", default="bilinear", choices=get_args(InterpolationMode), help="Resampling method."
)

e2p_parser = subparsers.add_parser("e2p", help="Convert equirectangular to perspective.", add_help=False)
Expand Down Expand Up @@ -88,7 +90,7 @@ def main():
help="Roll camera degrees. Positive values rotate counterclockwise; negative values rotate clockwise.",
)
e2p_parser.add_argument(
"--mode", "-m", default="bilinear", choices=["bilinear", "nearest"], help="Resampling method."
"--mode", "-m", default="bilinear", choices=get_args(InterpolationMode), help="Resampling method."
)

args = parser.parse_args()
Expand Down
8 changes: 2 additions & 6 deletions py360convert/c2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
cube_list2h,
equirect_facetype,
equirect_uvgrid,
mode_to_order,
sample_cubefaces,
)

Expand Down Expand Up @@ -72,12 +73,7 @@ def c2e(
np.ndarray
Equirectangular image.
"""
if mode == "bilinear":
order = 1
elif mode == "nearest":
order = 0
else:
raise ValueError(f'Unknown mode "{mode}".')
order = mode_to_order(mode)

if cube_format == "horizon":
if not isinstance(cubemap, np.ndarray):
Expand Down
8 changes: 2 additions & 6 deletions py360convert/e2c.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
cube_h2dice,
cube_h2dict,
cube_h2list,
mode_to_order,
sample_equirec,
uv2coor,
xyz2uv,
Expand Down Expand Up @@ -77,12 +78,7 @@ def e2c(
squeeze = False

h, w = e_img.shape[:2]
if mode == "bilinear":
order = 1
elif mode == "nearest":
order = 0
else:
raise ValueError(f'Unknown mode: "{mode}".')
order = mode_to_order(mode)

xyz = xyzcube(face_w)
uv = xyz2uv(xyz)
Expand Down
8 changes: 2 additions & 6 deletions py360convert/e2p.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from .utils import (
DType,
InterpolationMode,
mode_to_order,
sample_equirec,
uv2coor,
xyz2uv,
Expand Down Expand Up @@ -64,12 +65,7 @@ def e2p(

in_rot = np.deg2rad(in_rot_deg)

if mode == "bilinear":
order = 1
elif mode == "nearest":
order = 0
else:
raise ValueError(f'Unknown mode: "{mode}".')
order = mode_to_order(mode)

u = -u_deg * np.pi / 180
v = v_deg * np.pi / 180
Expand Down
48 changes: 47 additions & 1 deletion py360convert/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,57 @@
from numpy.typing import NDArray
from scipy.ndimage import map_coordinates

_mode_to_order = {
"nearest": 0,
"linear": 1,
"bilinear": 1,
"biquadratic": 2,
"quadratic": 2,
"quad": 2,
"bicubic": 3,
"cubic": 3,
"biquartic": 4,
"quartic": 4,
"biquintic": 5,
"quintic": 5,
}

CubeFormat = Literal["horizon", "list", "dict", "dice"]
InterpolationMode = Literal["bilinear", "nearest"]
InterpolationMode = Literal[
"nearest",
"linear",
"bilinear",
"biquadratic",
"quadratic",
"quad",
"bicubic",
"cubic",
"biquartic",
"quartic",
"biquintic",
"quintic",
]
DType = TypeVar("DType", bound=np.generic, covariant=True)


def mode_to_order(mode: InterpolationMode) -> int:
"""Convert a human-friendly interpolation string to integer equivalent.

Parameters
----------
mode: str
Human-friendly interpolation string.

Returns
-------
The order of the spline interpolation
"""
try:
return _mode_to_order[mode.lower()]
except KeyError:
raise ValueError(f'Unknown mode "{mode}".') from None


def xyzcube(face_w: int) -> NDArray[np.float32]:
"""
Return the xyz coordinates of the unit cube in [F R B L U D] format.
Expand Down
Loading