(RegionProposal Network)RPN网络结构及详解[通俗易懂]

(RegionProposal Network)RPN网络结构及详解[通俗易懂]RPN(RegionProposalNetwork)区域生成网络Faster-RCNN的核心。在这里整理。1.anchors。特征可以看做一个尺度51*39的256通道图像,对于该图像的每一个位置,考虑9个可能的候选窗口:三种面积{128,256,512}×{128,256,512}×三种比例{1:1,1:2,2:1}{1:1,1:2,2:1}。这些候选窗口称为anchors…

大家好,又见面了,我是你们的朋友全栈君。

RPN(RegionProposal Network)区域生成网络 

Faster-RCNN的核心。在这里整理。

 

1.anchors

特征可以看做一个尺度51*39的256通道图像,对于该图像的每一个位置,考虑9个可能的候选窗口:三种面积{128,256,512}×{128,256,512}×三种比例{1:1,1:2,2:1}{1:1,1:2,2:1}。这些候选窗口称为anchors。下图示出51*39个anchor中心,以及9种anchor示例。 
这里写图片描述

{1282,2562,5122}×{1282,2562,5122}×三种比例{1:1,1:2,2:1}{1:1,1:2,2:1}。这些候选窗口称为anchors。下图示出51*39个anchor中心,以及9种anchor示例。 
这里写图片描述

 

2.SOFTMAX的两支

(RegionProposal Network)RPN网络结构及详解[通俗易懂]

 计算每个像素256-d的9个尺度下的值,得到9个anchor,我们给每个anchor分配一个二进制的标签(前景背景)。我们分配正标签前景给两类anchor:1)与某个ground truth(GT)包围盒有最高的IoU重叠的anchor(也许不到0.7),2)与任意GT包围盒有大于0.7的IoU交叠的anchor。注意到一个GT包围盒可能分配正标签给多个anchor。我们分配负标签(背景)给与所有GT包围盒的IoU比率都低于0.3的anchor。非正非负的anchor对训练目标没有任何作用,由此输出维度为(2*9)18,一共18维。

假设在conv5 feature map中每个点上有k个anchor(默认k=9),而每个anhcor要分foreground和background,所以每个点由256d feature转化为cls=2k scores;而每个anchor都有[x, y, w, h]对应4个偏移量,所以reg=4k coordinates

补充一点,全部anchors拿去训练太多了,训练程序会在合适的anchors中随机选取128个postive anchors+128个negative anchors进行训练。

 

——————————————————-分割线——————————————————————-

以上是传统的RPN,下面是Faster R-CNN 的RPN部分。

 

3.bounding box regression

前2.)中已经计算出foreground anchors,使用bounding box regression回归得到预设anchor-box到ground-truth-box之间的变换参数,即平移(dx和dy)和伸缩参数(dw和dh),由此得到初步确定proposal。

 

如图9所示绿色框为飞机的Ground Truth(GT),红色为提取的foreground anchors,那么即便红色的框被分类器识别为飞机,但是由于红色的框定位不准,这张图相当于没有正确的检测出飞机。所以我们希望采用一种方法对红色的框进行微调,使得foreground anchors和GT更加接近。

(RegionProposal Network)RPN网络结构及详解[通俗易懂](RegionProposal Network)RPN网络结构及详解[通俗易懂]

图9

缩进对于窗口一般使用四维向量(x, y, w, h)表示,分别表示窗口的中心点坐标和宽高。对于图 10,红色的框A代表原始的Foreground Anchors绿色的框G代表目标的GT,我们的目标是寻找一种关系,使得输入原始的anchor A经过映射得到一个跟真实窗口G更接近的回归窗口G’,即:给定A=(Ax, Ay, Aw, Ah),寻找一种映射f,使得f(Ax, Ay, Aw, Ah)=(G’x, G’y, G’w, G’h),其中(G’x, G’y, G’w, G’h)≈(Gx, Gy, Gw, Gh)。

(RegionProposal Network)RPN网络结构及详解[通俗易懂](RegionProposal Network)RPN网络结构及详解[通俗易懂]

图10

那么经过何种变换才能从图6中的A变为G’呢? 比较简单的思路就是:

缩进 1. 先做平移

(RegionProposal Network)RPN网络结构及详解[通俗易懂](RegionProposal Network)RPN网络结构及详解[通俗易懂]

缩进 2. 再做缩放

(RegionProposal Network)RPN网络结构及详解[通俗易懂](RegionProposal Network)RPN网络结构及详解[通俗易懂]

