Turning a flat sensor into a semi-spherical one

Hmm, okay i’m probably more confused at that paper than anything haha.

I now realize I was actually thinking of an equirecetangular projection the whole time. I even wrote some code thinking “This gnomonic projection works really well”, not realizing it was actually equirectangular.

The python code below takes an image, calculates the angule in azimuth and elevation from the focal axis then simply distributes the angles evenly into a grid of pixels, the result is shown below:

And the python code:

import cv2
import numpy as np
import math

## PARAMETERS ##

pixelDegDensity = 6 # How many pixels you get in the output image per degree
fov = math.radians(115) # Horizontal FOV
img = cv2.imread('Screenshot_16.png')

## WORKINGS ##

cv2.imshow("Main", img)

height, width, _ = img.shape
outWidth = round(math.degrees(fov) * pixelDegDensity)
outHeight = round(outWidth * 9/16)
newImg = np.zeros((outHeight, outWidth, 3), dtype=np.uint8)
focalLength = (width/2) / math.tan(fov/2) #in pixel units

mpx = round(width/2)
mpy = round(height/2)
outMpx = round(outWidth/2)
outMpy = round(outHeight/2)

## FOR EVERY DEG INCREMENT, FIND THE X AND Y IT INSECTS IN THE IMAGE, THEN PLACE THAT IN A NEW IMAGE ##

for outX in range(outWidth):
    az = (outX - outMpx) / pixelDegDensity
    x = round(focalLength * math.tan(math.radians(az)))
    for outY in range(outHeight):
        el = (outY - outMpy) / pixelDegDensity 
        y = round(math.sqrt(focalLength ** 2 + x **2) * math.tan(math.radians(el)))
        for c in range(0, 3):
            if -mpx < x < mpx and -mpy < y < mpy:
                newImg[outY, outX, c] = img[y + mpy, x + mpx, c]

cv2.imshow("image Output", newImg)

Slightly messy, and the mapping could be precalculated.

I realize in the end you can’t have your cake and eat it. Either you can perfectly replicate the eyes an animal, but not have a rectangular image which works with classical algorithms, or you make a compromise, where each pixel doesn’t correspond to an equal receptive area.

Thank you so much for helping and your patience haha, I think this is solved for now.

EDIT: After even further thinking, i’ve realized what i’m doing is two steps:

  1. Inverse gnomonic projection to get the angle that each ray crossed the focal axis
  2. Equirectangular projection (which is trivial as it is just simply placing each pixel value for each degree in an image).