• (四)线性插值



    欢迎访问个人网络日志🌹🌹知行空间🌹🌹


    1.线性插值

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

    图片来自于线性插值
    在这里插入图片描述

    如上图,已知坐标 ( x 0 , y 0 ) , ( x 1 , y 1 ) (x_0, y_0),(x_1,y_1) (x0,y0),(x1,y1),要求区间 [ x 0 , x 1 ] [x_0, x_1] [x0,x1]中间一个x位置在直线上的值,使用线性插值的方法如下,两点式直线方程可写为:

    x − x 0 x 1 − x 0 = y − y 0 y 1 − y 0 \frac{x-x_0}{x_1-x_0}=\frac{y-y_0}{y_1-y_0} x1x0xx0=y1y0yy0

    记方程左右的等值为 α \alpha α,则可得 α = x − x 0 x 1 − x 0 \alpha=\frac{x-x_0}{x_1-x_0} α=x1x0xx0,

    y = ( 1 − α ) y 0 + α y 1 y=(1-\alpha)y_0+\alpha y_1 y=(1α)y0+αy1

    上式可用来计算 y y y。实际上当 x ∉ [ x 0 , x 1 ] x\notin[x_0,x_1] x/[x0,x1] α ∉ [ 0 , 1 ] \alpha\notin[0,1] α/[0,1]时,上式仍然可以使用,这种情况下,这种方法叫作线性外插

    2.双线性插值

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

    图片来自双线性插值
    在这里插入图片描述

    现在函数值是和 ( x , y ) (x,y) (x,y)相关的二维函数, z = f ( x , y ) z=f(x, y) z=f(x,y), 可将上图当成是沿z轴方向的俯视图, Q 11 , Q 12 , Q 21 , Q 22 Q_{11}, Q_{12}, Q_{21}, Q_{22} Q11,Q12,Q21,Q22是已知的四个点,双线性插值所做的事情即根据这四个点求中间点 P P P的值,上图中

    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)" role="presentation" style="position: relative;">f(Q11)=f(x1,y1)f(Q12)=f(x1,y2)f(Q21)=f(x2,y1)f(Q22)=f(x2,y2)
    f(Q11)=f(x1,y1)f(Q12)=f(x1,y2)f(Q21)=f(x2,y1)f(Q22)=f(x2,y2)

    求P需先求中间点 R 1 , R 2 R_1,R_2 R1,R2, R 1 R_1 R1可根据 Q 11 , Q 12 Q_{11},Q_{12} Q11,Q12用线性插值公式来求, R 2 R_2 R2可根据 Q 21 , Q 22 Q_{21},Q_{22} Q21,Q22用线性插值公式来求。

    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 2 ) = x 2 − x x 2 − x 1 f ( Q 12 ) + x − x 1 x 2 − x 1 f ( Q 22 )

    f(R1)=x2xx2x1f(Q11)+xx1x2x1f(Q21)f(R2)=x2xx2x1f(Q12)+xx1x2x1f(Q22)" role="presentation" style="position: relative;">f(R1)=x2xx2x1f(Q11)+xx1x2x1f(Q21)f(R2)=x2xx2x1f(Q12)+xx1x2x1f(Q22)
    f(R1)=x2x1x2xf(Q11)+x2x1xx1f(Q21)f(R2)=x2x1x2xf(Q12)+x2x1xx1f(Q22)

    得到 R 1 , R 2 R_1,R_2 R1,R2后,对这两点再应用线性插值即可求 P P P,

    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)

    3.示例

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

    已知 ( 2 , 2 ) , ( 2 , 3 ) , ( 3 , 2 ) , ( 3 , 3 ) (2,2),(2,3),(3,2),(3,3) (2,2),(2,3),(3,2),(3,3)四个像素点的值分别为 20 , 15 , 30 , 40 20,15,30,40 20,15,30,40,用双线性插值求其中间点 P ( 2.6 , 2.4 ) P(2.6,2.4) P(2.6,2.4)的像素值的过程如下,

    图片来自双线性插值
    在这里插入图片描述

    f ( R 1 ) = 0.4 × 20 + 0.6 × 30 = 26 f ( R 2 ) = 0.4 × 15 + 0.6 × 40 = 30 f ( P ) = 0.6 × 26 + 0.4 × 30 = 27.6 ≈ 28

    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" role="presentation" style="position: relative;">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
    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]]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    手动计算双线性插值过程,需先将resize后大小为2x2destination图像对应的点再还原到source源图像上去,然后才能在原图像上应用双线性插值,这里将目标图像点映射到源图像上的坐标计算公式为:
    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)×srcWidthdstWidth0.5Y=(dstY+0.5)×srcHeightdstHeight0.5" role="presentation" style="position: relative;">X=(dstX+0.5)×srcWidthdstWidth0.5Y=(dstY+0.5)×srcHeightdstHeight0.5
    X=(dstX+0.5)×dstWidthsrcWidth0.5Y=(dstY+0.5)×dstHeightsrcHeight0.5

    • dstX 是resize后图像上的像素点坐标
    • srcWidth/srcHeight源图像宽高,dstWidth/dstHeight resize后图像的宽高

    这个公式可以写成:
    s r c X + 0.5 d s t X + 0.5 = s r c W i d t h d s t W i d t h \frac{srcX + 0.5}{dstX + 0.5} = \frac{srcWidth}{dstWidth} dstX+0.5srcX+0.5=dstWidthsrcWidth
    可理解成将resize后每个像素点中心和原图上对应点开始一半像素的位置对齐。

    计算过程为:

    图片来自双线性插值
    在这里插入图片描述

    可见与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.]]]])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

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

    其他

    关于双线性插值,可以将上述公式 f ( P ) f(P) f(P)展开成 f ( Q i j ) f(Q_{ij}) f(Qij)的加权和,其物理含义可借助下图表示:

    图片来自于RoI Pooling 与 RoI Align 的区别
    在这里插入图片描述


    欢迎访问个人网络日志🌹🌹知行空间🌹🌹


    参考资料

  • 相关阅读:
    视野修炼-技术周刊第59期
    QT+OSG/osgEarth编译之二十三:Shapelib+Qt编译(一套代码、一套框架,跨平台编译,版本:Shapelib-1.5.0)
    【zookeeper】zookeeper介绍
    Java流程控制
    AI大模型探索之路-基础篇5:GLM-4解锁国产大模型的全能智慧与创新应用
    c# 学习教程
    【滤波跟踪】扩展卡尔曼滤波的无人机路径跟踪【含Matlab源码 2236期】
    2022 极术通讯-Arm 虚拟硬件加速物联网软件开发
    ubuntu 18.04 中 eBPF samples/bpf 编译
    红外物理学习笔记 ——第三章
  • 原文地址:https://blog.csdn.net/lx_ros/article/details/126312139