prior_box层
https://www.jianshu.com/p/5195165bbd06
1.step_w、step_h其实就相当于faster中的feat_stride,也就是把这些点从feature map映射回原图,同时也可以看出min_size、max_size这些都是直接在针对原图来讲的
2.以mobileNet-ssd为例子:https://github.com/chuanqi305/MobileNet-SSD/blob/master/train.prototxt
layer {
name: "conv11_mbox_priorbox"
type: "PriorBox"
bottom: "conv11"
bottom: "data"
top: "conv11_mbox_priorbox"
prior_box_param {
min_size: 60.0
aspect_ratio: 2.0
flip: true
clip: false
variance: 0.1
variance: 0.1
variance: 0.2
variance: 0.2
offset: 0.5
}
}
layer {
name: "conv13_mbox_priorbox"
type: "PriorBox"
bottom: "conv13"
bottom: "data"
top: "conv13_mbox_priorbox"
prior_box_param {
min_size: 105.0
max_size: 150.0
aspect_ratio: 2.0
aspect_ratio: 3.0
flip: true
clip: false
variance: 0.1
variance: 0.1
variance: 0.2
variance: 0.2
offset: 0.5
}
}
只有conv11的anchor个数是3,其他5层都是6,原因是conv11只有min_size,没有max_size,并且aspect_ratio只有1个,其他5层都是两个,也就是说conv11是1+1*2=3,其他5层是1+1+2*2=6
prior_box_layer.cpp里,aspect_ratios_根据这层的param存储相应的aspect ratio.如果flip为true,param里一个aspect ratio就要存储他本身和他的倒数两个值
aspect_ratios_.clear();
aspect_ratios_.push_back(.);
flip_ = prior_box_param.flip();
for (int i = ; i < prior_box_param.aspect_ratio_size(); ++i) {
float ar = prior_box_param.aspect_ratio(i);
bool already_exist = false;
for (int j = ; j < aspect_ratios_.size(); ++j) { //检查是否有重复的
if (fabs(ar - aspect_ratios_[j]) < 1e-) {
already_exist = true;
break;
}
}
if (!already_exist) {
aspect_ratios_.push_back(ar); //如果flip为true,存储aspect ratio和他的倒数,否则只存储aspect ratio本身
if (flip_) {
aspect_ratios_.push_back(./ar);
}
}
}
对于每个点,先计算以min_size为长宽的正方形这个anchor;然后如果有max_size,计算以sqrt(min_size_ * max_size_)为长宽的正方形;然后计算aspect_ratios_中所有的aspect ratios,然后以这个aspect ratios计算box_width = min_size_ * sqrt(ar)和box_height = min_size_ / sqrt(ar),prototxt中的param里,一个ratio要存储他和他的倒数,这样一个ratio就要求两个anchor
for (int h = ; h < layer_height; ++h) {
for (int w = ; w < layer_width; ++w) {
float center_x = (w + offset_) * step_w;
float center_y = (h + offset_) * step_h;
float box_width, box_height;
for (int s = ; s < min_sizes_.size(); ++s) {
int min_size_ = min_sizes_[s];
// first prior: aspect_ratio = 1, size = min_size
box_width = box_height = min_size_;
// xmin
top_data[idx++] = (center_x - box_width / .) / img_width;
// ymin
top_data[idx++] = (center_y - box_height / .) / img_height;
// xmax
top_data[idx++] = (center_x + box_width / .) / img_width;
// ymax
top_data[idx++] = (center_y + box_height / .) / img_height; if (max_sizes_.size() > ) {
CHECK_EQ(min_sizes_.size(), max_sizes_.size());
int max_size_ = max_sizes_[s];
// second prior: aspect_ratio = 1, size = sqrt(min_size * max_size)
box_width = box_height = sqrt(min_size_ * max_size_);
// xmin
top_data[idx++] = (center_x - box_width / .) / img_width;
// ymin
top_data[idx++] = (center_y - box_height / .) / img_height;
// xmax
top_data[idx++] = (center_x + box_width / .) / img_width;
// ymax
top_data[idx++] = (center_y + box_height / .) / img_height;
} // rest of priors
for (int r = ; r < aspect_ratios_.size(); ++r) {
float ar = aspect_ratios_[r];
if (fabs(ar - .) < 1e-) {
continue;
}
box_width = min_size_ * sqrt(ar);
box_height = min_size_ / sqrt(ar);
// xmin
top_data[idx++] = (center_x - box_width / .) / img_width;
// ymin
top_data[idx++] = (center_y - box_height / .) / img_height;
// xmax
top_data[idx++] = (center_x + box_width / .) / img_width;
// ymax
top_data[idx++] = (center_y + box_height / .) / img_height;
}
}
}
}
3.从reshape可以看出,输出的shape是(1,2,layer_width * layer_height * num_priors_ * 4),layer_width * layer_height * num_priors_ * 4是每个feature map上每个点乘以anchor数,再每个anchor乘以对应的4个坐标,比如整个blob中第一个4个值存储的就是feature map中第一个像素点的min size对应的正方形那个anchor的4个坐标值,第二个就是第一个像素点对应的max size对应的anchor的4个坐标值
void PriorBoxLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
const int layer_width = bottom[]->width();
const int layer_height = bottom[]->height();
vector<int> top_shape(, );
// Since all images in a batch has same height and width, we only need to
// generate one set of priors which can be shared across all images.
top_shape[] = ;
// 2 channels. First channel stores the mean of each prior coordinate.
// Second channel stores the variance of each prior coordinate.
top_shape[] = ;
top_shape[] = layer_width * layer_height * num_priors_ * ;
CHECK_GT(top_shape[], );
top[]->Reshape(top_shape);
}
注意到,输出是2channel的,第一个channel就是存储的真实的每个anchor的4个坐标,第二个channel存储的就是variance,variance_在layer_setup里面就初始化了4个值,这4个值就是来自于prototxt的param.这4个值分别对应4个坐标点,对于每个anchor,都会有对应这4个variance值,这些值存储在第二个channel,并且在第二个channel里面每4个值每4个值重复
top_data += top[]->offset(, );
if (variance_.size() == ) {
caffe_set<Dtype>(dim, Dtype(variance_[]), top_data);
} else {
int count = ;
for (int h = ; h < layer_height; ++h) {
for (int w = ; w < layer_width; ++w) {
for (int i = ; i < num_priors_; ++i) {
for (int j = ; j < ; ++j) {
top_data[count] = variance_[j];
++count;
}
}
}
}
}
4.http://www.360doc.com/content/17/0810/10/10408243_678091430.shtml
这两段代码都来自于bbox_util.cpp的DecodeBBox函数.prior_box层输出的prior_variance就是一个系数,这个系数乘以bounding box regression的回归值,在faster中,是直接在anchor的坐标上加bounding box regression,ssd这里可以对回归乘以一个系数.当然DecodeBBox其实也可以使用faster那种方式,可以通过参数控制
else {
// variance is encoded in bbox, we need to scale the offset accordingly.
decode_bbox->set_xmin(
prior_bbox.xmin() + prior_variance[] * bbox.xmin());
decode_bbox->set_ymin(
prior_bbox.ymin() + prior_variance[] * bbox.ymin());
decode_bbox->set_xmax(
prior_bbox.xmax() + prior_variance[] * bbox.xmax());
decode_bbox->set_ymax(
prior_bbox.ymax() + prior_variance[] * bbox.ymax());
}
else {
// variance is encoded in bbox, we need to scale the offset accordingly.
decode_bbox->set_xmin(
prior_bbox.xmin() + prior_variance[] * bbox.xmin() * prior_width);
decode_bbox->set_ymin(
prior_bbox.ymin() + prior_variance[] * bbox.ymin() * prior_height);
decode_bbox->set_xmax(
prior_bbox.xmax() + prior_variance[] * bbox.xmax() * prior_width);
decode_bbox->set_ymax(
prior_bbox.ymax() + prior_variance[] * bbox.ymax() * prior_height);
}
5.https://zhuanlan.zhihu.com/p/33544892 这个介绍了每层的prior如何确定min_size
对于后面的特征图,先验框尺度按照上面公式线性增加,但是先将尺度比例先扩大100倍,此时增长步长为 ,这样各个特征图的
为
,将这些比例除以100,然后再乘以图片大小,可以得到各个特征图的尺度为
,这种计算方式是参考SSD的Caffe源码。综上,可以得到各个特征图的先验框尺度
prior_box层的更多相关文章
- 整个ssd的网络和multibox_loss_layer
总结说来prior_box层只完成了一个提取anchor的过程,其他与gt的match,筛选正负样本比例都是在multibox_loss_layer完成的 http://www.360doc.com/ ...
- iOS总结_UI层自我复习总结
UI层复习笔记 在main文件中,UIApplicationMain函数一共做了三件事 根据第三个参数创建了一个应用程序对象 默认写nil,即创建的是UIApplication类型的对象,此对象看成是 ...
- 终于等到你:CYQ.Data V5系列 (ORM数据层)最新版本开源了
前言: 不要问我框架为什么从收费授权转到免费开源,人生没有那么多为什么,这些年我开源的东西并不少,虽然这个是最核心的,看淡了就也没什么了. 群里的网友:太平说: 记得一年前你开源另一个项目的时候我就说 ...
- UWP开发之ORM实践:如何使用Entity Framework Core做SQLite数据持久层?
选择SQLite的理由 在做UWP开发的时候我们首选的本地数据库一般都是Sqlite,我以前也不知道为啥?后来仔细研究了一下也是有原因的: 1,微软做的UWP应用大部分也是用Sqlite.或者说是微软 ...
- java中Action层、Service层和Dao层的功能区分
Action/Service/DAO简介: Action是管理业务(Service)调度和管理跳转的. Service是管理具体的功能的. Action只负责管理,而Service负责实施. DAO只 ...
- ABP领域层
1.实体Entites 1.1 概念 实体是DDD(领域驱动设计)的核心概念之一. 实体是具有唯一标识的ID且存储在数据库总.实体通常被映射成数据库中的一个表. 在ABP中,实体继承自Entity类. ...
- JavaScript学习笔记(一)——延迟对象、跨域、模板引擎、弹出层、AJAX示例
一.AJAX示例 AJAX全称为“Asynchronous JavaScript And XML”(异步JavaScript和XML) 是指一种创建交互式网页应用的开发技术.改善用户体验,实现无刷新效 ...
- jQuery遮罩层登录对话框
用户登录是许多网站必备的功能.有一种方式就是不管在网站的哪个页面,点击登录按钮就会弹出一个遮罩层,显示用户登录的对话框.这用方式比较灵活方便.而现在扫描二维码登录的方式也是很常见,例如QQ.微信.百度 ...
- 使用CSS3的box-shadow实现双透明遮罩层对话框
box-shadow介绍 在我之前的一篇文章<从天猫和支付宝身上学习opcity与rgba>中,介绍了实现双透明遮罩层效果的两种方法,分别是opacity和rgba.他们需要分别依赖于不同 ...
随机推荐
- GreenPlum 大数据平台--远程访问-->gpadmin客户端
一,客户端连接 01,配置文件说明 在master节点的$MASTER_DATA_DIRECTORY(这个是配置的环境变量:/greenplum/data/master/gpseg-1)/pg_hba ...
- 图解DTS和PTS
由于把视频编码成I,B,P等帧,如下图 假设现在有I,B,P帧,那么要传输和显示呢?? 如果按照显示顺序传输的话: 传输顺序就是I->B>P 当对B帧进行解码后,由于B帧无法单独显 ...
- matlab中如何根据t检验参数查找t检验值
这个问题花了一些时间.先看图 这个是t检验里面的公式,但是如何在matlab中找到该式子对应的值,我现在才知道. 就是这样:x=tinv(1-α/2,n-1)----t(n)分布的上侧α分位数 ...
- nyoj 1205——简单问题——————【技巧题】
简单问题 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 给你一个n*m的矩阵,其中的元素每一行从左到右按递增顺序排序,每一列从上到下按递增顺序排序,然后给你一些数x ...
- Ubuntu系统修改Python软链接
1.查看使用的版本 python --version 2.查看当前所使用版本的位置 which python 3.如果第二步结果是 /usr/bin/python 则直接删除即可 sudo rm /u ...
- Bitmap图片查看器
在Android 应用中使用assets目录下存放的资源文件,assets目录下存放的资源代表应用无法直接访问的原生资源,应用程序通过AssetManager以二 进制流的形式来读取资源.此应用是查看 ...
- 希尔排序——Java实现
一.排序思想 希尔排序(Shell’s Sort)是插入排序的一种,是直接插入排序算法的一种更高版本的改进版本. 把记录按步长gap分组,对每组记录采用直接插入排序方法进行排序: 随着步长逐渐减小,所 ...
- Google Kickstart在线测试规则以及注意事项
谷歌招聘在如火如荼的进行中,进谷歌都需要经过谷歌kickstart在线测试,然后过了之后还有五轮的面试- -.好吧毕竟你待遇高,你强你有理.. 下面介绍一下进谷歌的第一关google kickstar ...
- rbac——界面、权限
一.模板继承 知识点: users.html / roles.html 继承自 base.html 页面滚动时,固定 .menu { background-color: bisque; positio ...
- 关于Activity
Activity与界面 1.Activity相当于浏览器的标签.相当于空白的网页,界面相当于浏览器内的网页. 2.将Activity与界面绑定就相当于在浏览器内填写了相应的网页. 3.Activity ...