Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
Paddle
提交
35dec3d7
P
Paddle
项目概览
PaddlePaddle
/
Paddle
1 年多 前同步成功
通知
2305
Star
20932
Fork
5423
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1423
列表
看板
标记
里程碑
合并请求
543
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
Paddle
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1,423
Issue
1,423
列表
看板
标记
里程碑
合并请求
543
合并请求
543
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
35dec3d7
编写于
1月 30, 2018
作者:
D
dangqingqing
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fix bug in unit test.
上级
2731fd96
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
82 addition
and
63 deletion
+82
-63
paddle/operators/multiclass_nms_op.cc
paddle/operators/multiclass_nms_op.cc
+50
-34
python/paddle/v2/fluid/tests/test_multiclass_nms_op.py
python/paddle/v2/fluid/tests/test_multiclass_nms_op.py
+32
-29
未找到文件。
paddle/operators/multiclass_nms_op.cc
浏览文件 @
35dec3d7
...
...
@@ -41,13 +41,22 @@ class MulticlassNMSOp : public framework::OperatorWithKernel {
"The rank of Input(Bboxes) must be 3."
);
PADDLE_ENFORCE_EQ
(
score_dims
.
size
(),
3
,
"The rank of Input(Scores) must be 3."
);
PADDLE_ENFORCE_EQ
(
box_dims
[
2
],
4
);
PADDLE_ENFORCE_EQ
(
box_dims
[
1
],
4
);
PADDLE_ENFORCE_EQ
(
box_dims
[
0
],
score_dims
[
2
]);
// Here the box_dims[0] is not the real dimension of output.
// It will be rewritten in the computing kernel.
ctx
->
SetOutputDim
(
"Out"
,
{
box_dims
[
0
],
6
});
}
protected:
framework
::
OpKernelType
GetExpectedKernelType
(
const
framework
::
ExecutionContext
&
ctx
)
const
override
{
return
framework
::
OpKernelType
(
framework
::
ToDataType
(
ctx
.
Input
<
framework
::
LoDTensor
>
(
"Scores"
)
->
type
()),
ctx
.
device_context
());
}
};
template
<
class
T
>
...
...
@@ -158,12 +167,12 @@ class MulticlassNMSKernel : public framework::OpKernel<T> {
const
Tensor
&
scores
,
const
Tensor
&
bboxes
,
std
::
map
<
int
,
std
::
vector
<
int
>>*
indices
,
int
*
num_nmsed_out
)
const
{
int64_t
background_label
=
ctx
.
Attr
<
int
64_t
>
(
"background_label"
);
int64_t
nms_top_k
=
ctx
.
Attr
<
int
64_t
>
(
"nms_top_k"
);
int64_t
keep_top_k
=
ctx
.
Attr
<
int
64_t
>
(
"keep_top_k"
);
int64_t
background_label
=
ctx
.
Attr
<
int
>
(
"background_label"
);
int64_t
nms_top_k
=
ctx
.
Attr
<
int
>
(
"nms_top_k"
);
int64_t
keep_top_k
=
ctx
.
Attr
<
int
>
(
"keep_top_k"
);
T
nms_threshold
=
static_cast
<
T
>
(
ctx
.
Attr
<
float
>
(
"nms_threshold"
));
T
nms_eta
=
static_cast
<
T
>
(
ctx
.
Attr
<
float
>
(
"nms_eta"
));
T
score_threshold
=
static_cast
<
T
>
(
ctx
.
Attr
<
float
>
(
"
confidenc
e_threshold"
));
T
score_threshold
=
static_cast
<
T
>
(
ctx
.
Attr
<
float
>
(
"
scor
e_threshold"
));
int64_t
class_num
=
scores
.
dims
()[
0
];
int64_t
predict_dim
=
scores
.
dims
()[
1
];
...
...
@@ -173,7 +182,7 @@ class MulticlassNMSKernel : public framework::OpKernel<T> {
Tensor
score
=
scores
.
Slice
(
c
,
c
+
1
);
NMSFast
(
bboxes
,
score
,
score_threshold
,
nms_threshold
,
nms_eta
,
nms_top_k
,
&
((
*
indices
)[
c
]));
num_det
+=
indices
[
c
].
size
();
num_det
+=
(
*
indices
)
[
c
].
size
();
}
*
num_nmsed_out
=
num_det
;
...
...
@@ -230,8 +239,8 @@ class MulticlassNMSKernel : public framework::OpKernel<T> {
odata
[
count
*
kOutputDim
+
3
]
=
bdata
[
1
];
// ymin
odata
[
count
*
kOutputDim
+
4
]
=
bdata
[
2
];
// xmax
odata
[
count
*
kOutputDim
+
5
]
=
bdata
[
3
];
// ymax
count
++
;
}
count
++
;
}
}
...
...
@@ -240,10 +249,9 @@ class MulticlassNMSKernel : public framework::OpKernel<T> {
auto
*
scores
=
ctx
.
Input
<
Tensor
>
(
"Scores"
);
auto
*
outs
=
ctx
.
Output
<
LoDTensor
>
(
"Out"
);
auto
box_dims
=
boxes
->
dims
();
auto
score_dims
=
scores
->
dims
();
int64_t
batch_size
=
box
_dims
[
0
];
int64_t
batch_size
=
score
_dims
[
0
];
int64_t
class_num
=
score_dims
[
1
];
int64_t
predict_dim
=
score_dims
[
2
];
...
...
@@ -291,35 +299,37 @@ class MulticlassNMSOpMaker : public framework::OpProtoAndCheckerMaker {
"(Tensor) A 2-D Tensor with shape [M, 4] represents the location "
"predictions with M bboxes. 4 is the number of "
"each location coordinates."
);
Add
Out
put
(
"Scores"
,
"(Tensor) A 3-D Tensor with shape [N, C, M] represents the "
"confidence predictions. N is the batch size, C is the class "
"number, M is number of predictions for each class, which is "
"the same with Bboxes."
);
AddAttr
<
int
64_t
>
(
Add
In
put
(
"Scores"
,
"(Tensor) A 3-D Tensor with shape [N, C, M] represents the "
"confidence predictions. N is the batch size, C is the class "
"number, M is number of predictions for each class, which is "
"the same with Bboxes."
);
AddAttr
<
int
>
(
"background_label"
,
"(int64_t, defalut: 0) "
"The index of background label, the background label will be ignored."
)
.
SetDefault
(
0
);
AddAttr
<
float
>
(
"score_threshold"
,
"(float) "
"Only consider detections whose confidences are larger than "
"a threshold. If not provided, consider all boxes."
);
AddAttr
<
int
>
(
"nms_top_k"
,
"(int64_t) "
"Maximum number of detections to be kept according to the "
"confidences aftern the filtering detections based on "
"score_threshold"
);
AddAttr
<
float
>
(
"nms_threshold"
,
"(float, defalut: 0.3) "
"The threshold to be used in
nms
."
)
"The threshold to be used in
NMS
."
)
.
SetDefault
(
0.3
);
AddAttr
<
int64_t
>
(
"nms_top_k"
,
"(int64_t) "
"Maximum number of results to be kept."
);
AddAttr
<
float
>
(
"nms_eta"
,
"(float) "
"The parameter for adaptive
nms
."
)
"The parameter for adaptive
NMS
."
)
.
SetDefault
(
1.0
);
AddAttr
<
int64_t
>
(
"keep_top_k"
,
"(int64_t) "
"Number of total bboxes to be kept per image after nms "
"step. -1 means keeping all bboxes after nms step."
);
AddAttr
<
float
>
(
"confidence_threshold"
,
"(float) "
"Only consider detections whose confidences are larger than "
"a threshold. If not provided, consider all boxes."
);
AddAttr
<
int
>
(
"keep_top_k"
,
"(int64_t) "
"Number of total bboxes to be kept per image after NMS "
"step. -1 means keeping all bboxes after NMS step."
);
AddOutput
(
"Out"
,
"(LoDTensor) A 2-D LoDTensor with shape [No, 6] represents the "
"detections. Each row has 6 values: "
...
...
@@ -329,15 +339,21 @@ class MulticlassNMSOpMaker : public framework::OpProtoAndCheckerMaker {
"offset is N + 1, if LoD[i + 1] - LoD[i] == 0, means there is "
"no detected bbox."
);
AddComment
(
R"DOC(
This operator
s
is to do multi-class non maximum suppression (NMS) on a batched
This operator is to do multi-class non maximum suppression (NMS) on a batched
of boxes and scores.
This op greedily selects a subset of detection bounding boxes, pruning
away boxes that have high IOU (intersection over union) overlap (> thresh)
with already selected boxes. It operates independently for each class for
which scores are provided, pruning boxes with score less than a provided
threshold prior to applying NMS.
In the NMS step, this operator greedily selects a subset of detection bounding
boxes that have high scores larger than score_threshold, if providing this
threshold, then selects the largest nms_top_k confidences scores if nms_top_k
is larger than -1. Then this operator pruns away boxes that have high IOU
(intersection over union) overlap with already selected boxes by adaptive
threshold NMS based on parameters of nms_threshold and nms_eta.
Aftern NMS step, only at most keep_top_k number of total bboxes are to be kept
per image if keep_top_k is larger than -1.
This operator support multi-class and batched inputs. It applying NMS
independently for each class.
)DOC"
);
}
};
...
...
python/paddle/v2/fluid/tests/test_multiclass_nms_op.py
浏览文件 @
35dec3d7
...
...
@@ -69,7 +69,7 @@ def nms(boxes, scores, score_threshold, nms_threshold, top_k=200, eta=1.0):
sorted_indices
=
np
.
argsort
(
-
all_scores
,
axis
=
0
)
sorted_scores
=
all_scores
[
sorted_indices
]
if
top_k
<
-
1
and
top_k
<
sorted_indices
.
shape
[
0
]:
if
top_k
>
-
1
and
top_k
<
sorted_indices
.
shape
[
0
]:
sorted_indices
=
sorted_indices
[:
top_k
]
sorted_scores
=
sorted_scores
[:
top_k
]
...
...
@@ -82,7 +82,7 @@ def nms(boxes, scores, score_threshold, nms_threshold, top_k=200, eta=1.0):
if
keep
:
kept_idx
=
selected_indices
[
k
]
overlap
=
iou
(
boxes
[
idx
],
boxes
[
kept_idx
])
keep
=
overlap
<=
adaptive_threshold
keep
=
True
if
overlap
<=
adaptive_threshold
else
False
else
:
break
if
keep
:
...
...
@@ -103,14 +103,14 @@ def multiclass_nms(boxes, scores, background, score_threshold, nms_threshold,
if
c
==
background
:
continue
indices
=
nms
(
boxes
,
scores
[
c
],
score_threshold
,
nms_threshold
,
nms_top_k
)
selected_indices
.
append
((
c
,
indices
))
for
idx
in
indices
:
selected_indices
.
append
((
c
,
idx
))
num_det
+=
len
(
indices
)
if
keep_top_k
>
-
1
and
num_det
>
keep_top_k
:
score_index
=
[]
for
c
,
indices
in
selected_indices
:
for
idx
in
indices
:
score_index
.
append
((
scores
[
c
][
idx
],
c
,
idx
))
for
c
,
idx
in
selected_indices
:
score_index
.
append
((
scores
[
c
][
idx
],
c
,
idx
))
sorted_score_index
=
sorted
(
score_index
,
key
=
lambda
tup
:
tup
[
0
],
reverse
=
True
)
...
...
@@ -134,19 +134,16 @@ def batched_multiclass_nms(boxes, scores, background, score_threshold,
keep_top_k
)
lod
.
append
(
lod
[
-
1
]
+
len
(
nmsed_outs
))
if
len
(
nmsed_outs
)
==
0
:
continue
for
c
,
indices
in
nmsed_outs
:
for
idx
in
indices
:
xmin
,
ymin
,
xmax
,
ymax
=
boxes
[
idx
][:]
det_outs
.
append
(
(
c
,
scores
[
n
][
c
][
idx
],
c
,
xmin
,
ymin
,
xmax
,
ymax
))
for
c
,
idx
in
nmsed_outs
:
xmin
,
ymin
,
xmax
,
ymax
=
boxes
[
idx
][:]
det_outs
.
append
([
c
,
scores
[
n
][
c
][
idx
],
xmin
,
ymin
,
xmax
,
ymax
])
return
det_outs
,
lod
class
TestMulticlassNMSOp
(
OpTest
):
def
setUp
(
self
):
self
.
op_type
=
'multiclass_nms'
N
=
7
M
=
12
3
0
M
=
12
4
0
C
=
21
BOX_SIZE
=
4
background
=
0
...
...
@@ -155,7 +152,17 @@ class TestMulticlassNMSOp(OpTest):
keep_top_k
=
200
score_threshold
=
0.01
scores
=
np
.
random
.
random
((
N
,
C
,
M
)).
astype
(
'float32'
)
scores
=
np
.
random
.
random
((
N
*
M
,
C
)).
astype
(
'float32'
)
def
softmax
(
x
):
shiftx
=
x
-
np
.
max
(
x
).
clip
(
-
64.
)
exps
=
np
.
exp
(
shiftx
)
return
exps
/
np
.
sum
(
exps
)
scores
=
np
.
apply_along_axis
(
softmax
,
1
,
scores
)
scores
=
np
.
reshape
(
scores
,
(
N
,
M
,
C
))
scores
=
np
.
transpose
(
scores
,
(
0
,
2
,
1
))
boxes
=
np
.
random
.
random
((
M
,
BOX_SIZE
)).
astype
(
'float32'
)
boxes
[:,
0
:
2
]
=
boxes
[:,
0
:
2
]
*
0.5
boxes
[:,
2
:
4
]
=
boxes
[:,
0
:
2
]
*
0.5
+
0.5
...
...
@@ -163,8 +170,19 @@ class TestMulticlassNMSOp(OpTest):
nmsed_outs
,
lod
=
batched_multiclass_nms
(
boxes
,
scores
,
background
,
score_threshold
,
nms_threshold
,
nms_top_k
,
keep_top_k
)
nmsed_outs
=
np
.
array
(
nmsed_outs
).
astype
(
'float32'
)
self
.
op_type
=
'multiclass_nms'
self
.
inputs
=
{
'Bboxes'
:
boxes
,
'Scores'
:
scores
}
self
.
outputs
=
{
'Out'
:
(
nmsed_outs
,
[
lod
])}
self
.
attrs
=
{
'background_label'
:
0
,
'nms_threshold'
:
nms_threshold
,
'nms_top_k'
:
nms_top_k
,
'keep_top_k'
:
keep_top_k
,
'score_threshold'
:
score_threshold
,
'nms_eta'
:
1.0
,
}
def
test_check_output
(
self
):
self
.
check_output
()
...
...
@@ -182,18 +200,3 @@ class TestIOU(unittest.TestCase):
if
__name__
==
'__main__'
:
unittest
.
main
()
# N = 7
# M = 8
# C = 5
# BOX_SIZE = 4
# background = 0
# nms_threshold = 0.3
# nms_top_k = 400
# keep_top_k = 200
# score_threshold = 0.5
# scores = np.random.random((N, C, M)).astype('float32')
# boxes = np.random.random((M, BOX_SIZE)).astype('float32')
# boxes[:, 0 : 2] = boxes[:, 0 : 2] * 0.5
# boxes[:, 2 : 4] = boxes[:, 0 : 2] * 0.5 + 0.5
# print nmsed_outs, lod
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录