Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
PaddleDetection
提交
a375f671
P
PaddleDetection
项目概览
PaddlePaddle
/
PaddleDetection
大约 1 年 前同步成功
通知
695
Star
11112
Fork
2696
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
184
列表
看板
标记
里程碑
合并请求
40
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
PaddleDetection
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
184
Issue
184
列表
看板
标记
里程碑
合并请求
40
合并请求
40
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
a375f671
编写于
10月 20, 2020
作者:
W
wangguanzhong
提交者:
GitHub
10月 20, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add distribute_fpn_proposals (#1582)
上级
1e417485
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
199 addition
and
5 deletion
+199
-5
ppdet/modeling/layers.py
ppdet/modeling/layers.py
+2
-1
ppdet/modeling/ops.py
ppdet/modeling/ops.py
+134
-4
ppdet/modeling/tests/test_ops.py
ppdet/modeling/tests/test_ops.py
+63
-0
未找到文件。
ppdet/modeling/layers.py
浏览文件 @
a375f671
...
@@ -19,6 +19,7 @@ from paddle.fluid.dygraph.base import to_variable
...
@@ -19,6 +19,7 @@ from paddle.fluid.dygraph.base import to_variable
from
ppdet.core.workspace
import
register
,
serializable
from
ppdet.core.workspace
import
register
,
serializable
from
ppdet.py_op.target
import
generate_rpn_anchor_target
,
generate_proposal_target
,
generate_mask_target
from
ppdet.py_op.target
import
generate_rpn_anchor_target
,
generate_proposal_target
,
generate_mask_target
from
ppdet.py_op.post_process
import
bbox_post_process
from
ppdet.py_op.post_process
import
bbox_post_process
from
.
import
ops
@
register
@
register
...
@@ -308,7 +309,7 @@ class RoIExtractor(object):
...
@@ -308,7 +309,7 @@ class RoIExtractor(object):
offset
=
2
offset
=
2
k_min
=
self
.
start_level
+
offset
k_min
=
self
.
start_level
+
offset
k_max
=
self
.
end_level
+
offset
k_max
=
self
.
end_level
+
offset
rois_dist
,
restore_index
,
rois_num_dist
=
fluid
.
layer
s
.
distribute_fpn_proposals
(
rois_dist
,
restore_index
,
rois_num_dist
=
op
s
.
distribute_fpn_proposals
(
roi
,
roi
,
k_min
,
k_min
,
k_max
,
k_max
,
...
...
ppdet/modeling/ops.py
浏览文件 @
a375f671
...
@@ -34,7 +34,7 @@ __all__ = [
...
@@ -34,7 +34,7 @@ __all__ = [
#'box_coder',
#'box_coder',
#'yolo_box',
#'yolo_box',
#'multiclass_nms',
#'multiclass_nms',
#
'distribute_fpn_proposals',
'distribute_fpn_proposals'
,
'collect_fpn_proposals'
,
'collect_fpn_proposals'
,
#'matrix_nms',
#'matrix_nms',
]
]
...
@@ -52,11 +52,13 @@ def collect_fpn_proposals(multi_rois,
...
@@ -52,11 +52,13 @@ def collect_fpn_proposals(multi_rois,
**This OP only supports LoDTensor as input**. Concat multi-level RoIs
**This OP only supports LoDTensor as input**. Concat multi-level RoIs
(Region of Interest) and select N RoIs with respect to multi_scores.
(Region of Interest) and select N RoIs with respect to multi_scores.
This operation performs the following steps:
This operation performs the following steps:
1. Choose num_level RoIs and scores as input: num_level = max_level - min_level
1. Choose num_level RoIs and scores as input: num_level = max_level - min_level
2. Concat multi-level RoIs and scores
2. Concat multi-level RoIs and scores
3. Sort scores and select post_nms_top_n scores
3. Sort scores and select post_nms_top_n scores
4. Gather RoIs by selected indices from scores
4. Gather RoIs by selected indices from scores
5. Re-sort RoIs by corresponding batch_id
5. Re-sort RoIs by corresponding batch_id
Args:
Args:
multi_rois(list): List of RoIs to collect. Element in list is 2-D
multi_rois(list): List of RoIs to collect. Element in list is 2-D
LoDTensor with shape [N, 4] and data type is float32 or float64,
LoDTensor with shape [N, 4] and data type is float32 or float64,
...
@@ -75,14 +77,18 @@ def collect_fpn_proposals(multi_rois,
...
@@ -75,14 +77,18 @@ def collect_fpn_proposals(multi_rois,
the shape is [B]. Default: None
the shape is [B]. Default: None
name(str, optional): For detailed information, please refer
name(str, optional): For detailed information, please refer
to :ref:`api_guide_Name`. Usually name is no need to set and
to :ref:`api_guide_Name`. Usually name is no need to set and
None by default.
None by default.
Returns:
Returns:
Variable:
Variable:
fpn_rois(Variable): 2-D LoDTensor with shape [N, 4] and data type is
fpn_rois(Variable): 2-D LoDTensor with shape [N, 4] and data type is
float32 or float64. Selected RoIs.
float32 or float64. Selected RoIs.
rois_num(Tensor): 1-D Tensor contains the RoIs's number of each
rois_num(Tensor): 1-D Tensor contains the RoIs's number of each
image. The shape is [B] and data type is int32. B is the number of
image. The shape is [B] and data type is int32. B is the number of
images.
images.
Examples:
Examples:
.. code-block:: python
.. code-block:: python
...
@@ -92,11 +98,12 @@ def collect_fpn_proposals(multi_rois,
...
@@ -92,11 +98,12 @@ def collect_fpn_proposals(multi_rois,
multi_rois = []
multi_rois = []
multi_scores = []
multi_scores = []
for i in range(4):
for i in range(4):
multi_rois.append(
fluid
.data(
multi_rois.append(
paddle.static
.data(
name='roi_'+str(i), shape=[None, 4], dtype='float32', lod_level=1))
name='roi_'+str(i), shape=[None, 4], dtype='float32', lod_level=1))
for i in range(4):
for i in range(4):
multi_scores.append(
fluid
.data(
multi_scores.append(
paddle.static
.data(
name='score_'+str(i), shape=[None, 1], dtype='float32', lod_level=1))
name='score_'+str(i), shape=[None, 1], dtype='float32', lod_level=1))
fpn_rois = fluid.layers.collect_fpn_proposals(
fpn_rois = fluid.layers.collect_fpn_proposals(
multi_rois=multi_rois,
multi_rois=multi_rois,
multi_scores=multi_scores,
multi_scores=multi_scores,
...
@@ -141,3 +148,126 @@ def collect_fpn_proposals(multi_rois,
...
@@ -141,3 +148,126 @@ def collect_fpn_proposals(multi_rois,
if
rois_num_per_level
is
not
None
:
if
rois_num_per_level
is
not
None
:
return
output_rois
,
rois_num
return
output_rois
,
rois_num
return
output_rois
return
output_rois
def
distribute_fpn_proposals
(
fpn_rois
,
min_level
,
max_level
,
refer_level
,
refer_scale
,
rois_num
=
None
,
name
=
None
):
"""
**This op only takes LoDTensor as input.** In Feature Pyramid Networks
(FPN) models, it is needed to distribute all proposals into different FPN
level, with respect to scale of the proposals, the referring scale and the
referring level. Besides, to restore the order of proposals, we return an
array which indicates the original index of rois in current proposals.
To compute FPN level for each roi, the formula is given as follows:
.. math::
roi\_scale &= \sqrt{BBoxArea(fpn\_roi)}
level = floor(&\log(
\\
frac{roi\_scale}{refer\_scale}) + refer\_level)
where BBoxArea is a function to compute the area of each roi.
Args:
fpn_rois(Variable): 2-D Tensor with shape [N, 4] and data type is
float32 or float64. The input fpn_rois.
min_level(int32): The lowest level of FPN layer where the proposals come
from.
max_level(int32): The highest level of FPN layer where the proposals
come from.
refer_level(int32): The referring level of FPN layer with specified scale.
refer_scale(int32): The referring scale of FPN layer with specified level.
rois_num(Tensor): 1-D Tensor contains the number of RoIs in each image.
The shape is [B] and data type is int32. B is the number of images.
If it is not None then return a list of 1-D Tensor. Each element
is the output RoIs' number of each image on the corresponding level
and the shape is [B]. None by default.
name(str, optional): For detailed information, please refer
to :ref:`api_guide_Name`. Usually name is no need to set and
None by default.
Returns:
Tuple:
multi_rois(List) : A list of 2-D LoDTensor with shape [M, 4]
and data type of float32 and float64. The length is
max_level-min_level+1. The proposals in each FPN level.
restore_ind(Variable): A 2-D Tensor with shape [N, 1], N is
the number of total rois. The data type is int32. It is
used to restore the order of fpn_rois.
rois_num_per_level(List): A list of 1-D Tensor and each Tensor is
the RoIs' number in each image on the corresponding level. The shape
is [B] and data type of int32. B is the number of images
Examples:
.. code-block:: python
import paddle.fluid as fluid
import paddle
paddle.enable_static()
fpn_rois = paddle.static.data(
name='data', shape=[None, 4], dtype='float32', lod_level=1)
multi_rois, restore_ind = fluid.layers.distribute_fpn_proposals(
fpn_rois=fpn_rois,
min_level=2,
max_level=5,
refer_level=4,
refer_scale=224)
"""
num_lvl
=
max_level
-
min_level
+
1
if
in_dygraph_mode
():
assert
rois_num
is
not
None
,
"rois_num should not be None in dygraph mode."
attrs
=
(
'min_level'
,
min_level
,
'max_level'
,
max_level
,
'refer_level'
,
refer_level
,
'refer_scale'
,
refer_scale
)
multi_rois
,
restore_ind
,
rois_num_per_level
=
core
.
ops
.
distribute_fpn_proposals
(
fpn_rois
,
rois_num
,
num_lvl
,
num_lvl
,
*
attrs
)
return
multi_rois
,
restore_ind
,
rois_num_per_level
check_variable_and_dtype
(
fpn_rois
,
'fpn_rois'
,
[
'float32'
,
'float64'
],
'distribute_fpn_proposals'
)
helper
=
LayerHelper
(
'distribute_fpn_proposals'
,
**
locals
())
dtype
=
helper
.
input_dtype
(
'fpn_rois'
)
multi_rois
=
[
helper
.
create_variable_for_type_inference
(
dtype
)
for
i
in
range
(
num_lvl
)
]
restore_ind
=
helper
.
create_variable_for_type_inference
(
dtype
=
'int32'
)
inputs
=
{
'FpnRois'
:
fpn_rois
}
outputs
=
{
'MultiFpnRois'
:
multi_rois
,
'RestoreIndex'
:
restore_ind
,
}
if
rois_num
is
not
None
:
inputs
[
'RoisNum'
]
=
rois_num
rois_num_per_level
=
[
helper
.
create_variable_for_type_inference
(
dtype
=
'int32'
)
for
i
in
range
(
num_lvl
)
]
outputs
[
'MultiLevelRoIsNum'
]
=
rois_num_per_level
helper
.
append_op
(
type
=
'distribute_fpn_proposals'
,
inputs
=
inputs
,
outputs
=
outputs
,
attrs
=
{
'min_level'
:
min_level
,
'max_level'
:
max_level
,
'refer_level'
:
refer_level
,
'refer_scale'
:
refer_scale
})
if
rois_num
is
not
None
:
return
multi_rois
,
restore_ind
,
rois_num_per_level
return
multi_rois
,
restore_ind
ppdet/modeling/tests/test_ops.py
浏览文件 @
a375f671
...
@@ -154,5 +154,68 @@ class TestCollectFpnProposals(LayerTest):
...
@@ -154,5 +154,68 @@ class TestCollectFpnProposals(LayerTest):
post_nms_top_n
=
2000
)
post_nms_top_n
=
2000
)
class
TestDistributeFpnProposals
(
LayerTest
):
def
test_distribute_fpn_proposals
(
self
):
rois_np
=
np
.
random
.
rand
(
10
,
4
).
astype
(
'float32'
)
rois_num_np
=
np
.
array
([
4
,
6
]).
astype
(
'int32'
)
with
self
.
static_graph
():
rois
=
paddle
.
static
.
data
(
name
=
'rois'
,
shape
=
[
10
,
4
],
dtype
=
'float32'
)
rois_num
=
paddle
.
static
.
data
(
name
=
'rois_num'
,
shape
=
[
None
],
dtype
=
'int32'
)
multi_rois
,
restore_ind
,
rois_num_per_level
=
ops
.
distribute_fpn_proposals
(
fpn_rois
=
rois
,
min_level
=
2
,
max_level
=
5
,
refer_level
=
4
,
refer_scale
=
224
,
rois_num
=
rois_num
)
fetch_list
=
multi_rois
+
[
restore_ind
]
+
rois_num_per_level
output_stat
=
self
.
get_static_graph_result
(
feed
=
{
'rois'
:
rois_np
,
'rois_num'
:
rois_num_np
},
fetch_list
=
fetch_list
,
with_lod
=
True
)
output_stat_np
=
[]
for
output
in
output_stat
:
output_np
=
np
.
array
(
output
)
if
len
(
output_np
)
>
0
:
output_stat_np
.
append
(
output_np
)
with
self
.
dynamic_graph
():
rois_dy
=
base
.
to_variable
(
rois_np
)
rois_num_dy
=
base
.
to_variable
(
rois_num_np
)
multi_rois_dy
,
restore_ind_dy
,
rois_num_per_level_dy
=
ops
.
distribute_fpn_proposals
(
fpn_rois
=
rois_dy
,
min_level
=
2
,
max_level
=
5
,
refer_level
=
4
,
refer_scale
=
224
,
rois_num
=
rois_num_dy
)
output_dy
=
multi_rois_dy
+
[
restore_ind_dy
]
+
rois_num_per_level_dy
output_dy_np
=
[]
for
output
in
output_dy
:
output_np
=
output
.
numpy
()
if
len
(
output_np
)
>
0
:
output_dy_np
.
append
(
output_np
)
for
res_stat
,
res_dy
in
zip
(
output_stat_np
,
output_dy_np
):
self
.
assertTrue
(
np
.
array_equal
(
res_stat
,
res_dy
))
def
test_distribute_fpn_proposals_error
(
self
):
program
=
Program
()
with
program_guard
(
program
):
fpn_rois
=
paddle
.
static
.
data
(
name
=
'data_error'
,
shape
=
[
10
,
4
],
dtype
=
'int32'
,
lod_level
=
1
)
self
.
assertRaises
(
TypeError
,
ops
.
distribute_fpn_proposals
,
fpn_rois
=
fpn_rois
,
min_level
=
2
,
max_level
=
5
,
refer_level
=
4
,
refer_scale
=
224
)
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
unittest
.
main
()
unittest
.
main
()
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录