Bilinear Interpolation from wikipedia

1.5k views Asked by At

I've tried reading the bilinear interpolation on the Wikipedia page https://en.wikipedia.org/wiki/Bilinear_interpolation and I have implemented one of the algorithms and I wanted to know if I'm doing it right or not.

This is the algorithm I implemented from the page: Bilinear interpolation from unit squre

This what I tried to implement in code:

for(int i = 0; i < w; i++) {
    for( int j = 0; j < h; j++) {
        new_img(i,j,0) = old_img(i,j,0)*(1-i)(1-j) + old_img(i+1,j,0)*i*(1-j) + old_img(i,j+1)*(1-i)*j + old_img(i+1,j+1,0)*i*j;
    }
}

Is that how to implement it?

1

There are 1 answers

6
TzviLederer On

The bilinear interpolation deals with upsampling an imgae. It try to estimate the value of an array (e.g. an image) between the known values. For example, if i have an image and I want to estimate its value in the location (10.5, 24.5), the value will be a weighted average of the values in the four neighbors: (10,24), (10,25), (11,24), (11,25) which are known. The formula is the equation you posted in your question.

This is the python code:

    scale_factor = 0.7

    shape = np.array(image.shape[:2])
    new_shape = np.ceil(shape * scale_factor).astype(int)

    grid = np.meshgrid(np.linspace(0, 1, new_shape[1]), np.linspace(0, 1, new_shape[0]))
    grid_mapping = [i * s for i, s in zip(grid, shape[::-1])]

    resized_image = np.zeros(tuple(new_shape))
    for x_new_im in range(new_shape[1]):
        for y_new_im in range(new_shape[0]):
            mapping = [grid_mapping[i][y_new_im, x_new_im] for i in range(2)]
            x_1, y_1 = np.floor(mapping).astype(int)
            try:
                resized_image[y_new_im, x_new_im] = do_interpolation(f=image[y_1: y_1 + 2, x_1: x_1 + 2], x=mapping[0] - x_1, y=mapping[1] - y_1)
            except ValueError:
                pass


def do_interpolation(f, x, y):
    return np.array([1 - x, x]).dot(f).dot([[1 - y], [y]])

Explanation:
new_shape = np.ceil(shape * scale_factor).astype(int) - calculate the new image shape after rescale.
grid = np.meshgrid(np.linspace(0, 1, new_shape[1]), np.linspace(0, 1, new_shape[0]))
grid_mapping = [i * s for i, s in zip(grid, shape[::-1])] - generate a x,y grid, when x goes from 0 to the width of the resized image and y goes from 0 to the hight of the new image. Now, we have the inverse mapping from the new image to the original one.
In the for loop we look at every pixel in the resized image and where is its source in the original image. The source will not be an integer but float (a fraction).
Now we take the four pixels in the original image that are around the mapped x and y. For example, if the mapped x,y is in (17.3, 25.7) we will take the four values of the original image in the pixels: (17, 25), (17, 26), (18, 25), (18, 26). Then we will apply the equation you bring.

note:
I add a try-except because I did not want to deal with boundaries, but you can edit the code to do it.