Skip to main content

equirectangular image processing with python using minimum dependencies

Project description

equilib

Processing Equirectangular Images with Python

PyPI version Python versions CI GitHub license Documentation
equilib

equilib is a library for processing equirectangular (360°) images in Python.

  • Pure Python, with numpy and torch as the only runtime dependencies.
  • Runs on CPU and CUDA tensors, with batched and mixed-precision processing.
  • Automatic input-type detection (numpy.ndarray or torch.Tensor).
  • Extras such as rotation-matrix creation and a customizable grid sampler.
  • Highly modular and extensible.

📖 Full documentation: https://haruishi43.github.io/equilib/

Installation

Prerequisites:

  • Python >=3.9
  • PyTorch >=2.8
pip install pyequilib

Transforms

equilib provides transforms between equirectangular, cubemap, and perspective images. Each transform ships both a class API and a func API.

Transform Description
Cube2Equi / cube2equi cubemap → equirectangular
Equi2Cube / equi2cube equirectangular → cubemap
Equi2Equi / equi2equi equirectangular → equirectangular
Equi2Pers / equi2pers equirectangular → perspective
Pers2Equi / pers2equi perspective → equirectangular

The class API instantiates a reusable object configured once; the func API takes the configuration on every call. The class API calls the func API internally, so there is no behavioral difference — both are extensible.

Inputs are channel-first (BxCxHxW or CxHxW); the output type matches the input. Common arguments shared across transforms:

  • rots: rotation as three angles pitch, yaw, roll in radians.
  • z_down (bool): use a z-axis-down coordinate system. Default False.
  • mode (str): interpolation mode. Default "bilinear".
  • clip_output (bool): clip values to the input range. Default True.

Basic usage

Example with Equi2Pers / equi2pers.

class API

import numpy as np
from PIL import Image
from equilib import Equi2Pers

# Input equirectangular image (channel-first: HWC -> CHW)
equi_img = np.asarray(Image.open("./some_image.jpg"))
equi_img = np.transpose(equi_img, (2, 0, 1))

rots = {
    "roll": 0.0,
    "pitch": np.pi / 4,  # rotate vertical
    "yaw": np.pi / 4,    # rotate horizontal
}

equi2pers = Equi2Pers(height=480, width=640, fov_x=90.0, mode="bilinear")
pers_img = equi2pers(equi=equi_img, rots=rots)

func API

import numpy as np
from PIL import Image
from equilib import equi2pers

equi_img = np.asarray(Image.open("./some_image.jpg"))
equi_img = np.transpose(equi_img, (2, 0, 1))

rots = {"roll": 0.0, "pitch": np.pi / 4, "yaw": np.pi / 4}

pers_img = equi2pers(
    equi=equi_img,
    rots=rots,
    height=480,
    width=640,
    fov_x=90.0,
    mode="bilinear",
)

See the documentation for every transform's arguments, or browse the examples under tests, benchmarks, and scripts.

Coordinate system

A right-handed XYZ global coordinate system: x-axis faces forward and z-axis faces up.

  • roll: counter-clockwise rotation about the x-axis
  • pitch: counter-clockwise rotation about the y-axis
  • yaw: counter-clockwise rotation about the z-axis

Pass z_down=True to flip the system so the z-axis faces down. See more in the coordinate system docs.

Grid sampling

To process equirectangular images quickly, equilib relies on grid sampling and implements its own numpy and torch backends to minimize dependencies and exploit cuda and batching:

  • The torch backend uses the built-in torch.nn.functional.grid_sample by default, with a customizable pure-torch implementation also available.
  • The numpy backend uses a pure-numpy implementation that is faster than scipy and more robust than cv2.remap. You can override it with scipy or cv2 via the override_func argument.

See the grid sampling docs and the benchmark scripts in benchmarks/.

Development

This project uses uv and Ruff. Image/video assets are stored with Git LFS (git lfs install once before cloning).

git clone https://github.com/haruishi43/equilib.git
cd equilib
uv sync --group dev      # create the venv and install package + dev tools

uv run pytest tests      # run tests
uv run ruff check .      # lint
uv run ruff format .     # format

Pull requests and issues are welcome. See CONTRIBUTING.md for the full workflow, including how releases are published.

Roadmap

  • Cache the rotation-invariant grid prep in the class API (all rotation-based transforms; bitwise-identical to the func path). Saves ~6–17% per call on the torch path and up to ~20% for equi2equi; negligible for the numpy equi2pers/equi2cube where the sampler dominates. See benchmarks/cache_benchmark.py.
  • Optional full-grid cache for the fixed-rotation (static camera) case
  • Speed up the pure-numpy grid_sample (the dominant cost on the numpy path, ~100 ms/call)
  • Try torch.compile on grid construction instead of a hand-written c++/cuda kernel
  • More accurate intrinsic matrix using vertical FOV for equi2pers
  • Multiprocessing support (slow on torch.distributed)
  • Compute the torch grid on-device to avoid the per-call CPU→GPU round-trip
  • Resolve the equi2cube z-axis orientation uncertainty and add coverage for the untested paths
  • Add GPU/CUDA coverage to CI (currently CPU-only due to costs)

Citation

If this project was helpful to your work, please cite it:

@software{pyequilib2021github,
  author = {Haruya Ishikawa},
  title = {PyEquilib: Processing Equirectangular Images with Python},
  url = {https://github.com/haruishi43/equilib},
  version = {0.6.0},
  year = {2021},
}

Acknowledgements

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyequilib-0.6.0.tar.gz (241.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyequilib-0.6.0-py3-none-any.whl (62.2 kB view details)

Uploaded Python 3

File details

Details for the file pyequilib-0.6.0.tar.gz.

File metadata

  • Download URL: pyequilib-0.6.0.tar.gz
  • Upload date:
  • Size: 241.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyequilib-0.6.0.tar.gz
Algorithm Hash digest
SHA256 12e8156b6cc829d283b2dd4f956ad222a019f5b6a52e7ff4b49c65eb68a77b94
MD5 af60a14d0e8ce7d598438f2fbcfb57c3
BLAKE2b-256 7f73a583269cb2637966b061c34729112ff9d419ed30b1d4650f7e3f1c123062

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyequilib-0.6.0.tar.gz:

Publisher: python-publish.yml on haruishi43/equilib

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyequilib-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: pyequilib-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 62.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyequilib-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f2399c19589ae5a282efe0d13c1aa9f577ccfd06ecaca44d1665c21a0ceab5f2
MD5 faf7ab3a376702e1a986eaf19bc2d552
BLAKE2b-256 682c37c892457b1602f368de5b5010e94f0e54616a65d58a9c079484c2240cc9

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyequilib-0.6.0-py3-none-any.whl:

Publisher: python-publish.yml on haruishi43/equilib

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page