一文读懂Faster RCNN - 白裳的文章 - 知乎 https://zhuanlan.zhihu.com/p/31426458
fasterrcnn面向的任务
fasterrcnn的任务是目标检测, 属于fastrcnn系列, 该系列通常与yolo系列作为对比.
fasterrcnn属于两阶段检测的实现方式, 完成了端到端的处理, 而且效率和准确率大大优于之前的fastrcnn系列.

上图, 网络整体结构
这部分是基于预训练模型(VGG16), 目的是提取图像特征feature map, 之后的处理共享了这些特征.
代码思路: 1, 将图片进行尺寸上的放缩. 2, 使用vgg提取特征, 在提取过程中, 图片经过4次下采样, 最终输出的尺寸变为1/16倍, 深度变为16倍.

RPN模型, 这是论文的核心, 使用RPN来生成检测框, 正因为它的存在fasterrcnn的效率才如此地高.
RPN网络实际分为2条线,上面一条通过softmax分类anchors获得positive和negative分类, 下面一条用于计算对于anchors的bounding box regression偏移量,以获得精确的proposal. 而最后的Proposal层则负责综合positive anchors和对应bounding box regression偏移量获取proposals,同时剔除太小和超出边界的proposals。其实整个网络到了Proposal Layer这里,就完成了相当于目标定位的功能。
代码思路:
其实RPN最终就是在原图尺度上,设置了密密麻麻的候选Anchor。然后用cnn去判断哪些Anchor是里面有目标的positive anchor,哪些是没目标的negative anchor。所以,仅仅是个二分类而已!
- anchor归回
使postive anchor 更接近ground true, 实现是对每个anchor重构出4个位置偏移参数进行学习.
# anchor偏移量回归def __init__():self.conv1 = nn.Conv2d(in_channels, mid_channels, 3, 1, 1)self.loc = nn.Conv2d(mid_channels, n_anchor * 4, 1, 1, 0)def forward(self, x): ## 将vgg的输出进行conv1x1卷积,论文中mid_channels = 512h = F.relu(self.conv1(x))# (b,c,h,w) -> (b,4*n_anchor,h,w), 深度变为四倍的原因是重构出每个特征点对应的anchors的四个位置偏移.rpn_locs = self.loc(h)# (b,4*n_anchor,h,w) -> (b,h,w,4*n_anchor) --view重构-> (b,h*w*n_anchor,4)rpn_locs = rpn_locs.permute(0, 2, 3, 1).contiguous().view(n, -1, 4) # 得到所有anchor的四个位置偏移.# 将rpn_locs 传给Proposal模块

- anchor分类
将每个特征点的ahchor做一个二分类, 判别是前景还是背景. 原论文使用softmax做二分类,故每个anchor对应两个输出概率. 如果使用logistic的话, 每个anchor指对应一个输出概率, 原理是一样的.
实现: 对每个anchor重构出2个softmax概率输出.
# 前背景分类def __init__():self.conv1 = nn.Conv2d(in_channels, mid_channels, 3, 1, 1)self.score = nn.Conv2d(mid_channels, n_anchor * 2, 1, 1, 0)def forward(self,x):# 将vgg的输出进行conv1x1卷积,论文中mid_channels = 512h = F.relu(self.conv1(x))# (b,n_anchor,h,w) -> (b,2*n_anchor,h,w). 由softmax分类,每个anchor对应2个概率输出.rpn_scores = self.score(h)# (b,2*n_anchor,h,w) -> (b,h,w,2*n_anchor)rpn_scores = rpn_scores.permute(0, 2, 3, 1).contiguous()# (b,h,w,2*n_anchor) --重构--> (b, h, w, n_anchor, 2) 计算softmaxrpn_softmax_scores = F.softmax(rpn_scores.view(n, hh, ww, n_anchor, 2), dim=4)rpn_fg_scores = rpn_softmax_scores[:, :, :, :, 1].contiguous() # 得到前景的分类概率# (b, hh, ww, n_anchor, 2) --重构->(b,hh*ww*n_anchor*2) 得到所有anchor的前景分类概率rpn_fg_scores = rpn_fg_scores.view(n, -1)# (n*hh*ww*n_anchor, 2)--重构--> (b,h*w*n_anchor,2)rpn_scores = rpn_scores.view(n, -1, 2) # 得到每一张feature map上所有anchor的分类输出值# rpn_scores 传递给Proposal模块
