https://zhuanlan.zhihu.com/p/36095768

我的推断,第二第三阶段应该不是把所有anchor进行bounding box regression,然后再选取当前条件下的所有roi,而是第一阶段选取512个roi,然后把在第一阶段匹配好的roi送到第二、三阶段

layer {
name: "proposals_2nd"
type: "DecodeBBox"
bottom: "bbox_pred"
bottom: "rois"
bottom: "match_gt_boxes"
top: "proposals_2nd"
bbox_reg_param {
bbox_mean: 0 bbox_mean: 0 bbox_mean: 0 bbox_mean: 0
bbox_std: 0.1 bbox_std: 0.1 bbox_std: 0.2 bbox_std: 0.2
}
propagate_down: 0
propagate_down: 0
propagate_down: 0
}

这段代码就证明了这个想法:rois来自于第一阶段proposal_info,这些rois也是在第一阶段做roi-pooling用来训练的。

个人感觉cascade的模型就是4张图提取512个roi进行训练,然后经过第一阶段训练后,把这512个roi经过回归精修然后去除回归后x1大于x2和y1大于y2的和回归后和gt的iou大于0.95的,这样roi可能就没有512个了.把这些输入给第二阶段的proposal_info_2nd,让这个层再去决定训练样本,这样大可能训练的数据是不足512,并且3个阶段其实都是训练的同一个批roi,也就是说第一阶段进去的那些roi,后面几个阶段实际上也在训练他们,而不是新出来的框DecodeBbox层的输入是bbox_pred,rois和match_gt_boxes.首先明确一点,rpn网络会输出很多proposals出来,ProposalTarget层将这些proposals和gt算iou,确定正负样本并选取1:3的比例,然后输出rois,rois就是拿来具体训练的从rpn中获得那部分预提取框.DecodeBbox层就是将这些原本的rois回归成更精准的框,也就是在原始的rois的坐标上增加经过训练得到的回归的值,这个是通过DecodeBBoxesWithPrior函数实现.DecodeBbox层分为大致3个步骤:1.回归得到更精准的rois  2.去掉回归后x1大于x2和y1大于y2的框  3.去掉回归后和gt的iou大于0.95的框
这部分的结果

