indus / kubi

a fast and flexible cubemap generator
MIT License
55 stars 15 forks source link
360-photo cubemap equirectangular-to-cubemap libvips panorama python
kubi logo

kubi is a fast and flexible cubemap generator based on libvips

Install

pip install git+https://github.com/indus/kubi.git

Requirements

Description

kubi can convert equirectangular images into a variety of common layouts. All image formats supported by vips (JPEG, PNG, TIFF, WEBP, HEIF, ...) can be used for input and output. With the DZ format of libvips it is even possible to create tiled images of the cubefaces.
When used with a glob pattern for multiple input files, kubi generates an index file once and reuses it while processing all matched images. This can lead to a significant speedup.

Usage

none row column
none row column
crossL crossR crossH
crossL crossR crossH

With some fiddling the file and folder structure could be made compatiple to 360° image viewers.
The above would work with Marzipano:

Marzipano.ImageUrlSource.fromString("<some_path>/dstfile_{f}/{z}/{y}/{x}.jpg");

Benchmark

system: CPU: i7-6700 CPU @ 3.40GHz, 4 cores; MEM: 64GB; OS: Win 10

single input file

input: equirectangular image with 4096x2048px
output: cubemap with a cross layout

face size 1024px 2048px 4096px
kubi 0.9s 1.6s 4.7s
py360convert 2.6s 8.6s 32.2s
any others ? - - -

single input file - tiled output

input: equirectangular image with 4096x2048px
output: cubemap as seperate tiles

face size 1024px 2048px 4096px
kubi 0.9s 1.3s 3.1s
panorama_windows.exe 1.5s 4.7s 16.9s
any others ? - - -

multiple input files

If only a few cubemaps are needed, performance is probably of minor concern. But with kubi it should also be possible to process thousands of animation frames in a reasonable time:

input: multiple equirectangular images with 4096x2048px
output: multiple cubemaps with a cross layout and a face size of 2048px
count total time time per cubemap
1 1.7s 1.7s
2 2.6s 1.3s
3 3.5s 1.2s
5 5.2s 1.0s
10 9.9s 1.0s
20 18.5s 0.9s

Transforms

In addition to regular cubemaps, two optimized mappings can be generated:

Both transforms are univariate and therefore very easy to implement. They both significantly reduce the distortion of the cubemap and thus optimize the pixel yield. However, support in other tools and libraries is rather scarce.

error ltr: regular cubemap, EAC, OTC
area error_area
distance error_distance

To ensure the correct representation of a transformed cubemap, the reverse transformation must be performed at some point. The following example shows this for the OTC transformation in a fragment shader.

//FRAGMENT SHADER for OTC

vec3 n = vNormal.xyz; // or vPosition

n /= max(max(abs(n.x),abs(n.y)),abs(n.z));
n = atan(n * tan(0.8687));

gl_FragColor = textureCube(otcSampler, n);