In the previous blog, we learned how to find the pixel coordinate in the input image and then we discussed nearest neighbour algorithm. In this blog, we will discuss Bi-linear interpolation method in detail.
Bi-linear interpolation means applying a linear interpolation in two directions. Thus, it uses 4 nearest neighbors, takes their weighted average to produce the output
So, let’s first discuss what is linear interpolation and how it is performed?
Linear interpolation means we estimate the value using linear polynomials. Suppose we have 2 points having value 10 and 20 and we want to guess the values in between them. Simple Linear interpolation looks like this
More weight is given to the nearest value(See 1/3 and 2/3 in the above figure). For 2D (e.g. images), we have to perform this operation twice once along rows and then along columns that is why it is known as Bi-Linear interpolation.
Algorithm for Bi-linear Interpolation:
Suppose we have 4 pixels located at (0,0), (1,0), (0,1) and (1,1) and we want to find value at (0.3,0.4).
- First, find the value along rows i.e at position A:(0,0.4) and B:(1,0.4) by linear interpolation.
- After getting the values at A and B, apply linear interpolation for point (0.3,0.4) between A and B and this is the final result.
Let’s see how to do this for images. We take the same 2×2 image from the previous blog and want to upscale it by a factor of 2 as shown below
Same assumptions as we took in the last blog, pixel is of size 1 and is located at the center.
- Let’s take ‘P1’. First, we find the position of P1 in the input image. By projecting the 4×4 image on the input 2×2 image we get the coordinates of P1 as (0.25,0.25). (For more details, See here)
- Since P1 is the border pixel and has no values to its left, so OpenCV replicates the border pixel. This means the row or column at the very edge of the original is replicated to the extra border(padding). OpenCV has different methods to add borders which you can check here.
- So, now our input image (after border replication) looks like this. Note the values in red shows the input image.
- To find the value of P1, let’s first visualize where P1 is in the input image (previous step image). Below figure shows the upper left 2×2 input image region and the location of P1 in that.
- Before applying Bi-linear interpolation let’s see how weights are distributed.
Both Matlab and OpenCV yield different results for interpolation because their weight distribution is done differently. Here, I will only explain for OpenCV.
In OpenCV, weights are distributed according to this equation
1 2 3 |
fx = (float)((dx+0.5)*scale_x - 0.5); sx = cvFloor(fx); fx -= sx; |
Where dx is the column index of the unknown pixel and fx is the weight that is assigned to the right pixel, 1-fx is given to the left pixel. Scale_x is the ratio of input width by output width. Similarly, for y, dy is the row index and scale_y is the ratio of heights now.
After knowing how weights are calculated let’s get back to the problem again.
- For P1, both row and column index i.e dx, and dy =0 so, fx = 0.75 and fy =0.75.
- We apply linear interpolation with weights fx for both A and B(See Image-1) as 0.75*10(right) + 0.25*10 = 10 (Explained in the Algorithm above)
- Now, for P1 apply linear interpolation between A and B with the weights fy as 0.75*10(B) +0.25*10(A) = 10
- So, we get P1 =10. Similarly, repeat for other pixels.
The final result we get is shown below:
This produces smoother results than the nearest neighbor but, the results for sharp transitions like edges, are not ideal.
In the next blog, we will discuss Bi-cubic interpolation. Hope you enjoy reading.
If you have any doubt/suggestion please feel free to ask and I will do my best to help or improve myself. Good-bye until next time.
Thank you very much kang & atul! These articles helped me a lot. I want to know, how can I calculate the location of P for image resize by a factor of 3 or more?
Thanks Karan… Think of it in this way. Suppose you have a 2×2 image, each pixel of unit length that u want to upscale by 3. To fit the upscaled image(6×6) to this 2×2 image, the size of each pixel has to be 2/6 units in length. Since P is the pixel center, so for the first pixel this is equal to pixel size/2 i.e. 2/12. Similarly calculate for any upscale factor. Hope this helps.
Oh yeah, makes sense! Thanks again.
hi,
how do you get pixel value for P2,
i got 10 and not 12
please help
Actually the result for P2 will be 12.5 but the blogger has rounded it off as it is done in images. The center for P2 will be (0.25, 0.75), so the calculation will be 10*(1.5 – 0.75) + 20*(0.75 – 0.5) = 10*0.75 + 20*0.25 = 7.5 + 5 = 12.5.
can u pls tell me how you get 1.5
can you please explain, how to do boarder replication if the input size is 3×3 and output size is 10×10
Thank you so much for his article!!
Thanks for the sharing of this article.
But, I found this article is a bit confusing to me since the coordinate notion keeps on changing. Sometimes, the top left corner is (0, 0). Sometimes it is (-0.5, -0.5). Sometimes the order of x, y is interchanged.
Can you please tell how you’re calculating scale_x and scale_y?
Pingback: Ultimate Guide to Upscale Images with AI in Stable Diffusion