一小时吃透 R-CNN & Fast R-CNN & Faster R-CNN
Posted 我是小白呀
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一小时吃透 R-CNN & Fast R-CNN & Faster R-CNN相关的知识,希望对你有一定的参考价值。
一小时吃透 R-CNN & Fast R-CNN & Faster R-CNN
概述
R-CNN 家族是一个 two-stage 的目标检测算法.
目标检测算法
三大分类:
- 传统的目标检测算法:
- Cascade + HOG/DPM + Haar/SVM
- 候选窗 + 深度学习分类:
- R-CNN (Selective Search + CNN + SVM)
- Fast R-CNN (Selective Search + CNN + ROI)
- Faster R-CNN (RPN + CNN + ROI)
- 深度学习回归方法:
- Yolo
- SSD
- DenseBox
- RRC detection
- Deformable CNN
重点
SPP 池化 (2014)
SPP(Spatial Pyramid Pooling) 即金字塔池化, 可以帮助我们将图像切分成各种粗细级别, 然后整合特征. SPP 解决了 R-CNN 把图片统一缩放到一定的大小, 从而失去了多尺寸的信息的问题.
如图, 特征图通道数为 256, 通过金字塔池化我们可以得到 1 × 1, 2 × 2, 和 4 × 4 的特征图:
- 对整个图片池化每层得到一个点, 共 256 个点, 构成一个 1 × 256 的向量
- 将图片划分成 2 × 2 的格子, 共 256 个点, 构成一个 4 × 256 的向量
- 将图片划分成 4 × 4 的格子, 共 256 个点, 构成一个 16 × 256 的向量
- 对得到的结果进行拼接, 得到 (1 + 4 + 16) × 256 = 21 × 256 个向量
代码实现:
import math
import torch
import torch.nn.functional as F
# 构建SPP层(空间金字塔池化层)
class SPPLayer(torch.nn.Module):
def __init__(self, num_levels, pool_type='max_pool'):
super(SPPLayer, self).__init__()
self.num_levels = num_levels
self.pool_type = pool_type
def forward(self, x):
num, c, h, w = x.size() # num:样本数量 batch_size c:通道数 h:高 w:宽
for i in range(self.num_levels):
level = i+1
kernel_size = (math.ceil(h / level), math.ceil(w / level))
stride = (math.ceil(h / level), math.ceil(w / level))
pooling = (math.floor((kernel_size[0]*level-h+1)/2), math.floor((kernel_size[1]*level-w+1)/2))
# 选择池化方式
if self.pool_type == 'max_pool':
tensor = F.max_pool2d(x, kernel_size=kernel_size, stride=stride, padding=pooling).view(num, -1)
else:
tensor = F.avg_pool2d(x, kernel_size=kernel_size, stride=stride, padding=pooling).view(num, -1)
# 展开、拼接
if (i == 0):
x_flatten = tensor.view(num, -1)
else:
x_flatten = torch.cat((x_flatten, tensor.view(num, -1)), 1)
return x_flatten
金字塔池化通过最大池化解决了固定图像尺寸的限制, 并提高了提取特征的效率.
RPN 网络
RPN (Region Proposal Network) 是一种快速筛选候选框的算法. RPN 是基于滑动窗口的目标检测器, 输入是任意尺度的图像, 输出是一系列矩形候选区域.
RPN 网络 由一个 3 × 3 的卷积层, 分成两个 1 × 1的卷积层. 如图:
RPN 分为两个部分:
- 判断物体还是背景 (2 × 9): 通过 IOU 阈值, 把 IOU > 0.7 的作为物体, IOU < 0.3 的作为背景
- 修正坐标 (4 × 9): 找到锚框 (Anchor Box) 和真实框的映射关系. 可以通过平移和缩放实现.
RPN 的优势在于可以帮助我们判断物体和背景, 并使得锚框更接近真实框.
ROI 池化 (2015)
ROI (Region of Interest Pooling) 是 SPP 池化的简化版.
从大小不同的框中提取特征使得输出结果是等大的:
从上图我们可以看到一个 8 × 8 的特征图.
我们希望从这个 7 × 5 的预选框中得到 2 × 2 的特征.
比起 R-CNN 的一刀切, ROI 会从分割的四块区域进行最大池化 (Max Pooling)
ROI 池化 SPP 池化:
- 两者都是用来把不同尺寸特征输入转化为相同尺寸特征输出
- ROI 池化相当于单尺度的 SPP, 对一个输入只进行一次池化操作
R-CNN (2013)
R-CNN (Region Based Convolutional Neural Networks) 是第一个成功将深度学习应用到目标检测上的算法.
R-CNN 流程:
- 在图像中使用选择性搜索 (Selective Search) 确定 1000~2000 个候选框
- 将每个候选框缩放到相同大小 (应为存在全连接层), 输入到 CNN 内进行特征提取
- 对候选框中提取出的特征, 使用回归器判别是否食欲一个特定类
- 对于某一类别的候选框, 用回归器进一步调整其位置
Fast R-CNN (2015)
Selective Search 提取候选框特征图送入 ROI 池化层 (简化版 SPP). Fast R-CNN 利用共享卷积层, 避免了每个候选框都进入 CNN. Fast R-CNN 把最后的 bbox regression 放进了神经网络内部, 与区域分类合并成为了一个 multi-task 模型实现端到端训练.
Faster R-CNN 流程:
- 在图像中使用选择性搜索 (Selective Search) 确定 1000~2000 个候选框
- 对整张图进行 CNN, 得到特征图 (feature map)
- 找到每个候选框在特征图上映射图像的一小块(patch), 将这一小块作为每个候选框的卷积特征输入到 SPP 层和之后的层
- 对候选框中提出的特征, 使用分类器判别是否属于一个特定类
- 对于属于某一类别的候选框, 用回归器进行进一步调整其位置
Faster R-CNN (2016)
Faster R-CNN 使用 RPN 提取候选框, 将特征图送入 ROI 池化层, 最后的 bbox regression 放进了神经网络内部, 与区域分类合并成为了一个 multi-task 模型实现端到端训练.
Faster R-CNN 流程:
- 对整张图进行 CNN, 得到特征图 (feature map)
- 卷积特征输入到 RPN, 得到候选框的特征信息
- 对候选框中提取出的特征, 使用分类器判别是否属于一个特定类
- 对于属于某一类的候选框, 用回归器进一步调整其位置
对比
Fast R-CNN vs R-CNN
Fast R-CNN 在 R-CNN 的基础上对整张图进行卷积得到特征图在用候选框映射. 使用 ROI 池化到统一大小, 并使用 softmax 分类替代了 SVM 和 bbox 回归.
Faster R-CNN vs Fast R-CNN
Faster R-CNN 在 Fast R-CNN 的基础上将特征抽取, 候选框提取, 候选框回归, 分类都整合到了一个网络中. 通过引入 RPN 代替原有的候选框生成方法, 大大提高了候选框的生成速度.
以上是关于一小时吃透 R-CNN & Fast R-CNN & Faster R-CNN的主要内容,如果未能解决你的问题,请参考以下文章