(RegionProposal Network)RPN网络结构及详解

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_38325803/article/details/102721762
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_36269513/article/details/80421990

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的两支

 计算每个像素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更加接近。

图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)。

图10

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

缩进 1. 先做平移

缩进 2. 再做缩放

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

(后两个公式写错了,是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)四个变换。那么目标函数可以表示为:

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

函数优化目标为:

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;

图10

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

图11

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

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

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


  
  
  1. layer{
  2. name:"data"
  3. top:"data"
  4. type:"Input"
  5. input_param{
  6. shape{ dim: 1 dim: 3 dim: 224 dim: 224}
  7. }
  8. }
  9. #========= conv1-conv5 ============
  10. layer {
  11. name: "conv1"
  12. type: "Convolution"
  13. bottom: "data"
  14. top: "conv1"
  15. param { lr_mult: 1.0 }
  16. param { lr_mult: 2.0 }
  17. convolution_param {
  18. num_output: 96
  19. kernel_size: 7
  20. pad: 3
  21. stride: 2
  22. }
  23. }
  24. layer {
  25. name: "relu1"
  26. type: "ReLU"
  27. bottom: "conv1"
  28. top: "conv1"
  29. }
  30. layer {
  31. name: "norm1"
  32. type: "LRN"
  33. bottom: "conv1"
  34. top: "norm1"
  35. lrn_param {
  36. local_size: 3
  37. alpha: 0.00005
  38. beta: 0.75
  39. norm_region: WITHIN_CHANNEL
  40. engine: CAFFE
  41. }
  42. }
  43. layer {
  44. name: "pool1"
  45. type: "Pooling"
  46. bottom: "norm1"
  47. top: "pool1"
  48. pooling_param {
  49. kernel_size: 3
  50. stride: 2
  51. pad: 1
  52. pool: MAX
  53. }
  54. }
  55. layer {
  56. name: "conv2"
  57. type: "Convolution"
  58. bottom: "pool1"
  59. top: "conv2"
  60. param { lr_mult: 1.0 }
  61. param { lr_mult: 2.0 }
  62. convolution_param {
  63. num_output: 256
  64. kernel_size: 5
  65. pad: 2
  66. stride: 2
  67. }
  68. }
  69. layer {
  70. name: "relu2"
  71. type: "ReLU"
  72. bottom: "conv2"
  73. top: "conv2"
  74. }
  75. layer {
  76. name: "norm2"
  77. type: "LRN"
  78. bottom: "conv2"
  79. top: "norm2"
  80. lrn_param {
  81. local_size: 3
  82. alpha: 0.00005
  83. beta: 0.75
  84. norm_region: WITHIN_CHANNEL
  85. engine: CAFFE
  86. }
  87. }
  88. layer {
  89. name: "pool2"
  90. type: "Pooling"
  91. bottom: "norm2"
  92. top: "pool2"
  93. pooling_param {
  94. kernel_size: 3
  95. stride: 2
  96. pad: 1
  97. pool: MAX
  98. }
  99. }
  100. layer {
  101. name: "conv3"
  102. type: "Convolution"
  103. bottom: "pool2"
  104. top: "conv3"
  105. param { lr_mult: 1.0 }
  106. param { lr_mult: 2.0 }
  107. convolution_param {
  108. num_output: 384
  109. kernel_size: 3
  110. pad: 1
  111. stride: 1
  112. }
  113. }
  114. layer {
  115. name: "relu3"
  116. type: "ReLU"
  117. bottom: "conv3"
  118. top: "conv3"
  119. }
  120. layer {
  121. name: "conv4"
  122. type: "Convolution"
  123. bottom: "conv3"
  124. top: "conv4"
  125. param { lr_mult: 1.0 }
  126. param { lr_mult: 2.0 }
  127. convolution_param {
  128. num_output: 384
  129. kernel_size: 3
  130. pad: 1
  131. stride: 1
  132. }
  133. }
  134. layer {
  135. name: "relu4"
  136. type: "ReLU"
  137. bottom: "conv4"
  138. top: "conv4"
  139. }
  140. layer {
  141. name: "conv5"
  142. type: "Convolution"
  143. bottom: "conv4"
  144. top: "conv5"
  145. param { lr_mult: 1.0 }
  146. param { lr_mult: 2.0 }
  147. convolution_param {
  148. num_output: 256
  149. kernel_size: 3
  150. pad: 1
  151. stride: 1
  152. }
  153. }
  154. layer {
  155. name: "relu5"
  156. type: "ReLU"
  157. bottom: "conv5"
  158. top: "conv5"
  159. }
  160. layer {
  161. name: "rpn_conv1"
  162. type: "Convolution"
  163. bottom: "conv5"
  164. top: "rpn_conv1"
  165. param { lr_mult: 1.0 }
  166. param { lr_mult: 2.0 }
  167. convolution_param {
  168. num_output: 256
  169. kernel_size: 3 pad: 1 stride: 1
  170. weight_filler { type: "gaussian" std: 0.01 }
  171. bias_filler { type: "constant" value: 0 }
  172. }
  173. }
  174. layer {
  175. name: "rpn_relu1"
  176. type: "ReLU"
  177. bottom: "rpn_conv1"
  178. top: "rpn_conv1"
  179. }
  180. layer {
  181. name: "rpn_cls_score"
  182. type: "Convolution"
  183. bottom: "rpn_conv1"
  184. top: "rpn_cls_score"
  185. param { lr_mult: 1.0 }
  186. param { lr_mult: 2.0 }
  187. convolution_param {
  188. num_output: 18
  189. kernel_size: 1 pad: 0 stride: 1
  190. weight_filler { type: "gaussian" std: 0.01 }
  191. bias_filler { type: "constant" value: 0 }
  192. }
  193. }
  194. layer {
  195. name: "rpn_bbox_pred"
  196. type: "Convolution"
  197. bottom: "rpn_conv1"
  198. top: "rpn_bbox_pred"
  199. param { lr_mult: 1.0 }
  200. param { lr_mult: 2.0 }
  201. convolution_param {
  202. num_output: 36
  203. kernel_size: 1 pad: 0 stride: 1
  204. weight_filler { type: "gaussian" std: 0.01 }
  205. bias_filler { type: "constant" value: 0 }
  206. }
  207. }
  208. layer {
  209. bottom: "rpn_cls_score"
  210. top: "rpn_cls_score_reshape"
  211. name: "rpn_cls_score_reshape"
  212. type: "Reshape"
  213. reshape_param { shape { dim: 0 dim: 2 dim: -1 dim: 0 } }
  214. }
  215. layer {
  216. name: 'rpn-data'
  217. type: 'Python'
  218. bottom: 'rpn_cls_score'
  219. bottom: 'gt_boxes'
  220. bottom: 'im_info'
  221. bottom: 'data'
  222. top: 'rpn_labels'
  223. top: 'rpn_bbox_targets'
  224. top: 'rpn_bbox_inside_weights'
  225. top: 'rpn_bbox_outside_weights'
  226. python_param {
  227. module: 'rpn.anchor_target_layer'
  228. layer: 'AnchorTargetLayer'
  229. param_str: "'feat_stride': 16"
  230. }
  231. }
  232. layer {
  233. name: "rpn_loss_cls"
  234. type: "SoftmaxWithLoss"
  235. bottom: "rpn_cls_score_reshape"
  236. bottom: "rpn_labels"
  237. propagate_down: 1
  238. propagate_down: 0
  239. top: "rpn_cls_loss"
  240. loss_weight: 1
  241. loss_param {
  242. ignore_label: -1
  243. normalize: true
  244. }
  245. }
  246. layer {
  247. name: "rpn_loss_bbox"
  248. type: "SmoothL1Loss"
  249. bottom: "rpn_bbox_pred"
  250. bottom: "rpn_bbox_targets"
  251. bottom: "rpn_bbox_inside_weights"
  252. bottom: "rpn_bbox_outside_weights"
  253. top: "rpn_loss_bbox"
  254. loss_weight: 1
  255. smooth_l1_loss_param { sigma: 3.0 }
  256. }
  257. layer {
  258. name: "dummy_roi_pool_conv5"
  259. type: "DummyData"
  260. top: "dummy_roi_pool_conv5"
  261. dummy_data_param {
  262. shape { dim: 1 dim: 9216 }
  263. data_filler { type: "gaussian" std: 0.01 }
  264. }
  265. }
  266. layer {
  267. name: "fc6"
  268. type: "InnerProduct"
  269. bottom: "dummy_roi_pool_conv5"
  270. top: "fc6"
  271. param { lr_mult: 0 decay_mult: 0 }
  272. param { lr_mult: 0 decay_mult: 0 }
  273. inner_product_param {
  274. num_output: 4096
  275. }
  276. }
  277. layer {
  278. name: "relu6"
  279. type: "ReLU"
  280. bottom: "fc6"
  281. top: "fc6"
  282. }
  283. layer {
  284. name: "fc7"
  285. type: "InnerProduct"
  286. bottom: "fc6"
  287. top: "fc7"
  288. param { lr_mult: 0 decay_mult: 0 }
  289. param { lr_mult: 0 decay_mult: 0 }
  290. inner_product_param {
  291. num_output: 4096
  292. }
  293. }
  294. layer {
  295. name: "silence_fc7"
  296. type: "Silence"
  297. bottom: "fc7"
  298. }

参考文献:

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

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

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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_36269513/article/details/80421990

RPN(RegionProposal Network)区域生成网络 

猜你喜欢

转载自blog.csdn.net/qq_38325803/article/details/102721762
今日推荐