【RCNN】
文章目录
1.基础知识
1.1 目标检测
既要把图中的物体识别出来,又要用方框框出它的位置
图像识别+定位
图像识别(classification)
输入:图片
输出:物体的类别
评估方法:准确率
定位(localization)
输入:图片
输出:方框在图片中的位置(x,y,w,h)
评估方法:检测评价函数(intersection-over-union)iou
定位的问题的解决思路有那些?
思路一:看做回归问题
我们需要预测出(x,y,w,h)四个参数的值,从而得出方框的位置
思路二:取图像窗口
咱们取不同大小的框
让框出现在不同的位置,得出这个框的判定得分
取得分最高的那个框
【传统的目标检测方法流程】
【输入】——【候选区 特征提取 [分类器判定目标 or 背景 ]】—— 【nms】—— 【输出】
1.2 IOU的定义
IoU 的全称为交并比(Intersection over Union),通过这个名称我们大概可以猜到 IoU 的计算方法。IoU 计算的是 “预测的边框” 和 “真实的边框” 的交集和并集的比值。
def IoU(box,boxes):
"""
@ box 候选框 [x1,y1,x2,y2]
@ boxes 标记 [x1,y1,w,h]
"""
face_area=boxes[:,2]*boxes[:,3] # w*h
actual_area=(box[2]-box[0])**2 # 候选框的面积
# 计算候选框和真实框相交的坐标
x1=np.maximum(box[0],boxes[:,0])
y1=np.maximum(box[1],boxes[:,1])
x2=np.minimum(box[2],boxes[:,2]+boxes[:,0])
y2=np.minimum(box[3],boxes[:,3]+boxes[:,1])
w=np.maximum(0,x2-x1+1)
h=np.maximum(0,y2-y1+1)
inter_area=w*h
return inter_area/(face_area+actual_area-inter_area)
1.3 非极大值抑制
nms 算法过程
- 将所有框的得分排序,选中最高分及其对应的框
- 遍历其余的框,如果和当前最高分框的重叠面积(IOU)大于一定阈值,我们将框删除
- 从未处理的框中继续选一个得分最高的,重复上述过程
''' 比如:A、B、C、D、E、F、G、H、I、J 假设 A 的得分最高,IOU>0.7,剔除 1. 计算与A的 IOU, 若 BEG(和A的IOU) > 0.7 , 剔除 BEG 2. 若剩下 C、D、F、H、I、J 中F得分最高,计算和F的IOU DHI > 0.7 剔除 3. 若 C、J 中C得分最高,J与C计算IOU,若结果>0.7 剔除J 输出3个目标 A/F/C '''
'''
1. 计算候选框的面积时加1?
候选框面积算的是像素点数,比如候选框左上和右下点坐标相同时,面积应该为1,如果计算面积时不+1,候选框面积就变成0了
'''
import numpy as np
def py_nms(dets, thresh):
'''
Pure Python NMS baseline
@ dets = [x1,y1,x2,y2,scores]
@ thresh 阈值
'''
x1 = dets[:, 0]
y1 = dets[:, 1]
x2 = dets[:, 2]
y2 = dets[:, 3]
scores = dets[:, 4]
#每一个候选框的面积
areas = (x2 - x1 + 1) * (y2 - y1 + 1)
order = scores.argsort()[::-1] # order是按照score降序排序的
keep = [] # 最后保留的边框
while order.size > 0:
i = order[0] # 当前得分最大的框
keep.append(i)
# 计算图片i分别与其余图片相交的矩形的坐标
xx1 = np.maximum(x1[i], x1[order[1:]])
yy1 = np.maximum(y1[i], y1[order[1:]])
xx2 = np.minimum(x2[i], x2[order[1:]])
yy2 = np.minimum(y2[i], y2[order[1:]])
# 计算出各个相交矩形的面积
w = np.maximum(0.0, xx2 - xx1 + 1)
h = np.maximum(0.0, yy2 - yy1 + 1)
inter = w * h
#计算重叠度IOU:重叠面积/(面积1+面积2-重叠面积)
ovr = inter / (areas[i] + areas[order[1:]] - inter)
#找到重叠度不高于阈值的矩形框索引
inds = np.where(ovr <= thresh)[0]
'''将order序列更新,由于前面得到的矩形框索引要比矩形框在原order序列中的索引小1,所以要把这个1加回来'''
order = order[inds + 1]
return keep
# test
if __name__ == "__main__":
dets = np.array([[30, 20, 230, 200, 1],
[50, 50, 260, 220, 0.9],
[210, 30, 420, 5, 0.8],
[430, 280, 460, 360, 0.7]])
thresh = 0.35
keep_dets = py_nms(dets, thresh)
print(keep_dets)
print(dets[keep_dets])
[0, 2, 3]
[[ 30. 20. 230. 200. 1. ]
[ 210. 30. 420. 5. 0.8]
[ 430. 280. 460. 360. 0.7]]
2.原理
1.R-CNN
RCNN 算法分为4个步骤
- 【候选区域生成】一张图生成1k—2k个候选区域(selective search【选择性搜索】)
- 【特征提取】对于每个候选区域,利用深度网络提取特征
- 【类别判断】特征送入每一类的SVM分类器,判断是否属于该类
- 【位置精修】使用回归器精细修正候选区域
特征提取——使用深度网络提取特征前,首先将候选区域归一化成同一尺寸227*227
深度特征
-
训练分类网路[alexNet]
-
模型做fine-tuning(类别数1000改为20,去掉FC)
-
特征提取-1.提取候选区域[选择搜索]
2.对每个区域:修正区域为cnn的输入,利用网络对候选区域提取到特征)
【特征提取】-提取候选框【选择性搜索】 0. 生成区域集R 1. 计算区域集R里每个相邻区域的相似度S=(s1,s2.) 2. 找出相似度最高的两个区域,将其合并为新集,添加进R 3. 从S中移除所有与step2中有关的子集 4. 计算新集与所有子集的相似度 5. 跳至step2,直到S为空
-
训练svm分类器,每个类别对应一个svm
-
回归精修候选框位置,利用回归模型判定框的精准度
特点
速度——经典的目标检测算法使用滑动窗口依次判断所有可能的区域,本文则采用(selective search方法)预先提取一系列较可能是物体的候选区域,之后仅在这些候选区域上(采用CNN)提取特征,进行判断。
训练集——经典的目标检测算法在区域中提取人工设定的特征,本文则采用深度网络进行特征提取。
使用两个数据集
- 一个较大的识别库(ImageNet ILSVC 2012)—标定每一张图片中物体的类别,一千万图像,1000类
- 一个较小的检验库(Pascal voc 2007)标定每张图片中,物体的类别和位置,一万图像,20类
本文使用库进行预训练得到CNN(有监督训练),而后用检验库调优参数,最后在检测库上评测
缺点
1. 候选框选择算法耗时严重
2. 重叠区域特征重复计算
3. 分步骤进行,过程繁琐
3.论文笔记
0.摘要
在这篇论文里,我们提出了一种简单并且可扩展的检测算法,可以将mAP在VOC2012最好结果的基础上提高30%以上——达到了53.3%。我们的方法结合了两个关键的因素:
- 在候选区域上,自下而上使用大型卷积神经网络(CNNs),用以定位和分割物体
- 带标签的训练数据不足时,先针对辅助任务进行有监督预训练,再进行特定任务的调优,就可以产生明显的性能提升。
R-CNN 的发展
在过去的十多年时间里,传统的机器视觉领域,通常采用特征描述子来应对目标识别任务,这些特征描述子最常见的就是 SIFT 和 HOG.而 OpenCV 有现成的 API 可供大家实现相关的操作。
SIFT 和 HOG 的王者地位最近被卷积神经网络撼动。
论文作者尝试将 AlexNet 在 ImageNet 目标识别的能力泛化到 PASCAL VOC 目标检测上面来。
但一切开始之前,需要解决两个主要的问题。
- 如何利用深度的神经网络去做目标的定位?
- 如何在一个小规模的数据集上训练能力强劲的网络模型?
论文作者给出了思路。
利用候选区域与 CNN 结合
借鉴了滑动窗口思想,R-CNN 采用对区域进行识别的方案。
具体是:
- 给定一张输入图片,从图片中提取 2000 个类别独立的候选区域。
- 对于每个区域利用 CNN 抽取一个固定长度的特征向量。
- 再对每个区域利用 SVM 进行目标分类。
利用预训练与微调解决标注数据缺乏的问题
采用在 ImageNet 上已经训练好的模型,然后在 PASCAL VOC 数据集上进行 fine-tune。
因为 ImageNet 的图像高达几百万张,利用卷积神经网络充分学习浅层的特征,然后在小规模数据集做规模化训练,从而可以达到好的效果。
现在,我们称之为迁移学习
R-CNN 的目标识别之路
前面内容提到过,R-CNN 系统分为 3 个阶段,反应到架构上由 3 个模块完成。
候选区域的生成,这些候选区域其中包含了 R-CNN 最终定位的结果。
神经网络去针对每个候选区域提取固定长度的特征向量。
一系列的 SVM 分类器。
候选区域
能够生成候选区域的方法很多,比如:
生成候选区的方法很多
- objectness
- selective search
R-CNN采用
- category-independen object proposals
- constrained parametric min-cuts(cpmc)
- multi-scale combinatorial grouping
- Ciresan
特征提取
R-CNN 抽取了一个 4096 维的特征向量,采用的是 Alexnet
需要注意的是 Alextnet 的输入图像大小是 227x227。
而通过 Selective Search 产生的候选区域大小不一,为了与 Alexnet 兼容,R-CNN 采用了非常暴力的手段,那就是无视候选区域的大小和形状,统一变换到 227*227 的尺寸。
有一个细节,在对 Region 进行变换的时候,首先对这些区域进行膨胀处理,在其 box 周围附加了 p 个像素,也就是人为添加了边框,在这里 p=16。
测试阶段的目标检测
在测试阶段,R-CNN 在每张图片上抽取近 2000 个候选区域。
然后将每个候选区域进行尺寸的修整变换,送进神经网络以读取特征,然后用 SVM 进行类别的识别,并产生分数。
候选区域有 2000 个,所以很多会进行重叠。
针对每个类,通过计算 IoU 指标,采取非极大性抑制,以最高分的区域为基础,剔除掉那些重叠位置的区域。
运行时分析
两个因素可以让目标识别变得高效。
CNN 的参数是所有类别共享的。
R-CNN 生成的特征向量维度较少。论文拿应用在 UVA 采用的空间金字塔技术相比,它们生成的特征维度是 360k,而 R-cnn 就 4K 多。
也就是运行过程中,参数变少了,所以比传统的高效。
体现在提取特征的时间,如果用 GPU ,13s/张,CPU 53s/张。
R-cnn 能够处理 100k 种类别,在一个多核的 CPU 上只要花费 10 多秒。
与 UVA 相比,如果处理 100k 个预测,需要 134GB 内存空间,而 R-CNN 只要 1.5GB。
训练
前面已经提到过 R-CNN 采取迁移学习。
提取在 ILSVRC 2012 的模型和权重,然后在 VOC 上进行 fine-tune。
需要注意的是,这里在 ImageNet 上训练的是模型识别物体类型的能力,而不是预测 bbox 位置的能力。
ImageNet 的训练当中需要预测 1000 个类别,而 R-CNN 在 VOC 上进行迁移学习时,神经网络只需要识别 21 个类别。这是 VOC 规定的 20 个类别加上背景这个类别。
R-CNN 将候选区域与 GroundTrue 中的 box 标签相比较,如果 IoU > 0.5,说明两个对象重叠的位置比较多,于是就可以认为这个候选区域是 Positive,否则就是 Negetive.
训练策略是:采用 SGD 训练,初始学习率为 0.001,mini-batch 大小为 128.
对象识别相关
通常对待一个二值化的分类器,它的结果只要 2 中,Positive 和 Negetive。
比如,有一个汽车分类器,它可以轻松地确认,一个方框里面包含了一辆汽车,那么它肯定就是 Positive。
也可以很清楚地确认,如果一个背景方框中没有包含汽车,那么它就是 Negetive。
但是,比较难确认的是,如果一个方框,只有一部分与汽车重叠,那么如何标注这个方框呢?
R-CNN 采用的是 IoU 的阈值,这个 threshold 取 0.3,如果一个区域与 Ground tureth 的 IoU 值低于设定的阈值,那么可以讲它看成是 Negetive.
IoU 的 threshold 它不是作者胡乱取值的,而是来自 {0,0.1,0.2,0.3,0.4,0.5} 的数值组合的。
而且,这个数值至关重要,如果 threshold 取值为 0.5,mAP 指标直接下降 5 个点,如果取值为 0,mAP 下降 4 个点。
一旦特征抽取成功,R-CNN 会用 SVM 去识别每个区域的类别,但这需要优化。
因为训练的数据太大,不可能一下子填充到电脑内存当中,R-CNN 作者采取了一种叫做 Hard negetive mining 的手段。
R-CNN 的在 PASCAL-VOC 2010-12 的表现
R-CNN 是在 PASCAL VOC 2012 进行最终的 fine-tune,也是在 VOC 2012 的训练集上优化 SVM.
然后,还与当时 4 个强劲的对手,也就是 4 个不同的目标检测算法进行了比较。
值得关注的是,上面表格中 UVA 检测系统也采取了相同的候选区域算法,但 R-CNN 的表现要好于它。
可视化、框架精简和错误检测
我们都知道,在卷积神经网络中,第一层可以直接用来显示,而且肉眼可视,通常他们是为了捕捉物体边缘,及突出的颜色信息,但越往后的卷积层越抽象,这个时候进行可视化就是一个挑战了。
Zeiler 和 Fergus 提出了一种基于反卷积手段的可视化研究,但 R-CNN 的作者直接提供了一个没有参数的方法,简单直接。
思路是挑选一个特征出来,把它直接当成一个物体分类器,然后计算它们处理不同的候选区域时,activation 的值,这个值代表了特征对这块区域的响应情况,然后将 activation 作为分数排名,取前几位,然后显示这些候选区域,自然也可以清楚明白,这个 feature 大概是什么。
R-CNN 作者将 pool5 作为可视化对象,它的 feature map 是 6x6x255 的规格,可以理解为有 256 个小方块,每个方块对应一个特征。
下面的图表中显示了这以可视化的效果,这里只显示了 256 个特征中的 6 个,每个特征取 activation 值最高的 16 个区域。
上图应该很明白了,对于同一类特征,activation 相差不大,这也是卷积神经网络能够准确识别物体的直观体现。
框架精简
AlexNet 有 7 层,那么那些层是关键指标呢?哪些层可有可无呢?
pool5 在上一小节已经讨论过了,那么 fc6 和 f7 就成了研究的对象。
fc6 与 pool5 构成全连接,为了计算 feature 它会乘以一个 4096x9216 的权重矩阵,然后在与一组 bias 相加,所以它有 3700 多万的参数。
fc7 是最后一层,它的权重矩阵是 4096x409,它的参数有 1678 万多的参数。
但经过作者在 PASCAL 上不做 fine-tune 处理,直接测试,可以发现 fc7 的意义没有 fc6 大,甚至移除它之后,对于 mAP 结果指标没有影响。
移除 fc7 就表示可以减少将近 1800 万个参数。
同时移除 fc6 和 fc7 并没有多大的损失,甚至结果还要好一点点。
所以,神经网络最神奇的力量来自卷积层,而不是全连接层。
上面说的是没有 fine-tune 的情况,那么在 fine-tune 的情况是什么呢?
结果证明,fine-tune 后 fc6 与 fc7 提升的效果明显。
所以结论就是,pool5 从 ImageNet 训练集中学习了物体的泛化能力,而能力的提升则是通过特定领域的 fine-tune。
举个例子,神经网络在 ImageNet 数据集中学习到了 100 种猫的特征,而我自己的数据集只有两种猫,经过 fine-tune 训练后,这个神经网络可以更准确识别这两种猫了。
R-CNN 还与其他的特征方法进行了能力比较,作者选取了两种基于 DPM 的方法,DPM ST 和 DPM HSC,结果都证明,R-CNN 要好于它们。
4.问题
为什么微调时和训练SVM时采取的正负样本阈值【0.5和0.3】不一致?
微调阶段是由于CNN对小样本容易过拟合,需要大量训练数据,故对IoU限制宽松:Ground Truth+与Ground Truth相交IoU>0.5的建议框为正样本,否则为负样本;
SVM这种机制是由于其适用于小样本训练,故对样本IoU限制严格:Ground Truth为正样本,与Ground Truth相交IoU<0.3的建议框为负样本。
为什么不直接采用微调后的AlexNet CNN网络最后一层SoftMax进行21分类
因为微调时和训练SVM时所采用的正负样本阈值不同,微调阶段正样本定义并不强调精准的位置,而SVM正样本只有Ground Truth;并且微调阶段的负样本是随机抽样的,而SVM的负样本是经过hard negative mining方法筛选的;导致在采用SoftMax会使PSACAL VOC 2007测试集上mAP从54.2%降低到50.9%。