R-CNN 详解
Rich feature hierarchies for accurate object detection and semantic segmentation
R-CNN 的 2 个主要思想:
(1)使用卷积神经网络来提取生成的 region proposals 中的特征。
(2)当样本数据匮乏时。先在大型的图像识别的数据集上进行监督预训练,然后在目标检测上微调,对性能有显著的提升。
一、算法流程
1. 生成 region proposals
使用 selective search 生成 2000 个左右的 region proposals
2. CNN 特征提取
使用 CNN 对生成的 region proposals 提取特征
3. SVM 分类
使用多个 SVM 分类器分类
4. 位置精修
使用回归器,进行边界回归
二、流程详解
(一)生成 region proposals
使用 selective search 生成 2000 个左右的 region proposals
selective search 只是生成 region proposals 的一种方法,还有很多其他的方法。其主要思想就是:输入一张图片,首先通过图像分割的方法获得很多小的区域,然后对这些小的区域不断进行合并,一直到无法合并为止。此时这些原始的小区域和合并得到的区域的就是我们得到的 region proposals。
(二)CNN 特征提取
使用 CNN 对生成的 region proposals 提取特征
1、预处理
(A)原 region proposals。(B)tightest square with context。(C)tightest square without context。(D)warp
第一、第三行添加 context padding(P = 0),第二、第四行添加 context padding(P = 16)
为了适应卷积神经网络的固定的输入(AlexNet:227 x 227),我们对生成的 region 进行变换。变换的策略有如下两种:
1、tightest square
(1)with context(图像中的上下文 context 是指 ROI 周边的像素)
将 region 沿着短边用原图填充为正方形,到原图像的边界还未填充为正方形时使用原图像的均值填充,然后将此时的图像 resize 至模型的输入大小,以适应模型的输入。在输入 CNN 模型时需要减去此图像的均值
(2)without context
将 region 直接使用图像均值填充为正方形,然后将此时的图像 resize 至模型的输入大小。在输入 CNN 模型时需要减去图像的均值。
2、warp
直接暴力的将图像 resize 至模型的输入大小。这种方法可能会导致图形的拉伸。不过在实现 R-CNN 网络时,作者使用的就是这种方法。
以上所有的方法:
(1)在输入CNN模型时都需要减去均值。
(2)可以再添加 context padding(P),
即先添加 padding(P),填充为正方形后再进行 resize至模型输入大小。作者尝试的最佳的 P 值为 16。
2、训练阶段
预训练:
使用 ILSVRC 2012 对 AlexNet 网络进行预训练,学习率为0.01。然后将最后一层的 1000 分类的 softmax 换为 21 类(20 分类 + 1 背景)
注意:
(1)实际上作者做了消融研究,表明对最终影响最大的是前面的卷积层,而不是后面的全连接层,不过为了不丢失精度,这里没有去掉后面的全连接层。
(2)卷积神经网络的结构可以替换,也就是可以使用其他的模型(比如 VGG16),且使用模型的效果会对最终的结果产生巨大的影响。
fine-tuning:
region proposals 的
I
O
U
≥
0.5
IOU \ge 0.5
IOU≥0.5 的 region 作为正样本。
I
O
U
<
0.5
IOU \lt 0.5
IOU<0.5 的 region 作为负样本。对于每个 batch,使用 32 个正样本和 96 个负样本(batch size = 128)输入预训练过的 AlexNet 进行 fine-tuning 。学习率为预训练时的
1
10
\frac{1}{10}
101,即 0.001。
3、测试阶段
将 region proposals(预处理后的) 放入网络中生成 4096 维的特征向量。
(三)SVM 分类
使用多个 SVM 分类器分类
1、训练阶段
每一个类有一个 SVM 分类器,需要再额外加一个背景类。使用 ground truth 作为正例,使用 IOU < \lt < 0.3 的作为负例,先经过 hard negative mining method(详解见下面(1))进行筛选,再输入SVM进行训练。(其中 threshold 0.3 是经过网格搜索,搜索 { 0 , 0.1 , 0.2 , . . . , 0.5 } \{0,0.1,0.2,..., 0.5\} {0,0.1,0.2,...,0.5}得到的)
注意:在 CNN 的训练阶段和 SVM 的训练阶段的正负样例的定义不同。因为如果在 CNN 网络部分就使用 ground truth 作为正例,样本量就太小,不足进行模型的训练,容易过拟合。而如果在 SVM训练阶段 使用 I O U ≥ 0.5 IOU\ge0.5 IOU≥0.5 作为正例,会发生尺度的抖动,使目标检测的结果不精确(作者经过试验证明)
(1)Hard Negative Mining Method
对于 hard Negative Mining(困难样本挖掘)可以理解为错题集,你不会把所有的错题都放到错题集中,你会挑出那些你最容易错的题放到错题集中,Hard Negative Mining Method 就是这样。
首先是negative,即负样本,其次是hard,说明是困难样本,也可以说是容易将负样本看成正样本的那些样本,例如roi里没有物体,全是背景,这时候分类器很容易正确分类成背景,这个就叫 easy negative;如果roi里有二分之一个物体,标签仍是负样本,这时候分类器就容易把他看成正样本,这时候就是 had negative。hard negative mining 就是多找一些 hard negative 加入负样本集,进行训练,这样会比 easy negative 组成的负样本集效果更好。
2、测试阶段
将经过 CNN 提取的特征向量直接输入各个 SVM 分类器,预测其属于此类的概率。后使用 NMS 对 bounding box 进行剔除。
(1)NMS
NMS 要翻译成 “非极大值抑制”,而不是 “非最大值抑制”,因为极大值有多个,而最大值只有一个。在目标检测中,我们有多个 bounding box。
算法步骤:
先对每个框的score进行排序,首先选择第一个,也就是 score 最高的框,它一定是我们要保留的框。然后拿它和剩下的框进行比较,如果 IOU 大于一定阈值,说明两者重合度高,应该去掉,这样筛选出的框就是和第一个框重合度低的框,第一次迭代结束。第二次从保留的框中选出score第一的框,重复上述过程直到没有框保留了。
import numpy as np
def nms(dets, thresh):
"""Pure Python NMS baseline."""
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]
keep = []
while order.size > 0:
i = order[0]
keep.append(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
ovr = inter / (areas[i] + areas[order[1:]] - inter)
inds = np.where(ovr <= thresh)[0]
order = order[inds + 1]
return keep
(四)位置精修
使用回归器,进行边界回归
使用 bounding-box 回归进行位置精修,作者尝试了两种,一种是不加 BBox 的,一种是加 BBox 的。发现加上 BBox 对最终性能有很大的提高。即论文中的 R-CNN BB 模型(BB 为 bbox)
具体方法如下:
记当前的 region ,也就是上图中黄色的框的部分为(其中 x, y 为中点坐标,不是左上角的坐标,w, h 为宽高):
P
i
=
(
P
x
i
,
P
y
i
,
P
w
i
,
P
h
i
)
P^i=(P_x^i, P_y^i,P_w^i,P_h^i)
Pi=(Pxi,Pyi,Pwi,Phi)
ground truth,也就是上图中的绿色框为 :
G
i
=
(
G
x
i
,
G
y
i
,
G
w
i
,
G
h
i
)
G^i=(G_x^i,G_y^i,G_w^i,G_h^i)
Gi=(Gxi,Gyi,Gwi,Ghi)
我们的目标就是学习一个变换,使得 region proposal 映射到 ground truth,记这个映射为
d
(
P
)
d(P)
d(P):
其中
P
w
d
x
(
P
)
P_wd_x(P)
Pwdx(P) 为
Δ
x
\Delta{x}
Δx,
P
h
d
y
(
P
)
P_hd_y(P)
Phdy(P) 为
Δ
y
\Delta{y}
Δy
G x ^ = P w d x ( P ) + P x \hat{G_x}=P_wd_x(P)+P_x Gx^=Pwdx(P)+Px
G y ^ = P h d y ( P ) + P y \hat{G_y}=P_hd_y(P)+P_y Gy^=Phdy(P)+Py
G w ^ = P w e x p ( d w ( P ) ) \hat{G_w}=P_wexp(d_w(P)) Gw^=Pwexp(dw(P))
G h ^ = P h e x p ( d h ( P ) ) \hat{G_h}=P_hexp(d_h(P)) Gh^=Phexp(dh(P))
记映射
p
o
o
l
5
pool_5
pool5 到 P 为
ϕ
5
(
P
)
\phi_5(P)
ϕ5(P),那么我们可以得到
d
∗
(
P
)
=
w
∗
T
ϕ
5
(
P
)
d_*(P)=w_*^T\phi_5(P)
d∗(P)=w∗Tϕ5(P) (*是 x, y, h, w 之一,
w
∗
w_*
w∗是需要学习的参数)
使用最小二乘法得出:
w ∗ = arg min w ^ ∗ ∑ i N ( t ∗ i − w ^ ∗ T ϕ 5 ( P i ) ) 2 + λ ∣ ∣ w ^ ∗ ∣ ∣ 2 w_*=\argmin_{\hat{w}_*}\sum_i^N(t_*^i-\hat{w}_*^T\phi_5(P^i))^2+\lambda||\hat{w}_*||^2 w∗=w^∗argmini∑N(t∗i−w^∗Tϕ5(Pi))2+λ∣∣w^∗∣∣2
那么对于回归的目标
t
∗
t_*
t∗ 定义如下:
t
x
=
(
G
x
−
P
x
)
/
P
w
t_x=(G_x-P_x)/P_w
tx=(Gx−Px)/Pw
t y = ( G y − P y ) / P h t_y=(G_y-P_y)/P_h ty=(Gy−Py)/Ph
t w = l o g ( G w / P w ) t_w=log(G_w/P_w) tw=log(Gw/Pw)
t h = l o g ( G h / P h ) t_h=log(G_h/P_h) th=log(Gh/Ph)
通过优化 loss 我们就可以对最终的 bounding box 的位置进行调整。