我们之前都是图像分类的任务,最后一个全连接层得到所有分类的得分。现在我们来研究计算机视觉的其他任务,比如语义分割、图像分类与定位、目标检测、实例分割等。
本课重点
-
语义分割
-
定位与检测
1 语义分割(Semantic Segmentation)
在语义分割任务中,输入一张图片,希望输出能对图像的每个像素做出分类,判断这个像素是属于物体或者背景,不再像之前那样整张图片都是一个类。语义分割不会区分实例,只关心像素,所以如果图中有两头牛,会把两块像素都归为牛,不会分开每一头,以后会讲到实例分割(Instance Segmentation)可以区分实例。
实现语义分割的一个想法是滑动窗口,即将图像分成一个个的小块,然后使用CNN网络计算小块的中心元素属于哪个分类。这样做的一个问题是,需要为每个像素计算一次,很多运算都是重复的,实际上没人会这么做。
另一个想法是全卷积( Fully Convolutional),将网络的所有层都设计成卷积层,这样就能实现一次对图像的所有像素进行预测。比如使用3x3的卷积层然后使用零填充保持输入输出的空间尺寸,最终得到一个CxHxW的特征图,其中C是像素分类的数量,这样的一个特征图就一次计算了所有像素的分类得分。然后使用交叉熵损失、取平均、反向传播等操作进行训练。由于要为每个像素设置标签,这样的数据集花费是非常昂贵的。这里的数据集需要先确定图像属于哪个类别,比如猫,然后对图像的像素点设置类别。实际应用中,如果一直保持空间尺寸的话计算量会很庞大,所以不能设置这种结构。
使用全卷积网络的一种好的形式是在网络内部使用降采样(downsampling)然后使用升采样(upsampling),只在最初的几个卷积层保持尺寸,然后降采样比如池化或跨进卷积(strided convolution)来降低尺寸,进行一系列卷积后升采样到原来的尺寸。之所以需要去池化是因为池化减少了像素值,降低了图像的清晰度,丢失了图像空间结构,不知道这些像素原来在哪里,所以也就不明确边界应该在什么位置,所以需要进行去池化得到这些空间信息。
然后问题是如何进行升采样呢?
- 去池化(Unpooling):分为最邻近(Nearest Neighbor)和“钉床”(Bed of Nails)。最邻近在去池化区域重复输入值;“钉床”的去池化区域左上角是原输入值,其他为0。
- 最大去池化(Max Unpooling):与最大池化相对应,记住池化时使用了哪个位置的索引,去池化时再放回原处,其他位置为0。降采样层和升采样层必须要一一 对应。
- 转置卷积(Transpose Convolution):卷积层的权重是可学习的,跨进卷积可以降低输入的尺寸,步长往往就是输入输出的比率。转置卷积是和卷积相反的过程,比如一个2x2的输入进行卷积核是3x3、步长为2、填充1的转置卷积,取第一个输入乘以卷积核放在输出的第一个区域(包括填充)即可。然后取第二个输入,输出的步长为2,放在第二个位置,重叠部分直接相加。这种方式是可学习的。其他名字:Deconvolution (bad)、Upconvolution、Fractionally strided convolution、Backward strided convolution.
在一维中可能会表现的更清晰:滤波器被输入加权后直接放到输出中,输出的步长为2,下一个位置要平移两个像素,重叠的部分直接相加。最后为了使输出是输入的两倍,需要裁掉一个像素。
之所以称作转置卷积,可以通过矩阵乘法来解释,以一个一维的输入为例 a = [a, b, c, d],现在做 3x1 的卷积,卷积核为 [x, y, z],步长1填充1,此时的卷积可以看作是卷积核组成的一个大的矩阵 X 与输入 a 做乘法,如下图左边所示。(图上应为xyz,书写错误。)卷积核在输入 a 上滑动对应元素相乘后相加得到输出的过程,完全等价于卷积核组成的大矩阵与输入 a 的乘法。然后将 X 转置与 a 相乘,即转置卷积,结果就是一个正常的卷积,改变的只是填充规则。
现在如果步长为2,情况就不一样了。左边的卷积仍然可以看作是乘法,而右侧的转置卷积就变成用输入加权后的卷积核在输出上的叠加。
综上,语义分割任务的实现方法如下图所示:
此外,多视角3D重建( Multi-view 3D Reconstruction)也使用了降采样和升采样的方法。
2 定位与检测
2.1 定位( Localization)
定位( Localization)往往是与分类(Classificatio)结合在一起的,如果图片分类是一只猫,同时我们也想知道猫在这张图片的什么位置,要用一个框给框起来。这与目标检测(Object Detection)是不同的,定位是一旦图像已经归为哪一类,比如猫,这样我们就会有一个明确的目标去寻找,找出它的边界即可。而目标检测是要检测出图像上存在的物体。
定位可以复用分类的方法,比如AlexNet。如下图所示,最后一个全连接层,除了得到1000个类别的得分,还会得到一个长为4的向量,表示目标的位置。这样最后就有两个损失,一个是正确分类的Softmax损失,另一个是正确位置的L2损失,L1、L2等损失也称作回归损失(Regression Loss)。最后将两个损失通过某些超参数加权得到总损失,和之前的超参数不同的是,以前的超参数改变是为了减小损失,而这里的加权超参数直接会改变损失值的表达式,损失变大变小都有可能。使用总损失求梯度。这里使用的网络是使用ImageNet 预训练过的模型,进行迁移学习。
2.2 目标检测
目标检测任务是这样的:我们有几个感兴趣的类别,比如猫狗鱼等等,现在输入一张图像,图像上有几个物体事先是不知道的,当我们我们感兴趣的物体在图像上出现时,我们希望模型能自动标记出目标物体的位置,并判断出具体的分类。这实际上是很有挑战的任务,也是计算机视觉中很核心的任务,对此的研究已经经历了很多年,也有非常多的方法。
与定位最大的区别是,我们不知道图上会有多少对象。比如图像上只有一只猫,我们最终的输出只有一个位置四个数字;有两只狗一只猫,会输出3个位置12个数字;那么有一群鸭子呢?数量就很多了。所以目标检测问题不能看作定位中的回归问题。
另一个想法是把目标检测问题看作分类问题。类似语义分割的想法,将图像分成一个个的小块,让每一个小块通过卷积网络判断这块是背景?是猫?是狗?可以这么想,但是这个小块该怎么获得呢?不同的物体可能会有不同的大小、位置以及长宽比,这将是无数的情况,如果都要进行卷积,那么计算量是非常大的。
2.2.1 使用候选区域
R-CNN
实际上,更实用的方法是候选区域(Region Proposals )方法。选择性搜索(Selective Search )方法就是在目标对象周围设定2000个形状大小位置不一的候选区域,目标物体在候选区域的可能性还是比较大的。然后对这些区域卷积,找到目标物体,虽然大多数区域都是无用的。与寻找几乎个区域比起来,这种方法要高效的多。此外,这不是深度学习的方法,是机器学习算法。R-CNN就是基于这种观点提出的。首先对输入图片使用区域备选算法,获取2000个感兴趣的区域(Regions of interest, roi),由于这些区域大小不一,所以需要处理成同样的尺寸才能通过CNN,之后使用SVM对区域进行分类。可以使用线性回归损失来校正包围框,比如虽然这个框选中的物体是一个缺少头部的狗,就需要对包围框进行校正。总之,这是一个多损失网络。
Fast R-CNN
R-CNN的问题是计算消耗大、磁盘占用多、运行速度慢,即使测试时也要30秒测试一张图片,因为有2000个区域。解决方法时使用快速R-CNN(Fast R-CNN ),不在原始图像生成备选区域,而是先整张图片通过卷积网络得到特征图,然后在特征图上使用备选区域算法得到感兴趣的区域在特征图的映射,之后使用 Rol Pool将所有区域变成同样尺寸。然后一方面使用softmax损失进行分类,一方面使用回归损失比如L1平滑损失校正包围框,总损失是两部分的和,然后反向传播进行训练。
如下图所示,效果还是很明显的。但是快速R-CNN也有一个问题是运行时间被区域备选方案限制。
Faster R-CNN
解决方案是更快的R-CNN(Faster R-CNN)。这种方法的改进是与其使用固定的算法得到备选区域,不如让网络自己学习自己的备选区域应该是什么。如下图所示,前面仍然是通过卷积网络获得特征图,然后通过一个备选区域网络(Region Proposal Network,RPN),该网络会做两件事,一是计算分类损失,选择的区域是目标还是不是目标;二是校正包围框。得到备选区域后接下来的步骤就和快速R-CNN一致了,也是得到最后的分类得分和校正包围框。训练的过程会综合这四个损失,最终效果很好。
Mask R-CNN
Mask R-CNN是在Faster R-CNN基础上改进而来,是2017年发布的方法。首先将整张图像通过卷积网络和候选框生成网络,得到候选特征在特征图上的映射再调整尺寸,到这里和Faster R-CNN都是相同的;现在不仅是得到分类得分和校正包围框,还要增加一个分支通过卷积网络对每一个候选框预测一个分割区域模板。这个新增的分支就是一个在候选框中进行的微型语义分割任务。这样上下两个分支的任务就很明确了——上面的分支需要计算分类得分确定候选框中的目标属于哪个分类以及通过对候选框坐标的回归来预测边界框的坐标;下面的分支基本类似一个微型语义分割网络,会对候选框中的每个像素进行分类,判断每个像素是否属于候选框的中目标。
Mask R-CNN综合了上面讲的很多方法,最终的效果也是非常好的。比如下图最左边,不仅框出了每个物体还分割了像素,即使很远地方的人也被清晰的分割出来了。
此外,Mask R-CNN也可以识别动作,方法是在上面分支中增加一个关节坐标损失,这样就能同时进行分类、检测、动作识别、语义分割。此外,基于Faster R-CNN,运行速度也是非常快的。下图展示的效果是很令人惊讶的,可以同时识别出图上有多少人,分割出他们的像素区域,并且会标示他们的动作姿势。
2.2.2 不使用候选区域
使用前馈模型。
YOLO / SSD
YOLO 即 “You Only Look Once” 和 SSD 即 “Single-Shot MultiBox Detector”,这两个模型是在同一时期提出的(2016),它们不会使用候选框分别进行处理,而是尝试将其作为回归问题,通过一个大的卷积网络,一次完成所有预测。给定输入图像,分成网格状比如7x7,然后在每个小单元中心处使用 B 个基本的边界框,比如高的、宽的、正方形的,这样总共有 7x7xB个基本框。现在想对每个网格单元的所有基本边界框预测目标物体,首先要预测每个基本边界框偏移来确定边界框和真实物体的位置差值,使用5个值(dx, dy, dh, dw, confidence)来表示偏差;然后预测每个网格单元里目标的 C 个分类(包括背景)得分,这样每个网格单元都会得到一个分类得分,即目标所属类别。最终的输出就是一个三维的张量:7x7x(5*B+C)。
2.2.3 目标检测方法综述
基础网络:VGG16, ResNet-101, Inception V2, Inception V3, Inception ResNet, MobileNet;
检测方法:Faster R-CNN, Mask R-CNN, R-FCN, YOLO / SSD等。Faster R-CNN虽然慢但是准确,SSD虽然快但不够精确;
超参数:图像尺寸、备选区域个数。
TensorFlow Detection API(Faster RCNN, SSD, RFCN, Mask R-CNN):点击这里
密集标注( Dense Captioning)
- 目标检测 + 图像标注 = 密集标注
- 将Faster R-CNN和LSTM结合起来
2.2.4 三维目标检测
- 平面图上的一个点对应3D空间的一条射线;
- 平面图上的一个边界框对应截取的一个3D空间;
- 平面图的物体可以投射到相机视角空间的任意距离和大小,所以在三维空间目标可以定位在任意位置。
二维平面的目标检测只需确定 [x, y, w, h],3D的定位框需要确定的坐标为 [x, y, z, roll, pitch, yaw],简化后可以不需要 roll 和 pitch。比2D目标检测要复杂的多。
检测方法
Monocular Camera(单目相机):和Faster R-CNN原理相似,只是备选区域是三维的;
Camera + LiDAR;
RGB-Depth Camera:也是“Faster RCNN in 3D”。
总结
语义分割:降采样与升采样的全卷积网络;使用转置卷积进行升采样。
分类与定位:原图像分类网络加入边界框回归损失。
-
目标检测:
- 基于区域备选的Faster R-CNN / 不使用备选区域的SSD;
- 卷积网络+区域备选网络+Rol Pool+多种损失;
- Mask R-CNN效果非常好;
- 3D目标检测。