How do I implement bilinear interpolation for image data represented as a numpy array in python?
1 Answer 1
I found many questions on this topic and many answers, though none were efficient for the common case that the data consists of samples on a grid (i.e. a rectangular image) and represented as a numpy array. This function can take lists as both x and y coordinates and will perform the lookups and summations without need for loops.
def bilinear_interpolate(im, x, y):
x = np.asarray(x)
y = np.asarray(y)
x0 = np.floor(x).astype(int)
x1 = x0 + 1
y0 = np.floor(y).astype(int)
y1 = y0 + 1
x0 = np.clip(x0, 0, im.shape[1]-1);
x1 = np.clip(x1, 0, im.shape[1]-1);
y0 = np.clip(y0, 0, im.shape[0]-1);
y1 = np.clip(y1, 0, im.shape[0]-1);
Ia = im[ y0, x0 ]
Ib = im[ y1, x0 ]
Ic = im[ y0, x1 ]
Id = im[ y1, x1 ]
wa = (x1-x) * (y1-y)
wb = (x1-x) * (y-y0)
wc = (x-x0) * (y1-y)
wd = (x-x0) * (y-y0)
return wa*Ia + wb*Ib + wc*Ic + wd*Id
ffriend
Hi Alex, I was looking just for the same thing, and your implementation looks pretty good. I grasped basic usage, but can you please provide some advanced examples (with several coordinates) to make this answer even better?
Pete Florence
Hey @AlexFlint, thanks for posting this and I have a small suggestion. This small diff in just the last line will make this compatible with 2D grids of D-dimensional values, i.e. [WxHxD], as in a D=3 rgb image or higher:
return (Ia.T*wa).T + (Ib.T*wb).T + (Ic.T*wc).T + (Id.T*wd).T Let me know if you have any questions? Thanks!ohad edelstain
@AlexFlint I am looking at the wiki definition: en.wikipedia.org/wiki/Bilinear_interpolation and I am missing in your solution the devide by (y1-y0)*(x1-x0) what am I missing? is there a reason not to divide?
sebasth
@ohadedelstain note that in the answer
y1 = y0 + 1 and x1 = x0 + 1, therefore (y1-y0)*(x1-x0) is always 1.pups
There is a bug here. wa..wd need to be computed before applying clipping to {x0, x1, y0, y1} otherwise the boundary cases are incorrect.
lang-py