UpSampling上采样相关技术

一、参考资料

上采样和上卷积的区别
怎样通俗易懂地解释反卷积?
卷积和池化的区别、图像的上采样(upsampling)与下采样(subsampled)
[读论文]用全卷积Res网络做深度估计
对抗生成网络GAN系列——DCGAN简介及人脸图像生成案例
深度学习中常用的几种卷积(上篇):标准二维卷积、转置卷积、1*1卷积(附Pytorch测试代码)
反卷积(Deconvolution)、上采样(UnSampling)与上池化(UnPooling)

二、相关介绍

1. 上采样(UpSampling)

1.1 上采样的概念

在应用在计算机视觉的深度学习领域,由于输入图像通过卷积神经网络(CNN)提取特征后,输出的尺寸往往会变小,而有时我们需要将图像恢复到原来的尺寸以便进行进一步的计算(e.g.图像的语义分割)。这个采用扩大图像尺寸,实现图像由小分辨率到大分辨率的映射的操作,叫做上采样(UpSample)。简单理解,下采样是缩小图像的尺寸,上采样则是放大图像的尺寸。

理论上来说,上采样放大图像并不能带来更多关于该图像的信息,因此图像的质量将不可避免地受到影响。

1.2 常用上采样方法

一般来说,将缩小的图像还原成原始图像大多数都是采用插值算法,即将新元素插入到图像的像素点之间。常用的插值算法有:最近邻插值(Nearest neighbor interpolation)、双线性插值(Bi-linear interpolation),均值插值中值插值。另外,深度学习领域,常用的上采样方法还包括:转置卷积(Transposed Convolution),反池化(UnPooling)。

1.3 上采样的应用

  1. FCN、UNet:对输入图片进行像素级分割,使用上采样操作还原图片分辨率。
  2. GAN:对输入图片进行学习并生成图片,使用上采样操作将提取的特征图还原到原图尺寸。

