参考
- 基于深度学习的目标检测技术演进。
- 七月在线RCNN扩展课程。
- Faster-RCNN算法精读
1. 从分类到检测。
分类已经学习过了四大网络(AlexNet,VGG,InceptionNer,ResNet),对于一个分类问题,数据量足够的话,根据分类复杂性搭建不同深度的卷积神经网络就基本可以解决这个问题了。具体的工业实现的话肯定会有这样或者那样的问题,就需要具体问题具体分析了。
分类的前提是我们能拿到一个目标的纯净图像(尽可能少的包含背景),我们拿来训练的图像一般也是这样的,这是一个计算机视觉中的一个基本任务。
在实际的工程中,这样的分类问题是不现实的,我们通常拿到的图片或者视频往往包含不止一个物体,或者这种物体不占图片的主要内容。下面这张图片显示了物体分类定位识别方面所要解决的问题。
单目标:
classification:分类问题。
classification+localization:分类加定位。
多目标:
object detection:定位不同目标并且识别,画出其矩形框。
instance segmentation:定位不同目标并识别,画出其边缘。
从左至右难度是逐渐递增的。RCNN系列的论文主要是针对于第三类的问题,即Object Detection。这种问题简单的来说就是图像识别+定位。
图像识别:输出图片的类别及置信率。
**图像定位: ** 输出方框在图片中的位置。
如同我们上面所说的,CNN已经可以完成大部分的图像识别(分类)任务了,所以需要解决的问题主要是定位。
定位问题的思路主要有两种:
a.看做是回归问题。
即把(x,y,w,h)看做是图像的函数,通过训练一个神经网络。来获得方框的位置。之所以看做是回归是因为x,y,w,h这种组合的量是足够大的,所以不能当做分类来做。另外框的位置和图像的边缘,颜色等信息是有关的,所以做一个回归还是有道理的。
先搭建一个识别图像的神经网络。
在AlexNet VGG GoogleLenet上fine-tuning一下就可以了:
在上面的神经网络的尾部展开(前面CNN前面保持不变,对CNN的结尾做出改进,加了两个头,一个用来分类一个用来回归)
- 回归损失用L2距离损失就可以。训练使用SGD来训练。
- 预测截断可以把两个头部拼在一起,实现不同的功能。
需要做两次fine-tuning,第一次在AlexNet上做,第二次将头部改成回归,前面的卷积部分不变,再做一次。
回归的这个头加在哪里呢?有不同的思路可以采用:
- 加在最后一个卷积层后面(如VGG)
- 加在最后一个全连接层后面(如R-CNN)
note:实际上做回归比作分类要难得多,回归的训练收敛的时间也较长,所以实际工程中应该设法将回归问题改为分类问题,上面的网络也采用了classification的网络来计算卷积部分的权值,然后在这个基础上再进行回归的训练。
b. 在原图上取图像窗口。
一种显而易见的思路是用各种大小不等的框来遍历整张图片,输入到CNN,然后根据CNN得到的classification评分。但是这个方法也太耗时了,首先框取多达就是个问题,如果从打大小来一遍一遍遍历的话,就只能奢求GPU非常多了,还真有人这样做过。
这样做确实是太耗时了,对其CNN预测与回归的部分进行了一部分优化:
把后面的全连接层改成卷积层,这种改变并不是等价的,而是通过1*1的卷积来进行特征融合,相当于进行了权值共享较少了参数量,可以进行一部分提速,但这种提速并不是本质的,这种方法的本质还是在于选框太多,这部分才是最耗费时间和硬盘的。
而且对于单目标图像可以这么搞,如果是多目标图像呢,这一下子难度就是暴增了。
所以候选框到底有没有一些简单有效的提取方式呢?有许多这方面的工作,而且取得了一些不错的效果,这样就可以只找出含有目标的框,然后送入CNN,这样就可以避免暴力枚举所有的框了。
最著名的方法:EdgeBoxes和SelectiveSearch,一些典型的算法性能对比:
其中SelectiveSearch在OpenCV的contrib库里还有这样的模块可以调用。使用了边缘,颜色等信息对图像进行分块和融合,然后进行候选框提取。
到这里铺垫就完了,下面开始介绍R-CNN。
2. RCNN
基于上面结合SelectiveSearch的思路,RCNN就出现了:
主要分为下面几个步骤:
-
训练或者下载一个分类模型(比如可以把AlexNet拿来):
-
对改模型来做fint-tuning, 将分类数按照需求改动,去掉最后一个全连接层。
-
特征提取。
利用SelectiveSearch来进行选框,对于每一个候选框,resize后送入CNN,做一次前向运算,将第五个池化层的输出,存到硬盘里。
-
训练一个SVM分类器,二分类的,对于每一类都需要训练一个分类器。
-
检测完成之后,使用回归模型来精修候选框位置,训练一个线性回归模型来判断这个框是否框的比较完美。
整个过程借用论文中的图:
初始R-CNN的思路大概就是这样,可以很明显得看到的缺点:
- 每个候选框都通过CNN,计算量是很大的,而且不同候选框中存在着重叠,重复运算肯定是存在的,是否可以设法减少这些重复运算。
- 训练占用空间,候选框较多,CONV5的卷积特征需要存储。
- 训练步骤繁琐(微调网络+训练SVM+训练回归XBOX)
3.Fast-RCNN
说Fast-RCNN之前有必要说一下SPP-NET(SPP:Spatial Pyramid Pooling(空间金字塔池化))
两个特点:
1.结合空间金字塔方法实现CNNs对任意尺度输入,一般CNN之后接全连接层或者分类器,需要输入固定尺寸,因此不得不对图片进行裁剪和缩放处理,这些预处理会造成数据的丢失或者几何失真(不过以前确实是这么做的),SPP的第一个贡献就是讲金字塔的思想加入CNN,实现了数据的多尺度适应性。
如图,在卷积层和全连接层之间加入了SPP,此时网络的输入是任意的,SPP中每一个pooling的filter会根据输入来调整大小,而SPP的输出尺度始终是固定的。
- 只对原图做一次卷积提取。
R-CNN中,每个候选框都需要resize到统一大小,然后输入CNN中,前面说可,这样有大量的重复计算,所以SPP根据这个缺点做了优化:只对原图做一次卷积网络从而得到整张图的feature map,然后找到每个候选框在特征图上的映射patch,然后将patch作为每个候选框的卷积特征输入到SPP和之后的层,这样就可以节省大量的计算时间,比R-CNN有100倍左右的提速。
Fast-RCNN就是借鉴了SPPnet的方法,对R-CNN进行了改进,主要的改进:
- 借鉴了SPP,每一张图只需要过一次CNN网络,再原图上通过SS(selective search)提取框,然后映射到过了CNN之后的feature map上,再通过roi_pool层,将特征图上大小不一的候选区编程大小统一的数据,送入下一层。关于roi_pool层和细节和训练可以看这里
-
分类使用softmax代替,xbox回归也和其结合在一起,真正变成了端到端的一个模型。
做了这些改变之后,性能上的提升是非常明显的:
4.Faster R-CNN
如果说Fast R-CNN速度的瓶颈还有待提高的话,那么这个瓶颈就在SS(selective search)上,即使是只过一遍CNN减少了很多耗时,selective search获取候选框的过程还是非常耗时的,要达到实时性的要求非常困难。
Faster-RCNN就从这里入手,解决了这个问题,解决的方法是就是把这个选框的任务也交给神经网络来做,这个神经网络叫做RPN(region proposal Network)。具体的做法是将RPN放在最后一个卷积层后面,将RPN直接训练得到候选区域:
关于RPN的简介可以看这里:RPN
虚线一下是RPN的结构,包括一个33的滑动窗口,然后两路11的卷积得到物体分类和框位置回归,滑动窗口的位置提供了物体的大体位置信息,回归提供了框更精确的位置信息。
为什么选用3*3的卷积核,这应该是和感受野大小对应的,这个主要是和feature map的尺寸有关,经过前面的卷积层之后feature map和原图相比是有缩小的,这里只算一个比例,比如说原图大小是1024_1024,经过5层卷积之后变成16_16(每一层都有一个2_2pooling),3_3的感受野占比3/16,对应原图中为190的感受野,这样的大小比较合适了。
RPN的另外一个机制是anchor,这是其核心。上面说到,需要确定每个华创中心对应的感受野中存在目标与否,然后目标大小和长宽比例上都是不一的,所以需要多个尺度的窗,anchor机制就是给出一个基准窗大小,按照倍数和长宽比例得到不同的窗,比如论文中基准窗的大小是16,给了(8,16,32)三种倍数,和(0.5,1,2)三种比例,这样可以得到几种尺度的anchor。
对60_40的map进行滑窗时,以中心像素为基点构造9中anchor映射到原图1000_600的图像中,总共可以得到大约2万个anchor。
RPN是单独训练的,最后再和整个网络放在一起进行联合训练,整个训练过程:
作者采用四步训练法:
1) 单独训练RPN网络,网络参数由预训练模型载入;
2) 单独训练Fast-RCNN网络,将第一步RPN的输出候选区域作为检测网络的输入。具体而言,RPN输出一个候选框,通过候选框截取原图像,并将截取后的图像通过几次conv-pool,然后再通过roi-pooling和fc再输出两条支路,一条是目标分类softmax,另一条是bbox回归。截止到现在,两个网络并没有共享参数,只是分开训练了;
3) 再次训练RPN,此时固定网络公共部分的参数,只更新RPN独有部分的参数;
4) 那RPN的结果再次微调Fast-RCNN网络,固定网络公共部分的参数,只更新Fast-RCNN独有部分的参数。
至此,网络训练结束,网络集检测-识别于一体,测试阶段流程图如下:
有一些实现细节,比如RPN网络得到的大约2万个anchor不是都直接给Fast-RCNN,因为有很多重叠的框。文章通过非极大值抑制的方法,设定IoU为0.7的阈值,即仅保留覆盖率不超过0.7的局部最大分数的box(粗筛)。最后留下大约2000个anchor,然后再取前N个box(比如300个)给Fast-RCNN。Fast-RCNN将输出300个判定类别及其box,对类别分数采用阈值为0.3的非极大值抑制(精筛),并仅取分数大于某个分数的目标结果(比如,只取分数60分以上的结果)。【这一大段都是来自于[3]】
下面的这个比较来自于参考1:
最后总结一下各大算法的步骤:
RCNN
1. 在图像中确定约1000-2000个候选框 (使用选择性搜索)
2. 每个候选框内图像块缩放至相同大小,并输入到CNN内进行特征提取
3. 对候选框中提取出的特征,使用分类器判别是否属于一个特定类
4. 对于属于某一特征的候选框,用回归器进一步调整其位置
Fast RCNN
1. 在图像中确定约1000-2000个候选框 (使用选择性搜索)
2. 对整张图片输进CNN,得到feature map
3. 找到每个候选框在feature map上的映射patch,将此patch作为每个候选框的卷积特征输入到SPP layer和之后的层
4. 对候选框中提取出的特征,使用分类器判别是否属于一个特定类
5. 对于属于某一特征的候选框,用回归器进一步调整其位置
Faster RCNN
1. 对整张图片输进CNN,得到feature map
2. 卷积特征输入到RPN,得到候选框的特征信息
3. 对候选框中提取出的特征,使用分类器判别是否属于一个特定类
4. 对于属于某一特征的候选框,用回归器进一步调整其位置
最后上一张速度和准确度的对比:
location+classification这个框架基本上这一套算法就搭建得比较完整了,这都是由RBG大神几乎以一己之力做完的,出了仰望还能干吗呢?肯定还有好多细节论文没看是看不到的,我只是作为了解,所以就这样了。