根据百度百科的介绍:线性插值是指插值函数为一次多项式的插值方式。线性插值的几何意义即为利用过A点和B点的直线来近似表示原函数。线性插值可以用来近似代替原函数,也可以用来计算得到查表过程中表中没有的数值。
那么如下图所示,假设已知 y 1 = f ( x 1 ) y_1=f(x_1) y1=f(x1), y 2 = f ( x 2 ) y_2=f(x_2) y2=f(x2),现在要通过线性插值的方式得到区间 [ x 1 , x 2 ] [x_1, x_2] [x1,x2]内任何一点的 f ( x ) f(x) f(x)值。
通过上图我们很容易得到以下公式:
y − y 1 x − x 1 = y 2 − y 1 x 2 − x 1 \frac{y-y_1}{x-x_1}=\frac{y_2-y_1}{x_2-x_1} x−x1y−y1=x2−x1y2−y1
变换可以得到:
y = x 2 − x x 2 − x 1 y 1 + x − x 1 x 2 − x 1 y 2 y=\frac{x_2-x}{x_2-x_1}y_1+\frac{x-x_1}{x_2-x_1}y_2 y=x2−x1x2−xy1+x2−x1x−x1y2
为了方便后面理解,我们也可以写成:
f ( x ) = x 2 − x x 2 − x 1 f ( x 1 ) + x − x 1 x 2 − x 1 f ( x 2 ) f(x)=\frac{x_2-x}{x_2-x_1}f(x_1)+\frac{x-x_1}{x_2-x_1}f(x_2) f(x)=x2−x1x2−xf(x1)+x2−x1x−x1f(x2)
同样根据百度百科的介绍:双线性插值,又称为双线性内插。在数学上,双线性插值是有两个变量的插值函数的线性插值扩展,其核心思想是在两个方向分别进行一次线性插值。
通过以上介绍我们知道,双线性插值就是分别在两个方向上分别进行一次简单的线性插值即可。如下图所示,每个点的数值是由 z = f ( x , y ) z=f(x, y) z=f(x,y)即 x , y x, y x,y两个变量决定。下图可理解为沿z轴方向的俯视图(画三维麻烦)。我们已知 Q 11 Q_{11} Q11, Q 12 Q_{12} Q12, Q 21 Q_{21} Q21, Q 22 Q_{22} Q22四个点的值,现在要在 Q 11 , Q 12 , Q 21 , Q 22 Q_{11}, Q_{12}, Q_{21}, Q_{22} Q11,Q12,Q21,Q22四个点中插入一个点 P P P,并算出 P P P点的值。
根据上图我们已知 Q 11 Q_{11} Q11, Q 12 Q_{12} Q12, Q 21 Q_{21} Q21, Q 22 Q_{22} Q22四个点的值:
f ( Q 11 ) = f ( x 1 , y 1 ) f ( Q 12 ) = f ( x 1 , y 2 ) f ( Q 21 ) = f ( x 2 , y 1 ) f ( Q 22 ) = f ( x 2 , y 2 ) f(Q_{11}) =f(x_1, y_1)\\ \; \\ f(Q_{12})=f(x_1, y_2) \\ \; \\ f(Q_{21})=f(x_2, y_1) \\ \; \\ f(Q_{22})=f(x_2, y_2) f(Q11)=f(x1,y1)f(Q12)=f(x1,y2)f(Q21)=f(x2,y1)f(Q22)=f(x2,y2)
在求 P P P点的值之前,首先根据线性插值的方法求得 R 1 , R 2 R_1, R_2 R1,R2的值。对于 R 1 R_1 R1点,我们可以根据 Q 11 , Q 21 Q_{11}, Q_{21} Q11,Q21两个点根据线性插值的办法得到。而 Q 11 , Q 21 Q_{11}, Q_{21} Q11,Q21两个点的 y y y值是相同的,所以两点的连线可看做只关于 x x x一个变量的函数。
根据上面得到的线性插值公式:
f ( x ) = x 2 − x x 2 − x 1 f ( x 1 ) + x − x 1 x 2 − x 1 f ( x 2 ) f(x)=\frac{x_2-x}{x_2-x_1}f(x_1)+\frac{x-x_1}{x_2-x_1}f(x_2) f(x)=x2−x1x2−xf(x1)+x2−x1x−x1f(x2)
我们可以求得 R 1 R_1 R1点的值:
f ( R 1 ) = x 2 − x x 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_{21}) f(R1)=x2−x1x2−xf(Q11)+x2−x1x−x1f(Q21)
同理,我们可以得到 R 2 R_2 R2点的值:
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)=x2−x1x2−xf(Q12)+x2−x1x−x1f(Q22)
得到 R 1 , R 2 R_1, R_2 R1,R2的插值后,接着我们去计算 P P P点的插值。 R 1 , R 2 R_1, R_2 R1,R2两个点的 x x x值是相同的,所以两点的连线可看做只关于 y y y一个变量的函数。通过线性插值公式可以得到:
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)=y2−y1y2−yf(R1)+y2−y1y−y1f(R2)
带入 f ( R 1 ) , f ( R 2 ) f(R_1), f(R_2) f(R1),f(R2)后可得到:
f ( P ) = ( x 2 − x ) ( y 2 − y ) ( x 2 − x 1 ) ( y 2 − y 1 ) f ( Q 11 ) + ( x − x 1 ) ( y 2 − y ) ( x 2 − x 1 ) ( y 2 − y 1 ) f ( Q 21 ) + ( x 2 − x ) ( y − y 1 ) ( x 2 − x 1 ) ( y 2 − y 1 ) f ( Q 12 ) + ( x − x 1 ) ( y − y 1 ) ( x 2 − x 1 ) ( y 2 − y 1 ) f ( Q 22 ) f(P) = \frac{(x_2-x)(y_2-y)}{(x_2-x_1)(y_2-y_1)}f(Q_{11})+ \frac{(x-x_1)(y_2-y)}{(x_2-x_1)(y_2-y_1)}f(Q_{21}) \\ \; \\ \;\;\;\;\;\;\;\;\; + \frac{(x_2-x)(y-y_1)}{(x_2-x_1)(y_2-y_1)}f(Q_{12})+\frac{(x-x_1)(y-y_1)}{(x_2-x_1)(y_2-y_1)}f(Q_{22}) f(P)=(x2−x1)(y2−y1)(x2−x)(y2−y)f(Q11)+(x2−x1)(y2−y1)(x−x1)(y2−y)f(Q21)+(x2−x1)(y2−y1)(x2−x)(y−y1)f(Q12)+(x2−x1)(y2−y1)(x−x1)(y−y1)f(Q22)
在图像处理中,常见的坐标系如下图所示,以图像左上角为坐标原点,水平向右为x轴正方向,竖直向下为y轴正方向。注意像素值是从 ( 0 , 0 ) (0, 0) (0,0)点开始,假设我们在图像中插入一个点 P P P,离 P P P点最近的相邻四个像素点是 Q 11 , Q 12 , Q 21 , Q 22 Q_{11}, Q_{12}, Q_{21}, Q_{22} Q11,Q12,Q21,Q22并利用双线性插值的方法求其值。
由于 Q 11 , Q 12 , Q 21 , Q 22 Q_{11}, Q_{12}, Q_{21}, Q_{22} Q11,Q12,Q21,Q22四个点是图像中相邻的像素,故有:
x 2 − x 1 = 1 , y 2 − y 1 = 1 x_2-x_1=1,\ \ y_2-y_1=1 x2−x1=1, y2−y1=1
带入公式进一步化简可得:
f ( P ) = ( x 2 − x ) ( y 2 − y ) f ( Q 11 ) + ( x − x 1 ) ( y 2 − y ) f ( Q 21 ) + ( x 2 − x ) ( y − y 1 ) f ( Q 12 ) + ( x − x 1 ) ( y − y 1 ) f ( Q 22 ) f(P) = (x_2-x)(y_2-y)f(Q_{11})+ (x-x_1)(y_2-y)f(Q_{21}) \\ \; \\ \;\;\;\;\;\;\;\;\; + (x_2-x)(y-y_1)f(Q_{12})+(x-x_1)(y-y_1)f(Q_{22}) f(P)=(x2−x)(y2−y)f(Q11)+(x−x1)(y2−y)f(Q21)+(x2−x)(y−y1)f(Q12)+(x−x1)(y−y1)f(Q22)
我们令:
x − x 1 = u , y − y 1 = v x-x_1=u,\; \; \; y-y_1=v x−x1=u,y−y1=v
带入公式可得:
f ( P ) = ( 1 − u ) ( 1 − v ) f ( Q 11 ) + u ( 1 − v ) f ( Q 21 ) + ( 1 − u ) v f ( Q 12 ) + u v f ( Q 22 ) f(P) = (1-u)(1-v)f(Q_{11})+ u(1-v)f(Q_{21}) \\ \; \\ \;\;\;\;\;\;\;\;\; + (1-u)vf(Q_{12})+uvf(Q_{22}) f(P)=(1−u)(1−v)f(Q11)+u(1−v)f(Q21)+(1−u)vf(Q12)+uvf(Q22)
我们令:
x 1 = i , y 1 = j f ( Q 11 ) = f ( i , j ) x_1=i,\;\;\;y_1=j\\ f(Q_{11})=f(i,j) x1=i,y1=jf(Q11)=f(i,j)
那么有:
f ( Q 11 ) = f ( i , j ) , f ( Q 12 ) = f ( i , j + 1 ) f ( Q 21 ) = f ( i + 1 , j ) , f ( Q 22 ) = f ( i + 1 , j + 1 ) f(Q_{11})=f(i,j),\;\;\;f(Q_{12})=f(i,j+1)\\ f(Q_{21})=f(i+1,j),\;\;\;f(Q_{22})=f(i+1,j+1) f(Q11)=f(i,j),f(Q12)=f(i,j+1)f(Q21)=f(i+1,j),f(Q22)=f(i+1,j+1)
进一步带入公式得:
f ( P ) = ( 1 − u ) ( 1 − v ) f ( i , j ) + u ( 1 − v ) f ( i + 1 , j ) + ( 1 − u ) v f ( i , j + 1 ) + u v f ( i + 1 , j + 1 ) f(P) = (1-u)(1-v)f(i,j)+ u(1-v)f(i+1,j) \\ \; \\ \;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\; + (1-u)vf(i,j+1)+uvf(i+1,j+1) f(P)=(1−u)(1−v)f(i,j)+u(1−v)f(i+1,j)+(1−u)vf(i,j+1)+uvf(i+1,j+1)
以上公式中,你觉得哪个好理解,你就用哪个。
假设 P P P点的坐标是 ( 2.6 , 2.4 ) (2.6,2.4) (2.6,2.4),那么距离最近的四个像素点是 ( 2 , 2 ) , ( 2 , 3 ) , ( 3 , 2 ) , ( 3 , 3 ) (2,2),(2,3),(3,2),(3,3) (2,2),(2,3),(3,2),(3,3)那么 u = 0.6 , v = 0.4 u=0.6,v=0.4 u=0.6,v=0.4,假设:
f ( 2 , 2 ) = 20 , f ( 2 , 3 ) = 15 f ( 3 , 2 ) = 30 , f ( 3 , 3 ) = 40 f(2,2)=20,\;f(2,3)=15\\ f(3,2)=30,\;f(3,3)=40 f(2,2)=20,f(2,3)=15f(3,2)=30,f(3,3)=40
通过上面的公式:
f ( P ) = ( 1 − u ) ( 1 − v ) f ( i , j ) + u ( 1 − v ) f ( i + 1 , j ) + ( 1 − u ) v f ( i , j + 1 ) + u v f ( i + 1 , j + 1 ) f(P) = (1-u)(1-v)f(i,j)+ u(1-v)f(i+1,j) \\ \; \\ \;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\; + (1-u)vf(i,j+1)+uvf(i+1,j+1) f(P)=(1−u)(1−v)f(i,j)+u(1−v)f(i+1,j)+(1−u)vf(i,j+1)+uvf(i+1,j+1)
计算可得(一般为小数时,会四舍五入):
f ( P ) = 0.4 × 0.6 × 20 + 0.6 × 0.6 × 30 + 0.4 × 0.4 × 15 + 0.6 × 0.4 × 40 = 27.6 ≈ 28 f(P) = 0.4\times0.6\times20+ 0.6\times0.6\times30 \\ \; \\ \;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\; + 0.4\times0.4\times15+0.6\times0.4\times40=27.6\approx28 f(P)=0.4×0.6×20+0.6×0.6×30+0.4×0.4×15+0.6×0.4×40=27.6≈28
下面使用opencv中的resize函数(插值方法选择双线性插值)来进行测试。首先创建一个 3 × 3 3\times3 3×3的灰度图片,参数如下:
[[30, 20, 10],
[10, 40, 60],
[20, 30, 40]]
下图为该 3 × 3 3\times3 3×3灰度图片的grid网格(蓝色),从 ( 0 , 0 ) (0,0) (0,0)点开始。现在要通过双线性插值的方式resize到 2 × 2 2\times2 2×2大小。首先,需要计算resize后 2 × 2 2\times2 2×2大小的灰度图片映射在原图像( 3 × 3 3\times3 3×3灰度图片)上的坐标。
根据计算公式( d s t dst dst表示resize后的信息, s r c src src为resize前的信息):
X = ( d s t X + 0.5 ) × ( s r c W i d t h / d s t W i d t h ) − 0.5 Y = ( d s t Y + 0.5 ) × ( s r c H e i g h t / d s t H e i g h t ) − 0.5 X = (dstX+0.5)\times(srcWidth/dstWidth)-0.5 \\ Y = (dstY+0.5)\times(srcHeight/dstHeight)-0.5 X=(dstX+0.5)×(srcWidth/dstWidth)−0.5Y=(dstY+0.5)×(srcHeight/dstHeight)−0.5
可以得到 2 × 2 2\times2 2×2灰度图片 ( 0 , 0 ) (0,0) (0,0)点坐标映射在原图上的坐标:
x = ( 0 + 0.5 ) × ( 3 / 2 ) − 0.5 = 0.25 y = ( 0 + 0.5 ) × ( 3 / 2 ) − 0.5 = 0.25 x = (0+0.5)\times(3/2)-0.5=0.25 \\ y = (0+0.5)\times(3/2)-0.5=0.25 x=(0+0.5)×(3/2)−0.5=0.25y=(0+0.5)×(3/2)−0.5=0.25
以此类推,可得到如下图所示的黄色grid网格:
对于点 ( 0.25 , 0.25 ) (0.25,0.25) (0.25,0.25),周围最近的四个像素是 ( 0 , 0 ) , ( 1 , 0 ) , ( 0 , 1 ) , ( 1 , 1 ) (0,0),(1,0),(0,1),(1,1) (0,0),(1,0),(0,1),(1,1)可得 u = 0.25 , v = 0.25 u=0.25,v=0.25 u=0.25,v=0.25:
f ( 0.25 , 0.25 ) = ( 1 − u ) ( 1 − v ) f ( 0 , 0 ) + u ( 1 − v ) f ( 1 , 0 ) + ( 1 − u ) v f ( 0 , 1 ) + u v f ( 1 , 1 ) = 0.75 ∗ 0.75 ∗ 30 + 0.25 ∗ 0.75 ∗ 20 + 0.75 ∗ 0.25 ∗ 10 + 0.25 ∗ 0.25 ∗ 40 = 25 f(0.25,0.25) = (1-u)(1-v)f(0,0)+ u(1-v)f(1,0) \\ \; \\ \;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\; + (1-u)vf(0,1)+uvf(1,1) \\ \;\\ =0.75*0.75*30+0.25*0.75*20+0.75*0.25*10+0.25*0.25*40=25 f(0.25,0.25)=(1−u)(1−v)f(0,0)+u(1−v)f(1,0)+(1−u)vf(0,1)+uvf(1,1)=0.75∗0.75∗30+0.25∗0.75∗20+0.75∗0.25∗10+0.25∗0.25∗40=25
对于点 ( 1.75 , 0.25 ) (1.75,0.25) (1.75,0.25),周围最近的四个像素是 ( 1 , 0 ) , ( 2 , 0 ) , ( 1 , 1 ) , ( 2 , 1 ) (1,0),(2,0),(1,1),(2,1) (1,0),(2,0),(1,1),(2,1)可得 u = 0.75 , v = 0.25 u=0.75,v=0.25 u=0.75,v=0.25:
f ( 1.75 , 0.25 ) = ( 1 − u ) ( 1 − v ) f ( 1 , 0 ) + u ( 1 − v ) f ( 2 , 0 ) + ( 1 − u ) v f ( 1 , 1 ) + u v f ( 2 , 1 ) = 0.25 ∗ 0.75 ∗ 20 + 0.75 ∗ 0.75 ∗ 10 + 0.25 ∗ 0.25 ∗ 40 + 0.75 ∗ 0.25 ∗ 60 = 23.125 ≈ 23 f(1.75,0.25) = (1-u)(1-v)f(1,0)+ u(1-v)f(2,0) \\ \; \\ \;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\; + (1-u)vf(1,1)+uvf(2,1) \\ \;\\ =0.25*0.75*20+0.75*0.75*10+0.25*0.25*40+0.75*0.25*60=23.125\approx23 f(1.75,0.25)=(1−u)(1−v)f(1,0)+u(1−v)f(2,0)+(1−u)vf(1,1)+uvf(2,1)=0.25∗0.75∗20+0.75∗0.75∗10+0.25∗0.25∗40+0.75∗0.25∗60=23.125≈23
对于点 ( 0.25 , 1.75 ) (0.25,1.75) (0.25,1.75),周围最近的四个像素是 ( 0 , 1 ) , ( 1 , 1 ) , ( 0 , 2 ) , ( 1 , 2 ) (0,1),(1,1),(0,2),(1,2) (0,1),(1,1),(0,2),(1,2)可得 u = 0.25 , v = 0.75 u=0.25,v=0.75 u=0.25,v=0.75:
f ( 0.25 , 1.75 ) = ( 1 − u ) ( 1 − v ) f ( 0 , 1 ) + u ( 1 − v ) f ( 1 , 1 ) + ( 1 − u ) v f ( 0 , 2 ) + u v f ( 1 , 2 ) = 0.75 ∗ 0.25 ∗ 10 + 0.25 ∗ 0.25 ∗ 40 + 0.75 ∗ 0.75 ∗ 20 + 0.25 ∗ 0.75 ∗ 30 = 21.25 ≈ 21 f(0.25,1.75) = (1-u)(1-v)f(0,1)+ u(1-v)f(1,1) \\ \; \\ \;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\; + (1-u)vf(0,2)+uvf(1,2) \\ \;\\ =0.75*0.25*10+0.25*0.25*40+0.75*0.75*20+0.25*0.75*30=21.25\approx21 f(0.25,1.75)=(1−u)(1−v)f(0,1)+u(1−v)f(1,1)+(1−u)vf(0,2)+uvf(1,2)=0.75∗0.25∗10+0.25∗0.25∗40+0.75∗0.75∗20+0.25∗0.75∗30=21.25≈21
对于点 ( 1.75 , 1.75 ) (1.75,1.75) (1.75,1.75),周围最近的四个像素是 ( 1 , 1 ) , ( 2 , 1 ) , ( 1 , 2 ) , ( 2 , 2 ) (1,1),(2,1),(1,2),(2,2) (1,1),(2,1),(1,2),(2,2)可得 u = 0.75 , v = 0.75 u=0.75,v=0.75 u=0.75,v=0.75:
f ( 1.75 , 1.75 ) = ( 1 − u ) ( 1 − v ) f ( 1 , 1 ) + u ( 1 − v ) f ( 2 , 1 ) + ( 1 − u ) v f ( 1 , 2 ) + u v f ( 2 , 2 ) = 0.25 ∗ 0.25 ∗ 40 + 0.75 ∗ 0.25 ∗ 60 + 0.25 ∗ 0.75 ∗ 30 + 0.75 ∗ 0.75 ∗ 40 = 41.875 ≈ 42 f(1.75,1.75) = (1-u)(1-v)f(1,1)+ u(1-v)f(2,1) \\ \; \\ \;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\; + (1-u)vf(1,2)+uvf(2,2) \\ \;\\ =0.25*0.25*40+0.75*0.25*60+0.25*0.75*30+0.75*0.75*40=41.875\approx42 f(1.75,1.75)=(1−u)(1−v)f(1,1)+u(1−v)f(2,1)+(1−u)vf(1,2)+uvf(2,2)=0.25∗0.25∗40+0.75∗0.25∗60+0.25∗0.75∗30+0.75∗0.75∗40=41.875≈42
opencv代码测试:
import cv2 as cv
import numpy as np
img = [[30, 20, 10],
[10, 40, 60],
[20, 30, 40]]
img = np.array(img, dtype=np.uint8)
print(img)
re_img = cv.resize(img, (2, 2), interpolation=cv.INTER_LINEAR)
print(re_img)
终端输出:
[[30 20 10]
[10 40 60]
[20 30 40]]
[[25 23]
[21 42]]
通过终端输出可知,opencv计算得到的结果与我们自己计算的结果是一致的。