缩进观察上面4个公式发现,需要学习的是dx(A),dy(A),dw(A),dh(A)这四个变换。当输入的anchor与GT相差较小时,可以认为这种变换是一种线性变换, 那么就可以用线性回归来建模对窗口进行微调(注意,只有当anchors和GT比较接近时,才能使用线性回归模型,否则就是复杂的非线性问题了)。对应于Faster RCNN原文,平移量(tx, ty)与尺度因子(tw, th)如下:

(RegionProposal Network)RPN网络结构及详解[通俗易懂](RegionProposal Network)RPN网络结构及详解[通俗易懂]

(后两个公式写错了,是tw,th)

缩进接下来的问题就是如何通过线性回归获得dx(A),dy(A),dw(A),dh(A)了。线性回归就是给定输入的特征向量X, 学习一组参数W, 使得经过线性回归后的值跟真实值Y(即GT)非常接近,即Y=WX。对于该问题,输入X是一张经过卷积获得的feature map,定义为Φ;同时还有训练传入的GT,即(tx, ty, tw, th)。输出是dx(A),dy(A),dw(A),dh(A)四个变换。那么目标函数可以表示为:(RegionProposal Network)RPN网络结构及详解[通俗易懂]

 

其中Φ(A)是对应anchor的feature map组成的特征向量,w是需要学习的参数,d(A)是得到的预测值(*表示 x,y,w,h,也就是每一个变换对应一个上述目标函数)。为了让预测值(tx, ty, tw, th)与真实值最小,得到损失函数:

(RegionProposal Network)RPN网络结构及详解[通俗易懂](RegionProposal Network)RPN网络结构及详解[通俗易懂]

函数优化目标为:(RegionProposal Network)RPN网络结构及详解[通俗易懂]

 

 

Boundingbox regression原理http://blog.csdn.net/elaine_bao/article/details/60469036

 

4.将预proposal利用feat_stride和im_info将anchors映射回原图,判断预proposal是否大范围超过边界,剔除严重超出边界的。

按照softmax score进行从大到小排序,提取前2000个预proposal,对这个2000个进行NMS(非极大值抑制),将得到的再次进行排序,输出300个proposal。

 

NMS(非极大值抑制)

由于锚点经常重叠,因此建议最终也会在同一个目标上重叠。为了解决重复建议的问题,我们使用一个简单的算法,称为非极大抑制(NMS)。NMS 获取按照分数排序的建议列表并对已排序的列表进行迭代,丢弃那些 IoU 值大于某个预定义阈值的建议,并提出一个具有更高分数的建议。总之,抑制的过程是一个迭代-遍历-消除的过程。如下图所示:

 

  • 将所有候选框的得分进行排序,选中最高分及其所对应的BB;

(RegionProposal Network)RPN网络结构及详解[通俗易懂]

图10

 

  • 遍历其余的框,如果它和当前最高得分框的重叠面积大于一定的阈值,我们将其删除。

(RegionProposal Network)RPN网络结构及详解[通俗易懂]

图11

 

  • 从没有处理的框中继续选择一个得分最高的,重复上述过程。

(RegionProposal Network)RPN网络结构及详解[通俗易懂]

 

 

 

框架流程:from:https://blog.csdn.net/zjucor/article/details/78232024

我的这个可以看到具体数据流动情况。

layer{
	name:"data"
    top:"data"
    type:"Input"
    input_param{
    	shape{ dim: 1 dim: 3 dim: 224 dim: 224}
    }
}
#========= conv1-conv5 ============

