图像卷积计算(Conv2D)

在计算机视觉领域, 往往我们输入的图像都很大,使用全连接网络的话,计算的代价较高. 另外图像也很难保留原有的特征,导致图像处理的准确率不高.

卷积神经网络(Convolutional Neural Network)是含有卷积层的神经网络. 卷积层的作用就是用来自动学习、提取图像的特征.

CNN网络主要有三部分构成:卷积层、池化层和全连接层构成,其中卷积层负责提取图像中的局部特征;池化层用来大幅降低参数量级(降维);全连接层类似人工神经网络的部分,用来输出想要的结果。

1. 卷积计算

  1. input 表示输入的图像
  2. filter 表示卷积核, 也叫做滤波器
  3. input 经过 filter 的得到输出为最右侧的图像,该图叫做特征图

那么, 它是如何进行计算的呢?卷积运算本质上就是在滤波器和输入数据的局部区域间做点积。

左上角的点计算方法:

按照上面的计算方法可以得到最终的特征图为:

2. Padding

通过上面的卷积计算过程,我们发现最终的特征图比原始图像小很多,如果想要保持经过卷积后的图像大小不变, 可以在原图周围添加 padding 来实现.

3. Stride

按照步长为1来移动卷积核,计算特征图如下所示:

如果我们把 Stride 增大为2,也是可以提取特征图的,如下图所示:

4. 多通道卷积计算

实际中的图像都是多个通道组成的,我们怎么计算卷积呢?

计算方法如下:

  1. 当输入有多个通道(Channel), 例如 RGB 三个通道, 此时要求卷积核需要拥有相同的通道数.
  2. 每个卷积核通道与对应的输入图像的各个通道进行卷积.
  3. 将每个通道的卷积结果按位相加得到最终的特征图.

如下图所示:

5. 多卷积核卷积计算

上面的例子里我们只使用一个卷积核进行特征提取, 实际对图像进行特征提取时, 我们需要使用多个卷积核进行特征提取. 这个多个卷积核可以理解为从不同到的视角、不同的角度对图像特征进行提取.

那么, 当使用多个卷积核时, 应该怎么进行特征提取呢?

6.  特征图大小

输出特征图的大小与以下参数息息相关:

  1. size: 卷积核/过滤器大小,一般会选择为奇数,比如有 1*1, 3*3, 5*5*
  2. Padding: 零填充的方式
  3. Stride: 步长

那计算方法如下图所示:

  1. 输入图像大小: W x W
  2. 卷积核大小: F x F
  3. Stride: S
  4. Padding: P
  5. 输出图像大小: N x N

以下图为例:

  1. 图像大小: 5 x 5
  2. 卷积核大小: 3 x 3
  3. Stride: 1
  4. Padding: 1
  5. (5 – 3 + 2) / 1 + 1 = 5, 即得到的特征图大小为: 5 x 5

7. PyTorch 卷积层 API

图像中主要用 Conv2D 卷积层,接下来了解下它的使用。示例代码:

import torch.nn as nn
import torch
import torch.nn.functional as F


# 1. nn.Conv2d 参数解释
def test01():

    # Conv2d 表示卷积层, 由 out_channels 个卷积核组成,每个卷积核有 in_channels 个通道
    conv2d = nn.Conv2d(in_channels=3, out_channels=5, kernel_size=2)

    # 卷积核权重参数:
    # 5: 表示需要 5 个卷积核, 输出几个通道 out_channels 对应就有几个卷积核
    # 3: 输入的图像有 in_channels=3 个,那么对应每个卷积核就有 3 个通道
    # [2, 2]: 表示卷积核的 kernel size
    # torch.Size([5, 3, 2, 2])
    print(conv2d.weight.shape)

    # 卷积核偏置参数:
    # 5: 表示共有 5 个卷积核对应 5 个偏置
    # torch.Size([5])
    print(conv2d.bias.shape)

    # 卷积时候向右、向下的步长分别为 1
    # (1, 1)
    print(conv2d.stride)

    # 卷积时候向右、向下的填充分别为 0
    # (0, 0)
    print(conv2d.padding)

    # 卷积时候向右、向下的扩张为 1,可以增加范围
    # (1, 1)
    print(conv2d.dilation)


# 2. nn.Conv2d 计算过程
def test02():

    torch.manual_seed(0)
    inputs = torch.randint(0, 10, size=[2, 3, 3, 3]).float()
    print(inputs)
    print('-' * 60)

    # 设置卷积核权重参数
    weight = torch.ones(size=[5, 3, 2, 2]).float()
    # 设置卷积核偏置参数
    bias = torch.zeros(size=[5,]).float()
    output = F.conv2d(inputs, weight=weight, bias=bias)
    print(output)


if __name__ == '__main__':
    test02()

未经允许不得转载:一亩三分地 » 图像卷积计算(Conv2D)