I have to transform and remap an equirectangular image to an other equirectangular image with a 90° roll.
I did it with Pano2VR.
The problem is that I have to do it programmatically from the server side. So I can't use a G.U.I. to do it.
First, I oriented my research to imagemagick. I tried the Fred ImageMagick scripts but could not find anyone to do what I want to do. Moreover, the processing time of an image appears very long compared to Pano2VR.
I directed my investigations to OpenCV and the libgnomonic. It's presently the most interesting way. This library allows te user to transform projections (equirectangular to rectilinear and vice versa) or make equirectangular mapping transformation. I played with Norama-suite wich contains some scripts to deal with the library. For example, I would to convert an rectilinear image to an equirectangular but the output was just a black background image (why ? I didn't find the answer).
However, this second link could resolve my problem. I have this image :
and I want to transform it to this image
Well, I'm not comfortable at all with C. I think I should use this two files :
But I don't know how. And above all, I want to understand.
Am I on the right way ? What transformation is applied on the first image ? Is there a way to do it with python or a bash script ?
Well, thank you for your help.
**EDIT Transposition of C in python ** The following code didn't work and return and IndexError. However I tried to catch and pass the exception and the first right part of the image did not seem changed.
import math
from PIL import Image
img = Image.open("img1.jpg")
img = img.convert('RGB')
pixel = img.load()
width, height = img.size
img2 = img.copy()
for y in xrange(height):
for x in xrange(width):
xx = 2*(y+0.5) / width - 1.0
yy = 2*(y+0.5)/ height - 1.0
lng = math.pi * xx
lat = 0.5 * math.pi * yy
# NOTE! These axes are transposed because that's what the question is about
Z = math.cos(lat) * math.cos(lng) # normally X
Y = math.cos(lat) * math.sin(lng) # normally Y
X = -math.sin(lat) # normally -Z
D = math.sqrt(X*X+Y*Y)
lat = math.atan2(Z, D) # ? normally lat = math.asin(Z)
lng = math.atan2(Y, X)
#ix and iy must be integers
ix = int((0.5 * lng / math.pi + 0.5) * width - 0.5)
iy = int((lat/math.pi + 0.5) * height - 0.5)
#not sure of this part to remap the image
newpixel = pixel[ix, iy]
img2.putpixel([(x+width/4) % width, y], newpixel)
#I tries as mentionned in the following code to invert x and y in the two previous lines but the index error out of range comes back
img2.show()
Your transformation has two steps. The first step is a transformation of the projection sphere, the second is the 90° roll.
A 90° roll of an equirectangular image is just a horizontal shift of a quarter of the image width. The first transformation is more complicated: You basically want to rotate the sphere so that the north pole is at latitude 0 and longitude 0 (somewhere in the Gulf of Guinea, if you take thze Earth as reference.)
You can go about this transformation with these steps;
Here's C code that works. (I know that you have tagged the question with Python, but the code below is mostly formulas that work similarly in python. You have to take care: All of the number are floating point numbers except the pixel indixes x
, y
, ix
and iy
. I would have done this in Python, but I have no experience with the Python Image Library.)
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
double xx = 2 * (x + 0.5) / width - 1.0;
double yy = 2 * (y + 0.5) / height - 1.0;
double lng = pi * xx;
double lat = 0.5 * pi * yy;
double X, Y, Z;
double D;
int ix, iy;
Z = cos(lat) * cos(lng); // corresponds to original x
Y = cos(lat) * sin(lng); // corresponds to original y
X = -sin(lat); // corresponds to original z
D = sqrt(X*X + Y*Y); // distance in the XY plane
lat = atan2(Z, D);
lng = atan2(Y, X);
ix = (0.5 * lng / pi + 0.5) * width - 0.5;
iy = (lat / pi + 0.5) * height - 0.5;
dest[y][(x + width / 4) % width] = src[iy][ix];
// width/4 offset ist the 90° roll
// % width wraps the longitude
}
}
The quality of the resulting image is okay, but not as good as that of your reference image, especially near the poles. A better algorithm woul average and smoothze the colour values. The algorithm above just maps one destination pixel to a source pixel.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With