2. 下采样(subsampling

下采样(subsampling)又称为降采样(downsampling),主要目的是缩小图像尺寸,使得图像符合显示区域的大小,或者生成对应图像的缩略图。在计算机视觉中,CNN特征提取过程即为下采样过程。

对于一幅图像I尺寸为 MxN,对其进行s倍下采样,即得到 (M/s)x(N/s) 尺寸的得分辨率图像,并且s是M和N的公约数。如果是矩阵形式的图像,就是把原始图像sxs窗口内的图像变成一个像素,该像素点的值就是窗口内所有像素的均值。

3. 反池化vs上采样vs转置卷积的通俗理解

在这里插入图片描述

图(a)表示反池化( UnPooling )过程,特点是在 Maxpooling 的时候保留最大值的位置信息,之后在UnPooling 阶段使用该信息扩充 Feature Map,除最大值位置以外,其余补0。

图(b)表示上采样( UnSampling )过程,特点是在 UnSampling 阶段没有使用 MaxPooling 时的位置信息,而是直接将内容复制来扩充 Feature Map。从图中即可看到两者结果的不同。

图©表示转置卷积(Conv2DTranspose)过程,特点是在 Conv2DTranspose 阶段需要学习参数(类似标准卷积过程),理论上来说, Conv2DTranspose 可以实现 UnPoolingUnSampling,只要卷积核的参数设置合理。

4. 反池化vs转置卷积的可视化

原始论文:[5]
在这里插入图片描述

图(a)是输入层;图(b)是14x14反卷积的结果;图©是28x28的 UnPooling 结果;图(d)是28x28的Conv2DTranspose 结果;图(e)是56*56的 Unpooling 结果;图(f)是56x56 Conv2DTranspose 的结果;图(g)是112x112 的UnPooling 的结果;图(h)是112x112的 Conv2DTranspose 的结果;图(i)和图(j)分别是224x224的 UnPoolingConv2DTranspose 的结果。

三、上采样相关方法

1. 转置卷积(Transposed Convolution)

关于转置卷积的详细介绍,请参考另一篇博客:深入浅出理解转置卷积Conv2DTranspose

2. 反池化(UnPooling)

原始论文:[6]

UnPooling 是在CNN中常用的来表示 max pooling 的逆向过程(逆操作),可以提高特征图的空间分辨率。鉴于 max pooling 不可逆,论文使用了switch变量集合来记录 max pooling 阶段的位置,对于一个训练好的模型switch变量集合是已知的,跑一遍程序即可。

简单来说,UnPooling 记住 max pooling 阶段最大item 的位置,比如一个3x3的矩阵,max pooling 的size为2x2,stride为1,其余位置至为0。

在这里插入图片描述

2.1 方法一

最大池化的逆向过程,在最大值的位置补最大值,其他位置补0。
在这里插入图片描述

2.2 方法二

原始论文:[1]、[4]

在这里插入图片描述

用2x2的块进行反池化操作,左上角为实值,其他位置补0。

2.3 方法三

原始论文:[3]

在卷积神经网络中, max pooling 操作是不可逆的,但可以通过一组转换变量(switch variables)来记录每个池化区域内最大值的位置,从而获得近似的反池化。switch variables 对应 Pooling indices3D max pooling 如下图所示:

在这里插入图片描述

上图中,特征图z划分为2x2的区域,每个区域用不同颜色表示。对每个区域进行最大池化操作,得到池化图p和转换图s。其中,k表示维度,转换图s记录了每个区域最大值的位置。

2.4 方法四

原始论文:[6]
在这里插入图片描述
在这里插入图片描述

2.5 方法五

原始论文:[5]
在这里插入图片描述

3. 上卷积(up-convolution)

原始论文:[1]

upconv上卷积是什么? monodepth源码阅读

3.1 up-convolution结构

UpConv:2×2 unpooling (zero-insertion) followed by a single 5×5 convolution.

上卷积(Up-convolution,简称UpConv),其结构如下图所示:

在这里插入图片描述

上卷积的结构unpooling+convolution,可以理解为:上采样+convolution

标准卷积的结构convolution+pooling,可以理解为:convolution+下采样

论文中提到,每次 up-convolution 后增加一个卷积层可以显著提高生成图像的质量。

3.2 up-convolution计算步骤

当在卷积层之前进行unpooling 操作时,可以将 unpooling+convolution 视为与标准CNN中执行的 convolution+pooling 步骤相反的步骤。

up-convolution 的计算过程,包含三个步骤:

  1. unpooling过程。把特征图中的一个元素映射成2×2的尺寸,左上角(the top left corner)为输入值(entry value),其他三个位置为零值;
  2. convolution过程。用5×5的卷积进行卷积计算;
  3. ReLu激活过程。

在这里插入图片描述

4. fast up-convolution(改进版)

原始论文:[1]

4.1 fast up-convolution结构

基于普通up-convolution改进的 fast up-convolution,其结构如下图所示:

在这里插入图片描述

4.2 fast up-convolution计算步骤

在这里插入图片描述

上图中,top为普通的 up-convolution,bottom为 fast up-convolution。原始特征图与4个不同的 filters 进行卷积得到4个不同的特征图,再将4个特征图交叉合并为一个 feature map,最终输出结果与普通的 up-convolution 结果相同。

5. 上投影(up-projection

原始论文:[1]

UpProj:2 × 2 unpooling (zero-insertion) followed by a two-branched residual structure that computes a total of three convolutions (two 5 × 5 and one 3 × 3).

上投影(up-projection,简称UpProj),其结构如下图所示:
在这里插入图片描述

6. NNConv5

原始论文:[7]

NNConv5:5 × 5 convolution followed by nearest-neighbor interpolation[8] with a scale factor of 2.

NNConv5 的结构如下图所示:

在这里插入图片描述

四、PyTorch中的上采样方法

深入理解PyTorch中的Upsample

在PyTorch中,Upsample支持不同的缩放模式,包括最近邻方法、双线性插值、三线性插值等。在PyTorch中,可以通过nn模块下的Upsample 或者functional模块下的interpolate函数来进行缩放操作。

1. torch.nn.Upsample(推荐)

官方文档:torch.nn.Upsample

1.1 函数原型

CLASS torch.nn.Upsample(size=None, 
                        scale_factor=None, 
                        mode='nearest', 
                        align_corners=None, 
                        recompute_scale_factor=None)

参数解释

  • size (int or Tuple[int] or Tuple[int, int] or Tuple[int, int, int], optional) – output spatial sizes.
  • scale_factor (float or Tuple[float] or Tuple[float, float] or Tuple[float, float, float], optional) – multiplier for spatial size. Has to match input size if it is a tuple.
  • mode (str, optional) – the upsampling algorithm: one of 'nearest', 'linear', 'bilinear', 'bicubic' and 'trilinear'. Default: 'nearest'.
  • align_corners (bool, optional) – if True, the corner pixels of the input and output tensors are aligned, and thus preserving the values at those pixels. This only has effect when mode is 'linear', 'bilinear', 'bicubic', or 'trilinear'. Default: False.
  • recompute_scale_factor (bool, optional) – recompute the scale_factor for use in the interpolation calculation. If recompute_scale_factor is True, then scale_factor must be passed in and scale_factor is used to compute the output size. The computed output size will be used to infer new scales for the interpolation. Note that when scale_factor is floating-point, it may differ from the recomputed scale_factor due to rounding and precision issues. If recompute_scale_factor is False, then size or scale_factor will be used directly for interpolation.

Shape

  • Input: ( N , C , W i n ) , ( N , C , H i n , W i n ) o r ( N , C , D i n , H i n , W i n ) (N, C, W_{in}), (N,C,H_{in},W_{in}) or (N, C, D_{in}, H_{in}, W_{in}) (N,C,Win),(N,C,Hin,Win)or(N,C,Din,Hin,Win)
  • Output: ( N , C , W o u t ) , ( N , C , H o u t , W o u t ) o r ( N , C , D o u t , H o u t , W o u t ) (N, C, W_{out}), (N, C, H_{out}, W_{out}) or (N, C, D_{out}, H_{out}, W_{out}) (N,C,Wout),(N,C,Hout,Wout)or(N,C,Dout,Hout,Wout), where

D o u t = ⌊ D i n × scale _ factor ⌋ H o u t = [ H i n × scale _ factor ] W o u t = ⌊ W i n × scale _ factor ⌋ \begin{gathered} D_{out} =\left\lfloor D_{in}\times\text{scale}\_\text{factor}\right\rfloor \\ H_{out} =\begin{bmatrix}H_{in}\times\text{scale}\_\text{factor}\end{bmatrix} \\ W_{out} =\left\lfloor W_{in}\times\text{scale}\_\text{factor}\right\rfloor \end{gathered} Dout=Din×scale_factorHout=[Hin×scale_factor]Wout=Win×scale_factor

1.2 代码示例

示例一

input = torch.arange(1, 5, dtype=torch.float32).view(1, 1, 2, 2)
"""
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.]]]])
"""

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]]]])
"""

# Try scaling the same data in a larger tensor
input_3x3 = torch.zeros(3, 3).view(1, 1, 3, 3)
input_3x3[:, :, :2, :2].copy_(input)
"""
tensor([[[[1., 2., 0.],
          [3., 4., 0.],
          [0., 0., 0.]]]])
