torch.nn.functional.grid_sample(input, grid, mode='bilinear', padding_mode='zeros', align_corners=None)
提供一个input的Tensor以及一个对应的flow-field网格(比如光流,体素流等),然后根据grid中每个位置提供的坐标信息(这里指input中pixel的坐标),将input中对应位置的像素值填充到grid指定的位置,得到最终的输出。
关于input、grid以及output的尺寸如下所示:(input也可以是5D的Tensor,这里我们只考虑4D的情况)
这里的input和output就是输入的图片,或者是网络中的feature map。关键的处理过程在于grid,grid的最后一维的大小为2,即表示input中pixel的位置信息 ,这里一般会将x和y的取值范围归一化到
之间,
表示input左上角的像素的坐标,
表示input右下角的像素的坐标,对于超出这个范围的坐标
,函数将会根据参数padding_mode的设定进行不同的处理。
- padding_mode='zeros':对于越界的位置在网格中采用pixel value=0进行填充。
- padding_mode='border':对于越界的位置在网格中采用边界的pixel value进行填充。
- padding_mode='reflection':对于越界的位置在网格中采用关于边界的对称值进行填充。
对于mode='bilinear'参数,则定义了在input中指定位置的pixel value中进行插值的方法,为什么需要插值呢?因为前面我们说了,grid中表示的位置信息x和y的取值范围在 之间,这就意味着我们要根据一个浮点型的坐标值在input中对pixel value进行采样,mode有
nearest和bilinear
两种模式。 nearest就是直接采用与 距离最近处的像素值来填充grid,而bilinear则是采用双线性插值的方法来进行填充,总之其与nearest的区别就是nearest只考虑最近点的pixel value,而bilinear则采用
周围的四个pixel value进行加权平均值来填充grid。
双线性插值:
上面讲到双线性插值会对 周围的四个pixel value进行加权平均,那么每个位置的权重是多少呢?可以简单参考下图中双线性插值的例子:
其双线性插值的结果为:
采用下图我们可以对双线性插值有个更为直观的认识:
从上图中可以看到双线性插值就是首先在平面 内,对
和
进行插值得到
,对
和
进行插值得到
,随后在平面
内进行插值得到最终的
点的值就是最终所求的结果,这里的平面内插值其实就是采用我们高中学的,直线的两点式求出直线表达是,再带入自变量(x或y)的坐标得到插值的结果。联立两次直线的两点式就能得到双线性插值的结果,说到这里“双线性”也顾名思义了。
下面给出正式的推导:
已知四点的坐标如下所示:
Q11=(x1,y1,f(x1,y1)), Q21=(x2,y1,f(x2,y2)), Q12=(x1,y2,f(x3,y3)), Q22=(x2,y2,f(x4,y4))
其中有z=f(x,y):
先在x方向上进行插值有:
然后在y的方向上进行插值:
将x方向 和
带入到上式可得:
以上式子便是最终双线性插值的最终表达式,由于4个点的权重部分中分母是相同的可以忽略不计