文章目录
Papers
Deeplab 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
Auto Deeplab Auto-DeepLab: Hierarchical Neural Architecture Search for Semantic Image Segmentation
DeeplabV1
一、网络结构
- the backbone is VGG-16
- 然后为了使图像语义分割更准确,5 个 max-pooling 层中最后两个max-pooling层的stride=2 改为 stride = 1,kernel = 3。
最后卷积层的输出整体 stride 从 32x 下降至 8x。减少下采样的倍数意味着更少的图片语义信息的损失.
- 由于后两个 max-pooling 影响了其后的卷积层,使其视野分别下降了 2x 和 4x,为了保持其原来的视野,便将其改成空洞卷积,dilation 分别为 2 和 4,理念与DRN一致;
max_pooling层的下采样作用会使得后续特征图的感受野增大,在第2步将stride改为1,减少了感受野,于是后续为了保持感受野大小的不变,采用SAME的空洞卷积。
-
最后的全连接层替换成 1*1 的卷积层,使得其变成一个全卷积网络;
-
使用双线性插值上采样 8x 得到和原图大小一致的像素分类图;
-
使用 CRF(条件随机场)使最后分类结果的边缘更加精细。
二、训练过程
对于训练过程,其实并没有decoder的过程,而是直接将label图片resize成和encoder的特征图大小,也就是原图8x下采样的大小,然后 用encoder的特征图和resize后的label图片来计算损失函数.
将label图缩小至原来的1/8,再与ferature map一起计算损失函数。
def resize_labels(labels, size):
"""
Downsample labels for 0.5x and 0.75x logits by nearest interpolation.
Other nearest methods result in misaligned labels.
-> F.interpolate(labels, shape, mode='nearest')
-> cv2.resize(labels, shape, interpolation=cv2.INTER_NEAREST)
"""
new_labels = []
for label in labels:
label = label.float().numpy()
label = Image.fromarray(label).resize(size, resample=Image.NEAREST)
new_labels.append(np.asarray(label))
new_labels = torch.LongTensor(new_labels)
return new_labels
def build_metrics(model, batch, device):
CEL = nn.CrossEntropyLoss(ignore_index=255).to(device)
image_ids, images, labels = batch
labels = resize_labels(labels, size=(65, 65)).to(device) #label进行resize
logits = model(images.to(device))
loss_seg = CEL(logits, labels)
preds = torch.argmax(logits, dim=1)
accuracy = float(torch.eq(preds, labels).sum().cpu()) / (len(image_ids) * logits.shape[2] * logits.shape[3])
return loss_seg, accuracy
三、条件随机场
crf的作用是使得最后分类结果的边缘更加精细:
计算公式如下:
可以这样简单理解: 在对一个像素做分类时,不光考虑 DCNN 输出的结果,还要考虑周围像素的意见尤其像素值比较接近的,这样得出的语义分割结果会有更好的边缘。
reference on :https://zhuanlan.zhihu.com/p/138899030
prob = post_processor(raw_image, probs[i].detach().cpu().numpy())
#其中
post_processor = crf.DenseCRF(
iter_max=10, # 10
pos_xy_std=3, # 3
pos_w=3, # 3
bi_xy_std=140, # 121, 140
bi_rgb_std=5, # 5, 5
bi_w=5, # 4, 5
)
#这里用到了 pydensecrf模块来实现dense_crf
import numpy as np
import pydensecrf.densecrf as dcrf
import pydensecrf.utils as utils
class DenseCRF(object):
def __init__(self, iter_max, pos_w, pos_xy_std, bi_w, bi_xy_std, bi_rgb_std):
self.iter_max = iter_max
self.pos_w = pos_w
self.pos_xy_std = pos_xy_std
self.bi_w = bi_w
self.bi_xy_std = bi_xy_std
self.bi_rgb_std = bi_rgb_std
def __call__(self, image, probmap):
C, H, W = probmap.shape
U = utils.unary_from_softmax(probmap)
U = np.ascontiguousarray(U)
image = np.ascontiguousarray(image)
d = dcrf.DenseCRF2D(W, H, C)
d.setUnaryEnergy(U)
d.addPairwiseGaussian(sxy=self.pos_xy_std, compat=self.pos_w)
d.addPairwiseBilateral(
sxy=self.bi_xy_std, srgb=self.bi_rgb_std, rgbim=image, compat=self.bi_w
)
Q = d.inference(self.iter_max)
Q = np.array(Q).reshape((C, H, W))
return Q
DeeplabV2
作者提到DeepLab系列面临了三大挑战:
(1)挑战一:DCNN最初设计用于分类的多层max-pooling和全连接层会导致空间信息的丢失,解决方法是去掉大部分的max-pooling层并采用空洞卷积来增加输出的分辨率,以保留更多的空间信息;
(2)挑战二:待分割的图像存在多种尺寸的物体信息,一种标准的做法是将输入图片resize到不同尺寸输入相同参数的并行多路网络并将输出的多路feature map或者score map最终融合,这种方法确实可以增加结果准确率但是计算代价太大,参照spatial pyramid pooling,作者提出了 “atrous spatial pyramid pooling” (ASPP),就是将feature map通过并联的采用不同膨胀速率的膨胀卷积层(atrous conv.),并将输出结果融合来预测分割结果;
(3)挑战三:因为DCNN的平移不变性,同DeepLabv1,最终将全连接CRFs作为后处理来对DCNN分类后的结果进行精确化处理。
一、网络结构
DeepLabv2 较 Deeplabv1变化:
-
引入ASPP,能更好的处理多尺度物体的分割;这个有点和 SPP(Spacial Pyramid Pooling)类似.
-
backbone由VGG-16改为ResNet,带来一定效果的提升。
在模型最后进行像素分类之前增加一个类似Inception的结构, 包含不同rate的Atrous Conv,即ASPP。这样做的好处不仅有deeplabv1中提出的增加感受野的功能, 更重要的是可以增强模型对不同尺寸的同一物体语义信息的把握能力.
过程:
- 调整ImageNet pre-train的ResNet为全卷积结构,结合空洞卷积和ASPP得到粗略结果;
- 双线性插值扩大特征图到原图大小;
- 全连接条件随机场细化预测结果,输出最终结果。
二、训练策略
另外,DeepLabv2 采用了 Poly 的训练策略:
Pytorch 实现如下:
from torch.optim.lr_scheduler import _LRScheduler
class PolynomialLR(_LRScheduler):
def __init__(self, optimizer, step_size, iter_max, power, last_epoch=-1):
self.step_size = step_size
self.iter_max = iter_max
self.power = power
super(PolynomialLR, self).__init__(optimizer, last_epoch)
def polynomial_decay(self, lr):
return lr * (1 - float(self.last_epoch) / self.iter_max) ** self.power
def get_lr(self):
if (
(self.last_epoch == 0)
or (self.last_epoch % self.step_size != 0)
or (self.last_epoch > self.iter_max)
):
return [group["lr"] for group in self.optimizer.param_groups]
return [self.polynomial_decay(lr) for lr in self.base_lrs]
deeplabV3
深层卷积神经网络(DCNNs)应用于语义分割的任务,我们考虑了面临的两个挑战:
第一个挑战:连续池化操作或卷积中的stride导致的特征分辨率降低。这使得DCNN能够学习更抽象的特征表示。然而,这种不变性可能会阻碍密集预测任务,因为不变性也导致了详细空间信息的不确定。为了克服这个问题,提倡使用空洞卷积。
第二个挑战:多尺度物体的存在。几种方法已经被提出来处理这个问题,在本文中我们主要考虑了这些工作中的四种类型,如图所示。
- 第一种:Image Pyramid,将输入图片放缩成不同比例,分别应用在DCNN上,将预测结果融合得到最终输出
- 第二种:Encoder-Decoder,将Encoder阶段的多尺度特征运用到Decoder阶段上来恢复空间分辨率
- 第三种:在原始模型的顶端叠加额外的模块,以捕捉像素间长距离信息。例如Dense CRF,或者叠加一些其他的卷积层
- 第四种:Spatial Pyramid Pooling空间金字塔池化,使用不同采样率和多种视野的卷积核,以捕捉多尺度对象
一、网络结构
1)用级联的方式设计了空洞卷积模块
具体而言,我们取ResNet中最后一个block(ResNet的block4),并将他们级联到了一起,如图3所示。
有三个3×3卷积在这些块中,除了最后一个块,其余的模块中最后的一个卷积步长为2,类似于原来的ResNet。这么做背后的动机是,引入的stride使得更深的模块更容易捕获长距离的信息。如图3(a),整个图像的特征都可以汇聚在最后一个小分辨率的特征图中
2) 使用了Multi-Grid 策略
受到了采用不同大小网格层次结构的多重网格方法的启发,我们提出的模型在block4和block7中采用了不同的空洞率。
特别的,我们定义Multi_Grid = ( r 1 , r 2 , r 3 ) (r_1,r_2,r_3) (r1,r2,r3)为block4到block7内三个卷积层的unit rates。卷积层的最终空洞率等于unit rate和corresponding rate的乘积。例如,当output_stride = 16 ,Multi_Grid = (1, 2, 4),三个卷积就会在block4有 rates = 2 · (1, 2, 4) = (2, 4, 8) 。
3)将 batch normalization 加入到 ASPP模块:improved ASPP
见下文。
4)将全局上下文信息纳入模型
具体来说,在模型的最后一个特征图采用全局平均池化,将重新生成的图像级别的特征提供给带256个滤波器(和BN)的1×1卷积,然后双线性插值将特征提升到所需的空间维度。
最后改进后的ASPP包括:
- (a)一个1×1的卷积与三个3×3的rates=(6, 12, 18)的空洞卷积,滤波器数量都为256,包含BN层。针对output_stride=16的情况。
- (b)图像级特征: average-pooling -> 1×1 conv,滤波器数量256 -> BN -> bilinearly upsampe
当output_stride=8时,采样率要加倍。然后将所有分支的特征图通过一个1×1卷积(有256个滤波器和BN)concatenate起来,送入最后的1×1卷积以产生最终分数.
二、训练策略
Learning rate policy:
- 采用poly策略,其中power=0.9
Crop size:
- 为了大采样率的空洞卷积能够有效,需要较大的图片大小;否则,大采样率的空洞卷积权值就会主要用于padding区域。
- 在Pascal VOC 2012数据集的训练和测试中我们采用了513的裁剪尺寸。
Batch normalization:
- 我们在ResNet之上添加的模块都包括BN层
- 当output_stride=16时,采用batchsize=16,同时BN层的参数做参数衰减0.9997。
- 在增强的数据集上,以初始学习率0.007训练30K后,冻结BN层参数,然后采用output_stride=8,再使用初始学习率0.001在PASCAL官方的数据集上训练30K。
- 训练output_stride=16比output_stride=8要快很多,因为其中间的特征映射在空间上小四倍。但output_stride=16在特征映射上相对粗糙,快是因为牺牲了精度。
Upsampling logits:
在先前的工作上,我们是将output_stride=8的输出与Ground Truth下采样8倍做比较。
- 现在我们发现保持Ground Truth更重要,故我们是将最终的输出上采样8倍与完整的Ground Truth比较。
Data augmentation:
- 在训练阶段,随机缩放输入图像(从0.5到2.0)和随机左右翻转。