1.R-CNN
1.1 R-CNN
- 使用传统的锚框(提议区域)选择算法–选择性搜索算法* 选取高质量锚框。
- 对每一个锚框使用预训练模型对其提取特征,每个锚框需要调整为预训练模型所需要的输入尺寸。
- 使用支持向量机(SVM)对类别分类。
- 训练线性回归模型来预测边缘框偏移。
R-CNN速度很慢的原因是每张图片抽取上千个提议区域,就需要上千次卷积神经网络的前向传播来执行目标检测。
1.2 Fast R-CNN
与R-CNN对每个提议区域独立运行一个CNN的前向传播相比,引入了共享计算,减少了多个提议区域之间重叠区域的重复计算。
- Fast R-CNN将整个图像输入卷积神经网络提取特征图,而不是各个提议区域。设输入为一张图像,将卷积神经网络的输出的形状记为 1 × c × h 1 × w 1 1\times c \times h_1 \times w_1 1×c×h1×w1
- 使用选择性搜索生成提议区域,这些形状各异的提议区域在卷积神经网络的输出上分别标出了形状各异的兴趣区域。然后,这些感兴趣的区域需要进一步抽取出形状相同的特征(比如指定高度 h 2 h_2 h2和宽度 w 2 w_2 w2),以便于连结后输出。为了实现这一目标,Fast R-CNN引入了兴趣区域汇聚层(RoI pooling):将卷积神经网络的输出和提议区域作为输入,输出连结后的各个提议区域抽取的特征,形状为 n × c × h 2 × w 2 n \times c \times h_2 \times w_2 n×c×h2×w2。
- 通过全连接层将输出形状变换为 n × d n \times d n×d,其中超参数d取决于模型设计。
- 预测n个提议区域中每个区域的类别和边界框。将全连接层的输出转换为 n × q n \times q n×q(q为类别数量softmax分类)和 n × 4 n \times 4 n×4(坐标回归)。
1.3 Faster R-CNN
Faster R-CNN使用区域提议网络(RPN–神经网络)替代了Fast R-CNN的选择性搜索算法,使得提议区域的数量大幅度减少且还能保证目标检测的精度,从而更好的获取锚框。
- 图像经过CNN抽取特征图,RPN网络将这些特征图作为输入,再经过一系列卷积层抽取特征图,在这些特征图上利用选择性搜索算法(或者其他锚框生成算法)生成大量的Anchor box锚框,经过Binary Category Prediction(背景或有目标二分类)去除一些没有可能包括目标的锚框,经过Bounding Box Prediction(边界框预测)初步回归修正含有目标锚框的位置信息,使用非极大值抑制,把一些类似的锚框消除去重,最后得到一些高质量锚框。
- 将这些高质量锚框和特征图经过ROI pooling层,之后与Fast R-CNN 相同。
1.4 Mask R-CNN
在训练集中如果还标注了每个目标在输入图像中的像素级位置,可使用Mask R-CNN,如COCO数据集。
Mask R-CNN是基于Faster R-CNN修改而来的。 具体来说,Mask R-CNN将兴趣区域汇聚层替换为了 兴趣区域对齐层,使用双线性插值(bilinear interpolation)来保留特征图上的空间信息,从而更适于像素级预测。 兴趣区域对齐层的输出包含了所有与兴趣区域的形状相同的特征图。 它们不仅被用于预测每个兴趣区域的类别和边界框,还通过额外的全卷积网络预测目标的像素级位置。
2.SSD
SSD(单发多框检测)是one-stage网络
生成锚框
- 对输入图像的每个像素,生成多个以它为中心的锚框。
- 设置缩放比(scale)
s
1
,
.
.
.
,
s
n
s_1,...,s_n
s1,...,sn和宽高比(aspect ratio)取值
r
1
,
.
.
.
,
r
m
r_1,...,r_m
r1,...,rm,由于计算复杂性过高,在实践中只取包含
s
1
s_1
s1和
r
1
r_1
r1的组合。
( s 1 , r 1 ) , ( s 1 , r 2 ) , . . . , ( s 1 , r m ) , ( s 2 , r 1 ) , ( s 3 , r 1 ) , . . . , ( s n , r 1 ) (s_1,r_1),(s_1,r_2),...,(s_1,r_m),(s_2,r_1),(s_3,r_1),...,(s_n,r_1) (s1,r1),(s1,r2),...,(s1,rm),(s2,r1),(s3,r1),...,(sn,r1)
因此一个像素点为中心可生成 n + m − 1 n+m-1 n+m−1个锚框,一张图片可生成 w h ( n + m − 1 ) wh(n+m-1) wh(n+m−1)个锚框。
#@save
def multibox_prior(data, sizes, ratios):
"""生成以每个像素为中心具有不同形状的锚框"""
in_height, in_width = data.shape[-2:]
device, num_sizes, num_ratios = data.device, len(sizes), len(ratios)
boxes_per_pixel = (num_sizes + num_ratios - 1)
size_tensor = torch.tensor(sizes, device=device)
ratio_tensor = torch.tensor(ratios, device=device)
# 为了将锚点移动到像素的中心,需要设置偏移量。
# 因为一个像素的高为1且宽为1,我们选择偏移我们的中心0.5
offset_h, offset_w = 0.5, 0.5
steps_h = 1.0 / in_height # 在y轴上缩放步长
steps_w = 1.0 / in_width # 在x轴上缩放步长
# 生成锚框的所有中心点
center_h = (torch.arange(in_height, device=device) + offset_h) * steps_h
center_w = (torch.arange(in_width, device=device) + offset_w) * steps_w
shift_y, shift_x = torch.meshgrid(center_h, center_w)
shift_y, shift_x = shift_y.reshape(-1), shift_x.reshape(-1)
# 生成“boxes_per_pixel”个高和宽,
# 之后用于创建锚框的四角坐标(xmin,xmax,ymin,ymax)
w = torch.cat((size_tensor * torch.sqrt(ratio_tensor[0]),
sizes[0] * torch.sqrt(ratio_tensor[1:])))\
* in_height / in_width # 处理矩形输入
h = torch.cat((size_tensor / torch.sqrt(ratio_tensor[0]),
sizes[0] / torch.sqrt(ratio_tensor[1:])))
# 除以2来获得半高和半宽
anchor_manipulations = torch.stack((-w, -h, w, h)).T.repeat(
in_height * in_width, 1) / 2
# 每个中心点都将有“boxes_per_pixel”个锚框,
# 所以生成含所有锚框中心的网格,重复了“boxes_per_pixel”次
out_grid = torch.stack([shift_x, shift_y, shift_x, shift_y],
dim=1).repeat_interleave(boxes_per_pixel, dim=0)
output = out_grid + anchor_manipulations
return output.unsqueeze(0)
img = d2l.plt.imread('../img/catdog.jpg')
h, w = img.shape[:2]
print(h, w)
X = torch.rand(size=(1, 3, h, w))
Y = multibox_prior(X, sizes=[0.75, 0.5, 0.25], ratios=[1, 2, 0.5])
Y.shape
模型
- 一个基础网络来抽取特征(一般是VGG,也可以是ResNet),然后多个卷积层快来将上一次提供的特征图的高宽缩小,在浅层特征图生成的锚框像素点多,高宽较大,因此生成的锚框数量多,可用于检测较小的目标。深层网络的特征图中每个特征点单元的感受野更大,因此可用来检测较大的目标。
- 在每段都生成锚框,对每个锚框预测类别和边缘框。
3.YOLO
- SSD中锚框大量重叠,因此浪费了很多计算
- YOLO将图片均匀分成 S × S S \times S S×S个锚框
- 每个锚框预测B个边缘框
之后继续更新。。。