语义分割
目的:对一张图片上的每一个像素进行分类
实例分割是语义分割的延伸,要求区别出相同类别的不同个体
语义分割领域中的困难
- 数据问题
- 分割需要精确的像素级标注,包括每一个目标的轮廓等信息,因此使得制作数据集成本过高;
- 计算资源问题
- 高精度的语义分割模型一般需要更深的网络(ResNet101等),网络越深计算资源需求越大,轻量级的网络精度太低;
- 需要对每个像素进行预测,因此特征图的分辨率要尽可能高,内存需求大;
- 精细分割
- 目前的方法中对于图像中的大体积的东西能够很好的分类;
- 对于细小的类别,由于其轮廓太小,从而无法精确的定位轮廓,精度较低(医学图像领域尤为突出);
- 上下文信息
- 分割中上下文信息很重要,设计网络的时候要考虑如何应用上下文信息;
- 否则会造成一个目标被分成多个part,或者不同类别目标分类成相同类别;
语义分割方法的发展
非深度学习方法
pipline:经典的特征 + forst/boost + CRF的分割
每一个分类器一般只针对单一的类别设计,如果分割类别数很多,会造成计算复杂,训练难度大的问题。
非深度学习方法受特征的限制较大,精度较低。
深度学习方法
自2014年的FCN与Deeplabv1的提出,近几年深度学习语义分割方法进步明显
深度学习方法可以直接预测多类别目标,克服了非深度学习方法的单类别的限制
对于单类别问题,仍然是深度学习方法好,如道路分割等
目前的进展
从目前的发展趋势看,深度学习方法仍是主导方法。
深度学习方法一般都是在分类网络上进行精调,分类网络为了能获取更抽象的特征分层,采取了Conv+pool堆叠的方式,这导致了分辨率降低,丢失了很多信息,这对分割任务来说肯定是不好的,因为分割是对每一个像素进行分类,会造成定位精度不高。但同时更高层的特征对于分类又很重要。如何权衡这两者呢?
encoder-decoder方法
与经典的FCN中的skip-connection思想类似,encoder为分类网络,用于提取特征,而decoder则是将encoder的先前丢失的空间信息逐渐恢复,decoder的典型结构有U-Net/segnet/refineNet,该类方法虽然有一定的效果,能恢复部分信息,但毕竟信息已经丢失了,不可能完全恢复。
dialed FCN方法
deeplabv1提出的方法,将vgg的最后的两个pool层步长置为1,这样网络的输出分辨率从1/32变为1/8。可以保留更多的细节信息,同时也丢掉了复杂的decoder结构,但这种方法计算量大。deeplabv3+将这两者结合,效果比较好,但是计算量大。
评价指标
-
执行时间:非常依赖硬件设备及后台实现,在实验时不是最重要的,但在上线生产环境时一般要考虑是否满足硬实时的要求,因此是一个度量要求
-
内存占用
-
精确度:这里指的是逐像素标记的精度测量
假设共有k个类(从0到k中有一个类别属于背景),$P_{ij}$表示本属于$i$类但是被预测为$j$类的像素个数,$P_{ii}$表示为真正分对类的数量,而$P_{ij}$与$P_{ji}$分别被称为假正样本和假负样本
- Pixel Accuracy(PA,像素精度) 标记正确的像素占总像素的比例
- Mean Pixel Accuracy(MPA,平均像素精度) 计算每个类内被正确分类像素数比例,之后求所有类的平均数
- Mean Intersection over Union(mIoU,平均交并比) 为语义分割的标准度量,其计算两个集合的交集和并集之比,这两个集合分别为ground truth与predicted segmentation在每个类上计算IoU,之后将其求平均。
其中$k+1$为类别数,$P{ii}$表示TP,$P_{ij}$表示FN,$P_{ji}$表示FP($i$表示真实类别,$j$表示其他类别),最后那个地方减了一个$P_{ii}$是因为前面两项里加了2个$P_{ii}$
- Frequency weighted Intersection over Union(FWIoU,频权交并) mIoU的一种提升,这种方法根据每个类出现的频率设置权重
下面以一个简单的例子,说明怎么计算mIoU,由于分割也是分类问题,分类问题的指标一般使用混淆矩阵来求解,其实就是矩阵的每一行加每一列,再减去重复的TP
混淆矩阵 | 预测1 | 预测2 | 预测3 |
---|---|---|---|
实际1 | 43 | 5 | 2 |
实际2 | 2 | 45 | 3 |
实际3 | 0 | 1 | 49 |
- 类别1:TP=43,FN=7,FP=2,IoU1=43/(43+2+7)=82.69%
- 类别2:TP=45,FN=5,FP=6,IoU2=45/(45+5+6)=80.36%
- 类别3:TP=49,FN=1,FP=5,IoU3=49/(49+1+5)=89.09%
- mIoU=84.05%
常用数据集
忽视标签(ignore label)
忽视标签从字面上理解,就是该标签不用于计算损失,也不用于计算精度。以一个三个类别的例子为例。
该例子,包含3个目标类别,1个背景类别,1个忽视类别。
标签可以设置为:0,1,2,3,4
其中,0代表背景,1-4代表目标类别 如果忽视标签为4,则可以直接设置类别数为4(背景 + 目标),如果忽视标签为1-3,需要单独进行处理,比如deeplabv3+中是这样处理的
self.void_classes = [3, -1]
self.valid_classes = [0, 1, 2, 4]
self.class_names = ['unlabelled', 'c1','c2','c4']
self.ignore_index = 255
self.class_map = dict(zip(self.valid_classes, range(self.NUM_CLASSES)))
def encode_segmap(self, mask):
# Put all void classes to zero
for _voidc in self.void_classes:
mask[mask == _voidc] = self.ignore_index
for _validc in self.valid_classes:
mask[mask == _validc] = self.class_map[_validc]
return mask
Pascal VOC系列
M. Everingham, L. J. V. Gool, et al. The pascal visual object classes VOC challenge.// IJCV 2010. B. Hariharan, P. Arbelaez, et al. Semantic contours from inverse detectors. //ICCV2011.
可以用于:目标检测、语义分割等
原始VOC2012数据集:1464训练集,1449验证集,1456测试集。经过加强的数据集,包含10582训练集,1449验证集,1456测试集。目前论文结果均使用后者进行训练。该数据集特点包括:
- 数据集包含21类别目标,20类目标+1类背景,分辨率大小不完全相同,为此训练过程为了能处理batch图像,因此需要将图像固定到某一大小,deeplab里面使用321大小。
- 该数据集中,label处理时发现并没有忽视标签,均在0-21之间,因此不需要设置忽视标签。在deeplab版本里作者将ignore_index设为255,标签里面本来就没有255,设不设置没关系.
- 每幅图像包含的目标类别很少,但每个目标的轮廓还是比较复杂,因此,该数据集的分割精度没有想象中那么高。
CamVid
Brostow, G.J., Shotton, et al. Segmentation and recognition using structure from motion point clouds. //ECCV 2008 Vijay Badrinarayanan, Alex Kendall et al. SegNet: A Deep Convolutional Encoder-Decoder Architecture for Image Segmentation.//TPAMI 2017.
训练集367,验证集101,测试集233。三个均有标注文件
- 图像数量太少,因此很少有人跑这个数据集,只有少数轻量级分割网络会跑,如ENet/Segnet/LinkNet/Bisenet等,现在能看到的最好精度也就60多mIOU。
- 原始数据集分辨率为960×720,而Segnet将其处理为480*360,后者也是使用得多,可能是因为Segnet将其处理后的文件夹上传的原因吧。
- 该数据集也存在忽视标签,Segnet作者将其统一设置为11,类别数为11,标注为0-10,因此计算softmax损失时,需要设置ignore_index=11,或者在处理标签图片时,将mask[index==11] = -1,这样处理后不计算忽视标签的损失。
- 由于图像分辨率为480*360,且有11类目标,造成细小目标偏多,如行人,交通灯等。
Cityscapes
M. Cordts, M. Omran, et al. The Cityscapes Dataset for Semantic Urban Scene Understanding.//CVPR 2016.
适用于汽车自动驾驶的训练数据集,包括19种都市街道场景:road、side-walk、building、wal、fence、pole、traficlight、trafic sign、vegetation、terain、sky、person、rider、car、truck、bus、train、motorcycle 和 bicycle。
训练集2975,验证集500,测试集1525。训练集与验证集包括Fine annotations以及额外的19998个coarse annotations,可以于训练集一起训练。测试集标注没有公开。数据集主要特点包括:
- 标签包括:’name’/’id’/’trainId’/’category’/’catId’/’hasInstances’/’ignoreInEval’/’color ‘等,’id’是原始的标注id,而’trainId’是用于训练的Id,’ignoreInEval’为忽视对象。
- 原始的标注包括35类,其中有16类为在评测中忽视的类别,因此训练时候只有19类,因此标签可以设置为0-18,验证的时候也可以使用0-18。如果要测试,则需要将0-18反变化回原始标签。
- 原始标注文件包括:color.png/instanceIds.png/labelIds.png/polygons.json四个文件,其中,labelIds.png文件为原始标注,因此需要将该文件转换为trainIds,可以参考labels.py和preparation,转换后忽视标签为255,而其他标签为0-18,这样训练过程使用19类目标,忽视255。在处理过程中,可以将mask[index==255] = -1,这样损失函数不会计算。或者计算softmax损失的时候设置ignore_index=255。
- 图像分辨率较大,1024*2048,如果使用原图训练,计算量太大,一般会crop一定的大小,但也不能太小,太小效果很差,猜想:这也是这个数据集精度很难提升的一个原因。 从提交的评测结果可以看出,基本都是深度学习方法(没有全部过一遍)。传统算法在这种环境复杂的交通场景做分割难度还是太大了。
- 每幅图像涵盖的目标类别较多,同时,存在很多细小目标,使得分割难度进一步增大。
Microsoft COCO
一共有80个类别。这个数据集主要用于实例级别的分割(Instance-level Segmentation)以及图片描述(Image Caption)。