欢迎光临
我们一直在努力

通俗的讲解fcn网络

引言:为什么我们需要全卷积网络(FCN)?

在计算机视觉领域,图像识别从最开始的图像分类(判断图片中有什么物体)逐渐发展到了更精细的语义分割(判断图片中每个像素点属于哪个物体)。传统的基于CNN的分类网络(如VGG或ResNet)在特征提取的末端通常包含全连接层(FC Layer),它们将二维特征图拉平为一维向量,并输出固定的类别概率。

然而,全连接层的存在有两个致命的弱点,使其不适用于语义分割:
1. 空间信息丢失: 拉平操作彻底丢失了像素的空间位置信息。
2. 固定输入尺寸: FC层要求输入特征图必须是固定尺寸,这限制了模型的通用性。

全卷积网络(Fully Convolutional Network, FCN),由Long等人于2015年提出,完美地解决了这些问题。FCN的核心思想是:将网络中的所有全连接层替换为卷积层,从而实现端到端(End-to-End)的、像素到像素的预测。

FCN的技术核心:全连接层到卷积层的转换

FCN的关键基础设施技术在于两个方面:

1. 替换FC层

在分类网络中,最后一个卷积层输出的特征图(例如 $7\times 7\times 512$)被拉平,然后输入到FC层。在FCN中,我们用 $1\times 1$ 的卷积层替换这个FC层。一个 $1\times 1$ 的卷积层可以看作是在每个空间位置上独立地执行一个全连接操作,但它保持了输入的空间维度,同时极大地增加了模型的部署灵活性。

2. 上采样 (Upsampling)

由于深度卷积网络在下采样(池化)过程中,输出的特征图尺寸远小于输入图像,我们必须将低分辨率的特征图恢复到原始输入图像的尺寸,才能实现像素级的密集预测。FCN使用转置卷积(Transpose Convolution,也常被称为反卷积 Deconvolution)来实现高效的上采样操作。

转置卷积不是传统卷积的逆运算,它通过学习的方式,将低分辨率的特征图映射到高分辨率的输出,从而生成密集的分割图(Segmentation Map)。

实操:使用PyTorch构建一个简化的FCN

为了演示FCN的基础架构和可操作性,我们构建一个极简的FCN,它基于简单的特征提取骨干,并利用 $1\times 1$ 卷积和转置卷积完成分割任务。


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
import torch
import torch.nn as nn
import torch.nn.functional as F

# 定义一个简化的全卷积网络 (FCN)
class SimpleFCN(nn.Module):
    def __init__(self, num_classes=5):
        super(SimpleFCN, self).__init__()

        # 1. 特征提取骨干 (简化版 VGG)
        self.features = nn.Sequential(
            # 初始层
            nn.Conv2d(3, 64, kernel_size=3, padding=1), nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2), # 尺寸缩小 1/2

            # 中间层
            nn.Conv2d(64, 128, kernel_size=3, padding=1), nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2) # 尺寸缩小 1/4
        )

        # 2. 替代分类器的全卷积层
        # 使用 1x1 卷积核替换传统网络中的全连接层
        self.classifier = nn.Sequential(
            nn.Conv2d(128, 512, kernel_size=1), # 1x1 卷积
            nn.ReLU(inplace=True),
            nn.Dropout2d(p=0.5)
        )

        # 3. Score Layer: 映射到类别数量
        self.score = nn.Conv2d(512, num_classes, kernel_size=1)

        # 4. 上采样层:使用转置卷积恢复到原始尺寸
        # 目标: 将 1/4 尺寸的特征图恢复到原始尺寸 (即 4倍放大)
        # 公式: output_size = (input_size - 1) * stride - 2*padding + kernel_size
        # 对于 stride=4, kernel_size=8, padding=2: output_size = input_size * 4
        self.upsample = nn.ConvTranspose2d(num_classes, num_classes, kernel_size=8, stride=4, padding=2)

    def forward(self, x):
        # 1. 特征提取,得到 1/4 大小的特征图
        x_features = self.features(x)

        # 2. 全卷积分类
        x_classified = self.classifier(x_features)
        x_scored = self.score(x_classified)

        # 3. 上采样,恢复到原始图像尺寸
        output = self.upsample(x_scored)

        # 注意:在实际训练中,需要裁剪 (crop) 或调整尺寸以精确匹配原始输入尺寸。

        return output

# --- 模型验证与输出尺寸检查 ---
num_classes = 21 # PASCAL VOC 常用的类别数
model = SimpleFCN(num_classes=num_classes)

# 假设输入一张 3 通道,256x256 的图像
input_tensor = torch.randn(1, 3, 256, 256)

# 执行前向传播
output = model(input_tensor)

print(f"输入图像形状: {list(input_tensor.shape)}")
print(f"FCN 输出形状: {list(output.shape)}")

运行上述代码,你会看到输入形状为 [1, 3, 256, 256],而输出形状为 [1, 21, 256, 256]。这证明了模型已经成功地从原始图像生成了一个具有相同长宽的、通道数为类别数的分割图,实现了像素级的预测。

部署考量:FCN的优势

在模型部署基础设施中,FCN的纯卷积特性带来了巨大的优势:

  1. 尺寸灵活性: 由于网络中没有全连接层,FCN可以接受任意尺寸的输入图像。这对于处理不同分辨率的实时视频流或图像批次非常有利,无需预处理到固定大小。
  2. 计算效率: 相比于在特征图上多次重复计算的滑动窗口方法,FCN一次性完成所有计算,提高了推理速度。
  3. 模型转换: 纯卷积架构更容易稳定地转换为部署格式,如ONNX或TensorRT,因为转置卷积和 $1\times 1$ 卷积在各种AI加速硬件上的支持都非常成熟。
【本站文章皆为原创,未经允许不得转载】:汤不热吧 » 通俗的讲解fcn网络
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址