"""

m = nn.Upsample(scale_factor=2, mode='bilinear')  # align_corners=False
# Notice that values in top left corner are the same with the small input (except at boundary)
m(input_3x3)
"""
tensor([[[[1.0000, 1.2500, 1.7500, 1.5000, 0.5000, 0.0000],
          [1.5000, 1.7500, 2.2500, 1.8750, 0.6250, 0.0000],
          [2.5000, 2.7500, 3.2500, 2.6250, 0.8750, 0.0000],
          [2.2500, 2.4375, 2.8125, 2.2500, 0.7500, 0.0000],
          [0.7500, 0.8125, 0.9375, 0.7500, 0.2500, 0.0000],
          [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000]]]])
"""

m = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)
# Notice that values in top left corner are now changed
m(input_3x3)
"""
tensor([[[[1.0000, 1.4000, 1.8000, 1.6000, 0.8000, 0.0000],
          [1.8000, 2.2000, 2.6000, 2.2400, 1.1200, 0.0000],
          [2.6000, 3.0000, 3.4000, 2.8800, 1.4400, 0.0000],
          [2.4000, 2.7200, 3.0400, 2.5600, 1.2800, 0.0000],
          [1.2000, 1.3600, 1.5200, 1.2800, 0.6400, 0.0000],
          [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000]]]])
