I am looking for a fast way to interpolate a 3 channel image on a grid of x-y points. I have a functioning code using map_coordinates
. As you can see, i am doing 3 times the same thing, I would like a faster way that can do at least the 3 channels at the same time.
import numpy as np
from scipy.ndimage import map_coordinates
test_img = np.random.random((128, 160, 3))
x, y = np.meshgrid(np.arange(128), np.arange(160))
# here f is a 2d -> 2d map that will return floats. In my case
# it is a function to un-fisheye a picture.
x, y = f(x,y)
def interp_img(img, x, y, order=1):
"interpolates img on (x,y) grid"
return np.stack([map_coordinates(img[:,:,i], np.stack([y, x]), order=order) for i in range(3)], axis=-1)
interp_img(test_img, x, y)
replacing the map_coordinates
with a int casting (to find pixels) it is quite faster.
def int_map(img, x, y):
"int round reindexing of image"
return img[y.astype(int), x.astype(int), :]
%time out_img = interp_img(aimg, xc, yc)
>> CPU times: user 398 ms, sys: 72.4 ms, total: 470 ms
Wall time: 472 ms
%time out_img_int = int_map(aimg, xc, yc)
>> CPU times: user 54.8 ms, sys: 43.9 ms, total: 98.7 ms
Wall time: 98.5 ms
I think the following should work. (I've changed x/y to row/col to avoid confusion over swapping of axis order...)
import numpy as np
from scipy.ndimage import map_coordinates
test_img = np.random.random((128, 160, 3))
row, col, ch = np.meshgrid(
np.arange(128), np.arange(160), np.arange(3),
indexing='ij',
)
# here f is a 2d -> 2d map that will return floats. In my case
# it is a function to un-fisheye a picture.
row_in, col_in = f(row, col)
def interp_img(img, r, c, ch, order=1):
"interpolates color (3-channel) img on grid"
return map_coordinates(img, np.stack([r, c, ch]), order=order)
interp_img(test_img, row_in, col_in, ch)