Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Crayon鑫
Paddle
提交
7757a8ad
P
Paddle
项目概览
Crayon鑫
/
Paddle
与 Fork 源项目一致
Fork自
PaddlePaddle / Paddle
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
Paddle
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
7757a8ad
编写于
2月 12, 2018
作者:
C
chengduo
提交者:
GitHub
2月 12, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #8265 from chengduoZH/feature/add_prior_box_py
Add Python interface of prior_boxes
上级
8a0dd240
dff1bf33
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
302 addition
and
27 deletion
+302
-27
paddle/fluid/operators/prior_box_op.cc
paddle/fluid/operators/prior_box_op.cc
+16
-16
paddle/fluid/operators/prior_box_op.h
paddle/fluid/operators/prior_box_op.h
+4
-4
python/paddle/v2/fluid/layers/__init__.py
python/paddle/v2/fluid/layers/__init__.py
+4
-1
python/paddle/v2/fluid/layers/detection.py
python/paddle/v2/fluid/layers/detection.py
+214
-2
python/paddle/v2/fluid/tests/test_detection.py
python/paddle/v2/fluid/tests/test_detection.py
+62
-2
python/paddle/v2/fluid/tests/test_prior_box_op.py
python/paddle/v2/fluid/tests/test_prior_box_op.py
+2
-2
未找到文件。
paddle/fluid/operators/prior_box_op.cc
浏览文件 @
7757a8ad
...
...
@@ -38,8 +38,8 @@ class PriorBoxOp : public framework::OperatorWithKernel {
PADDLE_ENFORCE_LT
(
input_dims
[
3
],
image_dims
[
3
],
"The width of input must smaller than image."
);
auto
min_sizes
=
ctx
->
Attrs
().
Get
<
std
::
vector
<
in
t
>>
(
"min_sizes"
);
auto
max_sizes
=
ctx
->
Attrs
().
Get
<
std
::
vector
<
in
t
>>
(
"max_sizes"
);
auto
min_sizes
=
ctx
->
Attrs
().
Get
<
std
::
vector
<
floa
t
>>
(
"min_sizes"
);
auto
max_sizes
=
ctx
->
Attrs
().
Get
<
std
::
vector
<
floa
t
>>
(
"max_sizes"
);
auto
variances
=
ctx
->
Attrs
().
Get
<
std
::
vector
<
float
>>
(
"variances"
);
auto
aspect_ratios
=
ctx
->
Attrs
().
Get
<
std
::
vector
<
float
>>
(
"aspect_ratios"
);
bool
flip
=
ctx
->
Attrs
().
Get
<
bool
>
(
"flip"
);
...
...
@@ -47,15 +47,15 @@ class PriorBoxOp : public framework::OperatorWithKernel {
std
::
vector
<
float
>
aspect_ratios_vec
;
ExpandAspectRatios
(
aspect_ratios
,
flip
,
aspect_ratios_vec
);
in
t
num_priors
=
aspect_ratios_vec
.
size
()
*
min_sizes
.
size
();
size_
t
num_priors
=
aspect_ratios_vec
.
size
()
*
min_sizes
.
size
();
if
(
max_sizes
.
size
()
>
0
)
{
PADDLE_ENFORCE_EQ
(
max_sizes
.
size
(),
min_sizes
.
size
(),
"The number of min_size and max_size must be equal."
);
for
(
size_t
i
=
0
;
i
<
min_sizes
.
size
();
++
i
)
{
num_priors
+=
max_sizes
.
size
();
for
(
size_t
i
=
0
;
i
<
max_sizes
.
size
();
++
i
)
{
PADDLE_ENFORCE_GT
(
max_sizes
[
i
],
min_sizes
[
i
],
"max_size[%d] must be greater than min_size[%d]."
,
i
,
i
);
num_priors
+=
1
;
}
}
...
...
@@ -90,20 +90,20 @@ class PriorBoxOpMaker : public framework::OpProtoAndCheckerMaker {
"H is the height of input, W is the width of input, num_priors "
"is the box count of each position."
);
AddAttr
<
std
::
vector
<
in
t
>>
(
"min_sizes"
,
"(vector<in
t>) List of min sizes "
"of generated prior boxes."
)
.
AddCustomChecker
([](
const
std
::
vector
<
in
t
>&
min_sizes
)
{
AddAttr
<
std
::
vector
<
floa
t
>>
(
"min_sizes"
,
"(vector<floa
t>) List of min sizes "
"of generated prior boxes."
)
.
AddCustomChecker
([](
const
std
::
vector
<
floa
t
>&
min_sizes
)
{
PADDLE_ENFORCE_GT
(
min_sizes
.
size
(),
0
,
"Size of min_sizes must be at least 1."
);
for
(
size_t
i
=
0
;
i
<
min_sizes
.
size
();
++
i
)
{
PADDLE_ENFORCE_GT
(
min_sizes
[
i
],
0
,
PADDLE_ENFORCE_GT
(
min_sizes
[
i
],
0
.0
,
"min_sizes[%d] must be positive."
,
i
);
}
});
AddAttr
<
std
::
vector
<
in
t
>>
(
AddAttr
<
std
::
vector
<
floa
t
>>
(
"max_sizes"
,
"(vector<
in
t>) List of max sizes of generated prior boxes."
);
"(vector<
floa
t>) List of max sizes of generated prior boxes."
);
AddAttr
<
std
::
vector
<
float
>>
(
"aspect_ratios"
,
"(vector<float>) List of aspect ratios of generated prior boxes."
);
...
...
@@ -125,16 +125,16 @@ class PriorBoxOpMaker : public framework::OpProtoAndCheckerMaker {
.
SetDefault
(
true
);
AddAttr
<
float
>
(
"step_w"
,
"Prior boxes step across width, 0 for auto calculation."
)
"Prior boxes step across width, 0
.0
for auto calculation."
)
.
SetDefault
(
0.0
)
.
AddCustomChecker
([](
const
float
&
step_w
)
{
PADDLE_ENFORCE_G
T
(
step_w
,
0.0
,
"step_w should be larger than 0."
);
PADDLE_ENFORCE_G
E
(
step_w
,
0.0
,
"step_w should be larger than 0."
);
});
AddAttr
<
float
>
(
"step_h"
,
"Prior boxes step across height, 0 for auto calculation."
)
"Prior boxes step across height, 0
.0
for auto calculation."
)
.
SetDefault
(
0.0
)
.
AddCustomChecker
([](
const
float
&
step_h
)
{
PADDLE_ENFORCE_G
T
(
step_h
,
0.0
,
"step_h should be larger than 0."
);
PADDLE_ENFORCE_G
E
(
step_h
,
0.0
,
"step_h should be larger than 0."
);
});
AddAttr
<
float
>
(
"offset"
,
...
...
paddle/fluid/operators/prior_box_op.h
浏览文件 @
7757a8ad
...
...
@@ -60,8 +60,8 @@ class PriorBoxOpKernel : public framework::OpKernel<T> {
auto
*
boxes
=
ctx
.
Output
<
paddle
::
framework
::
Tensor
>
(
"Boxes"
);
auto
*
vars
=
ctx
.
Output
<
paddle
::
framework
::
Tensor
>
(
"Variances"
);
auto
min_sizes
=
ctx
.
Attr
<
std
::
vector
<
in
t
>>
(
"min_sizes"
);
auto
max_sizes
=
ctx
.
Attr
<
std
::
vector
<
in
t
>>
(
"max_sizes"
);
auto
min_sizes
=
ctx
.
Attr
<
std
::
vector
<
floa
t
>>
(
"min_sizes"
);
auto
max_sizes
=
ctx
.
Attr
<
std
::
vector
<
floa
t
>>
(
"max_sizes"
);
auto
input_aspect_ratio
=
ctx
.
Attr
<
std
::
vector
<
float
>>
(
"aspect_ratios"
);
auto
variances
=
ctx
.
Attr
<
std
::
vector
<
float
>>
(
"variances"
);
auto
flip
=
ctx
.
Attr
<
bool
>
(
"flip"
);
...
...
@@ -108,7 +108,7 @@ class PriorBoxOpKernel : public framework::OpKernel<T> {
T
box_width
,
box_height
;
int
idx
=
0
;
for
(
size_t
s
=
0
;
s
<
min_sizes
.
size
();
++
s
)
{
int
min_size
=
min_sizes
[
s
];
auto
min_size
=
min_sizes
[
s
];
// first prior: aspect_ratio = 1, size = min_size
box_width
=
box_height
=
min_size
;
// xmin
...
...
@@ -124,7 +124,7 @@ class PriorBoxOpKernel : public framework::OpKernel<T> {
idx
++
;
if
(
max_sizes
.
size
()
>
0
)
{
int
max_size
=
max_sizes
[
s
];
auto
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
);
...
...
python/paddle/v2/fluid/layers/__init__.py
浏览文件 @
7757a8ad
...
...
@@ -28,8 +28,11 @@ import device
from
device
import
*
import
math_op_patch
from
math_op_patch
import
*
import
detection
from
detection
import
*
__all__
=
[]
__all__
+=
math_op_patch
.
__all__
__all__
+=
detection
.
__all__
__all__
+=
nn
.
__all__
__all__
+=
io
.
__all__
...
...
@@ -37,4 +40,4 @@ __all__ += tensor.__all__
__all__
+=
control_flow
.
__all__
__all__
+=
ops
.
__all__
__all__
+=
device
.
__all__
__all__
+=
math_op_patch
.
__all__
__all__
+=
detection
.
__all__
python/paddle/v2/fluid/layers/detection.py
浏览文件 @
7757a8ad
# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserve.
# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserve
d
.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
...
...
@@ -16,8 +16,15 @@ All layers just related to the detection neural network.
"""
from
..layer_helper
import
LayerHelper
from
..framework
import
Variable
from
tensor
import
concat
from
ops
import
reshape
import
math
__all__
=
[
'detection_output'
,
]
__all__
=
[
'detection_output'
,
'prior_box'
,
]
def
detection_output
(
scores
,
...
...
@@ -114,3 +121,208 @@ def detection_output(scores,
'nms_eta'
:
1.0
})
return
nmsed_outs
def
prior_box
(
inputs
,
image
,
min_ratio
,
max_ratio
,
aspect_ratios
,
base_size
,
steps
=
None
,
step_w
=
None
,
step_h
=
None
,
offset
=
0.5
,
variance
=
[
0.1
,
0.1
,
0.1
,
0.1
],
flip
=
False
,
clip
=
False
,
min_sizes
=
None
,
max_sizes
=
None
,
name
=
None
):
"""
**Prior_boxes**
Generate prior boxes for SSD(Single Shot MultiBox Detector)
algorithm. The details of this algorithm, please refer the
section 2.2 of SSD paper (SSD: Single Shot MultiBox Detector)
<https://arxiv.org/abs/1512.02325>`_ .
Args:
inputs(list): The list of input Variables, the format
of all Variables is NCHW.
image(Variable): The input image data of PriorBoxOp,
the layout is NCHW.
min_ratio(int): the min ratio of generated prior boxes.
max_ratio(int): the max ratio of generated prior boxes.
aspect_ratios(list): the aspect ratios of generated prior
boxes. The length of input and aspect_ratios must be equal.
base_size(int): the base_size is used to get min_size
and max_size according to min_ratio and max_ratio.
step_w(list, optional, default=None): Prior boxes step
across width. If step_w[i] == 0.0, the prior boxes step
across width of the inputs[i] will be automatically calculated.
step_h(list, optional, default=None): Prior boxes step
across height, If step_h[i] == 0.0, the prior boxes
step across height of the inputs[i] will be automatically calculated.
offset(float, optional, default=0.5): Prior boxes center offset.
variance(list, optional, default=[0.1, 0.1, 0.1, 0.1]): the variances
to be encoded in prior boxes.
flip(bool, optional, default=False): Whether to flip
aspect ratios.
clip(bool, optional, default=False): Whether to clip
out-of-boundary boxes.
min_sizes(list, optional, default=None): If `len(inputs) <=2`,
min_sizes must be set up, and the length of min_sizes
should equal to the length of inputs.
max_sizes(list, optional, default=None): If `len(inputs) <=2`,
max_sizes must be set up, and the length of min_sizes
should equal to the length of inputs.
name(str, optional, None): Name of the prior box layer.
Returns:
boxes(Variable): the output prior boxes of PriorBoxOp.
The layout is [num_priors, 4]. num_priors is the total
box count of each position of inputs.
Variances(Variable): the expanded variances of PriorBoxOp.
The layout is [num_priors, 4]. num_priors is the total
box count of each position of inputs
Examples:
.. code-block:: python
prior_box(
inputs = [conv1, conv2, conv3, conv4, conv5, conv6],
image = data,
min_ratio = 20, # 0.20
max_ratio = 90, # 0.90
offset = 0.5,
base_size = 300,
variance = [0.1,0.1,0.1,0.1],
aspect_ratios = [[2.], [2., 3.], [2., 3.], [2., 3.], [2.], [2.]],
flip=True,
clip=True)
"""
def
_prior_box_
(
input
,
image
,
min_sizes
,
max_sizes
,
aspect_ratios
,
variance
,
flip
=
False
,
clip
=
False
,
step_w
=
0.0
,
step_h
=
0.0
,
offset
=
0.5
,
name
=
None
):
helper
=
LayerHelper
(
"prior_box"
,
**
locals
())
dtype
=
helper
.
input_dtype
()
box
=
helper
.
create_tmp_variable
(
dtype
)
var
=
helper
.
create_tmp_variable
(
dtype
)
helper
.
append_op
(
type
=
"prior_box"
,
inputs
=
{
"Input"
:
input
,
"Image"
:
image
},
outputs
=
{
"Boxes"
:
box
,
"Variances"
:
var
},
attrs
=
{
'min_sizes'
:
min_sizes
,
'max_sizes'
:
max_sizes
,
'aspect_ratios'
:
aspect_ratios
,
'variances'
:
variance
,
'flip'
:
flip
,
'clip'
:
clip
,
'step_w'
:
step_w
,
'step_h'
:
step_h
,
'offset'
:
offset
})
return
box
,
var
def
_reshape_with_axis_
(
input
,
axis
=
1
):
if
not
(
axis
>
0
and
axis
<
len
(
input
.
shape
)):
raise
ValueError
(
"The axis should be smaller than "
"the arity of input and bigger than 0."
)
new_shape
=
[
-
1
,
reduce
(
lambda
x
,
y
:
x
*
y
,
input
.
shape
[
axis
:
len
(
input
.
shape
)])
]
out
=
reshape
(
x
=
input
,
shape
=
new_shape
)
return
out
assert
isinstance
(
inputs
,
list
),
'inputs should be a list.'
num_layer
=
len
(
inputs
)
if
num_layer
<=
2
:
assert
min_sizes
is
not
None
and
max_sizes
is
not
None
assert
len
(
min_sizes
)
==
num_layer
and
len
(
max_sizes
)
==
num_layer
else
:
min_sizes
=
[]
max_sizes
=
[]
step
=
int
(
math
.
floor
(((
max_ratio
-
min_ratio
))
/
(
num_layer
-
2
)))
for
ratio
in
xrange
(
min_ratio
,
max_ratio
+
1
,
step
):
min_sizes
.
append
(
base_size
*
ratio
/
100.
)
max_sizes
.
append
(
base_size
*
(
ratio
+
step
)
/
100.
)
min_sizes
=
[
base_size
*
.
10
]
+
min_sizes
max_sizes
=
[
base_size
*
.
20
]
+
max_sizes
if
aspect_ratios
:
if
not
(
isinstance
(
aspect_ratios
,
list
)
and
len
(
aspect_ratios
)
==
num_layer
):
raise
ValueError
(
'aspect_ratios should be list and the length of inputs '
'and aspect_ratios should be the same.'
)
if
step_h
:
if
not
(
isinstance
(
step_h
,
list
)
and
len
(
step_h
)
==
num_layer
):
raise
ValueError
(
'step_h should be list and the length of inputs and '
'step_h should be the same.'
)
if
step_w
:
if
not
(
isinstance
(
step_w
,
list
)
and
len
(
step_w
)
==
num_layer
):
raise
ValueError
(
'step_w should be list and the length of inputs and '
'step_w should be the same.'
)
if
steps
:
if
not
(
isinstance
(
steps
,
list
)
and
len
(
steps
)
==
num_layer
):
raise
ValueError
(
'steps should be list and the length of inputs and '
'step_w should be the same.'
)
step_w
=
steps
step_h
=
steps
box_results
=
[]
var_results
=
[]
for
i
,
input
in
enumerate
(
inputs
):
min_size
=
min_sizes
[
i
]
max_size
=
max_sizes
[
i
]
aspect_ratio
=
[]
if
not
isinstance
(
min_size
,
list
):
min_size
=
[
min_size
]
if
not
isinstance
(
max_size
,
list
):
max_size
=
[
max_size
]
if
aspect_ratios
:
aspect_ratio
=
aspect_ratios
[
i
]
if
not
isinstance
(
aspect_ratio
,
list
):
aspect_ratio
=
[
aspect_ratio
]
box
,
var
=
_prior_box_
(
input
,
image
,
min_size
,
max_size
,
aspect_ratio
,
variance
,
flip
,
clip
,
step_w
[
i
]
if
step_w
else
0.0
,
step_h
[
i
]
if
step_w
else
0.0
,
offset
)
box_results
.
append
(
box
)
var_results
.
append
(
var
)
if
len
(
box_results
)
==
1
:
box
=
box_results
[
0
]
var
=
var_results
[
0
]
else
:
reshaped_boxes
=
[]
reshaped_vars
=
[]
for
i
in
range
(
len
(
box_results
)):
reshaped_boxes
.
append
(
_reshape_with_axis_
(
box_results
[
i
],
axis
=
3
))
reshaped_vars
.
append
(
_reshape_with_axis_
(
var_results
[
i
],
axis
=
3
))
box
=
concat
(
reshaped_boxes
)
var
=
concat
(
reshaped_vars
)
return
box
,
var
python/paddle/v2/fluid/tests/test_detection.py
浏览文件 @
7757a8ad
...
...
@@ -13,10 +13,13 @@
# limitations under the License.
from
__future__
import
print_function
import
unittest
import
paddle.v2.fluid
as
fluid
import
paddle.v2.fluid.core
as
core
import
paddle.v2.fluid.layers
as
layers
import
paddle.v2.fluid.layers.detection
as
detection
from
paddle.v2.fluid.framework
import
Program
,
program_guard
import
unittest
import
numpy
as
np
class
TestBook
(
unittest
.
TestCase
):
...
...
@@ -49,5 +52,62 @@ class TestBook(unittest.TestCase):
print
(
str
(
program
))
class
TestPriorBox
(
unittest
.
TestCase
):
def
test_prior_box
(
self
):
data_shape
=
[
3
,
224
,
224
]
box
,
var
=
self
.
prior_box_output
(
data_shape
)
assert
len
(
box
.
shape
)
==
2
assert
box
.
shape
==
var
.
shape
assert
box
.
shape
[
1
]
==
4
def
prior_box_output
(
self
,
data_shape
):
images
=
fluid
.
layers
.
data
(
name
=
'pixel'
,
shape
=
data_shape
,
dtype
=
'float32'
)
conv1
=
fluid
.
layers
.
conv2d
(
input
=
images
,
num_filters
=
3
,
filter_size
=
3
,
stride
=
2
,
use_cudnn
=
False
)
conv2
=
fluid
.
layers
.
conv2d
(
input
=
conv1
,
num_filters
=
3
,
filter_size
=
3
,
stride
=
2
,
use_cudnn
=
False
)
conv3
=
fluid
.
layers
.
conv2d
(
input
=
conv2
,
num_filters
=
3
,
filter_size
=
3
,
stride
=
2
,
use_cudnn
=
False
)
conv4
=
fluid
.
layers
.
conv2d
(
input
=
conv3
,
num_filters
=
3
,
filter_size
=
3
,
stride
=
2
,
use_cudnn
=
False
)
conv5
=
fluid
.
layers
.
conv2d
(
input
=
conv4
,
num_filters
=
3
,
filter_size
=
3
,
stride
=
2
,
use_cudnn
=
False
)
box
,
var
=
detection
.
prior_box
(
inputs
=
[
conv1
,
conv2
,
conv3
,
conv4
,
conv5
,
conv5
],
image
=
images
,
min_ratio
=
20
,
max_ratio
=
90
,
# steps=[8, 16, 32, 64, 100, 300],
aspect_ratios
=
[[
2.
],
[
2.
,
3.
],
[
2.
,
3.
],
[
2.
,
3.
],
[
2.
],
[
2.
]],
base_size
=
300
,
offset
=
0.5
,
flip
=
True
,
clip
=
True
)
return
box
,
var
if
__name__
==
'__main__'
:
unittest
.
main
()
python/paddle/v2/fluid/tests/test_prior_box_op.py
浏览文件 @
7757a8ad
...
...
@@ -65,9 +65,9 @@ class TestPriorBoxOp(OpTest):
self
.
batch_size
=
10
self
.
min_sizes
=
[
2
,
4
]
self
.
min_sizes
=
np
.
array
(
self
.
min_sizes
).
astype
(
'
int64'
)
self
.
min_sizes
=
np
.
array
(
self
.
min_sizes
).
astype
(
'
float32'
).
tolist
(
)
self
.
max_sizes
=
[
5
,
10
]
self
.
max_sizes
=
np
.
array
(
self
.
max_sizes
).
astype
(
'
int64'
)
self
.
max_sizes
=
np
.
array
(
self
.
max_sizes
).
astype
(
'
float32'
).
tolist
(
)
self
.
aspect_ratios
=
[
2.0
,
3.0
]
self
.
flip
=
True
self
.
real_aspect_ratios
=
[
1
,
2.0
,
1.0
/
2.0
,
3.0
,
1.0
/
3.0
]
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录