#include <cfloat>
#include <vector> #include "caffe/util/bbox_util.hpp"
#include "caffe/layers/decode_bbox_layer.hpp" namespace caffe { template <typename Dtype>
void DecodeBBoxLayer<Dtype>::LayerSetUp(
const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
// bbox mean and std
BBoxRegParameter bbox_reg_param = this->layer_param_.bbox_reg_param();
bbox_mean_.Reshape(,,,); bbox_std_.Reshape(,,,);
if (bbox_reg_param.bbox_mean_size() > && bbox_reg_param.bbox_std_size() > ) {
int num_means = this->layer_param_.bbox_reg_param().bbox_mean_size();
int num_stds = this->layer_param_.bbox_reg_param().bbox_std_size();
CHECK_EQ(num_means,); CHECK_EQ(num_stds,);
for (int i = ; i < ; i++) {
bbox_mean_.mutable_cpu_data()[i] = bbox_reg_param.bbox_mean(i);
bbox_std_.mutable_cpu_data()[i] = bbox_reg_param.bbox_std(i);
CHECK_GT(bbox_std_.mutable_cpu_data()[i],);
}
} else {
caffe_set(bbox_mean_.count(), Dtype(), bbox_mean_.mutable_cpu_data());
caffe_set(bbox_std_.count(), Dtype(), bbox_std_.mutable_cpu_data());
}
} template <typename Dtype>
void DecodeBBoxLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
// bottom: bbox_blob, prior_blob, (match_gt_boxes)
CHECK_EQ(bottom[]->num(),bottom[]->num());
if (bottom.size()>=) {
CHECK_EQ(bottom[]->num(),bottom[]->num());
CHECK(this->phase_ == TRAIN);
}
CHECK_EQ(bottom[]->channels(),);
CHECK_EQ(bottom[]->channels(),);
bbox_pred_.ReshapeLike(*bottom[]);
top[]->ReshapeLike(*bottom[]);
} template <typename Dtype>
void DecodeBBoxLayer<Dtype>::Forward_cpu(
const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
const int num = bottom[]->num();
const int bbox_dim = bottom[]->channels();
const int prior_dim = bottom[]->channels(); //decode prior box [img_id x1 y1 x2 y2]
const Dtype* prior_data = bottom[]->cpu_data();
vector<BBox> prior_bboxes;
for (int i = ; i < num; i++) {
BBox bbox;
bbox.xmin = prior_data[i*prior_dim + ];
bbox.ymin = prior_data[i*prior_dim + ];
bbox.xmax = prior_data[i*prior_dim + ];
bbox.ymax = prior_data[i*prior_dim + ];
prior_bboxes.push_back(bbox);
} // decode bbox predictions
const Dtype* bbox_data = bottom[]->cpu_data();
Dtype* bbox_pred_data = bbox_pred_.mutable_cpu_data(); DecodeBBoxesWithPrior(bbox_data,prior_bboxes,bbox_dim,bbox_mean_.cpu_data(),
bbox_std_.cpu_data(),bbox_pred_data); vector<bool> valid_bbox_flags(num,true);
// screen out mal-boxes
if (this->phase_ == TRAIN) {
for (int i = ; i < num; i++) {
const int base_index = i*bbox_dim+;
if (bbox_pred_data[base_index] > bbox_pred_data[base_index+]
|| bbox_pred_data[base_index+] > bbox_pred_data[base_index+]) {
valid_bbox_flags[i] = false;
}
}
}
// screen out high IoU boxes, to remove redundant gt boxes
if (bottom.size()== && this->phase_ == TRAIN) {
const Dtype* match_gt_boxes = bottom[]->cpu_data();
const int gt_dim = bottom[]->channels();
const float gt_iou_thr = this->layer_param_.decode_bbox_param().gt_iou_thr();
for (int i = ; i < num; i++) {
const float overlap = match_gt_boxes[i*gt_dim+gt_dim-];
if (overlap >= gt_iou_thr) {
valid_bbox_flags[i] = false;
}
}
} vector<int> valid_bbox_ids;
for (int i = ; i < num; i++) {
if (valid_bbox_flags[i]) {
valid_bbox_ids.push_back(i);
}
}
const int keep_num = valid_bbox_ids.size();
CHECK_GT(keep_num,); top[]->Reshape(keep_num, prior_dim, , );
Dtype* decoded_bbox_data = top[]->mutable_cpu_data();
for (int i = ; i < keep_num; i++) {
const int keep_id = valid_bbox_ids[i];
const int base_index = keep_id*bbox_dim+;
decoded_bbox_data[i*prior_dim] = prior_data[keep_id*prior_dim];
decoded_bbox_data[i*prior_dim+] = bbox_pred_data[base_index];
decoded_bbox_data[i*prior_dim+] = bbox_pred_data[base_index+];
decoded_bbox_data[i*prior_dim+] = bbox_pred_data[base_index+];
decoded_bbox_data[i*prior_dim+] = bbox_pred_data[base_index+];
}
} INSTANTIATE_CLASS(DecodeBBoxLayer);
REGISTER_LAYER_CLASS(DecodeBBox); } // namespace caffe

DecodeBBoxesWithPrior函数在bbox_util.cpp里实现,完成的功能就是把bounding box regression的结果对输入的prior_bbox(其实就是faster中的输入的region proposal)进行回归获得更精确的框坐标,然后存储在pred_data

template <typename Dtype>
void DecodeBBoxesWithPrior(const Dtype* bbox_data, const vector<BBox> prior_bboxes,
const int bbox_dim, const Dtype* means, const Dtype* stds,
Dtype* pred_data) {
const int num = prior_bboxes.size();
const int cls_num = bbox_dim/;
for (int i = ; i < num; i++) {
Dtype pw, ph, cx, cy;
pw = prior_bboxes[i].xmax-prior_bboxes[i].xmin+;
ph = prior_bboxes[i].ymax-prior_bboxes[i].ymin+;
cx = 0.5*(prior_bboxes[i].xmax+prior_bboxes[i].xmin);
cy = 0.5*(prior_bboxes[i].ymax+prior_bboxes[i].ymin);
for (int c = ; c < cls_num; c++) {
Dtype bx, by, bw, bh;
// bbox de-normalization
bx = bbox_data[i*bbox_dim+*c]*stds[]+means[];
by = bbox_data[i*bbox_dim+*c+]*stds[]+means[];
bw = bbox_data[i*bbox_dim+*c+]*stds[]+means[];
bh = bbox_data[i*bbox_dim+*c+]*stds[]+means[]; Dtype tx, ty, tw, th;
tx = bx*pw+cx; ty = by*ph+cy;
tw = pw*exp(bw); th = ph*exp(bh);
tx -= (tw-)/; ty -= (th-)/;
pred_data[i*bbox_dim+*c] = tx;
pred_data[i*bbox_dim+*c+] = ty;
pred_data[i*bbox_dim+*c+] = tx+tw-;
pred_data[i*bbox_dim+*c+] = ty+th-;
}
}
}

