faster-rcnn中ROI_POOIING层的解读
在没有出现sppnet之前,RCNN使用corp和warp来对图片进行大小调整,这种操作会造成图片信息失真和信息丢失。sppnet这个模型推出来之后(关于这个网络的描述,可以看看之前写的一篇理解:http://www.cnblogs.com/gongxijun/p/7172134.html),rg大神沿用了sppnet的思路到他的下一个模型中fast-rcnn中,但是roi_pooling和sppnet的思路虽然相同,但是实现方式还是不同的.我们看一下网络参数:
- layer {
- name: "roi_pool5"
- type: "ROIPooling"
- bottom: "conv5_3"
- bottom: "rois"
- top: "pool5"
- roi_pooling_param {
- pooled_w:
- pooled_h:
- spatial_scale: 0.0625 # /
- }
结合源代码,作者借助了sppnet的空域金字塔pool方式,但是和sppnet并不同的是,作者在这里只使用了(pooled_w,pooled_h)这个尺度,来将得到的每一个特征图分成(pooled_w,pooled_h),然后对每一块进行max_pooling取值,最后得到一个n*7*7固定大小的特征图。
- // ------------------------------------------------------------------
- // Fast R-CNN
- // Copyright (c) 2015 Microsoft
- // Licensed under The MIT License [see fast-rcnn/LICENSE for details]
- // Written by Ross Girshick
- // ------------------------------------------------------------------
- #include <cfloat>
- #include "caffe/fast_rcnn_layers.hpp"
- using std::max;
- using std::min;
- using std::floor;
- using std::ceil;
- namespace caffe {
- template <typename Dtype>
- void ROIPoolingLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
- const vector<Blob<Dtype>*>& top) {
- ROIPoolingParameter roi_pool_param = this->layer_param_.roi_pooling_param();
- CHECK_GT(roi_pool_param.pooled_h(), )
- << "pooled_h must be > 0";
- CHECK_GT(roi_pool_param.pooled_w(), )
- << "pooled_w must be > 0";
- pooled_height_ = roi_pool_param.pooled_h(); //定义网络的大小
- pooled_width_ = roi_pool_param.pooled_w();
- spatial_scale_ = roi_pool_param.spatial_scale();
- LOG(INFO) << "Spatial scale: " << spatial_scale_;
- }
- template <typename Dtype>
- void ROIPoolingLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
- const vector<Blob<Dtype>*>& top) {
- channels_ = bottom[]->channels();
- height_ = bottom[]->height();
- width_ = bottom[]->width();
- top[]->Reshape(bottom[]->num(), channels_, pooled_height_,
- pooled_width_);
- max_idx_.Reshape(bottom[]->num(), channels_, pooled_height_,
- pooled_width_);
- }
- template <typename Dtype>
- void ROIPoolingLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
- const vector<Blob<Dtype>*>& top) {
- const Dtype* bottom_data = bottom[]->cpu_data();
- const Dtype* bottom_rois = bottom[]->cpu_data();//获取roidb信息(n,x1,y1,x2,y2)
- // Number of ROIs
- int num_rois = bottom[]->num();//候选目标的个数
- int batch_size = bottom[]->num();//特征图的维度,vgg16的conv5之后为512
- int top_count = top[]->count();//需要输出的值个数
- Dtype* top_data = top[]->mutable_cpu_data();
- caffe_set(top_count, Dtype(-FLT_MAX), top_data);
- int* argmax_data = max_idx_.mutable_cpu_data();
- caffe_set(top_count, -, argmax_data);
- // For each ROI R = [batch_index x1 y1 x2 y2]: max pool over R
- for (int n = ; n < num_rois; ++n) {
- int roi_batch_ind = bottom_rois[];
- int roi_start_w = round(bottom_rois[] * spatial_scale_);//缩小16倍,将候选区域在原始坐标中的位置,映射到conv_5特征图上
- int roi_start_h = round(bottom_rois[] * spatial_scale_);
- int roi_end_w = round(bottom_rois[] * spatial_scale_);
- int roi_end_h = round(bottom_rois[] * spatial_scale_);
- CHECK_GE(roi_batch_ind, );
- CHECK_LT(roi_batch_ind, batch_size);
- int roi_height = max(roi_end_h - roi_start_h + , );//得到候选区域在特征图上的大小
- int roi_width = max(roi_end_w - roi_start_w + , );
- const Dtype bin_size_h = static_cast<Dtype>(roi_height)
- / static_cast<Dtype>(pooled_height_);//计算如果需要划分成(pooled_height_,pooled_weight_)这么多块,那么每一个块的大小(bin_size_w,bin_size_h);
- const Dtype bin_size_w = static_cast<Dtype>(roi_width)
- / static_cast<Dtype>(pooled_width_);
- const Dtype* batch_data = bottom_data + bottom[]->offset(roi_batch_ind);//获取当前维度的特征图数据,比如一共有(n,x1,x2,x3,x4)的数据,拿到第一块特征图的数据
- for (int c = ; c < channels_; ++c) {
- for (int ph = ; ph < pooled_height_; ++ph) {
- for (int pw = ; pw < pooled_width_; ++pw) {
- // Compute pooling region for this output unit:
- // start (included) = floor(ph * roi_height / pooled_height_)
- // end (excluded) = ceil((ph + 1) * roi_height / pooled_height_)
- int hstart = static_cast<int>(floor(static_cast<Dtype>(ph)
- * bin_size_h)); //计算每一块的位置
- int wstart = static_cast<int>(floor(static_cast<Dtype>(pw)
- * bin_size_w));
- int hend = static_cast<int>(ceil(static_cast<Dtype>(ph + )
- * bin_size_h));
- int wend = static_cast<int>(ceil(static_cast<Dtype>(pw + )
- * bin_size_w));
- hstart = min(max(hstart + roi_start_h, ), height_);
- hend = min(max(hend + roi_start_h, ), height_);
- wstart = min(max(wstart + roi_start_w, ), width_);
- wend = min(max(wend + roi_start_w, ), width_);
- bool is_empty = (hend <= hstart) || (wend <= wstart);
- const int pool_index = ph * pooled_width_ + pw;
- if (is_empty) {
- top_data[pool_index] = ;
- argmax_data[pool_index] = -;
- }
- for (int h = hstart; h < hend; ++h) {
- for (int w = wstart; w < wend; ++w) {
- const int index = h * width_ + w;
- if (batch_data[index] > top_data[pool_index]) {
- top_data[pool_index] = batch_data[index]; //在取每一块中的最大值,就是max_pooling操作.
- argmax_data[pool_index] = index;
- }
- }
- }
- }
- }
- // Increment all data pointers by one channel
- batch_data += bottom[]->offset(, );
- top_data += top[]->offset(, );
- argmax_data += max_idx_.offset(, );
- }
- // Increment ROI data pointer
- bottom_rois += bottom[]->offset();
- }
- }
- template <typename Dtype>
- void ROIPoolingLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
- const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {
- NOT_IMPLEMENTED;
- }
- #ifdef CPU_ONLY
- STUB_GPU(ROIPoolingLayer);
- #endif
- INSTANTIATE_CLASS(ROIPoolingLayer);
- REGISTER_LAYER_CLASS(ROIPooling);
- } // namespace caffe
进过以上的操作过后,就得到了固定大小的特征图啦,然后就可以进行全连接操作了. 但愿我说明白了.
---完.
faster-rcnn中ROI_POOIING层的解读的更多相关文章
- 对faster rcnn 中rpn层的理解
1.介绍 图为faster rcnn的rpn层,接自conv5-3 图为faster rcnn 论文中关于RPN层的结构示意图 2 关于anchor: 一般是在最末层的 feature map 上再用 ...
- BiLSTM-CRF模型中CRF层的解读
转自: https://createmomo.github.io/ BiLSTM-CRF模型中CRF层的解读: 文章链接: 标题:CRF Layer on the Top of BiLSTM - 1 ...
- tensorflow object detection faster r-cnn 中keep_aspect_ratio_resizer是什么意思
如果小伙伴的英语能力强可以直接阅读这里:https://stackoverflow.com/questions/45137835/what-the-impact-of-different-dimens ...
- AI佳作解读系列(二)——目标检测AI算法集杂谈:R-CNN,faster R-CNN,yolo,SSD,yoloV2,yoloV3
1 引言 深度学习目前已经应用到了各个领域,应用场景大体分为三类:物体识别,目标检测,自然语言处理.本文着重与分析目标检测领域的深度学习方法,对其中的经典模型框架进行深入分析. 目标检测可以理解为是物 ...
- Domain Adaptive Faster R-CNN:经典域自适应目标检测算法,解决现实中痛点,代码开源 | CVPR2018
论文从理论的角度出发,对目标检测的域自适应问题进行了深入的研究,基于H-divergence的对抗训练提出了DA Faster R-CNN,从图片级和实例级两种角度进行域对齐,并且加入一致性正则化来学 ...
- 【深度学习】目标检测算法总结(R-CNN、Fast R-CNN、Faster R-CNN、FPN、YOLO、SSD、RetinaNet)
目标检测是很多计算机视觉任务的基础,不论我们需要实现图像与文字的交互还是需要识别精细类别,它都提供了可靠的信息.本文对目标检测进行了整体回顾,第一部分从RCNN开始介绍基于候选区域的目标检测器,包括F ...
- 利用FPN构建Faster R-CNN检测
FPN就是所谓的金字塔结构的检测器,(Feature Pyramid Network) 把FPN融合到Faster rcnn中能够很大程度增加检测器对全图信息的认知, 步骤如图所示: 1.先将图像送入 ...
- 第三十一节,目标检测算法之 Faster R-CNN算法详解
Ren, Shaoqing, et al. “Faster R-CNN: Towards real-time object detection with region proposal network ...
- faster rcnn 做识别
faster rcnn 主要分为四个部分: 1. convolutional part: 特征提取 可以使用vgg,resnet 等等 2.region proposal network: 生成 re ...
随机推荐
- 201521123060 《Java程序设计》第5周学习总结
1.本周学习总结 2.书面作业 Q1.代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误.并分析输出结果. 答:不能 ...
- 201521123063 《Java程序设计》第三周学习总结
1.本周学习总结 初学面向对象,会学习到很多碎片化的概念与知识.尝试学会使用思维导图将这些碎片化的概念.知识组织起来.请使用纸笔或者下面的工具画出本周学习到的知识点.截图或者拍照上传. 2.书面作业 ...
- informix服务端口和oralce服务端口
查找informix的服务端口1>>more .profile 找到: INFORMIXDIR=/home/informix INFORMIXSERVER=aaaa2>>cd ...
- virtualbox修改主机名
virtualbox修改主机名 /etc/hostname /etc/hosts
- geotrellis使用(三十三)关于Geotrellis读取Geotiff的两个细节
前言 在上两篇文章中我介绍了如何直接将Geotiff(一个或者多个)发布为TMS服务.这中间其实我遇到了一个问题,并且这个问题伴随Geotrellis的几乎所有使用案例,下面我进行详细讲述. 一.问题 ...
- String类的一些常见的比较方法(4)
1:boolean equals(Object obj); //比较字符穿的内容是否相同 区分大小写的 2:boolean equalsIgnoreCase(String str); //比较字符穿的 ...
- pycharm 2017新建文件添加编码方式等
file->setting->Editor->File and Code Templates->Python Script 添加 #!/usr/bin/python3# -*- ...
- Quartz源码——QuartzSchedulerThread.run() 源码分析(三)
QuartzSchedulerThread.run()是主要处理任务的方法!下面进行分析,方便自己查看! 我都是分析的jobStore 方式为jdbc的SimpleTrigger!RAM的方式类似分析 ...
- java集合系列——List集合之Stack介绍(五)
1.Stack的简介 Stack 类表示后进先出(LIFO)的对象堆栈.它通过五个操作对类 Vector 进行了扩展 ,允许将向量视为堆栈.它提供了通常的 push 和 pop 操作,以及取堆栈顶点的 ...
- APUE 4 - 线程
对传统的UNIX进程来讲,一个进程中只有一个线程,这就意味着一个进程在同一时刻只能做一件事(即使是多核CPU).使用多线程技术, 我们可以设计程序使得一个进程在同一时刻做多件事.使用多线程编程具有以下 ...