# 双线性插值算法

# 1.线性插值

线性插值是指使用连接两个已知点的直线来确定同在这个直线上的未知点值的方法。

图片来自于线性插值 (opens new window)


如上图,已知坐标,要求区间中间一个x位置在直线上的值,使用线性插值的方法如下,两点式直线方程可写为:

xx0x1x0=yy0y1y0

记方程左右的等值为,则可得,

y=(1α)y0+αy1

上式可用来计算。实际上当时,上式仍然可以使用,这种情况下,这种方法叫作线性外插

# 2.双线性插值

知道线性插值后,双线性插值,又称双线性内插,就是在两条线上分别进行一次线性插值,等到两个中间点,再对中间点进行一次线性插值得到的,如下图:

图片来自双线性插值 (opens new window)

现在函数值是和相关的二维函数,, 可将上图当成是沿z轴方向的俯视图,是已知的四个点,双线性插值所做的事情即根据这四个点求中间点的值,上图中

f(Q11)=f(x1,y1)f(Q12)=f(x1,y2)f(Q21)=f(x2,y1)f(Q22)=f(x2,y2)

求P需先求中间点, 可根据用线性插值公式来求,可根据用线性插值公式来求。

f(R1)=x2xx2x1f(Q11)+xx1x2x1f(Q21)f(R2)=x2xx2x1f(Q12)+xx1x2x1f(Q22)

得到后,对这两点再应用线性插值即可求,

f(P)=y2yy2y1f(R1)+yy1y2y1f(R2)

# 3.示例

# 3.1 双线性插值求像素点的值

已知四个像素点的值分别为,用双线性插值求其中间点的像素值的过程如下,

图片来自双线性插值 (opens new window)

f(R1)=0.4×20+0.6×30=26f(R2)=0.4×15+0.6×40=30f(P)=0.6×26+0.4×30=27.628

# 3.2与OpneCV Resize方法做比较

使用OpenCVresize方法,插值方法选择双线性插值。将3x3的图像使用双线性插值resize2x2
使用OpenCV计算的结果为:

img = np.array([[30, 20, 10],
 [10, 40, 60],
 [20, 30, 40]], dtype=np.uint8)
img = cv2.resize(img, (2,2), cv2.INTER_LINEAR)
print(img)
# [[25 23]
#  [21 42]]

手动计算双线性插值过程,需先将resize后大小为2x2destination图像对应的点再还原到source源图像上去,然后才能在原图像上应用双线性插值,这里将目标图像点映射到源图像上的坐标计算公式为:

X=(dstX+0.5)×srcWidthdstWidth0.5Y=(dstY+0.5)×srcHeightdstHeight0.5
  • dstX 是resize后图像上的像素点坐标
  • srcWidth/srcHeight源图像宽高,dstWidth/dstHeight resize后图像的宽高

这个公式可以写成:

srcX+0.5dstX+0.5=srcWidthdstWidth

可理解成将resize后每个像素点中心和原图上对应点开始一半像素的位置对齐。

计算过程为:

图片来自双线性插值 (opens new window)

可见与OpenCV resize函数使用INTER_LINEAR方法时的结果相同。

上述原图坐标和resize后图像坐标的映射方式等同于TORCH.NN.FUNCTIONAL.INTERPOLATE函数align_corners=False时的场景,

import torch
import torch.nn.functional as F

t = torch.tensor(img, dtype=torch.float).reshape(1,1,3,3)
it0 = F.interpolate(t, size=2, mode = 'bilinear')
print(it0)
# tensor([[[[25.0000, 23.1250],
#           [21.2500, 41.8750]]]])
it0 = F.interpolate(t, size=2, mode = 'bilinear', align_corners=True)
print(it0)
# tensor([[[[30., 10.],
#           [20., 40.]]]])

关于align_corners参数的介绍可参考(三)TORCH.NN.FUNCTIONAL.INTERPOLATE使用说明 (opens new window)

# 其他

关于双线性插值,可以将上述公式展开成的加权和,其物理含义可借助下图表示:

图片来自于RoI Pooling 与 RoI Align 的区别 (opens new window)


(adsbygoogle = window.adsbygoogle || []).push({});

# 参考资料