faster-rcnn代码阅读-rpn-data层
这一节讲述rpn-data层,和这一层有关的结构图如下:

rpn-data层的prototxt定义如下:
layer {
name: 'rpn-data'
type: 'Python'
bottom: 'rpn_cls_score'
bottom: 'gt_boxes'
bottom: 'im_info'
bottom: 'data'
top: 'rpn_labels'
top: 'rpn_bbox_targets'
top: 'rpn_bbox_inside_weights'
top: 'rpn_bbox_outside_weights'
python_param {
module: 'rpn.anchor_target_layer'
layer: 'AnchorTargetLayer'
param_str: "'feat_stride': 16"
}
}
这一层的主要工作如下:
一、生成anchor,并将超出图像区域的anchor去除,得到有效的anchor;
二、给每一个anchor分配label,-1表示忽略该anchor,0表示背景,1表示前景(物体),得到labels;
三、计算RPN阶段的回归目标bbox_targets;
四、计算bbox_inside_weights、bbox_outside_weights,在计算SmoothL1Loss时用于加权;
五、上述过程得到的labels, bbox_targets, bbox_inside_weights, bbox_outside_weights,它们第一个维度的长度和有效anchor的个数是相同的,最后对它们进行扩充,将无效的anchor所对应的labels, bbox_targets, bbox_inside_weights, bbox_outside_weights分别加入其中,使这四个输出第一个维度的长度等于生成anchor的个数。
下面分别介绍这5个部分。
一、生成anchor
1、先生成一个base_anchor,长宽都为16,得出base_anchor的宽高和中心点:w, h, x_ctr, y_ctr;
2、由基准尺度(base_size=16)和3种长宽比0.5, 1, 2计算出3种宽高,再由步骤1得到的中心点计算出3个anchor的坐标;
3、再将3种尺度8, 16, 32和步骤2所得anchor的尺度相乘,得出9种宽高,结合步骤1所得中心点坐标,最终得到9个anchor的坐标。
4、使backbone输出的feature map的每一个位置的坐标间隔为feature map的降采样率(VGG为16),这样,feature map像素坐标的尺度就和输入网络的图像像素的坐标尺度一样了。将步骤3所得到的9个anchor的中心点分别移动到feature map每个像素的坐标位置上,便得到了最终的anchor。
二、分配label
1、构建一个label数组,长度有效anchor的数量,每个元素都初始化为-1;
2、计算每个anchor和所有gt的交并比;
3、将和所有gt的交并比都小于0.3的anchor,label分配为0,即为背景;
4、将和每一个gt交并比最大的anchor,label分配为1,即为前景;
5、将和任意一个gt交并比能大于0.7的anchor,label分配为1,即为前景;
6、RPN阶段的batchsize为256,前景anchor占比为0.5,因此有128个。如果前面得到的前景anchor的数量超过了128,则随机剔除多余的anchor,剔除的部分label置为-1;
7、batchsize为256,除去前景anchor的数量,剩余的即为背景anchor的数量。若背景anchor数量过多,则随机剔除多余的背景,剔除的部分label仍置为-1。
三、计算RPN阶段的回归目标
回归目标其实就是anchor的中心点坐标、宽、高和与之交并比最大的gt的偏差dx, dy, dw, dh,这些偏差不是二者直接作差得到的,而是经过一些转换才得到的,具体见下面的代码:
def bbox_transform(ex_rois, gt_rois):
ex_widths = ex_rois[:, 2] - ex_rois[:, 0] + 1.0
ex_heights = ex_rois[:, 3] - ex_rois[:, 1] + 1.0
ex_ctr_x = ex_rois[:, 0] + 0.5 * ex_widths
ex_ctr_y = ex_rois[:, 1] + 0.5 * ex_heights gt_widths = gt_rois[:, 2] - gt_rois[:, 0] + 1.0
gt_heights = gt_rois[:, 3] - gt_rois[:, 1] + 1.0
gt_ctr_x = gt_rois[:, 0] + 0.5 * gt_widths
gt_ctr_y = gt_rois[:, 1] + 0.5 * gt_heights targets_dx = (gt_ctr_x - ex_ctr_x) / ex_widths
targets_dy = (gt_ctr_y - ex_ctr_y) / ex_heights
targets_dw = np.log(gt_widths / ex_widths)
targets_dh = np.log(gt_heights / ex_heights) targets = np.vstack(
(targets_dx, targets_dy, targets_dw, targets_dh)).transpose()
return targets
四、计算一些权重,用于SmoothL1Loss的计算
1、bbox_inside_weights:将label为1的anchor权重赋为1,其他的都赋为0;
2、bbox_outside_weights:将前景和背景anchor的总数记为n,则前景和背景anchor权重都赋为1/n,其它的anchor权重都赋为0。
五、结果扩充
这一步的目的是为了使这一层的输出结果的维度和其它层的结果相匹配,直接能和其它层的输出结合起来,一起参与网络的前向和反向计算。
最后给出SmoothL1Loss的主要代码:
template <typename Dtype>
void SmoothL1LossLayer<Dtype>::LayerSetUp(
const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
SmoothL1LossParameter loss_param = this->layer_param_.smooth_l1_loss_param();
sigma2_ = loss_param.sigma() * loss_param.sigma();
has_weights_ = (bottom.size() >= );
if (has_weights_) {
CHECK_EQ(bottom.size(), ) << "If weights are used, must specify both "
"inside and outside weights";
}
} template <typename Dtype>
void SmoothL1LossLayer<Dtype>::Reshape(
const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
LossLayer<Dtype>::Reshape(bottom, top);
CHECK_EQ(bottom[]->channels(), bottom[]->channels());
CHECK_EQ(bottom[]->height(), bottom[]->height());
CHECK_EQ(bottom[]->width(), bottom[]->width());
if (has_weights_) {
CHECK_EQ(bottom[]->channels(), bottom[]->channels());
CHECK_EQ(bottom[]->height(), bottom[]->height());
CHECK_EQ(bottom[]->width(), bottom[]->width());
CHECK_EQ(bottom[]->channels(), bottom[]->channels());
CHECK_EQ(bottom[]->height(), bottom[]->height());
CHECK_EQ(bottom[]->width(), bottom[]->width());
}
diff_.Reshape(bottom[]->num(), bottom[]->channels(),
bottom[]->height(), bottom[]->width());
errors_.Reshape(bottom[]->num(), bottom[]->channels(),
bottom[]->height(), bottom[]->width());
// vector of ones used to sum
ones_.Reshape(bottom[]->num(), bottom[]->channels(),
bottom[]->height(), bottom[]->width());
for (int i = ; i < bottom[]->count(); ++i) {
ones_.mutable_cpu_data()[i] = Dtype();
}
} template <typename Dtype>
__global__ void SmoothL1Forward(const int n, const Dtype* in, Dtype* out,
Dtype sigma2) {
// f(x) = 0.5 * (sigma * x)^2 if |x| < 1 / sigma / sigma
// |x| - 0.5 / sigma / sigma otherwise
CUDA_KERNEL_LOOP(index, n) {
Dtype val = in[index];
Dtype abs_val = abs(val);
if (abs_val < 1.0 / sigma2) {
out[index] = 0.5 * val * val * sigma2;
} else {
out[index] = abs_val - 0.5 / sigma2;
}
}
} template <typename Dtype>
void SmoothL1LossLayer<Dtype>::Forward_gpu(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
int count = bottom[]->count();
caffe_gpu_sub(
count,
bottom[]->gpu_data(),
bottom[]->gpu_data(),
diff_.mutable_gpu_data()); // d := b0 - b1
if (has_weights_) {
// apply "inside" weights
caffe_gpu_mul(
count,
bottom[]->gpu_data(),
diff_.gpu_data(),
diff_.mutable_gpu_data()); // d := w_in * (b0 - b1)
}
SmoothL1Forward<Dtype><<<CAFFE_GET_BLOCKS(count), CAFFE_CUDA_NUM_THREADS>>>(
count, diff_.gpu_data(), errors_.mutable_gpu_data(), sigma2_);
CUDA_POST_KERNEL_CHECK; if (has_weights_) {
// apply "outside" weights
caffe_gpu_mul(
count,
bottom[]->gpu_data(),
errors_.gpu_data(),
errors_.mutable_gpu_data()); // d := w_out * SmoothL1(w_in * (b0 - b1))
} Dtype loss;
caffe_gpu_dot(count, ones_.gpu_data(), errors_.gpu_data(), &loss);
top[]->mutable_cpu_data()[] = loss / bottom[]->num();
}
其中:
1、bottom[0]为rpn_bbox_pred,即网络预测出的anchor与gt的偏差;
2、bottom[1]为rpn_bbox_targets,即为第三步计算出的anchor与gt的实际偏差;
3、bottom[2]为bbox_inside_weights;
4、bottom[3]为bbox_outside_weights。
这一层的代码链接见这里,此外涉及到的其它函数有generate_anchors,bbox_overlaps。
faster-rcnn代码阅读-rpn-data层的更多相关文章
- Faster RCNN代码理解(Python)
转自http://www.infocool.net/kb/Python/201611/209696.html#原文地址 第一步,准备 从train_faster_rcnn_alt_opt.py入: 初 ...
- Faster rcnn代码理解(4)
上一篇我们说完了AnchorTargetLayer层,然后我将Faster rcnn中的其他层看了,这里把ROIPoolingLayer层说一下: 我先说一下它的实现原理:RPN生成的roi区域大小是 ...
- Faster rcnn代码理解(2)
接着上篇的博客,咱们继续看一下Faster RCNN的代码- 上次大致讲完了Faster rcnn在训练时是如何获取imdb和roidb文件的,主要都在train_rpn()的get_roidb()函 ...
- Faster RCNN代码解析
1.faster_rcnn_end2end训练 1.1训练入口及配置 def train(): cfg.GPU_ID = 0 cfg_file = "../experiments/cfgs/ ...
- Faster R-CNN论文阅读摘要
论文链接: https://arxiv.org/pdf/1506.01497.pdf 代码下载: https://github.com/ShaoqingRen/faster_rcnn (MATLAB) ...
- Faster R-CNN代码例子
主要参考文章:1,从编程实现角度学习Faster R-CNN(附极简实现) 经常是做到一半发现收敛情况不理想,然后又回去看看这篇文章的细节. 另外两篇: 2,Faster R-CNN学习总结 ...
- Faster rcnn代码理解(3)
紧接着之前的博客,我们继续来看faster rcnn中的AnchorTargetLayer层: 该层定义在lib>rpn>中,见该层定义: 首先说一下这一层的目的是输出在特征图上所有点的a ...
- Faster rcnn代码理解(1)
这段时间看了不少论文,回头看看,感觉还是有必要将Faster rcnn的源码理解一下,毕竟后来很多方法都和它有相近之处,同时理解该框架也有助于以后自己修改和编写自己的框架.好的开始吧- 这里我们跟着F ...
- tensorflow faster rcnn 代码分析一 demo.py
os.environ["CUDA_VISIBLE_DEVICES"]=2 # 设置使用的GPU tfconfig=tf.ConfigProto(allow_soft_placeme ...
- 对faster rcnn代码讲解的很好的一个
http://www.cnblogs.com/houkai/p/6824455.html http://blog.csdn.net/u014696921/article/details/6032142 ...
随机推荐
- 在SpringCloud中MAVEN配置文件中的更改
<mirrors> <mirror> <id>alimaven</id> <mirrorOf>central</mirrorOf> ...
- Yii2中GridView
Yii2 GridView与dropdownList结合的用法 http://www.yiichina.com/tutorial/473 <?=$form->field($model, ' ...
- 剑指offer——数组中出现次数超过一半的数字(c++)
题目描述数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2.如 ...
- Linux环境进程间通信----系统 V 消息队列(二)
一.消息队列是一条由消息连接而成的链表,它保存在内核中,通过消息队列的引用标示符来访问. 二.消息队列不同于管道,通信的两个进程可以是完全无关的进程,它们之间不需要约定同步的方法.只要消息队列存在并且 ...
- windows API 创建系统托盘图标
系统托盘在我们使用的程序中很普遍,下面我们来看一个很不错的例子,使用Win32 API实现,对理解系统托盘有些帮助. [cpp] view plaincopy #include <windows ...
- makefile.new(7117) : error U1087: cannot have : and :: dependents for same target
makefile.new(7117) : fatal error U1087: cannot have : and :: dependents for same target(2012-05-21 2 ...
- 使用linkedhashmap实现LRU(最近最少使用缓存算法)
import java.util.LinkedHashMap; import java.util.Map; public class LRUCache<K, V> extends Link ...
- js获取url中的中文参数出现乱码
解决方法 function getQueryString(key){ var reg = new RegExp("(^|&)"+key+"=([^&]*) ...
- maven surefire入门
一.maven常用命令: mvn compile mvn install mvn test mvn clean mvn dependency:resolve -X #查看完整的debug信息!!! ...
- 专题:『systemd』
[COMMAND] Systemd Daemons: systemd networkd journald logind "user session" Systemd units: ...