layer {
	name: "conv1"
	type: "Convolution"
	bottom: "data"
	top: "conv1" 
	param { lr_mult: 1.0 }
	param { lr_mult: 2.0 }
	convolution_param {
		num_output: 96
		kernel_size: 7
		pad: 3  
		stride: 2
	}
}
layer {
	name: "relu1"
	type: "ReLU"
	bottom: "conv1"
	top: "conv1"
}
layer {
	name: "norm1"
	type: "LRN"
	bottom: "conv1"
	top: "norm1" 
	lrn_param {
		local_size: 3
		alpha: 0.00005
		beta: 0.75
		norm_region: WITHIN_CHANNEL
    engine: CAFFE
	}
}
layer {
	name: "pool1"
	type: "Pooling"
	bottom: "norm1"
	top: "pool1"
	pooling_param {
		kernel_size: 3
		stride: 2
		pad: 1
		pool: MAX
	}
}
layer {
	name: "conv2"
	type: "Convolution"
	bottom: "pool1"
	top: "conv2"
	param { lr_mult: 1.0 }
	param { lr_mult: 2.0 }
	convolution_param {
		num_output: 256
		kernel_size: 5
		pad: 2
		stride: 2
	}
}
layer {
	name: "relu2"
	type: "ReLU"
	bottom: "conv2"
	top: "conv2"
}
layer {
	name: "norm2"
	type: "LRN"
	bottom: "conv2"
	top: "norm2"
	lrn_param {
		local_size: 3
		alpha: 0.00005
		beta: 0.75
		norm_region: WITHIN_CHANNEL
    engine: CAFFE
	}
}
layer {
	name: "pool2"
	type: "Pooling"
	bottom: "norm2"
	top: "pool2"
	pooling_param {
		kernel_size: 3
		stride: 2
		pad: 1
		pool: MAX
	}
}
layer {
	name: "conv3"
	type: "Convolution"
	bottom: "pool2"
	top: "conv3"
	param { lr_mult: 1.0 }
	param { lr_mult: 2.0 }
	convolution_param {
		num_output: 384
		kernel_size: 3
		pad: 1
		stride: 1
	}
}
layer {
	name: "relu3"
	type: "ReLU"
	bottom: "conv3"
	top: "conv3"
}
layer {
	name: "conv4"
	type: "Convolution"
	bottom: "conv3"
	top: "conv4"
	param { lr_mult: 1.0 }
	param { lr_mult: 2.0 }
	convolution_param {
		num_output: 384
		kernel_size: 3
		pad: 1
		stride: 1
	}
}
layer {
	name: "relu4"
	type: "ReLU"
	bottom: "conv4"
	top: "conv4"
}
layer {
	name: "conv5"
	type: "Convolution"
	bottom: "conv4"
	top: "conv5"
	param { lr_mult: 1.0 }
	param { lr_mult: 2.0 }
	convolution_param {
		num_output: 256
		kernel_size: 3
		pad: 1
		stride: 1
	}
}
layer {
	name: "relu5"
	type: "ReLU"
	bottom: "conv5"
	top: "conv5"
}


layer {
  name: "rpn_conv1"
  type: "Convolution"
  bottom: "conv5"
  top: "rpn_conv1"
  param { lr_mult: 1.0 }
  param { lr_mult: 2.0 }
  convolution_param {
    num_output: 256
    kernel_size: 3 pad: 1 stride: 1
    weight_filler { type: "gaussian" std: 0.01 }
    bias_filler { type: "constant" value: 0 }
  }
}
layer {
  name: "rpn_relu1"
  type: "ReLU"
  bottom: "rpn_conv1"
  top: "rpn_conv1"
}
layer {
  name: "rpn_cls_score"
  type: "Convolution"
  bottom: "rpn_conv1"
  top: "rpn_cls_score"
  param { lr_mult: 1.0 }
  param { lr_mult: 2.0 }
  convolution_param {
    num_output: 18   
    kernel_size: 1 pad: 0 stride: 1 
    weight_filler { type: "gaussian" std: 0.01 }
    bias_filler { type: "constant" value: 0 }
  }
}
layer {
  name: "rpn_bbox_pred"
  type: "Convolution"
  bottom: "rpn_conv1"
  top: "rpn_bbox_pred"
  param { lr_mult: 1.0 }
  param { lr_mult: 2.0 }
  convolution_param {
    num_output: 36  
    kernel_size: 1 pad: 0 stride: 1
    weight_filler { type: "gaussian" std: 0.01 }
    bias_filler { type: "constant" value: 0 }
  }
}
layer {
   bottom: "rpn_cls_score"
   top: "rpn_cls_score_reshape" 
   name: "rpn_cls_score_reshape"
   type: "Reshape"
   reshape_param { shape { dim: 0 dim: 2 dim: -1 dim: 0 } }
}
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"
  }
}
layer {
  name: "rpn_loss_cls"
  type: "SoftmaxWithLoss" 
  bottom: "rpn_cls_score_reshape"
  bottom: "rpn_labels"
  propagate_down: 1
  propagate_down: 0
  top: "rpn_cls_loss"
  loss_weight: 1
  loss_param {
    ignore_label: -1
    normalize: true
  }
}
layer {
  name: "rpn_loss_bbox"
  type: "SmoothL1Loss" 
  bottom: "rpn_bbox_pred"
  bottom: "rpn_bbox_targets"
  bottom: "rpn_bbox_inside_weights"
  bottom: "rpn_bbox_outside_weights"
  top: "rpn_loss_bbox"
  loss_weight: 1
  smooth_l1_loss_param { sigma: 3.0 }
}


