双线性插值计算手动实现以及原理

双线性插值计算手动实现以及原理

代码

先贴代码吧,原理其实也比较简单,看代码基本也就理解了,时间太晚了,原理后续再补吧。

import torch
from torch.nn import functional as F
import numpy as np
from itertools import product
import warnings
warnings.filterwarnings('ignore')
def data_gen(in_wh,out_wh):
    in_w,in_h = in_wh
    out_w,out_h = out_wh
    inp = torch.range(0,in_h*in_w-1,1).reshape(1,1,in_h, in_w)
    new_h = torch.linspace(-1, 1, out_h).view(-1, 1).repeat(1, out_w)
    new_w = torch.linspace(-1, 1, out_w).repeat(out_h, 1)
    grid = torch.cat((new_w.unsqueeze(2), new_h.unsqueeze(2)), dim=2)#+2/5
    # print(grid.shape)
    grid = grid.unsqueeze(0).clip(-1,1)
    return inp,grid
def torch_interp(in_wh,out_wh):
    '''torch 插值'''
    inp,grid = data_gen(in_wh,out_wh)
    print(inp)
    outp = F.grid_sample(inp, grid=grid, align_corners=True)#和下面的二选一
    outp = torch.grid_sampler_2d(inp, grid,0,0, True)
    # print(outp)
    return outp
def my_interp(in_wh,out_wh):
    '''手动实现的插值计算'''
    inp,grid = data_gen(in_wh,out_wh)
    in_w,in_h = in_wh
    p_h = 2/(in_h-1)#计算h方向上每一份的长度
    p_w = 2/(in_w-1)#计算w方向上每一份的长度
    p_ = np.array([p_w,p_h])#合并
    inp = inp[0,0,:,:]
    grid = grid[0]
    out = np.zeros((grid.shape[0],grid.shape[1]))#初始化输出模板
    for (_i,_j) in product(range(grid.shape[0]),range(grid.shape[1])):
        maps = (grid[_i,_j]).cpu().numpy()
        interp_start = (maps+1)//p_#计算插值的起始点
        offset = (maps+1)%p_#计算距离起始点的偏移量
        interp_start = interp_start.astype(np.int32)
        # print(interp_start)
        w, pix = [], []
        for j,i in [(0,0),(0,1),(1,0),(1,1)]:
            w.append(abs((i*p_[0]-offset[0])*(p_[1]*j-offset[1]))/(p_[0]*p_[1]))#双线性插值的面积计算
            interp_start_ = interp_start+np.array([i,j])#计算插值的四个点中的某一个
            interp_start_[0]=interp_start_[0].clip(0,in_w-1)#控制不超出原图像边界
            interp_start_[1]=interp_start_[1].clip(0,in_h-1)
            pix.append(inp[interp_start_[1]][interp_start_[0]])
        w = np.array(w)
        pix = np.array(pix[::-1])
        interp_val = round((w*pix).sum(),3)
        out[_i,_j]=interp_val
    return out
#原始输入
in_wh = 9, 9
#目标输出
out_wh =5, 2
a = torch_interp(in_wh,out_wh)
b = my_interp(in_wh,out_wh)
a,b

结果:

tensor([[[[ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.],
          [ 9., 10., 11., 12., 13., 14., 15., 16., 17.],
          [18., 19., 20., 21., 22., 23., 24., 25., 26.],
          [27., 28., 29., 30., 31., 32., 33., 34., 35.],
          [36., 37., 38., 39., 40., 41., 42., 43., 44.],
          [45., 46., 47., 48., 49., 50., 51., 52., 53.],
          [54., 55., 56., 57., 58., 59., 60., 61., 62.],
          [63., 64., 65., 66., 67., 68., 69., 70., 71.],
          [72., 73., 74., 75., 76., 77., 78., 79., 80.]]]])
(tensor([[[[ 0.,  2.,  4.,  6.,  8.],
           [72., 74., 76., 78., 80.]]]]),
 array([[ 0.,  2.,  4.,  6.,  8.],
        [72., 74., 76., 78., 80.]]))

自己试了几组数据,结果均与torch一致。
在这里插入图片描述

原理

先简要说一下原理吧
在线性插值的情况下:
在这里插入图片描述

假设AB=AD/2,那么B的坐标等于(1-0.5)×A+0.5×D= 3.5
那么C点坐标等于(1-0.6)×A+0.6×D=3.8
那么在双线性插值的情况下,
增加了一个维度
在这里插入图片描述

E的像素值等于e = (D×a+B×c+A×d+C×b)/(A+B+C+D)
其中ABCD表示对应区域的面积。

  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值