pytorch|图像上采样方法 - 插值 反卷积 反池化

上采样方法总览 有3种上采样常见的方法:
一. 插值(bilinear)
二. 反卷积(Transposed Convolution)
三. 反池化(Unpooling)
pytorch 上采样: https://pytorch.org/docs/stable/_modules/torch/nn/modules/upsampling.html
一. 插值 interpolate 最简单的方式是重采样和插值:将输入图片input image进行rescale到一个想要的尺寸,而且计算每个点的像素点,使用如双线性插值 (Bilinear-Interpolation) 等插值方法对其余点进行插值。在AlexNet中就使用了较合适的插值方法。各种插值方法都有各自的优缺点。插值就是在不生成像素的情况下增加图像像素大小的一种方法,在周围像素色彩的基础上用数学公式计算丢失像素的色彩(也有的有些相机使用插值,人为地增加图像的分辨率)。所以在放大图像时,图像看上去会比较平滑、干净。但必须注意的是插值并不能增加图像信息。
1. 插值 - 线性 (linear) 看着就会吧!! 1和3 就填2.
pytorch|图像上采样方法 - 插值 反卷积 反池化
文章图片

根据图中的假设:已知点(x0,y0)、(x1,y1),试问在x处插值,y的值是多少?用我们初中学过的知识,已知两个点的坐标可以得到一条线,又已知线上一点的一个坐标可以求得这个点的另一个坐标值。这就是线性插值的原理。x只是表示的相对的位置,y才是我们想要的结果:
y = y 0 + ( y 1 ? y 0 ) ( x 1 ? x 0 ) ( x ? x 0 ) y=y_0 + \frac{(y_1-y_0)}{(x_1-x_0)}(x-x_0) y=y0?+(x1??x0?)(y1??y0?)?(x?x0?)
2. 插值 - 双线性 (bilinear) 如图,已知Q12,Q22,Q11,Q21,但是要插值的点为P点,这就要用双线性插值了,首先在x轴方向上,对R1和R2两个点进行插值,这个很简单,然后根据R1和R2对P点进行插值,这就是所谓的双线性插值。
pytorch|图像上采样方法 - 插值 反卷积 反池化
文章图片


双线性插值的案例:不对齐|对其;
注意: 用ONNX轉模型時,不支持bilinear

>>> import torch >>> import torch.nn as nn >>> input = torch.arange(1, 5).view(1, 1, 2, 2).float() >>> input tensor([[[[ 1.,2.], [ 3.,4.]]]])>>> m = nn.Upsample(scale_factor=2, mode='bilinear')# align_corners=False >>> m(input) tensor([[[[ 1.0000,1.2500,1.7500,2.0000], [ 1.5000,1.7500,2.2500,2.5000], [ 2.5000,2.7500,3.2500,3.5000], [ 3.0000,3.2500,3.7500,4.0000]]]])>>> m = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True) >>> m(input) tensor([[[[ 1.0000,1.3333,1.6667,2.0000], [ 1.6667,2.0000,2.3333,2.6667], [ 2.3333,2.6667,3.0000,3.3333], [ 3.0000,3.3333,3.6667,4.0000]]]])

bilinear不对其展示:
pytorch|图像上采样方法 - 插值 反卷积 反池化
文章图片

bilinear对其展示:
pytorch|图像上采样方法 - 插值 反卷积 反池化
文章图片

align_corners
这里参数align_corners的含义如下:
pytorch|图像上采样方法 - 插值 反卷积 反池化
文章图片

