Introduction to linear interpolation methods and image scaling

1 Linear interpolation

  Let the function y = f ( x ) y=f(x)y=f ( x ) at two pointsx 0 x_{0}x0 x 1 x_{1} x1The values ​​on are respectively y 0 y_{0}y0y 1 y_{1}y1. Find the polynomial y = p 1 ( x ) = a 0 + a 1 xy=p_{1}(x)=a_{0}+a_{1}xy=p1(x)=a0+a1x,使满足 p 1 ( x 0 ) = y 0 , p 1 ( x 1 ) = y 1 p_{1}(x_{0})=y_{0},p_{1}(x_{1})=y_{1} p1(x0)=y0,p1(x1)=y1. Its geometric meaning is found through A ( x 0 , y 0 ) A(x_{0},y_{0})A(x0,y0) B ( x 1 , y 1 ) B(x_{1},y_{1}) B(x1,y1) is a straight line. From analytical geometry we know: y = p 1 ( x ) = y 0 + y 1 − y 0 x 1 − x 0 ( x − x 0 ) y=p_{1}(x)=y_{0}+\frac{ y_{1}-y_{0}}{x_{1}-x_{0}}(x-x_{0})y=p1(x)=y0+x1x0y1y0(xx0) Rearrange the above formula to get:p 1 ( x ) = x − x 1 x 0 − x 1 y 0 + x − x 0 x 1 − x 0 y 1 p_{1}(x)=\frac{x -x_{1}}{x_{0}-x_{1}}y_{0}+\frac{x-x_{0}}{x_{1}-x_{0}}y_{1}p1(x)=x0x1xx1y0+x1x0xx0y1

2 Bilinear interpolation

2.1 Calculation formula

  Bilinear interpolation is a linear interpolation extension of the interpolation function of two variables. Its core idea is to perform linear interpolation in two directions. Here is the following figure as an example:
  Suppose now you want to know the unknown function fff is at pointP ( x , y ) P(x,y)P(x,y ) value, currently known functionfffQ 11 = ( x 1 , y 1 ) Q_{11}=(x_{1},y_{1})Q11=(x1,y1) Q 12 = ( x 1 , y 2 ) Q_{12}=(x_{1},y_{2}) Q12=(x1,y2) Q 21 = ( x 2 , y 1 ) Q_{21}=(x_{2},y_{1}) Q21=(x2,y1) Q 22 = ( x 2 , y 2 ) Q_{22}=(x_{2},y_{2}) Q22=(x2,y2) value.
Insert image description here
The calculation steps of bilinear interpolation are as follows:

  • First in xxLinear interpolation in the x direction, respectively calculate the function fff pointR 1 R_{1}R1and R 2 R_{2}R2value on. The calculation formula is as follows: f ( R 1 ) = x 2 − xx 2 − x 1 f ( Q ​​11 ) + x − x 1 x 2 − x 1 f ( Q ​​21 ) f(R_{1})=\frac{ x_{2}-x}{x_{2}-x_{1}}f(Q_{11})+\frac{x-x_{1}}{x_{2}-x_{1}}f(Q_ {twenty one})f(R1)=x2x1x2xf(Q11)+x2x1xx1f(Q21) f ( R 2 ) = x 2 − x x 2 − x 1 f ( Q 12 ) + x − x 1 x 2 − x 1 f ( Q 22 ) f(R_{2})=\frac{x_{2}-x}{x_{2}-x_{1}}f(Q_{12})+\frac{x-x_{1}}{x_{2}-x_{1}}f(Q_{22}) f(R2)=x2x1x2xf(Q12)+x2x1xx1f(Q22)
  • Secondly, use R 1 R_{1}R1and R 2 R_{2}R2Calculate PPP。其计算公式如下: f ( P ) = y 2 − y y 2 − y 1 f ( R 1 ) + y − y 1 y 2 − y 1 f ( R 2 ) f(P)=\frac{y_{2}-y}{y_{2}-y_{1}}f(R_{1})+\frac{y-y_{1}}{y_{2}-y_{1}}f(R_{2}) f(P)=y2y1y2yf(R1)+y2y1yy1f(R2)

2.2 Use cases

  The following is a method of modifying image pixels using bilinear interpolation.

from PIL import Image
import numpy as np
import math

def get_pixel(path):
    img=Image.open(path)
    pixel=img.load()
    data=[]
    for i in range(img.size[0]):
        for j in range(img.size[1]):
            data.extend(list(pixel[i,j]))
    data=np.reshape(np.array(data),(img.size[0],img.size[1],3))
    return img,data
    
def img_resize(height,width,img,data):
    #生成在图片上取样的x坐标、y坐标
    lin_height=np.linspace(0,img.size[0]-1,height)
    lin_width=np.linspace(0,img.size[1]-1,width)
              
    new_img=Image.new('RGB',(height,width),(0,0,0))
    
    x1=np.array(list(map(lambda x:x if x<(img.size[0]-1) else x-1,[math.floor(i) for i in lin_height])))
    x2=np.array(list(map(lambda x:x-1 if x==img.size[0] else x,[math.floor(i+1) for i in lin_height])))
    
    y1=np.array(list(map(lambda x:x if x<(img.size[1]-1) else x-1,[math.floor(i) for i in lin_width])))
    y2=np.array(list(map(lambda x:x-1 if x==img.size[1] else x,[math.floor(i+1) for i in lin_width])))
    pixel_list=[]
    for i in range(height):    
        Q_r1=data[x1[i],y1,:]*(x2[i]-lin_height[i])+data[x2[i],y1,:]*(lin_height[i]-x1[i])
        Q_r2=data[x1[i],y2,:]*(x2[i]-lin_height[i])+data[x2[i],y2,:]*(lin_height[i]-x1[i])
        Q=Q_r1*np.reshape(y2-lin_width,(-1,1))+\
            Q_r2*np.reshape(lin_width-y1,(-1,1))
        Q=Q.astype(int)
        for j in range(Q.shape[0]):
            new_img.putpixel((i,j),tuple(Q[j]))
    return new_img
if __name__=="__main__":
    path=r'/Users/sherry/Downloads/杀生丸.jpeg'
    img,data=get_pixel(path)
    new_img=img_resize(2000,2000,img,data)

Guess you like

Origin blog.csdn.net/yeshang_lady/article/details/132850861