"""

示例二

import torch.nn as nn

# 缩放比例为2,模式为最近邻方法
upsample = nn.Upsample(scale_factor=2, mode='nearest')
# 缩放比例为3,4,5,模式为双线性插值
upsample2 = nn.Upsample(scale_factor=(3,4,5), mode='bilinear')

2. torch.nn.functional.interpolate(限制较多)

官方文档:torch.nn.functional.interpolate

2.1 函数原型

torch.nn.functional.interpolate(input, 
                                size=None, 
                                scale_factor=None, 
                                mode='nearest', 
                                align_corners=None, 
                                recompute_scale_factor=None, 
                                antialias=False)

参数解释

  • input (Tensor) – the input tensor.
  • size (int or Tuple[int] or Tuple[int, int] or Tuple[int, int, int]) – output spatial size.
  • scale_factor (float or Tuple[float]) – multiplier for spatial size. If scale_factor is a tuple, its length has to match the number of spatial dimensions; input.dim() - 2.
  • mode (str) – algorithm used for upsampling: 'nearest' | 'linear' | 'bilinear' | 'bicubic' | 'trilinear' | 'area' | 'nearest-exact'. Default: 'nearest'.
  • align_corners (bool, optional) – Geometrically, we consider the pixels of the input and output as squares rather than points. If set to True, the input and output tensors are aligned by the center points of their corner pixels, preserving the values at the corner pixels. If set to False, the input and output tensors are aligned by the corner points of their corner pixels, and the interpolation uses edge value padding for out-of-boundary values, making this operation independent of input size when scale_factor is kept the same. This only has an effect when mode is 'linear', 'bilinear', 'bicubic' or 'trilinear'. Default: False.
  • recompute_scale_factor (bool, optional) – recompute the scale_factor for use in the interpolation calculation. If recompute_scale_factor is True, then scale_factor must be passed in and scale_factor is used to compute the output size. The computed output size will be used to infer new scales for the interpolation. Note that when scale_factor is floating-point, it may differ from the recomputed scale_factor due to rounding and precision issues. If recompute_scale_factor is False, then size or scale_factor will be used directly for interpolation. Default: None.
  • antialias (bool, optional) – flag to apply anti-aliasing. Default: False. Using anti-alias option together with align_corners=False, interpolation result would match Pillow result for downsampling operation. Supported modes: 'bilinear', 'bicubic'.

2.2 代码示例

import torch.nn.functional as F

# 缩放比例为2,模式为最近邻方法
upsample = F.interpolate(x, scale_factor=2, mode='nearest')
# 缩放比例为3,4,5,模式为双线性插值
upsample2 = F.interpolate(x, scale_factor=(3,4,5), mode='bilinear')

3. 针对图像缩放的上采样示例

下面给出一个以图像为例子的Upsample代码示例:

from PIL import Image
import torchvision.transforms as transforms
import torch.nn.functional as F

# 加载图像文件
img = Image.open('test.jpg')

# 定义Upsample操作
upsample = F.interpolate(x, scale_factor=2, mode='bilinear')

# 定义数据转换操作
transform = transforms.Compose([
    transforms.Resize(size=[256,256]), # 缩放到256*256大小
    transforms.ToTensor() # 转化为张量类型
    ])

# 数据转换
img_tensor = transform(img)

# 进行Upsample操作
img_tensor_upsampled = upsample(img_tensor.unsqueeze(0)).squeeze().detach()

# 转返回图像格式
img_upsampled = transforms.ToPILImage()(img_tensor_upsampled.cpu())

五、参考文献

[1] Laina I, Rupprecht C, Belagiannis V, et al. Deeper depth prediction with fully convolutional residual networks[C]//2016 Fourth international conference on 3D vision (3DV). IEEE, 2016: 239-248.

[2] Long J, Shelhamer E, Darrell T. Fully convolutional networks for semantic segmentation[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2015: 3431-3440.

[3] Zeiler M D, Taylor G W, Fergus R. Adaptive deconvolutional networks for mid and high level feature learning[C]//2011 international conference on computer vision. IEEE, 2011: 2018-2025.

[4] Dosovitskiy A, Tobias Springenberg J, Brox T. Learning to generate chairs with convolutional neural networks[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2015: 1538-1546.

[5] Noh H, Hong S, Han B. Learning deconvolution network for semantic segmentation[C]//Proceedings of the IEEE international conference on computer vision. 2015: 1520-1528.

[6] Zeiler M D, Fergus R. Visualizing and understanding convolutional networks[C]//Computer Vision–ECCV 2014: 13th European Conference, Zurich, Switzerland, September 6-12, 2014, Proceedings, Part I 13. Springer International Publishing, 2014: 818-833.

[7] Wofk D, Ma F, Yang T J, et al. Fastdepth: Fast monocular depth estimation on embedded systems[C]//2019 International Conference on Robotics and Automation (ICRA). IEEE, 2019: 6101-6108.

[8] Konrad J, Wang M, Ishwar P. 2d-to-3d image conversion by learning depth from examples[C]//2012 IEEE Computer Society Conference on Computer Vision and Pattern Recognition Workshops. IEEE, 2012: 16-22.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花花少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值