上面的图是source pixel为44上采样为target pixel为88的两种情况,这就是对齐和不对齐的差别,会对齐左上角元素,即设置为align_corners = True时输入的左上角元素是一定等于输出的左上角元素。但是有时align_corners = False时左上角元素也会相等,官网上给的例子就不太能说明两者的不同(也没有试出不同的例子,大家理解这个概念就行了)
如果您想下采样/常规调整大小,您应该使用interpolate()方法,这里的上采样方法已经不推荐使用了。
【引用: https://www.cnblogs.com/wanghui-garcia/p/11399053.html 】
3. 插值 - 最邻近元法(Nearest Neighbour Interpolation) 这是最简单的一种插值方法,不需要计算,在待求象素的四邻象素中,将距离待求象素最近的邻象素灰度赋给待求象素。更简单了,连计算都不计算了,直接填
注意: 用ONNX轉模型時,支持Nearest
>>> import torch >>> import torch.nn as nn >>> input = torch.arange(1, 5).view(1, 1, 2, 2).float() >>> input tensor([[[[ 1.,2.], [ 3.,4.]]]])>>> m = nn.Upsample(scale_factor=2, mode='nearest') >>> m(input) tensor([[[[ 1.,1.,2.,2.], [ 1.,1.,2.,2.], [ 3.,3.,4.,4.], [ 3.,3.,4.,4.]]]])最邻近元法结果展示:

pytorch|图像上采样方法 - 插值 反卷积 反池化
文章图片

Pytorch 代码展示 torch.nn.functional.interpolate - 插值函数
torch.nn.functional.interpolate(input, size=None, scale_factor=None, mode='nearest', align_corners=None)

向下或向上采样输入到给定的size或给定的scale_factor;由 mode 指定插值的算法.目前支持时间, 空间和体积上采样, 即预期输入 3-D, 4-D or 5-D 形状. 输入维度形式: mini-batch x channels x [可选的 depth] x [可选的 height] x width.
可用于上采样的模式有: nearest, linear (仅三维), bilinear (仅四维), trilinear (仅五维), area
参数:
参数 意义
input 输入张量( (Tensor) )
size 输出尺寸 ((int or Tuple__[int] or Tuple__[int, int] or Tuple__[int, int, int]))
scale_factor 空间大小的乘数. 如果是元组, 则必须匹配输入大小.( (float or Tuple__[float]) )
mode 上采样算法: ‘nearest’ , ‘linear’ , ‘bilinear’ , ‘trilinear’ , ‘area’. 默认值: ‘nearest’ (string)
align_corners 如果为True, 则输入和输出张量的角像素对齐, 从而保留这些像素的值. 仅在 mode 是 linear, bilinear, 或者 trilinear 时生效. 默认值: False (bool, 可选的)
note:
  1. 使用mode='bicubic',可能会导致overshoot
  2. 负值或图像大于255的值。
  3. 如果要减少过冲,请显式调用```result.clamp(Min=0,Max=255)``
警告
align_corners = True时, 线性插值模式(linear, bilinear, and trilinear)不会按比例对齐输出和输入像素, 因此输出值可能取决于输入大小.
接下来的函数不推荐使用 ① Upsample
② UpsamplingNearest2d
③ UpsamplingBilinear2d
都推荐nn.functional.interpolate(…)函数。
import torch.nn as nn nn.Upsample(scale_factor=2, mode='bilinear')

也有方法
torch.nn.UpsamplingNearest2d(size=None, scale_factor=None)

官方说不推荐用此类,黑人问好?
#推荐用 nn.functional.interpolate()

def upsample(input, size=None, scale_factor=None, mode='nearest', align_corners=None): r"""Upsamples the input to either the given :attr:`size` or the given :attr:`scale_factor`warning: This function is deprecated in favor of :func:`torch.nn.functional.interpolate`. This is equivalent with ``nn.functional.interpolate(...).

反卷积 反卷积,是卷积的逆过程,实现上采用转置卷积核的方法,又称作转置卷积 (transposed convolution)。为实现deconvolution,直接使deconv的前向传播模拟conv的反向传播。如何理解深度学习中的deconvolution networks
FCN的upsampling过程,就是把feature map,abcd进行一个反卷积,得到的新的feature map和之前对应的encoder feature map 相加。参考 FCN全卷积网络。
反池化 【pytorch|图像上采样方法 - 插值 反卷积 反池化】反池化,在池化过程中,记录下max-pooling在对应kernel中的坐标,在反池化过程中,将一个元素根据kernel进行放大,根据之前的坐标将元素填写进去,其他位置补0。 unPooling是在CNN中常用的来表示max pooling的逆操作。实现代码可以看SegNet的实现,TF-SegNet代码实现,参考 卷积神经网络CNN——SegNet。

    推荐阅读