Features of this project:
- Conversion between cubemap and equirectangular
- Equirectangular to planar
- Pure python implementation and depend only on numpy and scipy
- Vectorization implementation (in most of the place)
c2e
takes 300ms ande2c
takes 160ms on 1.6 GHz Intel Core i5 CPU
pip install py360convert
You can use the library with import py360convert
and through the command line tool convert360
.
The convert360 command line tool can be run like so. Use convert360 -h
for details. The convert360 python script is also doubles as ab example code for how to use this as a package in your code.
convert360 e2c assets/example_input.png out.png --size 200
Input Equirectangular | Output Cubemap |
---|---|
convert360 c2e assets/example_e2c.png out.png --width 800 --height 400
Input Cubemap | Output Equirectangular |
---|---|
You can see the blurring artifacts in the polar region because the equirectangular in above figure are resampled twice (e2c
then c2e
).
convert360 e2p assets/example_input.png out.png --width 300 --height 300 --yaw 120 --pitch 23
Input Equirectangular | Output Perspective |
---|---|
Convert the given cubemap to equirectangular.
Parameters:
-
cubemap
: Numpy array or list/dict of numpy array (depend oncube_format
). -
h
: Output equirectangular height. -
w
: Output equirectangular width. -
mode:str
: Interpolation method; typicallybilinear
ornearest
. Valid options: "nearest", "linear", "bilinear", "biquadratic", "quadratic", "quad", "bicubic", "cubic", "biquartic", "quartic", "biquintic", "quintic". -
cube_format
: Options:'dice'
(default),'horizon'
or'dict'
or'list'
. Indicates the format of the givencubemap
.-
Say that each face of the cube is in shape of
256 (width) x 256 (height)
-
'dice'
: a numpy array in shape of1024 x 768
like below example -
'horizon'
: a numpy array in shape of1536 x 256
like below example -
'list'
: alist
with 6 elements each of which is a numpy array in the shape of256 x 256
. It's just converted from 'horizon' format with one line of code:np.split(cube_h, 6, axis=1)
. -
'dict'
: adict
with 6 elements with keys'F', 'R', 'B', 'L', 'U', 'D'
each of which is a numpy array in shape of256 x 256
. -
Please refer to the source code if you still have any questions about the conversion between formats.
-
Convert the given equirectangular to cubemap.
Parameters:
e_img: NDArray
: Numpy array with shape [H, W, C].face_w: int
: The width of each cube face.mode:str
: Seec2e
.cube_format:str
: Seec2e
.
Take perspective image from given equirectangular. Parameters:
e_img
: Numpy array with shape [H, W, C].fov_deg
: Field of view given in int or tuple(h_fov_deg, v_fov_deg)
.u_deg
: Horizontal viewing angle in range [-pi, pi]. (- Left / + Right).v_deg
: Vertical viewing angle in range [-pi/2, pi/2]. (- Down/ + Up).out_hw
: Output image(height, width)
in tuple.in_rot_deg
: Inplane rotation.mode
:bilinear
ornearest
.
Example:
import numpy as np
from PIL import Image
import py360convert
cube_dice = np.array(Image.open('assets/demo_cube.png'))
# You can make conversion between supported cubemap format
cube_h = py360convert.cube_dice2h(cube_dice) # the inverse is cube_h2dice
cube_dict = py360convert.cube_h2dict(cube_h) # the inverse is cube_dict2h
cube_list = py360convert.cube_h2list(cube_h) # the inverse is cube_list2h
print('cube_dice.shape:', cube_dice.shape)
print('cube_h.shape:', cube_h.shape)
print('cube_dict.keys():', cube_dict.keys())
print('cube_dict["F"].shape:', cube_dict["F"].shape)
print('len(cube_list):', len(cube_list))
print('cube_list[0].shape:', cube_list[0].shape)
Output:
cube_dice.shape: (768, 1024, 3)
cube_h.shape: (256, 1536, 3)
cube_dict.keys(): dict_keys(['F', 'R', 'B', 'L', 'U', 'D'])
cube_dict["F"].shape: (256, 256, 3)
len(cube_list): 6
cube_list[0].shape: (256, 256, 3)