cascade DecodeBBox层的更多相关文章

  1. cascade rcnn论文总结

    1.bouding box regression总结: rcnn使用l2-loss 首先明确l2-loss的计算规则: L∗=(f∗(P)−G∗)2,∗代表x,y,w,h    整个loss : L= ...

  2. Django---进阶3

    目录 无名有名分组反向解析 路由分发 名称空间(了解) 伪静态(了解) 虚拟环境(了解) django版本区别 视图层 三板斧 JsonResponse对象 form表单上传文件及后端如何操作 req ...

  3. Django学习day04随堂笔记

    每日测验 """ 今日考题 1.列举你知道的orm数据的增删改查方法 2.表关系如何判定,django orm中如何建立表关系,有什么特点和注意事项 3.请画出完整的dj ...

  4. 66、django之模型层(model)--多表相关操作(图书管理小练习)

    前面几篇随笔的数据库增删改查操作都是在单表的操作上的,然而现实中不可能都是单表操作,更多的是多表操作,一对一,一对多,多对多的表结构才是我们经常需要处理的,本篇将带我们了解多表操作的一些相关操作.也会 ...

  5. 【Django】模型层说明

    [Django模型层] 之前大概介绍Django的文章居然写了两篇..这篇是重点关注了Django的模型层来进行学习. ■ 模型定义 众所周知,Django中的模型定义就是定义一个类,其基本结构是这样 ...

  6. 一 Django模型层简介(一)

    模型 django提供了一个强大的orm(关系映射模型)系统. 模型包含了你要在数据库中创建的字段信息及对数据表的一些操作 使用模型 定义好模型后,要告诉django使用这些模型,你要做的就是在配置文 ...

  7. 二 Djano模型层之模型字段选项

    字段选项 以下参数是全部字段类型都可用的,而且是可选的 null 如果为True,Django将在数据库中将空值存储为NULL.默认值为False 对于字符串字段,如果设置了null=True意味着& ...

  8. WEB框架-Django框架学习(二)- 模型层

    今日份整理为模型层 1.ORM简介 MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库, ...

  9. django 模型层(2)

    Django 模型层(2) 多表操作---模型之间的关系 1 一对一:作者----作者详细信息 2 一对多:书籍----出版社 3 多对多:书籍----作者 一  创建模型(主键(id)自动创建) 没 ...

随机推荐

  1. elastic 常用查询操作

    _ GET      http://127.0.0.1:9200/_cat/health?v  健康状况 GET      http://127.0.0.1:9200/_cat/indices?v  ...

  2. mysql 显示树结构表的节点全路径

    SELECT TYPEID AS TYPEID, pTYPEID AS 父TYPEID, levels AS 父到子之间级数, concat(paths, ',', TYPEID) AS 父到子路径, ...

  3. 【温故知新】c#抽象类abstract与接口interface

    1.什么是抽象类 先来看MSDN对抽象类描述: 抽象类是一些留有部分或全部成员未实现的类,以便可以由派生类来提供实现. 在面向对象的编程中,抽象类用作层次结构的基类,并表示不同对象类型组的通用功能.  ...

  4. TOJ 1885 Triangles

    Description It is always very nice to have little brothers or sisters. You can tease them, lock them ...

  5. URAL 1252 ——Sorting the Tombstones——————【gcd的应用】

    Sorting the Tombstones Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I ...

  6. 《Python编程从入门到实践》_第三章_列表简介

    什么是列表呢? 官方说明就是由一些列按特点顺序排列的元素组成.其实可以看出很多个字符串的有序组合吧,里面的内容可以随时的删除,增加,修改. 下面这个就是一个列表,python打印列表的时候会将中括号和 ...

  7. C#自定义控件 在 Toolbox显示不了的问题

    1) Close your solution2) Tools->Options->"Windows Form Designer" - find AutoToolboxP ...

  8. flask在centos下搭建web服务【uwsgi,nginx】

    centos操作系统 uWSGI是一个web服务器,Nginx进行反向代理的其实跟这些服务器可以说没有任何关系,你提供动态内容的服务器可以是apache/nginx/tomcat,当然也可以是uWSG ...

  9. 写C#代码时用到的中文简体字 、繁体字 对应的转化 (收藏吧)

    简体字    下面有与之对应的繁体字 private const String Jian = "啊阿埃挨哎唉哀皑癌蔼矮艾碍爱隘鞍氨安俺按暗岸胺案肮昂盎凹敖熬翱袄傲奥懊澳芭捌扒叭吧笆疤巴拔跋靶 ...

  10. 彻底消除wine中文乱码,QQ,kugoo等等....

    原文链接:http://forum.ubuntu.org.cn/viewtopic.php?t=290155 lendylongli wine下中文的配置方案步骤:1. 初始设置运行 winecfg, ...