Search code examples
pythonimage-processingbilinear-interpolation

Faulty image with Bilinear Interpolation


I am implementing Bilinear Interpolation to resize image. The function for bilinear interpolation and resizing is as follows:

def bl_resize(original_img, new_h, new_w):
    old_h, old_w, c = original_img.shape
    resized = np.ones((new_h, new_w, c))
    w_scale_factor = (old_w - 1) / (new_w - 1) if new_h != 0 else 0
    h_scale_factor = (old_h - 1) / (new_h - 1) if new_w != 0 else 0
    for i in range(new_h):
        for j in range(new_w):
            for k in range(c):
                x = i * h_scale_factor
                y = j * w_scale_factor
                x_floor = math.floor(x)
                x_ceil = min( old_h - 1, math.ceil(x))
                y_floor = math.floor(y)
                y_ceil = min(old_w - 1, math.ceil(y))

                if (x_ceil == x_floor) and (y_ceil == y_floor): 
                    q = original_img[int(x), int(y), k]
                else:
                    v1 = original_img[x_floor, y_floor, k]
                    v2 = original_img[x_ceil, y_floor, k]
                    v3 = original_img[x_floor, y_ceil, k]
                    v4 = original_img[x_ceil, y_ceil, k]

                    q1 = v1 * (x_ceil - x) + v2 * (x - x_floor)
                    q2 = v3 * (x_ceil - x) + v4 * (x - x_floor)
                    q = q1 * (y_ceil - y) + q2 * (y - y_floor)
                resized[i,j,k] = q
    return resized.astype(np.uint8)

I am using x_ceil = min( old_h - 1, math.ceil(x)) and y_ceil = min(old_w - 1, math.ceil(y)) to avoid access to index larger the the dimensions of the original image array. Without it I would get index out of range error for the last index in both dimensions.

The resized image using this code contains a black grid on it. Here are some output images. The first image is of a shrunken version of the original image and the second one is that of the enlarged one!

Image shrunk to smaller size

Image enlarged to larger size

EDIT: I have identified what is exactly causing the problem, but I don't understand why it is causing a problem. Changing the scale factor for both the dimensions from (old/new) to (old - 1)/(new - 1) lead to grid free results. I want to understand how the scale factor values can create a problem.


Solution

  • Well, after doing some debugging I figured out the reason. The black grid is obtained because of incorrectly assigned zero values to pixels where either x or y take integer values, that results in q = 0. I have documented everything here: https://meghal-darji.medium.com/implementing-bilinear-interpolation-for-image-resizing-357cbb2c2722#f91e-235aaa8634b8