论文笔记 - DeepLab全家桶

用于图像分割的DeepLab全家桶

参考资料

DeepLab 语义分割模型 v1、v2、v3、v3+ 概要(附 Pytorch 实现)
DeepLab v1: Semantic Image Segmentation with Deep Convolutional Nets and Fully Connected CRFs
DeepLab v2: DeepLab: Semantic Image Segmentation with Deep Convolutional Nets, Atrous Convolution, and Fully Connected CRFs
DeepLab v3: Rethinking Atrous Convolution for Semantic Image Segmentation
DeepLab v3+:Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation
GitHub: kazuto1011/deeplab-pytorch

DeepLab v1

参考资料

精读深度学习论文(20) DeepLab V1

素质四连

1) 要解决什么问题?

使用CNN做图像分割主要存在两个问题:

  • 下采样导致细节信息丢失
  • CNN的空间不变性(spatial invariance)。

2) 用什么方法解决?

  • 使用带孔卷积解决下采样问题;
  • 使用Dense CRF解决空间不变性问题;

3) 效果如何?

  • VOC2012最佳,71.6%的IoU;
  • 8 frames per second

4) 还存在什么问题?

  • 用VGG有些落后
  • 现在来看效果一般

Convolutional Neural Networks for Dense Image Labeling

DeepLab v1的backbone是VGG16,通篇文章讲述了如何在该模型上进行修改,从而让它变成有效的语义分割模型。

在每个像素点上计算分类得分是作者成功的关键。

为了实现在每个像素点上计算分类得分,作者首先将VGG16的全连接层转为卷积层,但直接这么做是不够的,因为这样的话原图上每32x32像素区域只有一个分类得分。

为了把步长从32改到8,作者引入了空洞卷积(这里叫the hole algorithm)

the hole algorithm

更多的细节不想过多的阅读了,包括CRF。以后有机会再了解吧,近期的图像分割方法都很少使用CRF了。

模型代码

直接上代码吧,backbone是resnet101,看了下GitHub上ResNet的代码,发现最新版才支持dilate选项,所以要先更新一下torchvision(0.3.0)才能用。

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
import torchvision.models as models

"""
resnet一共有4个block,第一个block是不允许设置dilate的;
所以replace_stride_with_dilation代表后3个block的dilate;
注意:当设置dilate时,该block的stride会自动设为1,详见官方实现:
https://github.com/pytorch/vision/blob/master/torchvision/models/resnet.py

且由于resnet只有最后一层用到num_classes,我们用不到,所以不需要传入该参数
"""
resnet101 = models.resnet101(pretrained=False, replace_stride_with_dilation=[False, 2, 4])

class DeepLabV1(nn.Sequential):
"""
backbone: resnet101
"""
def __init__(self, n_classes):
super(DeepLabV1, self).__init__()
self.add_module('features', nn.Sequential(
nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False),
nn.BatchNorm2d(64, eps=1e-5, momentum=0.999),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2, padding=1, ceil_mode=True)
))
self.add_module('layer1', resnet101.layer1)
self.add_module('layer2', resnet101.layer2)
self.add_module('layer3', resnet101.layer3)
self.add_module('layer4', resnet101.layer4)
self.add_module('fc', nn.Conv2d(2048, n_classes, 1))

运行结果和参考资料中的代码保持一致,所以还是很靠谱的!由于提供的代码是在DeepLabv2上训练的,所以这里就不训练DeepLabv1了。