项目说明

本项目利用PaddlePaddle及PaddleSeg套件对论文“Context Encoding for Semantic Segmentation (CVPR2018)”进行了Paddle版本的实现,取得了较为不错的结果。

一、简介

论文引入了上下文编码模块(Context Encoding Module)用于捕获全局上下文信息和突出与场景相关联的类别信息,这相当于加入场景的先验知识,类似于attention机制。结合现先进的扩张卷积策略和多尺度策略提出了语义分割框架EncNet(Context Encoding Network)。论文提出的EncNet在多个数据集上获得了state-of-the-art结果。

EncNet Architecture:

GAN提升语义分割效果 提升语义分割精度_paddlepaddle

主要模块

  • Encoding Module:对前面网络提取出的丰富的特征使用全连接层FC进行编码,其中一个编码分支直接送给SE-loss,进行场景中出现类别的预测;另一个分支对每个类别预测加权的尺度因子,然后这个加权的尺度因子对前面提出的每个通道的类别进行加权,然后再进行后面的上采样,最终计算loss。
  • Featuremap Attention:dense feature map经过一个encoding layer得到context embedding,然后通过FC得到一个classwise的score,作为权重。
  • Semantic Encoding loss:在编码层之上添加了一个带Sigmoid激活的FC层用于单独预测场景中出现的目标类别,并学习二进制交叉熵损失。不同于逐像素损失,SE loss 对于大小不同的目标有相同的贡献,这能够提升小目标的检测性能。

二、复现精度

Model

mIOU

ResNet101-EncNet(mmseg-pytorch)

78.5

ResNet101-EncNet(本项目Paddle)

78.3

由于训练的随机性,比现有复现低了一点点…但是也算是成功的复现啦~

NOTE:训练是4卡v100 batchsize=8(每张卡2)80k的结果。

三、数据集

使用的数据集为:Cityscapes

  • 数据集大小:19个类别的密集像素标注,5000张1024*2048大小的高质量像素级注释图像/20000个弱注释帧
  • 训练集:2975个图像
  • 验证集:500个图像
  • 测试集:1525个图像

数据集应有的结构:

data/
├── cityscapes
│   ├── gtFine
│   │   ├── test
│   │   ├── train
│   │   └── val
│   ├── leftImg8bit
│   │   ├── test
│   │   │   ├── berlin
│   │   │   ├── ...
│   │   │   └── munich
│   │   ├── train
│   │   │   ├── aachen
│   │   │   ├── ...
│   │   │   └── zurich
│   │   └── val
│   │       ├── frankfurt
│   │       ├── lindau
│   │       └── munster
│   ├── train.txt
│   ├── val.txt
│   ├── test.txt

四、代码

论文的详细内容还是需要结合代码才能理解得更深刻。本项目基于PaddleSeg开发套件进行。所有的训练评估方式都与PaddleSeg相同。可查阅PaddleSeg。

代码主要分为模型和损失两部分。

  • MODEL:位于ENCNet/paddleseg/models/encnet.py

主要模块:

class EncModule(nn.Layer):
    """Encoding Module used in EncNet.
    Args:
        in_channels (int): Input channels.
        num_codes (int): Number of code words.
    """
    def __init__(self, in_channels, num_codes):
        super(EncModule, self).__init__()
        self.encoding_project = layers.ConvBNReLU(in_channels,in_channels,1)
        # change to 1d
        self.encoding = nn.Sequential(
            Encoding(in_channels, num_codes),
            nn.BatchNorm1D(num_codes),
            nn.ReLU())
        self.fc = nn.Sequential(
            nn.Linear(in_channels, in_channels), nn.Sigmoid())

    def forward(self, x):
        """Forward function."""
        encoding_projection = self.encoding_project(x)
        encoding_feat = self.encoding(encoding_projection).mean(axis=1)
        batch_size, channels, _, _ = x.shape
        gamma = self.fc(encoding_feat)
        y = gamma.reshape((batch_size, channels, 1, 1))
        output = F.relu_(x + x * y)
        return encoding_feat, output
  • SE-LOSS:位于ENCNet/paddleseg/models/losses/encoding_cross_entropy_loss.py 的EncodingBCELoss
    主要是将语义分割标签转为one-hot编码后与模型输出的semantic-encoding结果进行二值交叉熵损失的计算。

数据集准备

# 创建cityscape文件夹
!mkdir data/cityscapes/
# 解压数据集中的gtFine
!unzip -nq -d data/gtFine/ data/data48855/gtFine_train.zip
!unzip -nq -d data/gtFine/ data/data48855/gtFine_val.zip
!unzip -nq -d data/gtFine/ data/data48855/gtFine_test.zip
!mv data/gtFine/ data/cityscapes/
# 解压数据集中的leftImg8bit
!unzip -nq -d data/leftImg8bit/ data/data48855/leftImg8bit_train.zip
!unzip -nq -d data/leftImg8bit/ data/data48855/leftImg8bit_val.zip
!unzip -nq -d data/leftImg8bit/ data/data48855/leftImg8bit_test.zip
!mv data/leftImg8bit/ data/cityscapes/
# 训练train.txt val.txt等文件的生成 
!python  ENCNet/tools/create_dataset_list.py /home/aistudio/data/cityscapes/ --type cityscapes --separator ","

训练

项目提供预训练的模型与日志,已经挂载到数据集中解压后可查看。output文件夹下有训练日志和可视化日志。

!python ENCNet/train.py --config ENCNet/configs/encnet/encnet_r101_d8_512x1024_80k_cityscapes.yml --num_workers 0 --use_vdl --do_eval --save_interval 1000 --save_dir encnet_r101_d8_512x1024_80k_cityscapes

训练可视化

GAN提升语义分割效果 提升语义分割精度_ci_02

评估

通过修改“–model_path /home/aistudio/output/model.pdparams"进行预训练模型选择,进行评估。

!python ENCNet/val.py --config  ENCNet/configs/encnet/encnet_r101_d8_512x1024_80k_cityscapes.yml  --model_path data/data118662/model.pdparams

总结

上下文内容对于像素任务而言非常重要,建模像素间关系对于改善语义分割结果很有好处。