概述

R-CNN 家族是一个 two-stage 的目标检测算法.

一小时吃透 R-CNN & Fast R-CNN & Faster R-CNN_目标检测

目标检测算法

一小时吃透 R-CNN & Fast R-CNN & Faster R-CNN_原力计划_02
三大分类:

  • 传统的目标检测算法:
    • 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 把图片统一缩放到一定的大小, 从而失去了多尺寸的信息的问题.
一小时吃透 R-CNN & Fast R-CNN & Faster R-CNN_卷积_03

如图, 特征图通道数为 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 个向量

一小时吃透 R-CNN & Fast R-CNN & Faster R-CNN_卷积_04
代码实现:

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 是基于滑动窗口的目标检测器, 输入是任意尺度的图像, 输出是一系列矩形候选区域.
一小时吃透 R-CNN & Fast R-CNN & Faster R-CNN_目标检测_05
RPN 网络 由一个 3 × 3 的卷积层, 分成两个 1 × 1的卷积层. 如图:
一小时吃透 R-CNN & Fast R-CNN & Faster R-CNN_JAVA_06
RPN 分为两个部分:

  1. 判断物体还是背景 (2 × 9): 通过 IOU 阈值, 把 IOU > 0.7 的作为物体, IOU < 0.3 的作为背景
  2. 修正坐标 (4 × 9): 找到锚框 (Anchor Box) 和真实框的映射关系. 可以通过平移和缩放实现.

RPN 的优势在于可以帮助我们判断物体和背景, 并使得锚框更接近真实框.

ROI 池化 (2015)

ROI (Region of Interest Pooling) 是 SPP 池化的简化版.
一小时吃透 R-CNN & Fast R-CNN & Faster R-CNN_原力计划_07
从大小不同的框中提取特征使得输出结果是等大的:
一小时吃透 R-CNN & Fast R-CNN & Faster R-CNN_卷积_08
从上图我们可以看到一个 8 × 8 的特征图.
一小时吃透 R-CNN & Fast R-CNN & Faster R-CNN_原力计划_09
我们希望从这个 7 × 5 的预选框中得到 2 × 2 的特征.
一小时吃透 R-CNN & Fast R-CNN & Faster R-CNN_池化_10
比起 R-CNN 的一刀切, ROI 会从分割的四块区域进行最大池化 (Max Pooling)
一小时吃透 R-CNN & Fast R-CNN & Faster R-CNN_JAVA_11
ROI 池化 SPP 池化:

  • 两者都是用来把不同尺寸特征输入转化为相同尺寸特征输出
  • ROI 池化相当于单尺度的 SPP, 对一个输入只进行一次池化操作
R-CNN (2013)

R-CNN (Region Based Convolutional Neural Networks) 是第一个成功将深度学习应用到目标检测上的算法.

一小时吃透 R-CNN & Fast R-CNN & Faster R-CNN_卷积_12

R-CNN 流程:

  1. 在图像中使用选择性搜索 (Selective Search) 确定 1000~2000 个候选框
  2. 将每个候选框缩放到相同大小 (应为存在全连接层), 输入到 CNN 内进行特征提取
  3. 对候选框中提取出的特征, 使用回归器判别是否食欲一个特定类
  4. 对于某一类别的候选框, 用回归器进一步调整其位置
Fast R-CNN (2015)

Selective Search 提取候选框特征图送入 ROI 池化层 (简化版 SPP). Fast R-CNN 利用共享卷积层, 避免了每个候选框都进入 CNN. Fast R-CNN 把最后的 bbox regression 放进了神经网络内部, 与区域分类合并成为了一个 multi-task 模型实现端到端训练.

一小时吃透 R-CNN & Fast R-CNN & Faster R-CNN_JAVA_13

Faster R-CNN 流程:

  1. 在图像中使用选择性搜索 (Selective Search) 确定 1000~2000 个候选框
  2. 对整张图进行 CNN, 得到特征图 (feature map)
  3. 找到每个候选框在特征图上映射图像的一小块(patch), 将这一小块作为每个候选框的卷积特征输入到 SPP 层和之后的层
  4. 对候选框中提出的特征, 使用分类器判别是否属于一个特定类
  5. 对于属于某一类别的候选框, 用回归器进行进一步调整其位置
Faster R-CNN (2016)

Faster R-CNN 使用 RPN 提取候选框, 将特征图送入 ROI 池化层, 最后的 bbox regression 放进了神经网络内部, 与区域分类合并成为了一个 multi-task 模型实现端到端训练.
一小时吃透 R-CNN & Fast R-CNN & Faster R-CNN_原力计划_14
Faster R-CNN 流程:

  1. 对整张图进行 CNN, 得到特征图 (feature map)
  2. 卷积特征输入到 RPN, 得到候选框的特征信息
  3. 对候选框中提取出的特征, 使用分类器判别是否属于一个特定类
  4. 对于属于某一类的候选框, 用回归器进一步调整其位置
对比

一小时吃透 R-CNN & Fast R-CNN & Faster R-CNN_目标检测_15

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_池化_16