layer {
  name: "dummy_roi_pool_conv5"
  type: "DummyData"
  top: "dummy_roi_pool_conv5"
  dummy_data_param {
    shape { dim: 1 dim: 9216 }
    data_filler { type: "gaussian" std: 0.01 }
  }
}
layer {
  name: "fc6"
  type: "InnerProduct"
  bottom: "dummy_roi_pool_conv5"
  top: "fc6"
  param { lr_mult: 0 decay_mult: 0 }
  param { lr_mult: 0 decay_mult: 0 }
  inner_product_param {
    num_output: 4096
  }
}
layer {
  name: "relu6"
  type: "ReLU"
  bottom: "fc6"
  top: "fc6"
}
layer {
  name: "fc7"
  type: "InnerProduct"
  bottom: "fc6"
  top: "fc7"
  param { lr_mult: 0 decay_mult: 0 }
  param { lr_mult: 0 decay_mult: 0 }
  inner_product_param {
    num_output: 4096
  }
}
layer {
  name: "silence_fc7"
  type: "Silence"
  bottom: "fc7"
}

(RegionProposal Network)RPN网络结构及详解[通俗易懂]

 

参考文献:

 

https://blog.csdn.net/ying86615791/article/details/72788414

https://blog.csdn.net/zjucor/article/details/78232024

https://blog.csdn.net/WZZ18191171661/article/details/79439212

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/152279.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • vue的双向绑定原理_vue的双向绑定原理及实现

    vue的双向绑定原理_vue的双向绑定原理及实现前置:弟弟也是小白一个,看源码以小萌新角度分析可能适合一些跟我一样的小白去理解,有讲不对的请大佬多多海涵和指点首先我觉得理解vue双向绑定原理应该要有略懂一下发布订阅者模式,我略带过一下。与观察者模式不同的是,发布订阅者多了一个中间调度中心而已。下面给两个比较好的例子观察者模式:观察者(Observer)直接订阅(Subscribe)主题(Subject),而当主题被激活的时候,会触发(FireEvent)观察者里的事件(用网上比较好的例子,忘记作者链接了,如果打扰到您请联系我删了)。.

    2022年10月18日
    4
  • 廖雪峰git学习资料-涂改笔记

    廖雪峰git学习资料-涂改笔记注意:本文章是看廖雪峰官网资料整理而来原地址如下:http://www.liaoxuefeng.com/附件为git常用命令 前言:注意的问题如果是首次提交会第一步:先在本地建立一个一样的仓库,称本地仓库。 第二步:在本地进行commit操作将把更新提交到本地仓库; 第三步:将服务器端的更新pull到本地仓库进行合并,最后将合并好的本地仓库push到服务…

    2025年9月27日
    5
  • 腾讯云的ssl免费证书申请_腾讯云认证证书

    腾讯云的ssl免费证书申请_腾讯云认证证书前提条件:域名是在在腾讯云上购买的1.购买SSL证书1.1登录腾讯云状态下,打开链接https://console.cloud.tencent.com/ssl1.2在证书列表上方点击“申请免费证书”按钮,然后直接点“确定”1.3根据提示填写相关信息,“下一步”1.4选用“自动DNS验证”,“确认申请”1.5等待证书颁发即可,一般1…

    2025年10月15日
    3
  • java简单入门教程_史上最快速最简单的java入门教程

    java简单入门教程_史上最快速最简单的java入门教程原标题:史上最快速最简单的java入门教程§java是什么?Java是一门开发软件的程序语言,用于编写比如:办公自动化软件、超市的销售系统、银行交易系统等程序软件.§准备写Java程序。准备工作分为三步:第一步:下载安装JDK开发环境(建议官网下载),基本都是下一步。第二步:配置JDK环境变量,主要配置bin和classpath(主要为了在控制台能方便执行程序。如果不怕麻烦,此步可以省略)。具体…

    2022年7月8日
    22
  • viewstub 的详细用法_pageinfo用法

    viewstub 的详细用法_pageinfo用法在开发应用程序的时候,经常会遇到这样的情况,会在运行时动态根据条件来决定显示哪个View或某个布局。那么最通常的想法就是把可能用到的View都写在上面,先把它们的可见性都设为View.GONE,然后在代码中动态的更改它的可见性。这样的做法的优点是逻辑简单而且控制起来比较灵活。但是它的缺点就是,耗费资源。虽然把View的初始可见View.GONE但是在Inflate布局的时候View仍然会被Infl…

    2022年4月19日
    50
  • IntelliJ IDEA安装教程(超详细)「建议收藏」

    IntelliJ IDEA安装教程(超详细)「建议收藏」IDEA安装教程目录一、JDK的彻底卸载(选做)二、JDK的安装三、IDEA的安装四、IDEA的“扩展”教程五、代码测试六、Error:Cannotdeterminepathto’tools.jar’libraryfor17(D:\jdk-17.0.1)报错的解决方案七、说明写在前面:JDK版本要与IDEA版本相匹配,不然会报错嗷(即:第六节所示)!因为我之前有JDK,所以为了更好的演示,我先把JDK17卸载了。如果你有JDK请查看你的JDK版本后进行第二步(…

    2022年6月26日
    70

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号