I inherited a Python script that does a proprietary image transformation of a rectangular Mercator map into an image displaying two side-by-side polar views. The code takes about 2 minutes to do the transformation for each image and write it out to a file. I’ve created a Pool to spin up 32 parallel transformations on a system with 32 cores & 128GB of RAM but with thousands of images it still takes about 1.5 hours to finish each day.
Before: https://www.oceanic.udel.edu/globaldataview/OmniGlobe/NRL/wind_waves/wind_waves_0001.jpg
After: https://www.oceanic.udel.edu/globaldataview/OmniGlobe/NRL/wind_waves/polarpair/wind_waves_0001.jpg
I’m hoping to leverage nVidia’s CUDA technology to drastically speed up this process so this will be my first attempt at doing anything with Python & CUDA.
Note that the output image is 4 pixels narrower than the input image (a requirement of the hardware that will be displaying it) so a 4000x2000 input image results in a 3996x2000 output polar pair image.
Pertinent Python code follows - any assistance in a direction to take would be much appreciated.
@numba.jit
def findSrcX(x,y,height): # x/y around origin, so +- x and +-y where 0/0 is the pole finds the x pos of the src img
if (x == 0):
if (y >= 0):
theta = np.pi / 2
if (y < 0):
theta = 3 * np.pi / 2
elif (x < 0):
theta = np.arctan(float(y)/float(x)) + np.pi
elif (y < 0):
theta = np.arctan(float(y)/float(x)) + 2 * np.pi
else:
theta = np.arctan(float(y)/float(x))
srcX = theta * height / np.pi
return srcX
@numba.jit
def findSrcY(x,y,height,outputHeight):
return np.sqrt(x**2 + y**2) * 2/outputHeight * height/2
@numba.jit
def findSrcXY(x,y,height,outputHeight):
x = x - outputHeight / 2
y = y - outputHeight / 2
return (findSrcX(x,y,height), findSrcY(x,y,height,outputHeight))
@numba.jit
def EquirectangularToPolar(src_filename, output_directory=None, outputHeight=0, match=False):
print("Processing " + src_filename)
srcimg = Image.open(src_filename)
width, height = srcimg.size
if (width != 2 * height):
LOG.warning(src_filename + " is not 2*1")
return
if match:
outputHeight = height
outputWidth = width - 4
else:
outputWidth = outputHeight * 2 - 4
LOG.debug("Creating canvas")
polarimg = Image.new('RGB', (outputWidth, outputHeight))
LOG.debug("Painting north pole onto canvas")
[polarimg.putpixel((outputHeight - x, y), srcimg.getpixel(findSrcXY(x,y,height,outputHeight)))
for x,y in np.ndindex((outputHeight, outputHeight))]
LOG.debug("Flipping source image")
srcimg = srcimg.transpose(Image.FLIP_TOP_BOTTOM) # to read south pole
LOG.debug("Painting south pole onto canvas")
[polarimg.putpixel((x + outputHeight - 4, y), srcimg.getpixel(findSrcXY(x,y,height,outputHeight)))
for x,y in np.ndindex((outputHeight, outputHeight))]