Giter VIP home page Giter VIP logo

photonbend's Introduction

Photonbend

Photonbend is a python module to handle photos, especially photos taken with fisheye lenses, and convert them between different kinds of lenses, FoV, and types of photos like inscribed circles, cropped circles, or even side-by-side double inscribed circles. It also allows you to rotate those photos, convert them to equirectangular panoramas or convert panoramas to fisheye photos.

It can be used as a library to handle images on your projects or it can be used as a standalone tool with its own set of commands to help you alter your photos taken with a fisheye lens, an omnidirectional camera such as the Samsung Gear 360 or an equirectangular panorama.

If you just want to use the tools go to the Scripts. If you want to undestand how it works just keep reading

Concepts

Fisheye photography

Unlike rectilinear lenses, fisheye lenses can capture great angles like 180º and even greater. With the right setup we can nowadays produce 360º images.

Equidistant Projection (lens)
A 360º fisheye photo with its center aiming at the ceiling.1

Those type of images follow a scheme like the one below:

Inscribed image scheme
Fisheye photo scheme depicting the angles produced by an equidistant lens

How it works

This module uses the information you provide about the image format, lenses, and FoV, couples it with mathematical functions that describes the ways the lenses behave, and makes use of trigonometry to map your planar photos or panoramas to a sphere (actually, the interior wall of a sphere. Using a sphere as a base lets you rotate the image. Using all those functions and trigonometry, it also lets you take a virtual picture of the interior of the sphere using different sorts of lenses and FoV to produce new images. It also lets you map a sphere to an equirectangular panorama.

Image maps

You can see examples on the scripts page

Convention

On the case of the images this software was designed to handle, the convention we adopted was the the center of the image is the top of the sphere, and its borders are the maximum angle of the FoV (In case of a 360 degree image, the sphere's bottom). This convention is important to understand the rotation scheme.

Rotation

This tool lets you rotate your images. For reference, the rotation is defined in 3 degrees of freedom, namely: pitch, yaw and roll, and their direction of rotation are those shown in the image below:

Rotation
For reference, on the scheme above, we are visualizing the image sphere looking down from its top.

Scripts

The module installs a a script 3 different commands to help you deal with your images.

Footnotes

  1. About the source image used on the examples:

    Author: Bob Dass
    Title: View From The Deck
    Available at: https://flickr.com/photos/54144402@N03/50677156243/in/faves-195024173@N05/
    License: Creative Commons - Attribution 2.0
    License summary here
    License text here

photonbend's People

Contributors

wmoreirae avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

photonbend's Issues

Transforming rectilinear to any other projection results in error

I noticed that there is an issue when transforming an image from rectilinear projection to any other type of projection due to an issue on line 88 of photonbend\core\lens.py.

if theta < 0:
    raise ValueError("The angle theta cannot be negative")
if theta > to_radians(89):
    raise ValueError(
        "The Rectilinear lens can't handle FoV larger than 179 degrees"
    )
return np.tan(theta)

Specifically, the computation of theta for a rectilinear lens results in a multi-element array that cannot be compared to 0 or to_radians(89). It is unclear to me why theta is multi-element. However, deleting these checks from lens.py causes the expected transformation, as verified by viewing the original equidistant image and recomputed equidistant image from a rectilinear transformation.

Full error output:
(prosilica) C:\Users\tonyl\Downloads\photonbend-main\photonbend-main\examples>photonbend alter-photo --itype inscribed --otype inscribed --ilens rectilinear --olens equidistant --ifov 140 --ofov 360 rectlinear-full_new.jpg equidistant_new.jpg
Traceback (most recent call last):
File "C:\Users\tonyl\anaconda3\envs\prosilica\lib\runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "C:\Users\tonyl\anaconda3\envs\prosilica\lib\runpy.py", line 86, in run_code
exec(code, run_globals)
File "C:\Users\tonyl\anaconda3\envs\prosilica\Scripts\photonbend.exe_main
.py", line 7, in
File "C:\Users\tonyl\anaconda3\envs\prosilica\lib\site-packages\click\core.py", line 1128, in call
return self.main(*args, **kwargs)
File "C:\Users\tonyl\anaconda3\envs\prosilica\lib\site-packages\click\core.py", line 1053, in main
rv = self.invoke(ctx)
File "C:\Users\tonyl\anaconda3\envs\prosilica\lib\site-packages\click\core.py", line 1659, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "C:\Users\tonyl\anaconda3\envs\prosilica\lib\site-packages\click\core.py", line 1395, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "C:\Users\tonyl\anaconda3\envs\prosilica\lib\site-packages\click\core.py", line 754, in invoke
return __callback(*args, **kwargs)
File "C:\Users\tonyl\anaconda3\envs\prosilica\lib\site-packages\photonbend\scripts\commands\alter_photo.py", line 154, in alter_photo
mapped_array = source_image.process_coordinate_map(destiny_map)
File "C:\Users\tonyl\anaconda3\envs\prosilica\lib\site-packages\photonbend\core\projection.py", line 220, in process_coordinate_map
positions_x, positions_y = self._make_cartesian_map(latitude, longitude)
File "C:\Users\tonyl\anaconda3\envs\prosilica\lib\site-packages\photonbend\core\projection.py", line 251, in _make_cartesian_map
distance = self.forward_lens(latitude) * self.f_distance
File "C:\Users\tonyl\anaconda3\envs\prosilica\lib\site-packages\photonbend\core\lens.py", line 88, in _rectilinear
if theta < 0:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Code to recreate:

photonbend alter-photo --itype inscribed --otype full --ilens equidistant --olens rectilinear --ifov 360 --ofov 140 equidistant.jpg rectlinear-full_new.jpg

photonbend alter-photo --itype full --otype inscribed --ilens rectilinear --olens equidistant --ifov 140 --ofov 360 rectlinear-full_new.jpg equidistant_new.jpg

original_vs_recomputed

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.