赞
踩
参考综述文章:
论文笔记-2019-Object Detection in 20 Years: A Survey
基于深度学习的目标检测算法综述(一)
基于深度学习的目标检测算法综述(二)
基于深度学习的目标检测算法综述(三)
优秀的GitHub仓库:
deep learning object detection
Awesome Object Detection
比较全面的整理:
我这两年的目标检测
最全目标检测相关资料整理
我这两年收藏的目标检测好文分享
RCNN的思想:
SPPNet的结构如下图:
SPPNet的特点是在最后一个卷积层后,接入了金字塔池化层,使用这种方式,可以让网络输入任意的图片,而且还会生成固定大小的输出。
金字塔池化:以下图为例,黑色图片代表卷积之后的特征图,接着我们以不同大小的块来提取特征,分别是4x4,2x2,1x1,将这三张网格放到下面这张特征图上,就可以得到16+4+1=21种不同的块(Spatial bins),我们从这21个块中,每个块提取出一个特征,这样刚好就是我们要提取的21维特征向量。这种以不同的大小格子的组合方式来池化的过程就是空间金字塔池化(SPP)
综上所述,SPPNet的训练过程如下:
空间金字塔池化层代码实现:
#coding=utf-8 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:样本数量 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)
Fast RCNN总体结构;
Fast RCNN相比于RCNN的改进之处主要有三点:
RoIPooling:对于每一个虚线窗口内的特征图,,SPP Layer采用多个尺度的池化层进行池化操作;而RoI pooling层则采用一种尺度的池化层进行下采样,将每个RoI区域的卷积特征分成4*4个bin,然后对每个bin内采用max pooling,这样就得到一共16维的特征向量。如下图所示:
多任务损失函数(Multi-task Loss):Fast R-CNN统一了类别输出任务和候选框回归任务,有两个损失函数:分类损失和回归损失。分类采用softmax代替SVM进行分类,共输出N(类别)+1(背景)类。softmax由于引入了类间竞争,所以分类效果优于SVM,SVM在R-CNN中用于二分类。回归损失输出的是4*N(类别),4表示的是(x,y,w,h分别表示候选框的中心坐标和宽、高)。
SVD对全连接层进行分解:由于一张图像约产生2000个RoI,将近一半多的时间用在全连接层计算,为了提高运算速度,可以用SVD(奇异值分解)对全连接层进行变换来提高运算速度。一个大的矩阵可以近似分解为三个小矩阵的乘积,分解后的矩阵的元素数目远小于原始矩阵的元素数目,从而达到减少计算量的目的。通过对全连接层的权值矩阵进行SVD分解,使得处理一张图像的速度明显提升。
综上所述,Fast RCNN的主要流程如下:
参考文章:
睿智的目标检测27——Pytorch搭建Faster R-CNN目标检测平台
捋一捋pytorch官方FasterRCNN代码
Faster RCNN的总体结构如下;
相比于Fast RCNN,Faster RCNN主要的改进有两点:
RPN(Region Proposal Network):RPN可以理解为一种全卷积网络,最终目的是前景背景分类 + 框位置的回归。之前得到的特征图有两个应用,一个是和ROIPooling结合使用、另一个是进行一次3x3的卷积后,进行一个18通道的1x1卷积,还有一个36通道的1x1卷积。
在Faster RCNN中,Anchor先验框的数量就是9,所以两个1x1卷积的结果实际上也就是:
class RegionProposalNetwork(nn.Module): def __init__( self, in_channels=512, mid_channels=512, ratios=[0.5, 1, 2], anchor_scales=[8, 16, 32], feat_stride=16, mode = "training", ): super(RegionProposalNetwork, self).__init__() self.anchor_base = generate_anchor_base(anchor_scales=anchor_scales, ratios=ratios) # 步长,压缩的倍数 self.feat_stride = feat_stride self.proposal_layer = ProposalCreator(mode) # 每一个网格上默认先验框的数量 n_anchor = self.anchor_base.shape[0] # 先进行一个3x3的卷积 self.conv1 = nn.Conv2d(in_channels, mid_channels, 3, 1, 1) # 分类预测先验框内部是否包含物体 self.score = nn.Conv2d(mid_channels, n_anchor * 2, 1, 1, 0) # 回归预测对先验框进行调整 self.loc = nn.Conv2d(mid_channels, n_anchor * 4, 1, 1, 0) normal_init(self.conv1, 0, 0.01) normal_init(self.score, 0, 0.01) normal_init(self.loc, 0, 0.01) def forward(self, x, img_size, scale=1.): n, _, hh, ww = x.shape # 对共享特征层进行一个3x3的卷积 h = F.relu(self.conv1(x)) # 回归预测 rpn_locs = self.loc(h) rpn_locs = rpn_locs.permute(0, 2, 3, 1).contiguous().view(n, -1, 4) # 分类预测 rpn_scores = self.score(h) rpn_scores = rpn_scores.permute(0, 2, 3, 1).contiguous().view(n, -1, 2) # 进行softmax rpn_softmax_scores = F.softmax(rpn_scores, dim=-1) rpn_fg_scores = rpn_softmax_scores[:, :, 1].contiguous() rpn_fg_scores = rpn_fg_scores.view(n, -1) rpn_scores = rpn_scores.view(n, -1, 2)
综上所述,Fast RCNN的步骤如下:
下图展示了4种利用特征的形式:
FPN算法大致结构如下图:一个自底向上的线路,一个自顶向下的线路,横向连接(lateral connection)。图中放大的区域就是横向连接,这里1*1的卷积核的主要作用是减少卷积核的个数,也就是减少了feature map的个数,并不改变feature map的尺寸大小。
综上所述,FPN算法的主要流程如下:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。