How to Perform Bilinear Interpolation in Python?

BILINEAR INTERPOLATION USING NUMPY AND SCIPY

Bilinear Interpolation is the process of estimating unknown values of a function with two variables to fill the gaps in a grid or a 2D space. It is the method of populating the gaps by using the known values and performing linear interpolation repeatedly.

It is based on a weighted average and resamples the nearest values to estimate a new value.

Interpolation on its own has many uses and applications. It is mainly used in image processing, data analysis, generating music, and many more.

Bilinear interpolation also has many applications. It is used in image processing, computer vision, numerical analysis, digital terrain modeling, and so on.

Refer to this article to learn how to interpolate 1D space.

Bilinear Interpolation

Let us understand the concept of bilinear interpolation in depth. As discussed above, it is the process of estimating new values based on a set of known values.

It considers the distance-based weighted average of the four nearest neighbors to interpolate a desired location. Let us understand this visually.

Suppose you have a 2D grid of values shown below.

2d Grid
2d Grid

Suppose you want to find a point in between these known points. We take the distance between each known point to the new point and calculate the weighted average to estimate what the new point could be. Let us visualize the grid in the following manner. Let A be the new point to be estimated. We calculate the distance between each known point to the new point desired to estimate the value.

Visualizing The Grid
Visualizing The Grid

Let us see how we can implement the bilinear interpolation with the two very well-known libraries, numpy and scipy.

Bilinear Interpolation using Numpy

There is no in-built module in numpy that performs bilinear interpolation directly. When using Numpy for such tasks, we need to compute everything manually with the help of its numerical functions. This helps us to understand the process better.

We are going to manually interpolate a value and then visualize it using matplotlib.

import numpy as np
import matplotlib.pyplot as plt
def bi_interpolation(arr, x, y):
    height, width = arr.shape
    x1 = int(x)
    y1 = int(y)
    x2 = x1 + 1
    y2 = y1 + 1
    if x2 >= width:
        x2 = x1
    if y2 >= height:
        y2 = y1

    p11 = arr[y1, x1]
    p12 = arr[y2, x1]
    p21 = arr[y1, x2]
    p22 = arr[y2, x2]

    x_diff = x - x1
    y_diff = y - y1

    interpolated = (p11 * (1 - x_diff) * (1 - y_diff) +
                          p21 * x_diff * (1 - y_diff) +
                          p12 * (1 - x_diff) * y_diff +
                          p22 * x_diff * y_diff)

    return interpolated

arr = np.array([[1, 2, 3],
                [4, 5, 6],
                [7, 8, 9]])
x = 1.5
y = 1.5
interpolated = bi_interpolation(arr, x, y)
print("Interpolated value at ({x}, {y}): {interpolated_value}")
xx, yy = np.meshgrid(range(arr.shape[1]), range(arr.shape[0]))
plt.plot(xx, yy, 'ko')
for i in range(arr.shape[0]):
    for j in range(arr.shape[1]):
        plt.text(j, i, f'{arr[i, j]}', ha='center', va='center')
plt.plot(x, y, 'ro')
plt.text(x, y, f'Interpolated: {interpolated:.2f}', ha='left', va='bottom')
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Bilinear Interpolation')
plt.show()

Here is the explanation.

Firstly, we are importing the two Python libraries – numpy and matplotlib.

Next, we define a function bi-interpolation that performs interpolation on an array called arr at x and y coordinates.

 x1 = int(x)
 y1 = int(y)
 x2 = x1 + 1
 y2 = y1 + 1

The x and y values are converted to integers so that if there is any decimal value, it is truncated. The integer values are stored in variables called x1 and y1.

x2 and y2 are the points close to the given point(x and y).

 if x2 >= width:
     x2 = x1
 if y2 >= height:
       y2 = y1

This code snippet ensures that the points do not go beyond the array’s dimensions and are adjusted with the height and width of the array.

p11 = arr[y1, x1]
p12 = arr[y2, x1]
p21 = arr[y1, x2]
p22 = arr[y2, x2]

This creates the points we need to interpolate a new point.

The x_diff and y_diff store the differences between the actual points and the points we give (x and y).

The next four lines assign the weights to the points surrounding the new point. The result is stored in a variable called interpolated. That’s the end of the function.

arr = np.array([[1, 2, 3],
                [4, 5, 6],
                [7, 8, 9]])
x = 1.5
y = 1.5
interpolated = bi_interpolation(arr, x, y)

The array we passed to the function and the coordinates at which we want the new point to be interpolated are initialized in the next two lines. The function is called with the specified values.

Next, we print the interpolated value and plot the grid after interpolation.

Interpolated value at (1.5, 1.5): 7.0
Bilinear Interpolation Using Numpy
Bilinear Interpolation Using Numpy

Bilinear Interpolation using SciPy

Unlike the numpy library, the scipy library does have a dedicated method for interpolation. We are going to use the method and interpolate a new point. It takes just a few lines of code.

import numpy as np
from scipy.interpolate import griddata
points = np.array([[0, 0], [0, 1], [1, 0], [1, 1],[2,1],[2,2],[1,2],[0,2]])  
values = np.array([1, 4, 7, 9,3,8,2,7])  
x = 0.5  
y = 0.5 
interpolated_value = griddata(points, values, (x, y), method='nearest')
print("Interpolated value at ({x}, {y}): {interpolated_value}")

We are importing the numpy library and the ‘scipy’ library’s ‘griddata’ module to interpolate.

We are defining the coordinate points of the axis and their corresponding values. Next, we specify the coordinates for the interpolated point.

The interpolated_value stores the interpolation result by the griddata method using the nearest interpolator.

The value of interpolation is printed.

Bilinear Interpolation Using Scipy
Bilinear Interpolation Using Scipy

We can visualize the grid after interpolation with the help of matplotlib.

plt.plot(points[:, 0], points[:, 1], 'ko', label='Input Points')
for i, val in enumerate(values):
    plt.text(points[i, 0], points[i, 1], str(val), ha='center', va='bottom')
plt.plot(x, y, 'ro', label='Interpolated Point')
plt.text(x, y, f'Interpolated: {interpolated_value:.2f}', ha='left', va='bottom')
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Bilinear Interpolation')
plt.legend()
plt.show()

Visualization
Visualization

Conclusion

To conclude, we have discussed the definition of bilinear interpolation and its widespread applications. Bilinear interpolation is based on a weighted average and resamples the nearest values to estimate a new value. It performs linear interpolation repeatedly to populate the gaps.

We have learned how to perform bilinear interpolation using two libraries- numpy and scipy. Although numpy doesn’t have an inbuilt method to perform interpolation, we could use its other functions to perform interpolation manually.

The scipy library does have a function dedicated to performing interpolation, and it was much easier to perform interpolation because all we had to was create a grid and specify the points.

We have also used the matplotlib library to visualize the results.

References

You can find the SciPy documentation here.

Numpy Documentation.

You can find other approaches to bilinear interpolation in this stack overflow answer chain.