Meiyang/paddle generate proposals 2 (#11285)

* create new op v9::GenerateProposalsSingleImage and support paddle generate proposal v2

* support scale in GenerateProposals

* Add output roi_num in GenerateProposal; change anchor's shape to [H, W, A, 4]

* fix paddle generate proposals frontend issue

* rename MKLDNNGenerateProposalsSingleImage to GenerateProposalsSingleImage

* add GenerateProposals attribute 'roi_num_type'

* fuse type togenerate_proposals

* multibatch support

* fix review comments; paddle tests added

* use pad instead of concat

* fix generate proposals visitor test parameter

* add testcase for generate proposal scale and fix generate proposals reference issue

* rename to GenerateProposals

* add generate proposals ngraph reshape test; opset9 support and test;

* fix compiling issue

* add dependency 'paddledet' on paddle frontend test

* Update src/core/include/ngraph/op/generate_proposals.hpp

Co-authored-by: Ilya Churaev <ilyachur@gmail.com>

* Update src/core/include/openvino/op/generate_proposals.hpp

Co-authored-by: Ilya Churaev <ilyachur@gmail.com>

* Update src/core/reference/include/ngraph/runtime/reference/generate_proposal.hpp

Co-authored-by: Ilya Churaev <ilyachur@gmail.com>

* Update src/core/src/op/generate_proposals.cpp

Co-authored-by: Ilya Churaev <ilyachur@gmail.com>

* Update src/core/include/ngraph/op/generate_proposals.hpp

Co-authored-by: Ilya Churaev <ilyachur@gmail.com>

* Update src/core/src/op/generate_proposals.cpp

Co-authored-by: Ilya Churaev <ilyachur@gmail.com>

* Update src/core/src/op/generate_proposals.cpp

Co-authored-by: Ilya Churaev <ilyachur@gmail.com>

* Update src/core/src/op/generate_proposals.cpp

Co-authored-by: Ilya Churaev <ilyachur@gmail.com>

* Update src/core/include/openvino/op/generate_proposals.hpp

Co-authored-by: Ilya Churaev <ilyachur@gmail.com>

* Update src/core/include/openvino/op/generate_proposals.hpp

Co-authored-by: Ilya Churaev <ilyachur@gmail.com>

* fix compiling issue after newly added commit

* clang fix

* fix compiling issue

* add paddledet dependency

* fix compiling issue

* fix compiling issue

* clang fix

* skip ppdet.modeling.ops in paddle generate proposals test

* single layer update after rebase master

* set pycocotools to 2.0.4

* skip ppdet.modeling.ops.__init__

* add paddle test dependency

* fix template issue

* rename mkldnn to dnnl

* fix template issue

* fix windows compiling issue

* update testcase vector construction

* add shape check and test; add some annotation; apply review suggestion

* Revert "add paddle test dependency"

This reverts commit 959a2d770d3f6cb28d4609981c79cc49a25847fd.

* rm dependency of paddledet for paddle frontend test

* update opset9 number

* fix windows issue

Co-authored-by: Luo Cheng <cheng.luo@intel.com>
Co-authored-by: Ilya Churaev <ilyachur@gmail.com>
This commit is contained in:
mei, yang
2022-05-16 09:13:52 +08:00
committed by GitHub
parent 6ce6a7662e
commit 9648080fbc
36 changed files with 2783 additions and 6 deletions

View File

@@ -41,6 +41,7 @@
#include <ngraph/runtime/reference/gather_nd.hpp>
#include <ngraph/runtime/reference/gather_tree.hpp>
#include <ngraph/runtime/reference/gelu.hpp>
#include <ngraph/runtime/reference/generate_proposal.hpp>
#include <ngraph/runtime/reference/greater.hpp>
#include <ngraph/runtime/reference/grn.hpp>
#include <ngraph/runtime/reference/group_convolution.hpp>
@@ -3296,6 +3297,79 @@ bool evaluate(const shared_ptr<op::v6::ExperimentalDetectronTopKROIs>& op,
return true;
}
template <element::Type_t ET>
bool evaluate(const shared_ptr<op::v9::GenerateProposals>& op,
const HostTensorVector& outputs,
const HostTensorVector& inputs) {
const auto attrs = op->get_attrs();
size_t post_nms_count = 0;
if (attrs.post_nms_count < 0) {
throw ngraph_error("The attribute post_nms_count of the operation "
"GenerateProposals must be a "
"nonnegative integer.");
} else {
post_nms_count = static_cast<size_t>(attrs.post_nms_count);
}
const auto output_type = op->get_input_element_type(0);
const auto im_info_shape = inputs[0]->get_shape();
const auto anchors_shape = inputs[1]->get_shape();
const auto deltas_shape = inputs[2]->get_shape();
const auto scores_shape = inputs[3]->get_shape();
const auto im_info_data = get_floats(inputs[0], im_info_shape);
const auto anchors_data = get_floats(inputs[1], anchors_shape);
const auto deltas_data = get_floats(inputs[2], deltas_shape);
const auto scores_data = get_floats(inputs[3], scores_shape);
std::vector<float> output_rois;
std::vector<float> output_scores;
std::vector<int64_t> output_num;
runtime::reference::generate_proposals(im_info_data,
anchors_data,
deltas_data,
scores_data,
attrs,
im_info_shape,
anchors_shape,
deltas_shape,
scores_shape,
output_rois,
output_scores,
output_num);
uint64_t num_selected = static_cast<uint64_t>(std::accumulate(output_num.begin(), output_num.end(), 0));
Shape output_rois_shape = Shape{num_selected, 4};
Shape output_scores_shape = Shape{num_selected};
outputs[0]->set_element_type(output_type);
outputs[0]->set_shape(output_rois_shape);
outputs[1]->set_element_type(output_type);
outputs[1]->set_shape(output_scores_shape);
const auto roi_num_type = op->get_output_element_type(2);
Shape output_roi_num_shape = Shape{im_info_shape[0]};
outputs[2]->set_element_type(roi_num_type);
outputs[2]->set_shape(output_roi_num_shape);
runtime::reference::generate_proposals_postprocessing(outputs[0]->get_data_ptr(),
outputs[1]->get_data_ptr(),
outputs[2]->get_data_ptr(),
output_type,
roi_num_type,
output_rois,
output_scores,
output_num,
output_rois_shape,
output_scores_shape);
return true;
}
template <element::Type_t ET>
bool evaluate(const shared_ptr<op::v6::ExperimentalDetectronGenerateProposalsSingleImage>& op,
const HostTensorVector& outputs,

View File

@@ -98,6 +98,7 @@ NGRAPH_OP(Assign, ngraph::op::v6)
NGRAPH_OP(CTCGreedyDecoderSeqLen, op::v6)
NGRAPH_OP(ExperimentalDetectronDetectionOutput, op::v6)
NGRAPH_OP(ExperimentalDetectronGenerateProposalsSingleImage, op::v6)
NGRAPH_OP(GenerateProposals, op::v9)
NGRAPH_OP(ExperimentalDetectronPriorGridGenerator, op::v6)
NGRAPH_OP(ExperimentalDetectronROIFeatureExtractor, op::v6)
NGRAPH_OP(ExperimentalDetectronTopKROIs, op::v6)

View File

@@ -0,0 +1,307 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <gtest/gtest.h>
#include "openvino/op/generate_proposals.hpp"
#include "base_reference_test.hpp"
using namespace reference_tests;
using namespace ov;
using Attrs = op::v9::GenerateProposals::Attributes;
namespace {
struct GPParams {
template <class IT, class RT>
GPParams(const Attrs& attrs,
const size_t batch, const size_t number_of_channels, const size_t height, const size_t width,
const element::Type& iType, const element::Type& roiNumType,
const std::vector<IT>& imageSizeInfoValues, const std::vector<IT>& anchorsValues,
const std::vector<IT>& deltasValues, const std::vector<IT>& scoresValues,
const std::vector<IT>& refRoisValues, const std::vector<IT>& refScoresValues,
const std::vector<RT>& refRoiNumValues,
const std::string& testcaseName = "")
: attrs(attrs),
inType(iType),
outType(iType),
roiNumType(roiNumType),
imageSizeInfoData(CreateTensor(iType, imageSizeInfoValues)),
anchorsData(CreateTensor(iType, anchorsValues)),
deltasData(CreateTensor(iType, deltasValues)),
scoresData(CreateTensor(iType, scoresValues)),
refRoisData(CreateTensor(iType, refRoisValues)),
refScoresData(CreateTensor(iType, refScoresValues)),
refRoiNumData(CreateTensor(roiNumType, refRoiNumValues)),
testcaseName(testcaseName) {
imageSizeInfoShape = Shape{batch, 3};
anchorsShape = Shape{height, width, number_of_channels, 4};
deltasShape = Shape{batch, number_of_channels * 4, height, width};
scoresShape = Shape{batch, number_of_channels, height, width};
}
Attrs attrs;
PartialShape imageSizeInfoShape;
PartialShape anchorsShape;
PartialShape deltasShape;
PartialShape scoresShape;
ov::element::Type inType;
ov::element::Type outType;
ov::element::Type roiNumType;
ov::Tensor imageSizeInfoData;
ov::Tensor anchorsData;
ov::Tensor deltasData;
ov::Tensor scoresData;
ov::Tensor refRoisData;
ov::Tensor refScoresData;
ov::Tensor refRoiNumData;
std::string testcaseName;
};
class ReferenceGPLayerTest : public testing::TestWithParam<GPParams>, public CommonReferenceTest {
public:
void SetUp() override {
auto params = GetParam();
function = CreateFunction(params);
inputData = {params.imageSizeInfoData, params.anchorsData, params.deltasData, params.scoresData};
refOutData = {params.refRoisData, params.refScoresData, params.refRoiNumData};
}
static std::string getTestCaseName(const testing::TestParamInfo<GPParams>& obj) {
auto param = obj.param;
std::ostringstream result;
result << "imageSizeInfoShape=" << param.imageSizeInfoShape << "_";
result << "anchorsShape=" << param.anchorsShape << "_";
result << "deltasShape=" << param.deltasShape << "_";
result << "scoresShape=" << param.scoresShape << "_";
result << "iType=" << param.inType << "_";
result << "oType=" << param.outType << "_";
result << "roiNumType=" << param.roiNumType;
if (param.testcaseName != "")
result << "_" << param.testcaseName;
return result.str();
}
private:
static std::shared_ptr<Model> CreateFunction(const GPParams& params) {
const auto im_info = std::make_shared<op::v0::Parameter>(params.inType, params.imageSizeInfoShape);
const auto anchors = std::make_shared<op::v0::Parameter>(params.inType, params.anchorsShape);
const auto deltas = std::make_shared<op::v0::Parameter>(params.inType, params.deltasShape);
const auto scores = std::make_shared<op::v0::Parameter>(params.inType, params.scoresShape);
const auto GenerateProposal = std::make_shared<op::v9::GenerateProposals>(im_info,
anchors,
deltas,
scores,
params.attrs);
GenerateProposal->set_roi_num_type(params.roiNumType);
return std::make_shared<ov::Model>(GenerateProposal->outputs(), ParameterVector {im_info, anchors, deltas, scores});
}
};
TEST_P(ReferenceGPLayerTest, CompareWithRefs) {
Exec();
}
template <element::Type_t IN_ET, element::Type_t OUT_RT>
std::vector<GPParams> generateGPFloatParams() {
using T = typename element_type_traits<IN_ET>::value_type;
using RT = typename element_type_traits<OUT_RT>::value_type;
Attrs attrs;
attrs.min_size = 1.0;
attrs.nms_threshold = 0.699999988079071;
attrs.pre_nms_count = 1000;
attrs.post_nms_count = 6;
attrs.nms_eta = 1.0;
attrs.normalized = true;
std::vector<GPParams> generateProposalParams {
GPParams(attrs,
1,
3, // A
2, // H
6, // W
IN_ET,
OUT_RT,
std::vector<T>{1.0f, 1.0f, 0.0f},
std::vector<T>(144, 1.0f), // anchors [H, W, A, 4]
std::vector<T>(144, 1.0f), // deltas [N, A * 4, H, W]
std::vector<T>{5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 4.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 8.0f, 1.0f}, // scores [N, A, H, W]
std::vector<T>(24, 1.0f), // ref rois
std::vector<T>{8.0f, 5.0f, 4.0f, 1.0f, 1.0f, 1.0f}, // ref scores
std::vector<RT>{6}, // ref roiNum
"eval"),
GPParams(attrs,
2,
3,
2,
6,
IN_ET,
OUT_RT,
std::vector<T>{150.0, 150.0, 0.0, 150.0, 150.0, 0.0},
std::vector<T>{12.0, 68.0, 102.0, 123.0, 46.0, 80.0, 79.0, 128.0, 33.0, 71.0, 127.0, 86.0, 33.0, 56.0, 150.0, 73.0,
5.0, 41.0, 93.0, 150.0, 74.0, 66.0, 106.0, 115.0, 17.0, 37.0, 87.0, 150.0, 31.0, 27.0, 150.0, 39.0,
29.0, 23.0, 112.0, 123.0, 41.0, 37.0, 103.0, 150.0, 8.0, 46.0, 98.0, 111.0, 7.0, 69.0, 114.0, 150.0,
70.0, 21.0, 150.0, 125.0, 54.0, 19.0, 132.0, 68.0, 62.0, 8.0, 150.0, 101.0, 57.0, 81.0, 150.0, 97.0,
79.0, 29.0, 109.0, 130.0, 12.0, 63.0, 100.0, 150.0, 17.0, 33.0, 113.0, 150.0, 90.0, 78.0, 150.0, 111.0,
47.0, 68.0, 150.0, 71.0, 66.0, 103.0, 111.0, 150.0, 4.0, 17.0, 112.0, 94.0, 12.0, 8.0, 119.0, 98.0,
54.0, 56.0, 120.0, 150.0, 56.0, 29.0, 150.0, 31.0, 42.0, 3.0, 139.0, 92.0, 41.0, 65.0, 150.0, 130.0,
49.0, 13.0, 143.0, 30.0, 40.0, 60.0, 150.0, 150.0, 23.0, 73.0, 24.0, 115.0, 56.0, 84.0, 107.0, 108.0,
63.0, 8.0, 142.0, 125.0, 78.0, 37.0, 93.0, 144.0, 40.0, 34.0, 150.0, 46.0, 30.0, 21.0, 150.0, 120.0},
std::vector<T>{9.062256, 10.883133, 9.8441105, 12.694285, 0.41781136, 8.749107, 14.990341, 6.587644, 1.4206103,
13.299262, 12.432549, 2.736371, 0.22732796, 6.3361835, 12.268727, 2.1009045, 4.771589, 2.5131326,
5.610736, 9.3604145, 4.27379, 8.317948, 0.60510135, 6.7446275, 1.0207708, 1.1352817, 1.5785321,
1.718335, 1.8093798, 0.99247587, 1.3233583, 1.7432803, 1.8534478, 1.2593061, 1.7394226, 1.7686696,
1.647999, 1.7611449, 1.3119122, 0.03007332, 1.1106564, 0.55669737, 0.2546148, 1.9181818, 0.7134989,
2.0407224, 1.7211134, 1.8565536, 14.562747, 2.8786168, 0.5927796, 0.2064463, 7.6794515, 8.672126,
10.139171, 8.002429, 7.002932, 12.6314945, 10.550842, 0.15784842, 0.3194304, 10.752157, 3.709805,
11.628928, 0.7136225, 14.619964, 15.177284, 2.2824087, 15.381494, 0.16618137, 7.507227, 11.173228,
0.4923559, 1.8227729, 1.4749299, 1.7833921, 1.2363617, -0.23659119, 1.5737582, 1.779316, 1.9828427,
1.0482665, 1.4900246, 1.3563544, 1.5341306, 0.7634312, 4.6216766e-05, 1.6161222, 1.7512476, 1.9363779,
0.9195784, 1.4906164, -0.03244795, 0.681073, 0.6192401, 1.8033613, 14.146055, 3.4043705, 15.292292,
3.5295358, 11.138999, 9.952057, 5.633434, 12.114562, 9.427372, 12.384038, 9.583308, 8.427233,
15.293704, 3.288159, 11.64898, 9.350885, 2.0037227, 13.523184, 4.4176426, 6.1057625, 14.400079,
8.248259, 11.815807, 15.713364, 1.0023532, 1.3203261, 1.7100681, 0.7407832, 1.09448, 1.7188418,
1.4412547, 1.4862992, 0.74790007, 0.31571656, 0.6398838, 2.0236106, 1.1869069, 1.7265586, 1.2624544,
0.09934269, 1.3508598, 0.85212964, -0.38968498, 1.7059708, 1.6533034, 1.7400402, 1.8123854, -0.43063712,
9.062256, 10.883133, 9.8441105, 12.694285, 0.41781136, 8.749107, 14.990341, 6.587644, 1.4206103,
13.299262, 12.432549, 2.736371, 0.22732796, 6.3361835, 12.268727, 2.1009045, 4.771589, 2.5131326,
5.610736, 9.3604145, 4.27379, 8.317948, 0.60510135, 6.7446275, 1.0207708, 1.1352817, 1.5785321,
1.718335, 1.8093798, 0.99247587, 1.3233583, 1.7432803, 1.8534478, 1.2593061, 1.7394226, 1.7686696,
1.647999, 1.7611449, 1.3119122, 0.03007332, 1.1106564, 0.55669737, 0.2546148, 1.9181818, 0.7134989,
2.0407224, 1.7211134, 1.8565536, 14.562747, 2.8786168, 0.5927796, 0.2064463, 7.6794515, 8.672126,
10.139171, 8.002429, 7.002932, 12.6314945, 10.550842, 0.15784842, 0.3194304, 10.752157, 3.709805,
11.628928, 0.7136225, 14.619964, 15.177284, 2.2824087, 15.381494, 0.16618137, 7.507227, 11.173228,
0.4923559, 1.8227729, 1.4749299, 1.7833921, 1.2363617, -0.23659119, 1.5737582, 1.779316, 1.9828427,
1.0482665, 1.4900246, 1.3563544, 1.5341306, 0.7634312, 4.6216766e-05, 1.6161222, 1.7512476, 1.9363779,
0.9195784, 1.4906164, -0.03244795, 0.681073, 0.6192401, 1.8033613, 14.146055, 3.4043705, 15.292292,
3.5295358, 11.138999, 9.952057, 5.633434, 12.114562, 9.427372, 12.384038, 9.583308, 8.427233,
15.293704, 3.288159, 11.64898, 9.350885, 2.0037227, 13.523184, 4.4176426, 6.1057625, 14.400079,
8.248259, 11.815807, 15.713364, 1.0023532, 1.3203261, 1.7100681, 0.7407832, 1.09448, 1.7188418,
1.4412547, 1.4862992, 0.74790007, 0.31571656, 0.6398838, 2.0236106, 1.1869069, 1.7265586, 1.2624544,
0.09934269, 1.3508598, 0.85212964, -0.38968498, 1.7059708, 1.6533034, 1.7400402, 1.8123854, -0.43063712},
std::vector<T>{0.7719922, 0.35906568, 0.29054508, 0.18124384, 0.5604661, 0.84750974, 0.98948747, 0.009793862, 0.7184191,
0.5560748, 0.6952493, 0.6732593, 0.3306898, 0.6790913, 0.41128764, 0.34593266, 0.94296855, 0.7348507,
0.24478768, 0.94024557, 0.05405676, 0.06466125, 0.36244348, 0.07942984, 0.10619422, 0.09412837, 0.9053611,
0.22870538, 0.9237487, 0.20986171, 0.5067282, 0.29709867, 0.53138554, 0.189101, 0.4786443, 0.88421875,
0.7719922, 0.35906568, 0.29054508, 0.18124384, 0.5604661, 0.84750974, 0.98948747, 0.009793862, 0.7184191,
0.5560748, 0.6952493, 0.6732593, 0.3306898, 0.6790913, 0.41128764, 0.34593266, 0.94296855, 0.7348507,
0.24478768, 0.94024557, 0.05405676, 0.06466125, 0.36244348, 0.07942984, 0.10619422, 0.09412837, 0.9053611,
0.22870538, 0.9237487, 0.20986171, 0.5067282, 0.29709867, 0.53138554, 0.189101, 0.4786443, 0.88421875},
std::vector<T>{149, 149, 149, 149, 149, 0, 149, 149, 149, 60.87443542480469, 149, 149, 149, 61.89498901367188, 149,
149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 0, 149, 149, 149, 60.87443542480469,
149, 149, 149, 61.89498901367188, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149},
std::vector<T>{0.9894874691963196, 0.9429685473442078,
0.9402455687522888, 0.9237486720085144,
0.9053611159324646, 0.8842187523841858,
0.9894874691963196, 0.9429685473442078,
0.9402455687522888, 0.9237486720085144,
0.9053611159324646, 0.8842187523841858},
std::vector<RT>{6, 6},
"batch_2"),
GPParams(attrs,
1,
3, // A
2, // H
6, // W
IN_ET,
OUT_RT,
std::vector<T>{200.0f, 200.0f, 4.0f},
std::vector<T>{0.0f, 1.0f, 2.0f, 3.0f,
4.0f, 5.0f, 6.0f, 7.0f,
8.0f, 9.0f, 10.0f, 11.0f,
12.0f, 13.0f, 14.0f, 15.0f,
16.0f, 17.0f, 18.0f, 19.0f,
20.0f, 21.0f, 22.0f, 23.0f,
24.0f, 25.0f, 26.0f, 27.0f,
28.0f, 29.0f, 30.0f, 31.0f,
32.0f, 33.0f, 34.0f, 35.0f,
36.0f, 37.0f, 38.0f, 39.0f,
40.0f, 41.0f, 42.0f, 43.0f,
44.0f, 45.0f, 46.0f, 47.0f,
48.0f, 49.0f, 50.0f, 51.0f,
52.0f, 53.0f, 54.0f, 55.0f,
56.0f, 57.0f, 58.0f, 59.0f,
60.0f, 61.0f, 62.0f, 63.0f,
64.0f, 65.0f, 66.0f, 67.0f,
68.0f, 69.0f, 70.0f, 71.0f,
72.0f, 73.0f, 74.0f, 75.0f,
76.0f, 77.0f, 78.0f, 79.0f,
80.0f, 81.0f, 82.0f, 83.0f,
84.0f, 85.0f, 86.0f, 87.0f,
88.0f, 89.0f, 90.0f, 91.0f,
92.0f, 93.0f, 94.0f, 95.0f,
96.0f, 97.0f, 98.0f, 99.0f,
100.0f, 101.0f, 102.0f, 103.0f,
104.0f, 105.0f, 106.0f, 107.0f,
108.0f, 109.0f, 110.0f, 111.0f,
112.0f, 113.0f, 114.0f, 115.0f,
116.0f, 117.0f, 118.0f, 119.0f,
120.0f, 121.0f, 122.0f, 123.0f,
124.0f, 125.0f, 126.0f, 127.0f,
128.0f, 129.0f, 130.0f, 131.0f,
132.0f, 133.0f, 134.0f, 135.0f,
136.0f, 137.0f, 138.0f, 139.0f,
140.0f, 141.0f, 142.0f, 143.0f}, // anchors H, W, A, 4
std::vector<T>{0.5337073 ,0.86607957,0.55151343,0.21626699,0.4462629, 0.03985678,
0.5157072 ,0.9932138 ,0.7565954 ,0.43803605,0.802818 ,0.14834064,
0.53932905,0.14314 ,0.3817048 ,0.95075196,0.05516243,0.2567484,
0.25508744,0.77438325,0.43561 ,0.2094628 ,0.8299043 ,0.44982538,
0.95615596,0.5651084 ,0.11801951,0.05352486,0.9774733 ,0.14439464,
0.62644225,0.14370479,0.54161614,0.557915 ,0.53102225,0.0840179,
0.7249888 ,0.9843559 ,0.5490522 ,0.53788143,0.822474 ,0.3278008,
0.39688024,0.3286012 ,0.5117038 ,0.04743988,0.9408995 ,0.29885054,
0.81039643,0.85277915,0.06807619,0.86430097,0.36225632,0.16606331,
0.5401001 ,0.7541649 ,0.11998601,0.5131829 ,0.40606487,0.327888 ,
0.27721855,0.6378373 ,0.22795396,0.4961256 ,0.3215895 ,0.15607187,
0.14782153,0.8908137 ,0.8835288 ,0.834191 ,0.29907143,0.7983525 ,
0.755875 ,0.30837986,0.0839176 ,0.26624718,0.04371626,0.09472824,
0.20689541,0.37622106,0.1083321 ,0.1342548 ,0.05815459,0.7676379 ,
0.8105144 ,0.92348766,0.26761323,0.7183306 ,0.8947588 ,0.19020908,
0.42731014,0.7473663 ,0.85775334,0.9340091 ,0.3278848 ,0.755993 ,
0.05307213,0.39705503,0.21003333,0.5625373 ,0.66188884,0.80521655,
0.6125863 ,0.44678232,0.97802377,0.0204936 ,0.02686367,0.7390654 ,
0.74631 ,0.58399844,0.5988792 ,0.37413648,0.5946692 ,0.6955776 ,
0.36377597,0.7891322 ,0.40900692,0.99139464,0.50169915,0.41435778,
0.17142445,0.26761186,0.31591868,0.14249913,0.12919712,0.5418711 ,
0.6523203 ,0.50259084,0.7379765 ,0.01171071,0.94423133,0.00841132,
0.97486794,0.2921785 ,0.7633071 ,0.88477814,0.03563205,0.50833166,
0.01354555,0.535081 ,0.41366324,0.0694767 ,0.9944055 ,0.9981207}, // deltas N, A * 4, H, W
std::vector<T>{0.56637216,0.90457034,0.69827306,0.4353543, 0.47985056,0.42658508,
0.14516132,0.08081771,0.1799732 ,0.9229515 ,0.42420176,0.50857586,
0.82664067,0.4972319 ,0.3752427 ,0.56731623,0.18241242,0.33252355,
0.30608943,0.6572437 ,0.69185436,0.88646156,0.36985755,0.5590753 ,
0.5256446 ,0.03342898,0.1344396 ,0.68642473,0.37953874,0.32575172,
0.21108444,0.5661886 ,0.45378175,0.62126315,0.26799858,0.37272978}, // scores N, A, H, W
std::vector<T>{4.49132, 4.30537, 8.75027, 8.8035,
0, 1.01395, 4.66909, 5.14337,
135.501, 137.467, 139.81, 141.726,
47.2348, 47.8342, 52.5503, 52.3864,
126.483, 128.3, 131.625, 133.707}, // ref rois
std::vector<T>{0.826641, 0.566372, 0.559075, 0.479851, 0.267999}, // ref scores
std::vector<RT>{5}, // ref roiNum
"eval_2")
};
return generateProposalParams;
}
std::vector<GPParams> generateGPCombinedParams() {
const std::vector<std::vector<GPParams>> GPTypeParams {
generateGPFloatParams<element::Type_t::f32, element::Type_t::i32>(),
generateGPFloatParams<element::Type_t::f32, element::Type_t::i64>(),
generateGPFloatParams<element::Type_t::f16, element::Type_t::i32>(),
generateGPFloatParams<element::Type_t::bf16, element::Type_t::i64>(),
};
std::vector<GPParams> combinedParams;
for (const auto& params : GPTypeParams) {
combinedParams.insert(combinedParams.end(), params.begin(), params.end());
}
return combinedParams;
}
INSTANTIATE_TEST_SUITE_P(smoke_GenerateProposals_With_Hardcoded_Refs, ReferenceGPLayerTest,
testing::ValuesIn(generateGPCombinedParams()), ReferenceGPLayerTest::getTestCaseName);
} // namespace

View File

@@ -11,6 +11,7 @@
#include <ngraph/opsets/opset5.hpp>
#include <ngraph/opsets/opset6.hpp>
#include <ngraph/opsets/opset8.hpp>
#include <ngraph/opsets/opset9.hpp>
#include <ngraph/runtime/reference/convert.hpp>
#include <vector>
@@ -33,6 +34,7 @@ bool fuse_type_to_nms4(const std::shared_ptr<ngraph::Node>& node, ngraph::elemen
bool fuse_type_to_nms5(const std::shared_ptr<ngraph::Node>& node, ngraph::element::Type to, size_t idx);
bool fuse_type_to_matrix_nms(const std::shared_ptr<ngraph::Node>& node, ngraph::element::Type to, size_t idx);
bool fuse_type_to_multiclass_nms(const std::shared_ptr<ngraph::Node>& node, ngraph::element::Type to, size_t idx);
bool fuse_type_to_generate_proposals(const std::shared_ptr<ngraph::Node>& node, ngraph::element::Type to, size_t idx);
bool fuse_type_to_topk(const std::shared_ptr<ngraph::Node>& node, ngraph::element::Type to, size_t idx);
bool fuse_type_to_maxpool(const std::shared_ptr<ngraph::Node>& node, ngraph::element::Type to, size_t idx);
bool fuse_type_to_nonzero(const std::shared_ptr<ngraph::Node>& node, ngraph::element::Type to, size_t idx);
@@ -258,6 +260,7 @@ bool ngraph::pass::ConvertPrecision::run_on_model(const std::shared_ptr<ngraph::
{opset5::NonMaxSuppression::get_type_info_static(), fuse_type_to_nms5},
{opset8::MatrixNms::get_type_info_static(), fuse_type_to_matrix_nms},
{opset8::MulticlassNms::get_type_info_static(), fuse_type_to_multiclass_nms},
{opset9::GenerateProposals::get_type_info_static(), fuse_type_to_generate_proposals},
{opset6::CTCGreedyDecoderSeqLen::get_type_info_static(), fuse_type_to_ctc_greedy_decoder_seq_len},
{opset4::TopK::get_type_info_static(), fuse_type_to_topk},
{opset8::MaxPool::get_type_info_static(), fuse_type_to_maxpool},
@@ -429,6 +432,20 @@ bool fuse_type_to_multiclass_nms(const std::shared_ptr<ngraph::Node>& node, ngra
return false;
}
bool fuse_type_to_generate_proposals(const std::shared_ptr<ngraph::Node>& node, ngraph::element::Type to, size_t idx) {
auto generate_proposals = ov::as_type_ptr<opset9::GenerateProposals>(node);
if (!generate_proposals) {
return false;
}
if ((idx == 2) && (to == element::i32 || to == element::i64)) {
generate_proposals->set_roi_num_type(to);
return true;
}
return false;
}
bool fuse_type_to_topk(const std::shared_ptr<ngraph::Node>& node, ngraph::element::Type to, size_t idx) {
if (auto topk = ov::as_type_ptr<opset4::TopK>(node)) {
if (idx == 1 && (to == element::i32 || to == element::i64)) {

View File

@@ -0,0 +1,15 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "openvino/op/generate_proposals.hpp"
namespace ngraph {
namespace op {
namespace v9 {
using ov::op::v9::GenerateProposals;
} // namespace v9
} // namespace op
} // namespace ngraph

View File

@@ -66,6 +66,7 @@
#include "ngraph/op/gather_nd.hpp"
#include "ngraph/op/gather_tree.hpp"
#include "ngraph/op/gelu.hpp"
#include "ngraph/op/generate_proposals.hpp"
#include "ngraph/op/greater.hpp"
#include "ngraph/op/greater_eq.hpp"
#include "ngraph/op/grn.hpp"

View File

@@ -0,0 +1,80 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "openvino/op/op.hpp"
#include "openvino/op/util/attr_types.hpp"
namespace ov {
namespace op {
namespace v9 {
/// \brief An operation GenerateProposals
/// computes ROIs and their scores based on input data.
class OPENVINO_API GenerateProposals : public Op {
public:
OPENVINO_OP("GenerateProposals", "opset9");
/// \brief Structure that specifies attributes of the operation
struct Attributes {
// minimum box width & height
float min_size;
// specifies NMS threshold
float nms_threshold;
// number of top-n proposals after NMS
int64_t post_nms_count;
// number of top-n proposals before NMS
int64_t pre_nms_count;
// specify whether the bbox is normalized or not.
// For example if *normalized* is true, width = x_right - x_left
// If *normalized* is false, width = x_right - x_left + 1.
bool normalized = true;
// specify eta parameter for adaptive NMS in generate proposals
float nms_eta = 1.0;
};
GenerateProposals() = default;
/// \brief Constructs a GenerateProposals operation.
///
/// \param im_info Input image info
/// \param anchors Input anchors
/// \param deltas Input deltas
/// \param scores Input scores
/// \param attrs Operation attributes
/// \param roi_num_type roi_num type
GenerateProposals(const Output<Node>& im_info,
const Output<Node>& anchors,
const Output<Node>& deltas,
const Output<Node>& scores,
const Attributes& attrs,
const element::Type& roi_num_type = element::i64);
bool visit_attributes(AttributeVisitor& visitor) override;
void validate_and_infer_types() override;
std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override;
const Attributes& get_attrs() const {
return m_attrs;
}
const element::Type& get_roi_num_type() const {
return m_roi_num_type;
}
void set_roi_num_type(const element::Type& output_type) {
NODE_VALIDATION_CHECK(this,
(output_type == ov::element::i64) || (output_type == ov::element::i32),
"The third output type must be int64 or int32.");
m_roi_num_type = output_type;
set_output_type(2, output_type, get_output_partial_shape(2));
}
private:
Attributes m_attrs;
ov::element::Type m_roi_num_type = ov::element::i64;
};
} // namespace v9
} // namespace op
} // namespace ov

View File

@@ -65,6 +65,7 @@
#include "openvino/op/gather_nd.hpp"
#include "openvino/op/gather_tree.hpp"
#include "openvino/op/gelu.hpp"
#include "openvino/op/generate_proposals.hpp"
#include "openvino/op/greater.hpp"
#include "openvino/op/greater_eq.hpp"
#include "openvino/op/grn.hpp"

View File

@@ -194,3 +194,4 @@ _OPENVINO_OP_REG(RDFT, ov::op::v9)
_OPENVINO_OP_REG(Eye, ov::op::v9)
_OPENVINO_OP_REG(ROIAlign, ov::op::v9)
_OPENVINO_OP_REG(SoftSign, ov::op::v9)
_OPENVINO_OP_REG(GenerateProposals, ov::op::v9)

View File

@@ -0,0 +1,47 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <ngraph/runtime/host_tensor.hpp>
#include <vector>
#include "ngraph/node.hpp"
#include "ngraph/op/util/op_types.hpp"
#include "ngraph/ops.hpp"
#include "ngraph/shape_util.hpp"
namespace ngraph {
namespace runtime {
namespace reference {
void generate_proposals(const std::vector<float>& im_info,
const std::vector<float>& anchors,
const std::vector<float>& deltas,
const std::vector<float>& scores,
const op::v9::GenerateProposals::Attributes& attrs,
const Shape& im_info_shape,
const Shape& anchors_shape,
const Shape& deltas_shape,
const Shape& scores_shape,
std::vector<float>& output_rois,
std::vector<float>& output_scores,
std::vector<int64_t>& num_rois);
void generate_proposals_postprocessing(void* prois,
void* pscores,
void* proi_num,
const ngraph::element::Type& output_type,
const ngraph::element::Type& roi_num_type,
const std::vector<float>& output_rois,
const std::vector<float>& output_scores,
const std::vector<int64_t>& num_rois,
const Shape& output_rois_shape,
const Shape& output_scores_shape);
} // namespace reference
} // namespace runtime
} // namespace ngraph

View File

@@ -0,0 +1,424 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "ngraph/runtime/reference/generate_proposal.hpp"
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstring>
#include <utility>
#include "ngraph/op/generate_proposals.hpp"
#include "ngraph/shape.hpp"
struct sProposalBox {
float x0;
float y0;
float x1;
float y1;
float score;
float keep;
};
static void generate_proposal_refine_anchors(const std::vector<float>& deltas,
const std::vector<float>& scores,
const std::vector<float>& anchors,
float* proposals,
const int64_t anchors_num,
const int64_t bottom_H,
const int64_t bottom_W,
const float img_H,
const float img_W,
const float min_box_H,
const float min_box_W,
const float max_delta_log_wh,
const float coordinates_offset) {
int64_t bottom_area = bottom_H * bottom_W;
for (int64_t h = 0; h < bottom_H; ++h) {
for (int64_t w = 0; w < bottom_W; ++w) {
// base index for anchors: anchors shape is [bottom_H, bottom_W, anchors_num, 4]
int64_t a_idx = (h * bottom_W + w) * anchors_num * 4;
// base index for proposals: proposals shape is [bottom_H, bottom_W, anchors_num, 6]
int64_t p_idx = (h * bottom_W + w) * anchors_num * 6;
// base index for scores: scores shape is [anchors_num, bottom_H, bottom_W]
int64_t sc_idx = h * bottom_W + w;
// base index for deltas: anchors shape is [anchors_num, 4, bottom_H, bottom_W]
int64_t d_idx = h * bottom_W + w;
for (int64_t anchor = 0; anchor < anchors_num; ++anchor) {
float x0 = anchors[a_idx + 0];
float y0 = anchors[a_idx + 1];
float x1 = anchors[a_idx + 2];
float y1 = anchors[a_idx + 3];
const float dx = deltas[d_idx + 0 * bottom_area];
const float dy = deltas[d_idx + 1 * bottom_area];
const float d_log_w = deltas[d_idx + 2 * bottom_area];
const float d_log_h = deltas[d_idx + 3 * bottom_area];
const float score = scores[sc_idx];
// width & height of box
const float ww = x1 - x0 + coordinates_offset;
const float hh = y1 - y0 + coordinates_offset;
// center location of box
const float ctr_x = x0 + 0.5f * ww;
const float ctr_y = y0 + 0.5f * hh;
// new center location according to deltas (dx, dy)
const float pred_ctr_x = dx * ww + ctr_x;
const float pred_ctr_y = dy * hh + ctr_y;
// new width & height according to deltas d(log w), d(log h)
const float pred_w = std::exp(std::min(d_log_w, max_delta_log_wh)) * ww;
const float pred_h = std::exp(std::min(d_log_h, max_delta_log_wh)) * hh;
// update upper-left corner location
x0 = pred_ctr_x - 0.5f * pred_w;
y0 = pred_ctr_y - 0.5f * pred_h;
// update lower-right corner location
x1 = pred_ctr_x + 0.5f * pred_w - coordinates_offset;
y1 = pred_ctr_y + 0.5f * pred_h - coordinates_offset;
// adjust new corner locations to be within the image region,
x0 = std::max<float>(0.0f, std::min<float>(x0, img_W - coordinates_offset));
y0 = std::max<float>(0.0f, std::min<float>(y0, img_H - coordinates_offset));
x1 = std::max<float>(0.0f, std::min<float>(x1, img_W - coordinates_offset));
y1 = std::max<float>(0.0f, std::min<float>(y1, img_H - coordinates_offset));
// recompute new width & height
const float box_w = x1 - x0 + coordinates_offset;
const float box_h = y1 - y0 + coordinates_offset;
proposals[p_idx + 0] = x0;
proposals[p_idx + 1] = y0;
proposals[p_idx + 2] = x1;
proposals[p_idx + 3] = y1;
proposals[p_idx + 4] = score;
proposals[p_idx + 5] = (min_box_W <= box_w) * (min_box_H <= box_h) * 1.0;
// update index for next anchor iter
a_idx += 4; // anchors shape is [bottom_H, bottom_W, anchors_num, 4], so add 4 for next anchor iter
p_idx += 6; // proposals shape is [bottom_H, bottom_W, anchors_num, 6], so add 6 for next anchor iter
sc_idx += bottom_area; // scores shape is [anchors_num, bottom_H, bottom_W], so add bottom_H * bottom_W
// for next anchor iter
d_idx += 4 * bottom_area; // deltas shape is [anchors_num, 4, bottom_H, bottom_W], so add 4 * bottom_H
// * bottom_W for next anchor iter
}
}
}
}
static void generate_proposal_unpack_boxes(const float* p_proposals,
float* unpacked_boxes,
int64_t* is_dead,
int64_t pre_nms_topn) {
for (int64_t i = 0; i < pre_nms_topn; ++i) {
unpacked_boxes[0 * pre_nms_topn + i] = p_proposals[6 * i + 0];
unpacked_boxes[1 * pre_nms_topn + i] = p_proposals[6 * i + 1];
unpacked_boxes[2 * pre_nms_topn + i] = p_proposals[6 * i + 2];
unpacked_boxes[3 * pre_nms_topn + i] = p_proposals[6 * i + 3];
unpacked_boxes[4 * pre_nms_topn + i] = p_proposals[6 * i + 4];
is_dead[i] = (p_proposals[6 * i + 5] == 1.0) ? 0 : 1;
}
}
static void generate_proposal_nms_cpu(const int64_t num_boxes,
int64_t is_dead[],
const float* boxes,
int64_t index_out[],
int64_t& num_out,
const int64_t base_index,
const float nms_thresh,
const int64_t max_num_out,
const float coordinates_offset) {
const int64_t num_proposals = num_boxes;
int64_t count = 0;
const float* x0 = boxes + 0 * num_proposals;
const float* y0 = boxes + 1 * num_proposals;
const float* x1 = boxes + 2 * num_proposals;
const float* y1 = boxes + 3 * num_proposals;
for (int64_t box = 0; box < num_boxes; ++box) {
if (is_dead[box])
continue;
index_out[count++] = base_index + box;
if (count == max_num_out)
break;
const float x0i = x0[box];
const float y0i = y0[box];
const float x1i = x1[box];
const float y1i = y1[box];
const float a_width = x1i - x0i;
const float a_height = y1i - y0i;
const float a_area = (a_width + coordinates_offset) * (a_height + coordinates_offset);
for (int64_t tail = box + 1; tail < num_boxes; ++tail) {
const float x0j = x0[tail];
const float y0j = y0[tail];
const float x1j = x1[tail];
const float y1j = y1[tail];
const float x0 = std::max(x0i, x0j);
const float y0 = std::max(y0i, y0j);
const float x1 = std::min(x1i, x1j);
const float y1 = std::min(y1i, y1j);
const float width = x1 - x0 + coordinates_offset;
const float height = y1 - y0 + coordinates_offset;
const float area = std::max(0.0f, width) * std::max(0.0f, height);
const float b_width = x1j - x0j;
const float b_height = y1j - y0j;
const float b_area = (b_width + coordinates_offset) * (b_height + coordinates_offset);
const float intersection_area = area / (a_area + b_area - area);
if ((nms_thresh < intersection_area) && (x0i <= x1j) && (y0i <= y1j) && (x0j <= x1i) && (y0j <= y1i))
is_dead[tail] = 1;
}
}
num_out = count;
}
static void generate_proposal_fill_output_blobs(const float* proposals,
const int64_t* roi_indices,
std::vector<float>& rois,
std::vector<float>& scores,
const int64_t num_proposals,
const int64_t num_rois,
const int64_t post_nms_topn) {
const float* src_x0 = proposals + 0 * num_proposals;
const float* src_y0 = proposals + 1 * num_proposals;
const float* src_x1 = proposals + 2 * num_proposals;
const float* src_y1 = proposals + 3 * num_proposals;
const float* src_score = proposals + 4 * num_proposals;
for (int64_t i = 0; i < num_rois; ++i) {
int64_t index = roi_indices[i];
rois.push_back(src_x0[index]);
rois.push_back(src_y0[index]);
rois.push_back(src_x1[index]);
rois.push_back(src_y1[index]);
scores.push_back(src_score[index]);
}
}
namespace ngraph {
namespace runtime {
namespace reference {
static void generate_proposals_single_image(const std::vector<float>& im_info,
const std::vector<float>& anchors,
const std::vector<float>& deltas,
const std::vector<float>& scores,
const op::v9::GenerateProposals::Attributes& attrs,
const Shape& im_info_shape,
const Shape& anchors_shape,
const Shape& deltas_shape,
const Shape& scores_shape,
std::vector<float>& output_rois,
std::vector<float>& output_scores,
int64_t& num_rois) {
const int64_t anchors_num = static_cast<int64_t>(scores_shape[1]);
// bottom shape: batch x (num_anchors) x H x W
const int64_t bottom_H = static_cast<int64_t>(deltas_shape[2]);
const int64_t bottom_W = static_cast<int64_t>(deltas_shape[3]);
// input image height & width
const float img_H = im_info[0];
const float img_W = im_info[1];
// scale factor for height & width
float scale_h = 1.0;
float scale_w = 1.0;
if (im_info.size() == 3) {
scale_h = im_info[2];
scale_w = im_info[2];
} else if (im_info.size() == 4) {
scale_h = im_info[2];
scale_w = im_info[3];
}
// minimum box width & height
const float min_box_H = attrs.min_size * scale_h;
const float min_box_W = attrs.min_size * scale_w;
const float nms_thresh = attrs.nms_threshold;
const int64_t post_nms_topn = attrs.post_nms_count;
// number of all proposals = num_anchors * H * W
const int64_t num_proposals = anchors_num * bottom_H * bottom_W;
// number of top-n proposals before NMS
const int64_t pre_nms_topn = std::min(num_proposals, attrs.pre_nms_count);
// bbox normalized flag
const float coordinates_offset = attrs.normalized ? 0 : 1.0;
std::vector<sProposalBox> proposals(num_proposals);
std::vector<float> unpacked_boxes(5 * pre_nms_topn);
std::vector<int64_t> is_dead(pre_nms_topn);
generate_proposal_refine_anchors(deltas,
scores,
anchors,
reinterpret_cast<float*>(proposals.data()),
anchors_num,
bottom_H,
bottom_W,
img_H,
img_W,
min_box_H,
min_box_W,
static_cast<const float>(std::log(1000. / 16.)),
coordinates_offset);
std::partial_sort(proposals.begin(),
proposals.begin() + pre_nms_topn,
proposals.end(),
[](const sProposalBox& struct1, const sProposalBox& struct2) {
return (struct1.score > struct2.score);
});
generate_proposal_unpack_boxes(reinterpret_cast<float*>(proposals.data()),
unpacked_boxes.data(),
is_dead.data(),
pre_nms_topn);
std::vector<int64_t> roi_indices(post_nms_topn);
generate_proposal_nms_cpu(pre_nms_topn,
is_dead.data(),
unpacked_boxes.data(),
roi_indices.data(),
num_rois,
0,
nms_thresh,
post_nms_topn,
coordinates_offset);
generate_proposal_fill_output_blobs(unpacked_boxes.data(),
roi_indices.data(),
output_rois,
output_scores,
pre_nms_topn,
num_rois,
post_nms_topn);
}
void generate_proposals(const std::vector<float>& im_info,
const std::vector<float>& anchors,
const std::vector<float>& deltas,
const std::vector<float>& scores,
const op::v9::GenerateProposals::Attributes& attrs,
const Shape& im_info_shape,
const Shape& anchors_shape,
const Shape& deltas_shape,
const Shape& scores_shape,
std::vector<float>& output_rois,
std::vector<float>& output_scores,
std::vector<int64_t>& num_rois) {
const auto im_info_size =
std::accumulate(im_info_shape.begin() + 1, im_info_shape.end(), 1, std::multiplies<size_t>());
const auto deltas_size =
std::accumulate(deltas_shape.begin() + 1, deltas_shape.end(), 1, std::multiplies<size_t>());
const auto scores_size =
std::accumulate(scores_shape.begin() + 1, scores_shape.end(), 1, std::multiplies<size_t>());
for (auto i = 0; i < im_info_shape[0]; i++) {
std::vector<float> cur_im_info(im_info.begin() + i * im_info_size,
im_info.begin() + i * im_info_size + im_info_size);
std::vector<float> cur_deltas(deltas.begin() + i * deltas_size, deltas.begin() + i * deltas_size + deltas_size);
std::vector<float> cur_scores(scores.begin() + i * scores_size, scores.begin() + i * scores_size + scores_size);
std::vector<float> output_roi;
std::vector<float> output_score;
int64_t num_roi;
generate_proposals_single_image(cur_im_info,
anchors,
cur_deltas,
cur_scores,
attrs,
im_info_shape,
anchors_shape,
deltas_shape,
scores_shape,
output_roi,
output_score,
num_roi);
output_rois.insert(output_rois.end(), output_roi.begin(), output_roi.end());
output_scores.insert(output_scores.end(), output_score.begin(), output_score.end());
num_rois.push_back(num_roi);
}
}
void generate_proposals_postprocessing(void* prois,
void* pscores,
void* proi_num,
const ngraph::element::Type& output_type,
const ngraph::element::Type& roi_num_type,
const std::vector<float>& output_rois,
const std::vector<float>& output_scores,
const std::vector<int64_t>& num_rois,
const Shape& output_rois_shape,
const Shape& output_scores_shape) {
size_t rois_num = output_rois_shape[0];
switch (output_type) {
case element::Type_t::bf16: {
bfloat16* rois_ptr = reinterpret_cast<bfloat16*>(prois);
bfloat16* scores_ptr = reinterpret_cast<bfloat16*>(pscores);
for (size_t i = 0; i < rois_num; ++i) {
rois_ptr[4 * i + 0] = bfloat16(output_rois[4 * i + 0]);
rois_ptr[4 * i + 1] = bfloat16(output_rois[4 * i + 1]);
rois_ptr[4 * i + 2] = bfloat16(output_rois[4 * i + 2]);
rois_ptr[4 * i + 3] = bfloat16(output_rois[4 * i + 3]);
scores_ptr[i] = bfloat16(output_scores[i]);
}
} break;
case element::Type_t::f16: {
float16* rois_ptr = reinterpret_cast<float16*>(prois);
float16* scores_ptr = reinterpret_cast<float16*>(pscores);
for (size_t i = 0; i < rois_num; ++i) {
rois_ptr[4 * i + 0] = float16(output_rois[4 * i + 0]);
rois_ptr[4 * i + 1] = float16(output_rois[4 * i + 1]);
rois_ptr[4 * i + 2] = float16(output_rois[4 * i + 2]);
rois_ptr[4 * i + 3] = float16(output_rois[4 * i + 3]);
scores_ptr[i] = float16(output_scores[i]);
}
} break;
case element::Type_t::f32: {
float* rois_ptr = reinterpret_cast<float*>(prois);
float* scores_ptr = reinterpret_cast<float*>(pscores);
memcpy(rois_ptr, output_rois.data(), shape_size(output_rois_shape) * sizeof(float));
memcpy(scores_ptr, output_scores.data(), shape_size(output_scores_shape) * sizeof(float));
} break;
default:;
throw ngraph_error("Unsupported input data type: "
"GenerateProposals operation"
" supports only fp32, fp16, or bf16 data.");
}
for (auto i = 0; i < num_rois.size(); i++) {
switch (roi_num_type) {
case element::Type_t::i32: {
int32_t* roi_num_ptr = reinterpret_cast<int32_t*>(proi_num);
roi_num_ptr[i] = static_cast<int32_t>(num_rois[i]);
} break;
case element::Type_t::i64: {
int64_t* roi_num_ptr = reinterpret_cast<int64_t*>(proi_num);
roi_num_ptr[i] = static_cast<int64_t>(num_rois[i]);
} break;
default:;
throw ngraph_error("Unsupported data type on output port 3: "
" supports only int32 or int64.");
}
}
}
} // namespace reference
} // namespace runtime
} // namespace ngraph

View File

@@ -0,0 +1,131 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <openvino/op/generate_proposals.hpp>
namespace ov {
namespace op {
namespace v9 {
template <class T>
void shape_infer(const GenerateProposals* op,
const std::vector<T>& input_shapes,
std::vector<T>& output_shapes) {
NODE_VALIDATION_CHECK(op, input_shapes.size() == 4 && output_shapes.size() == 3);
const auto& im_info_shape = input_shapes[0];
const auto& anchors_shape = input_shapes[1];
const auto& deltas_shape = input_shapes[2];
const auto& scores_shape = input_shapes[3];
const auto im_info_shape_rank = im_info_shape.rank();
NODE_VALIDATION_CHECK(op,
im_info_shape_rank.compatible(2),
"The 'input_im_info' input is expected to be a 2D. Got: ",
im_info_shape);
if (im_info_shape_rank.is_static()) {
NODE_VALIDATION_CHECK(op,
(im_info_shape[1].compatible(3) || im_info_shape[1].compatible(4)),
"The 'input_im_info' shape[1] is expected to be a compatible with [3] or [4]. Got: ",
im_info_shape);
}
const auto anchors_shape_rank = anchors_shape.rank();
NODE_VALIDATION_CHECK(op,
anchors_shape_rank.compatible(4),
"The 'input_anchors' input is expected to be a 4D. Got: ",
anchors_shape);
if (anchors_shape_rank.is_static()) {
NODE_VALIDATION_CHECK(op,
anchors_shape[3].compatible(4),
"The fourth dimension of 'input_anchors' should be compatible with 4. Got: ",
anchors_shape[3]);
}
const auto deltas_shape_rank = deltas_shape.rank();
const auto scores_shape_rank = scores_shape.rank();
NODE_VALIDATION_CHECK(op,
deltas_shape_rank.compatible(4),
"The 'input_deltas' input is expected to be a 4D. Got: ",
deltas_shape);
NODE_VALIDATION_CHECK(op,
scores_shape_rank.compatible(4),
"The 'input_scores' input is expected to be a 4D. Got: ",
scores_shape);
if (deltas_shape_rank.is_static() && scores_shape_rank.is_static()) {
NODE_VALIDATION_CHECK(op,
deltas_shape[0].compatible(scores_shape[0]),
"Batch for inputs 'input_deltas' and 'input_scores' should be "
"equal. Got: ",
deltas_shape[0],
scores_shape[0]);
NODE_VALIDATION_CHECK(op,
deltas_shape[1].compatible(scores_shape[1] * 4),
"Anchor number for inputs 'input_deltas' and 'input_scores' should be "
"equal. Got: ",
deltas_shape[1] / 4,
scores_shape[1]);
NODE_VALIDATION_CHECK(op,
deltas_shape[2].compatible(scores_shape[2]),
"Heights for inputs 'input_deltas' and 'input_scores' should be "
"equal. Got: ",
deltas_shape[2],
scores_shape[2]);
NODE_VALIDATION_CHECK(op,
deltas_shape[3].compatible(scores_shape[3]),
"Width for inputs 'input_deltas' and 'input_scores' should be "
"equal. Got: ",
deltas_shape[3],
scores_shape[3]);
if (im_info_shape_rank.is_static()) {
NODE_VALIDATION_CHECK(op,
deltas_shape[0].compatible(im_info_shape[0]),
"Batch for inputs 'im_info' and 'input_deltas' should be "
"equal. Got: ",
deltas_shape[0],
im_info_shape[0]);
}
}
if (scores_shape_rank.is_static() && anchors_shape_rank.is_static()) {
NODE_VALIDATION_CHECK(op,
anchors_shape[0].compatible(scores_shape[2]),
"Heights for inputs 'input_anchors' and 'input_scores' should be "
"equal. Got: ",
anchors_shape[0],
scores_shape[2]);
NODE_VALIDATION_CHECK(op,
anchors_shape[1].compatible(scores_shape[3]),
"Width for inputs 'input_anchors' and 'input_scores' should be "
"equal. Got: ",
anchors_shape[1],
scores_shape[3]);
NODE_VALIDATION_CHECK(op,
anchors_shape[2].compatible(scores_shape[1]),
"Anchor number for inputs 'input_anchors' and 'input_scores' should be "
"equal. Got: ",
anchors_shape[2],
scores_shape[1]);
}
output_shapes[0] = ov::PartialShape({Dimension::dynamic(), 4});
output_shapes[1] = ov::PartialShape::dynamic(1);
if (im_info_shape_rank.is_static()) {
output_shapes[2] = ov::PartialShape({im_info_shape[0]});
} else {
output_shapes[2] = ov::PartialShape::dynamic(1);
}
}
} // namespace v9
} // namespace op
} // namespace ov

View File

@@ -0,0 +1,70 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "openvino/op/generate_proposals.hpp"
#include "generate_proposals_shape_inference.hpp"
#include "itt.hpp"
using namespace std;
namespace ov {
op::v9::GenerateProposals::GenerateProposals(const Output<Node>& im_info,
const Output<Node>& anchors,
const Output<Node>& deltas,
const Output<Node>& scores,
const Attributes& attrs,
const element::Type& roi_num_type)
: Op({im_info, anchors, deltas, scores}),
m_attrs(attrs),
m_roi_num_type(roi_num_type) {
constructor_validate_and_infer_types();
}
shared_ptr<Node> op::v9::GenerateProposals::clone_with_new_inputs(const OutputVector& new_args) const {
NGRAPH_OP_SCOPE(v9_GenerateProposals_clone_with_new_inputs);
check_new_args_count(this, new_args);
return make_shared<ov::op::v9::GenerateProposals>(new_args.at(0),
new_args.at(1),
new_args.at(2),
new_args.at(3),
m_attrs,
m_roi_num_type);
}
bool op::v9::GenerateProposals::visit_attributes(AttributeVisitor& visitor) {
NGRAPH_OP_SCOPE(v9_GenerateProposals_visit_attributes);
visitor.on_attribute("min_size", m_attrs.min_size);
visitor.on_attribute("nms_threshold", m_attrs.nms_threshold);
visitor.on_attribute("post_nms_count", m_attrs.post_nms_count);
visitor.on_attribute("pre_nms_count", m_attrs.pre_nms_count);
visitor.on_attribute("normalized", m_attrs.normalized);
visitor.on_attribute("nms_eta", m_attrs.nms_eta);
visitor.on_attribute("roi_num_type", m_roi_num_type);
return true;
}
void op::v9::GenerateProposals::validate_and_infer_types() {
NGRAPH_OP_SCOPE(v9_GenerateProposals_validate_and_infer_types);
NODE_VALIDATION_CHECK(this, m_attrs.pre_nms_count > 0, "Attribute pre_nms_count must be larger than 0.");
NODE_VALIDATION_CHECK(this, m_attrs.post_nms_count > 0, "Attribute post_nms_count must be larger than 0.");
NODE_VALIDATION_CHECK(this, m_attrs.nms_eta == 1.0, "Attribute min_size must be 1.0.");
std::vector<PartialShape> output_shapes = {PartialShape{}, PartialShape{}, PartialShape{}};
std::vector<PartialShape> input_shapes = {get_input_partial_shape(0),
get_input_partial_shape(1),
get_input_partial_shape(2),
get_input_partial_shape(3)};
shape_infer(this, input_shapes, output_shapes);
const auto& input_et = get_input_element_type(0);
set_output_type(0, input_et, output_shapes[0]);
set_output_type(1, input_et, output_shapes[1]);
const auto& roi_num_type = get_roi_num_type();
NODE_VALIDATION_CHECK(this,
(roi_num_type == element::i64) || (roi_num_type == element::i32),
"The third output type must be int64 or int32.");
set_output_type(2, roi_num_type, output_shapes[2]);
}
} // namespace ov

View File

@@ -127,6 +127,7 @@ set(SRC
type_prop/erf.cpp
type_prop/exp.cpp
type_prop/experimental_detectron_generate_proposals.cpp
type_prop/generate_proposals.cpp
type_prop/experimental_detectron_roi_feature_extractor.cpp
type_prop/experimental_detectron_topkrois.cpp
type_prop/strided_slice.cpp
@@ -298,6 +299,7 @@ set(SRC
visitors/op/exp.cpp
visitors/op/experimental_detectron_detection_output.cpp
visitors/op/experimental_detectron_generate_proposals.cpp
visitors/op/generate_proposals.cpp
visitors/op/experimental_detectron_prior_grid_generator.cpp
visitors/op/experimental_detectron_topkrois.cpp
visitors/op/eye.cpp

View File

@@ -25,17 +25,31 @@ ie_check_pip_package(paddlepaddle WARNING paddle)
set(TEST_PADDLE_MODELS_DIRNAME test_model_zoo/paddle_test_models)
target_compile_definitions(${TARGET_NAME} PRIVATE -D TEST_PADDLE_MODELS_DIRNAME=\"${TEST_PADDLE_MODELS_DIRNAME}/\")
set(PADDLEDET_OPS_URL "https://raw.githubusercontent.com/PaddlePaddle/PaddleDetection/release/2.1/ppdet/modeling/ops.py")
set(PADDLEDET_DIRNAME ${CMAKE_CURRENT_BINARY_DIR}/thirdparty/PaddleDetection/ppdet/modeling/)
set(PADDLEDET_OPS_SHA256 "5cc079eda295ed78b58fba8223c51d85a931a7069ecad51c6af5c2fd26b7a8cb")
DownloadAndCheck(${PADDLEDET_OPS_URL} ${PADDLEDET_DIRNAME}/ops.py PADDLEDET_FATAL PADDLEDET_RESULT ${PADDLEDET_OPS_SHA256})
# If 'paddlepaddle' is not found, code will still be compiled
# but models will not be generated and tests will fail
# This is done this way for 'code style' and check cases - cmake shall pass, but CI machine doesn't need to have
# 'paddlepaddle' installed to check code style
if (paddlepaddle_FOUND)
if (paddlepaddle_FOUND AND ${PADDLEDET_RESULT} STREQUAL "ON")
set(TEST_PADDLE_MODELS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_PADDLE_MODELS_DIRNAME}/)
if (WIN32)
set(SETENV "set")
set(PATHSEP ";")
else()
set(SETENV "export")
set(PATHSEP ":")
endif()
file(GLOB_RECURSE PADDLE_ALL_SCRIPTS ${CMAKE_CURRENT_SOURCE_DIR}/*.py)
set(OUT_FILE ${TEST_PADDLE_MODELS}/generate_done.txt)
add_custom_command(OUTPUT ${OUT_FILE}
COMMAND ${PYTHON_EXECUTABLE}
COMMAND ${SETENV} PYTHONPATH=${PADDLEDET_DIRNAME}${PATHSEP}$ENV{PYTHONPATH} && ${PYTHON_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/test_models/gen_wrapper.py
${CMAKE_CURRENT_SOURCE_DIR}/test_models/gen_scripts
${TEST_PADDLE_MODELS}

View File

@@ -144,6 +144,13 @@ static const std::vector<std::string> models{std::string("argmax"),
// (CVS-82724: not support Axis as input),
std::string("gelu_erf"),
std::string("gelu_tanh"),
std::string("generate_proposals_v2_0"),
std::string("generate_proposals_v2_1"),
std::string("generate_proposals_v2_2"),
std::string("generate_proposals_v2_3"),
std::string("generate_proposals_v2_4"),
std::string("generate_proposals_v2_5"),
std::string("generate_proposals_v2_6"),
// greater_equal_big_int64(failure due to CPU inference),
std::string("greater_equal_big_int64"),
std::string("greater_equal_float32"),

View File

@@ -0,0 +1,161 @@
#
# pool2d paddle model generator
#
import numpy as np
from save_model import saveModel
import sys
def generate_proposals_v2(name: str, input_data: dict, attr: dict):
scores_np = input_data["scores"]
bbox_deltas_np = input_data["bbox_deltas"]
im_shape_np = input_data["im_shape"]
anchors_np = input_data["anchors"]
variances_np = input_data["variances"]
pre_nms_top_n = attr["pre_nms_top_n"]
post_nms_top_n = attr["post_nms_top_n"]
nms_thresh = attr["nms_thresh"]
min_size = attr["min_size"]
pixel_offset = attr["pixel_offset"]
import paddle
from ops import generate_proposals as generate_proposals
paddle.enable_static()
with paddle.static.program_guard(paddle.static.Program(), paddle.static.Program()):
scores = paddle.static.data(
name='scores', shape=scores_np.shape, dtype='float32') # [N, A, H, W]
bbox_deltas = paddle.static.data(
name='bbox_deltas', shape=bbox_deltas_np.shape, dtype='float32') # [N, 4 * A, H, W]
im_shape = paddle.static.data(
name='im_shape', shape=im_shape_np.shape, dtype='float32') # [N, 2]
anchors = paddle.static.data(
name='anchors', shape=anchors_np.shape, dtype='float32') # [H, W, A, 4]
variances = paddle.static.data(
name='var', shape=variances_np.shape, dtype='float32') # [H, W, A, 4]
rois, roi_probs, rois_num = generate_proposals(
scores,
bbox_deltas,
im_shape,
anchors,
variances,
pre_nms_top_n=pre_nms_top_n,
post_nms_top_n=post_nms_top_n,
nms_thresh=nms_thresh,
min_size=min_size,
pixel_offset=pixel_offset,
return_rois_num=True)
cpu = paddle.static.cpu_places(1)
exe = paddle.static.Executor(cpu[0])
# startup program will call initializer to initialize the parameters.
exe.run(paddle.static.default_startup_program())
outs = exe.run(
feed={
'scores': scores_np,
'bbox_deltas': bbox_deltas_np,
'im_shape': im_shape_np,
'anchors': anchors_np,
'var': variances_np
},
fetch_list=[rois, roi_probs, rois_num],
return_numpy=False)
# Save inputs in order of ngraph function, to facilite Fuzzy test,
# which accepts inputs and outputs in this order as well.
saveModel(name, exe, feedkeys=['scores', 'bbox_deltas', 'im_shape', 'anchors', 'var'],
fetchlist=[rois, roi_probs, rois_num],
inputs=[scores_np, bbox_deltas_np, im_shape_np, anchors_np, variances_np],
outputs=outs, target_dir=sys.argv[1])
if __name__ == "__main__":
input_data = dict()
attr = dict()
# test case 0
input_name = "generate_proposals_v2_0"
input_data["scores"] = np.random.rand(1, 3, 4, 4).astype('float32')
input_data["bbox_deltas"] = np.random.rand(1, 12, 4, 4).astype('float32')
input_data["im_shape"] = np.array([[200, 200]]).astype('float32')
input_data["anchors"] = np.reshape(np.arange(4 * 4 * 3 * 4),
[4, 4, 3, 4]).astype('float32')
input_data["variances"] = np.ones((4, 4, 3, 4)).astype('float32')
attr["pre_nms_top_n"] = 6000
attr["post_nms_top_n"] = 1000
attr["nms_thresh"] = 0.699999988079071
attr["min_size"] = 0
attr["pixel_offset"] = False
generate_proposals_v2(input_name, input_data, attr)
# test case 1
input_name = "generate_proposals_v2_1"
input_data["variances"] = np.ones((4 * 4 * 3, 4)).astype('float32')
input_data["anchors"] = np.reshape(np.arange(4 * 4 * 3 * 4),
[4 * 4 * 3, 4]).astype('float32')
attr["min_size"] = 4
attr["pixel_offset"] = True
generate_proposals_v2(input_name, input_data, attr)
# test case 2
input_name = "generate_proposals_v2_2"
bbox_deltas0 = np.random.rand(1, 12, 1, 4).astype('float32')
bbox_deltas1 = np.random.rand(1, 12, 2, 4).astype('float32')
input_data["bbox_deltas"] = np.concatenate((bbox_deltas0, bbox_deltas0, bbox_deltas1), axis = 2)
anchors0 = np.reshape(np.arange(1 * 4 * 3 * 4),
[1, 4, 3, 4]).astype('float32')
anchors1 = np.reshape(np.arange(3 * 4 * 3 * 4),
[3, 4, 3, 4]).astype('float32')
input_data["anchors"] = np.concatenate((anchors0, anchors1), axis = 0)
attr["nms_thresh"] = 0.5
generate_proposals_v2(input_name, input_data, attr)
# test case 3
input_name = "generate_proposals_v2_3"
attr["nms_thresh"] = 0.7
generate_proposals_v2(input_name, input_data, attr)
# test case 4
input_name = "generate_proposals_v2_4"
variances_0 = np.ones((11, 4)).astype('float32') * 0.5
variances_1 = np.ones((37, 4)).astype('float32')
input_data["variances"] = np.concatenate((variances_0, variances_1), axis = 0)
generate_proposals_v2(input_name, input_data, attr)
# test case 5
input_name = "generate_proposals_v2_5"
input_data["scores"] = np.random.rand(1, 6, 10, 8).astype('float32')
input_data["bbox_deltas"] = np.random.rand(1, 24, 10, 8).astype('float32')
input_data["im_shape"] = np.array([[1000, 1000]]).astype('float32')
input_data["anchors"] = np.reshape(np.arange(10 * 8 * 6 * 4),
[10, 8, 6, 4]).astype('float32')
input_data["variances"] = np.ones((10, 8, 6, 4)).astype('float32')
attr["pre_nms_top_n"] = 100
attr["post_nms_top_n"] = 60
generate_proposals_v2(input_name, input_data, attr)
# test case 6
input_name = "generate_proposals_v2_6"
input_data["scores"] = np.random.rand(2, 6, 10, 8).astype('float32')
input_data["bbox_deltas"] = np.random.rand(2, 24, 10, 8).astype('float32')
input_data["im_shape"] = np.array([[1000, 1000]] * 2).astype('float32')
input_data["anchors"] = np.reshape(np.arange(10 * 8 * 6 * 4),
[10, 8, 6, 4]).astype('float32')
input_data["variances"] = np.ones((10, 8, 6, 4)).astype('float32')
attr["pre_nms_top_n"] = 100
attr["post_nms_top_n"] = 60
generate_proposals_v2(input_name, input_data, attr)

View File

@@ -15,6 +15,7 @@
#include "openvino/opsets/opset6.hpp"
#include "openvino/opsets/opset7.hpp"
#include "openvino/opsets/opset8.hpp"
#include "openvino/opsets/opset9.hpp"
TEST(opset, opset1) {
auto op = std::make_shared<ov::opset1::Parameter>();
@@ -144,6 +145,22 @@ TEST(opset, opset8_dump) {
ASSERT_EQ(167, opset.get_types_info().size());
}
TEST(opset, opset9) {
auto op = std::make_shared<ov::opset9::Parameter>();
ASSERT_NE(nullptr, op);
EXPECT_TRUE(ov::op::util::is_parameter(op));
}
TEST(opset, opset9_dump) {
const auto& opset = ov::get_opset9();
std::cout << "All opset9 operations: ";
for (const auto& t : opset.get_types_info()) {
std::cout << t.name << " ";
}
std::cout << std::endl;
ASSERT_EQ(172, opset.get_types_info().size());
}
class MyOpOld : public ov::op::Op {
public:
static constexpr ov::DiscreteTypeInfo type_info{"MyOpOld", static_cast<uint64_t>(0)};

View File

@@ -86,7 +86,7 @@ TEST(type_info, find_in_map) {
test_map[b] = 1;
test_map[c] = 1;
const auto& opset = ov::get_opset8();
const auto& opset = ov::get_opset9();
// Reserve memory to avoid reallocation and copy of strings
// because type info uses pointers from the original memory
vector_names.reserve(opset.size() * 3);

View File

@@ -0,0 +1,166 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <vector>
#include "gtest/gtest.h"
#include "ngraph/ngraph.hpp"
#include "util/type_prop.hpp"
using namespace ngraph;
using GenerateProposals = op::v9::GenerateProposals;
using Attrs = op::v9::GenerateProposals::Attributes;
TEST(type_prop, generate_proposals) {
Attrs attrs;
attrs.min_size = 0.0f;
attrs.nms_threshold = 0.699999988079071f;
attrs.post_nms_count = 1000;
attrs.pre_nms_count = 1000;
const auto dyn_dim = Dimension::dynamic();
auto im_info = std::make_shared<op::Parameter>(element::f32, Shape{1, 4});
auto anchors = std::make_shared<op::Parameter>(element::f32, Shape{200, 336, 3, 4});
auto deltas = std::make_shared<op::Parameter>(element::f32, Shape{1, 12, 200, 336});
auto scores = std::make_shared<op::Parameter>(element::f32, Shape{1, 3, 200, 336});
auto proposals = std::make_shared<GenerateProposals>(im_info, anchors, deltas, scores, attrs);
ASSERT_EQ(proposals->get_output_element_type(0), element::f32);
ASSERT_EQ(proposals->get_output_element_type(1), element::f32);
ASSERT_EQ(proposals->get_output_element_type(2), element::i64);
EXPECT_EQ(proposals->get_output_partial_shape(0), (PartialShape{dyn_dim, 4}));
EXPECT_EQ(proposals->get_output_partial_shape(1), (PartialShape{dyn_dim}));
EXPECT_EQ(proposals->get_output_partial_shape(2), (PartialShape{1}));
im_info = std::make_shared<op::Parameter>(element::f32, PartialShape::dynamic(2));
anchors = std::make_shared<op::Parameter>(element::f32, PartialShape::dynamic(4));
deltas = std::make_shared<op::Parameter>(element::f32, PartialShape::dynamic(4));
scores = std::make_shared<op::Parameter>(element::f32, PartialShape::dynamic(4));
proposals = std::make_shared<GenerateProposals>(im_info, anchors, deltas, scores, attrs, element::i32);
ASSERT_EQ(proposals->get_output_element_type(0), element::f32);
ASSERT_EQ(proposals->get_output_element_type(1), element::f32);
ASSERT_EQ(proposals->get_output_element_type(2), element::i32);
EXPECT_EQ(proposals->get_output_partial_shape(0), (PartialShape{dyn_dim, 4}));
EXPECT_EQ(proposals->get_output_partial_shape(1), (PartialShape{dyn_dim}));
EXPECT_EQ(proposals->get_output_partial_shape(2), (PartialShape{dyn_dim}));
// assert throw
im_info = std::make_shared<op::Parameter>(element::f32, Shape{1, 4});
anchors = std::make_shared<op::Parameter>(element::f32, Shape{100, 336, 3, 4});
deltas = std::make_shared<op::Parameter>(element::f32, Shape{1, 12, 200, 336});
scores = std::make_shared<op::Parameter>(element::f32, Shape{1, 3, 200, 336});
ASSERT_THROW(proposals = std::make_shared<GenerateProposals>(im_info, anchors, deltas, scores, attrs, element::i32),
ngraph::CheckFailure)
<< "GenerateProposals node was created with invalid data.";
im_info = std::make_shared<op::Parameter>(element::f32, Shape{1, 4});
anchors = std::make_shared<op::Parameter>(element::f32, Shape{200, 336, 3, 4});
deltas = std::make_shared<op::Parameter>(element::f32, Shape{1, 12, 200, 300});
scores = std::make_shared<op::Parameter>(element::f32, Shape{1, 3, 200, 336});
ASSERT_THROW(proposals = std::make_shared<GenerateProposals>(im_info, anchors, deltas, scores, attrs, element::i32),
ngraph::CheckFailure)
<< "GenerateProposals node was created with invalid data.";
im_info = std::make_shared<op::Parameter>(element::f32, Shape{1, 4});
anchors = std::make_shared<op::Parameter>(element::f32, Shape{200, 336, 3, 4});
deltas = std::make_shared<op::Parameter>(element::f32, Shape{1, 12, 200, 336});
scores = std::make_shared<op::Parameter>(element::f32, Shape{1, 4, 200, 336});
ASSERT_THROW(proposals = std::make_shared<GenerateProposals>(im_info, anchors, deltas, scores, attrs, element::i32),
ngraph::CheckFailure)
<< "GenerateProposals node was created with invalid data.";
im_info = std::make_shared<op::Parameter>(element::f32, Shape{1, 2});
anchors = std::make_shared<op::Parameter>(element::f32, Shape{200, 336, 3, 4});
deltas = std::make_shared<op::Parameter>(element::f32, Shape{1, 12, 200, 336});
scores = std::make_shared<op::Parameter>(element::f32, Shape{1, 4, 200, 336});
ASSERT_THROW(proposals = std::make_shared<GenerateProposals>(im_info, anchors, deltas, scores, attrs, element::i32),
ngraph::CheckFailure)
<< "GenerateProposals node was created with invalid data.";
im_info = std::make_shared<op::Parameter>(element::f32, Shape{2, 4});
anchors = std::make_shared<op::Parameter>(element::f32, Shape{200, 336, 3, 4});
deltas = std::make_shared<op::Parameter>(element::f32, Shape{1, 12, 200, 336});
scores = std::make_shared<op::Parameter>(element::f32, Shape{1, 4, 200, 336});
ASSERT_THROW(proposals = std::make_shared<GenerateProposals>(im_info, anchors, deltas, scores, attrs, element::i32),
ngraph::CheckFailure)
<< "GenerateProposals node was created with invalid data.";
}
TEST(type_prop, generate_proposals_dynamic) {
struct ShapesAndAttrs {
PartialShape im_info_shape;
PartialShape anchors_shape;
PartialShape deltas_shape;
PartialShape scores_shape;
size_t post_nms_count;
};
const auto dyn_dim = Dimension::dynamic();
const auto dyn_shape = PartialShape::dynamic();
std::vector<ShapesAndAttrs> shapes = {
{{1, 3}, {200, 336, 3, 4}, {1, 12, 200, 336}, {1, 3, 200, 336}, 1000},
{{2, 3}, {200, 336, 3, 4}, {2, 12, 200, 336}, dyn_shape, 500},
{{1, 3}, {200, 336, 3, 4}, dyn_shape, {1, 3, 200, 336}, 700},
{{2, 3}, {200, 336, 3, 4}, dyn_shape, dyn_shape, 300},
{{1, 3}, dyn_shape, {1, 12, 200, 336}, {1, 3, 200, 336}, 200},
{{2, 3}, dyn_shape, {2, 12, 200, 336}, dyn_shape, 40},
{{1, 3}, dyn_shape, dyn_shape, {1, 3, 200, 336}, 70},
{{2, 3}, dyn_shape, dyn_shape, dyn_shape, 60},
{dyn_shape, {200, 336, 3, 4}, {1, 12, 200, 336}, {1, 3, 200, 336}, 500},
{dyn_shape, {200, 336, 3, 4}, {2, 12, 200, 336}, dyn_shape, 400},
{dyn_shape, {200, 336, 3, 4}, dyn_shape, {1, 3, 200, 336}, 350},
{dyn_shape, {200, 336, 3, 4}, dyn_shape, dyn_shape, 440},
{dyn_shape, dyn_shape, {1, 12, 200, 336}, {1, 3, 200, 336}, 315},
{dyn_shape, dyn_shape, {2, 12, 200, 336}, dyn_shape, 130},
{dyn_shape, dyn_shape, dyn_shape, {1, 3, 200, 336}, 1000},
{dyn_shape, dyn_shape, dyn_shape, dyn_shape, 700},
{{1, 3}, {dyn_dim, dyn_dim, dyn_dim, 4}, {1, 12, 200, 336}, {1, 3, 200, 336}, 540},
{{1, 3}, {dyn_dim, dyn_dim, dyn_dim, 4}, {1, 12, 200, 336}, {dyn_dim, dyn_dim, 200, 336}, 600},
{{2, 3}, {dyn_dim, dyn_dim, dyn_dim, 4}, {dyn_dim, dyn_dim, 200, 336}, {2, 3, 200, 336}, 75},
{{1, 3}, {dyn_dim, dyn_dim, dyn_dim, 4}, {dyn_dim, dyn_dim, 200, 336}, {dyn_dim, dyn_dim, 200, 336}, 80},
{{1, 3}, {200, 336, 3, 4}, {1, 12, 200, dyn_dim}, {1, 3, 200, dyn_dim}, 430},
{{2, 3}, {200, 336, 3, 4}, {2, 12, dyn_dim, 336}, {2, 3, dyn_dim, 336}, 180},
{{1, 3}, {200, 336, 3, 4}, {1, 12, dyn_dim, dyn_dim}, {1, 3, dyn_dim, dyn_dim}, 170},
{{1, 3}, {dyn_dim, dyn_dim, dyn_dim, 4}, {1, 12, 200, dyn_dim}, {1, 3, 200, dyn_dim}, 200},
{{2, 3}, {dyn_dim, dyn_dim, dyn_dim, 4}, {2, 12, dyn_dim, 336}, {2, 3, dyn_dim, 336}, 800},
{{1, 3}, {dyn_dim, dyn_dim, dyn_dim, 4}, {1, 12, dyn_dim, dyn_dim}, {1, 3, dyn_dim, dyn_dim}, 560},
};
for (const auto& s : shapes) {
Attrs attrs;
attrs.min_size = 0.0f;
attrs.nms_threshold = 0.699999988079071f;
attrs.post_nms_count = static_cast<int64_t>(s.post_nms_count);
attrs.pre_nms_count = 1000;
auto im_info = std::make_shared<op::Parameter>(element::f32, s.im_info_shape);
auto anchors = std::make_shared<op::Parameter>(element::f32, s.anchors_shape);
auto deltas = std::make_shared<op::Parameter>(element::f32, s.deltas_shape);
auto scores = std::make_shared<op::Parameter>(element::f32, s.scores_shape);
auto proposals = std::make_shared<GenerateProposals>(im_info, anchors, deltas, scores, attrs);
ASSERT_EQ(proposals->get_output_element_type(0), element::f32);
ASSERT_EQ(proposals->get_output_element_type(1), element::f32);
ASSERT_EQ(proposals->get_output_element_type(2), element::i64);
EXPECT_EQ(proposals->get_output_partial_shape(0), (PartialShape{dyn_dim, 4}));
EXPECT_EQ(proposals->get_output_partial_shape(1), (PartialShape{dyn_dim}));
if (s.im_info_shape.rank().is_static()) {
EXPECT_EQ(proposals->get_output_partial_shape(2), PartialShape{s.im_info_shape[0]});
} else {
EXPECT_EQ(proposals->get_output_partial_shape(2), PartialShape::dynamic(1));
}
}
}

View File

@@ -0,0 +1,53 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <vector>
#include "gtest/gtest.h"
#include "ngraph/ngraph.hpp"
#include "ngraph/op/util/attr_types.hpp"
#include "ngraph/opsets/opset9.hpp"
#include "util/visitor.hpp"
using namespace std;
using namespace ngraph;
using ngraph::test::NodeBuilder;
using ngraph::test::ValueMap;
using GenerateProposals = opset9::GenerateProposals;
using Attrs = opset9::GenerateProposals::Attributes;
TEST(attributes, generate_proposals) {
NodeBuilder::get_ops().register_factory<GenerateProposals>();
Attrs attrs;
attrs.min_size = 0.0f;
attrs.nms_threshold = 0.699999988079071f;
attrs.post_nms_count = 1000;
attrs.pre_nms_count = 1000;
attrs.normalized = true;
attrs.nms_eta = 1.0f;
auto im_info = std::make_shared<op::Parameter>(element::f32, Shape{1, 4});
auto anchors = std::make_shared<op::Parameter>(element::f32, Shape{200, 336, 3, 4});
auto deltas = std::make_shared<op::Parameter>(element::f32, Shape{1, 12, 200, 336});
auto scores = std::make_shared<op::Parameter>(element::f32, Shape{1, 3, 200, 336});
auto proposals = std::make_shared<GenerateProposals>(im_info, anchors, deltas, scores, attrs);
NodeBuilder builder(proposals);
auto g_proposals = ov::as_type_ptr<GenerateProposals>(builder.create());
const auto expected_attr_count = 7;
EXPECT_EQ(builder.get_value_map_size(), expected_attr_count);
EXPECT_EQ(g_proposals->get_attrs().min_size, proposals->get_attrs().min_size);
EXPECT_EQ(g_proposals->get_attrs().nms_threshold, proposals->get_attrs().nms_threshold);
EXPECT_EQ(g_proposals->get_attrs().post_nms_count, proposals->get_attrs().post_nms_count);
EXPECT_EQ(g_proposals->get_attrs().pre_nms_count, proposals->get_attrs().pre_nms_count);
EXPECT_EQ(g_proposals->get_attrs().normalized, proposals->get_attrs().normalized);
EXPECT_EQ(g_proposals->get_attrs().nms_eta, proposals->get_attrs().nms_eta);
EXPECT_EQ(g_proposals->get_roi_num_type(), proposals->get_roi_num_type());
}

View File

@@ -37,8 +37,10 @@ inline const ov::OpSet& get_opset_by_name(const std::string& opset_name) {
return ov::get_opset7();
} else if (opset_name == "opset8") {
return ov::get_opset8();
} else if (opset_name == "opset9") {
return ov::get_opset9();
} else if (opset_name.empty() || opset_name == "latest") {
return ov::get_opset8();
return ov::get_opset9();
} else {
FRONT_END_GENERAL_CHECK(false, "Unsupported opset name: ", opset_name);
}

View File

@@ -214,6 +214,7 @@ public:
m_opsets["opset6"] = ngraph::get_opset6();
m_opsets["opset7"] = ngraph::get_opset7();
m_opsets["opset8"] = ngraph::get_opset8();
m_opsets["opset9"] = ngraph::get_opset9();
}
std::shared_ptr<Function> convert();

View File

@@ -0,0 +1,94 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <map>
#include "default_opset.hpp"
#include "openvino/frontend/paddle/node_context.hpp"
namespace ov {
namespace frontend {
namespace paddle {
namespace op {
NamedOutputs generate_proposals_v2(const NodeContext& node) {
auto bbox_deltas = node.get_input("BboxDeltas"); // [N4 * AHW]
auto im_shape = node.get_input("ImShape"); // [N, 2]
auto scores = node.get_input("Scores"); // [NAHW]
auto anchors = node.get_input("Anchors"); // [HWA4] or [H * W * A, 4]
Output<Node> variances;
if (node.has_input("Variances"))
variances = node.get_input("Variances"); // [HWA4] or [H * W * A, 4]
// attribute
ov::op::v9::GenerateProposals::Attributes attrs;
float min_size = node.get_attribute<float>("min_size", 0.1);
attrs.min_size = min_size < 1.0f ? 1.0f : min_size;
attrs.nms_threshold = node.get_attribute<float>("nms_thresh", 0.5);
attrs.pre_nms_count = node.get_attribute<int>("pre_nms_topN", 6000);
attrs.post_nms_count = node.get_attribute<int>("post_nms_topN", 1000);
attrs.nms_eta = node.get_attribute<float>("eta", 1.0);
PADDLE_OP_CHECK(node, (attrs.nms_eta == 1.0), "Only support case of eta == 1.0 currently");
attrs.normalized = !node.get_attribute<bool>("pixel_offset", true);
// reshape anchors from to [H, W, A, 4] if it is [H * W * A, 4]
auto scores_shape = std::make_shared<default_opset::ShapeOf>(scores);
auto gather_indices = default_opset::Constant::create<int64_t>(ov::element::i64, {3}, {2, 3, 1});
auto gather_axis = default_opset::Constant::create<int64_t>(ov::element::i64, {}, {0});
auto partial_anchors_shape = std::make_shared<default_opset::Gather>(scores_shape, gather_indices, gather_axis);
auto const_4 = default_opset::Constant::create<int64_t>(ov::element::i64, {1}, {4});
auto anchors_shape = std::make_shared<default_opset::Concat>(OutputVector{partial_anchors_shape, const_4}, 0);
auto reshaped_anchors = std::make_shared<default_opset::Reshape>(anchors, anchors_shape, true);
auto variances_bbox_deltas = bbox_deltas;
if (variances.get_node()) {
// Reshape variances to [H, W, A, 4] if it is [H * W * A, 4]
auto dim4_variances = std::make_shared<default_opset::Reshape>(variances, anchors_shape, true);
// Transpose variances from [H, W, A, 4] to [A*4, H, W]
auto reshape_pattern = default_opset::Constant::create<int64_t>(ov::element::i64, {3}, {0, 0, -1});
auto reshaped_variances = std::make_shared<default_opset::Reshape>(dim4_variances, reshape_pattern, true);
auto transpose_order = default_opset::Constant::create(ov::element::i64, {3}, {2, 0, 1});
auto transposed_variances = std::make_shared<default_opset::Transpose>(reshaped_variances, transpose_order);
// auto transposed_variances = default_opset::Constant::create(ov::element::f32, {}, {2.0});
variances_bbox_deltas = std::make_shared<default_opset::Multiply>(bbox_deltas, transposed_variances);
}
// generate im_info from im_scale
auto pads_begin = default_opset::Constant::create<int64_t>(ov::element::i64, {2}, {0, 0});
auto pads_end = default_opset::Constant::create<int64_t>(ov::element::i64, {2}, {0, 1});
auto im_scale = default_opset::Constant::create(ov::element::f32, {}, {1.0});
auto im_info =
std::make_shared<default_opset::Pad>(im_shape, pads_begin, pads_end, im_scale, ov::op::PadMode::CONSTANT);
// input:
// 1. im_info: [N, 3] or [N, 4]
// 2. anchors: [H, W, A, 4]
// 3. deltas: [N, A*4, H, W]
// 4. scores: [N, A, H, W]
// output:
// 1. rois: [proposals_num, 4]
// 2. scores: [proposals_num]
// 3. roi_num: [N]
auto proposal = std::make_shared<ov::op::v9::GenerateProposals>(im_info,
reshaped_anchors,
variances_bbox_deltas,
scores,
attrs);
proposal->set_roi_num_type(ov::element::i32);
auto unsqueeze_scalar = default_opset::Constant::create(ov::element::i64, {}, {1});
auto probs = std::make_shared<default_opset::Unsqueeze>(proposal->output(1), unsqueeze_scalar);
// output
NamedOutputs named_outputs;
named_outputs["RpnRois"] = OutputVector{proposal->output(0)};
named_outputs["RpnRoiProbs"] = OutputVector{probs->output(0)};
named_outputs["RpnRoisNum"] = OutputVector{proposal->output(2)};
return named_outputs;
}
} // namespace op
} // namespace paddle
} // namespace frontend
} // namespace ov

View File

@@ -90,6 +90,7 @@ OP_CONVERTER(trilinear_interp_v2);
OP_CONVERTER(unsqueeze);
OP_CONVERTER(where);
OP_CONVERTER(yolo_box);
OP_CONVERTER(generate_proposals_v2);
} // namespace op
std::map<std::string, CreatorFunction> get_supported_ops() {
return {{"arg_max", op::argmax},
@@ -181,7 +182,8 @@ std::map<std::string, CreatorFunction> get_supported_ops() {
{"trilinear_interp_v2", op::trilinear_interp_v2},
{"unsqueeze2", op::unsqueeze},
{"where", op::where},
{"yolo_box", op::yolo_box}};
{"yolo_box", op::yolo_box},
{"generate_proposals_v2", op::generate_proposals_v2}};
};
} // namespace paddle

View File

@@ -45,7 +45,7 @@ inline void addInputOutput(cnpy::NpyArray& npy_array, test::TestCase& test_case,
if (is_input)
test_case.add_input(data);
else
test_case.add_expected_output(data);
test_case.add_expected_output(npy_array.shape, data);
}
static bool ends_with(std::string const& value, std::string const& ending) {

View File

@@ -182,6 +182,7 @@ const InferenceEngine::details::caseless_unordered_map<std::string, Type> type_t
{ "ExperimentalDetectronROIFeatureExtractor", Type::ExperimentalDetectronROIFeatureExtractor},
{ "ExperimentalDetectronPriorGridGenerator", Type::ExperimentalDetectronPriorGridGenerator},
{ "ExperimentalDetectronGenerateProposalsSingleImage", Type::ExperimentalDetectronGenerateProposalsSingleImage},
{ "GenerateProposals", Type::GenerateProposals},
{ "ExtractImagePatches", Type::ExtractImagePatches},
{ "NonMaxSuppression", Type::NonMaxSuppression},
{ "NonMaxSuppressionIEInternal", Type::NonMaxSuppression},
@@ -364,6 +365,8 @@ std::string NameFromType(const Type type) {
return "ExperimentalDetectronPriorGridGenerator";
case Type::ExperimentalDetectronGenerateProposalsSingleImage:
return "ExperimentalDetectronGenerateProposalsSingleImage";
case Type::GenerateProposals:
return "GenerateProposals";
case Type::ExtractImagePatches:
return "ExtractImagePatches";
case Type::NonMaxSuppression:

View File

@@ -98,6 +98,7 @@ enum class Type {
ExperimentalDetectronROIFeatureExtractor,
ExperimentalDetectronPriorGridGenerator,
ExperimentalDetectronGenerateProposalsSingleImage,
GenerateProposals,
ExtractImagePatches,
NonMaxSuppression,
MatrixNms,

View File

@@ -0,0 +1,483 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <cstring>
#include <cassert>
#include <cmath>
#include <string>
#include <vector>
#include <utility>
#include <algorithm>
#if defined(HAVE_AVX2)
#include <immintrin.h>
#endif
#include <ngraph/op/generate_proposals.hpp>
#include "ie_parallel.hpp"
#include "common/cpu_memcpy.h"
#include "generate_proposals.h"
namespace ov {
namespace intel_cpu {
namespace node {
namespace {
using namespace InferenceEngine;
struct Indexer4d {
int dim3_;
int dim23_;
int dim123_;
explicit Indexer4d(int dim0, int dim1, int dim2, int dim3):
dim3_(dim3), dim23_(dim2 * dim3), dim123_(dim1 * dim2 * dim3) {
(void)dim0;
}
int operator()(int i, int j, int k, int n) const {
return i * dim123_ + j * dim23_ + k * dim3_ + n;
}
};
void refine_anchors(const float* deltas, const float* scores, const float* anchors,
float* proposals, const int anchors_num, const int bottom_H,
const int bottom_W, const float img_H, const float img_W,
const float min_box_H, const float min_box_W,
const float max_delta_log_wh,
float coordinates_offset) {
Indexer4d delta_idx(anchors_num, 4, bottom_H, bottom_W);
Indexer4d score_idx(anchors_num, 1, bottom_H, bottom_W);
Indexer4d proposal_idx(bottom_H, bottom_W, anchors_num, 6);
Indexer4d anchor_idx(bottom_H, bottom_W, anchors_num, 4);
parallel_for2d(bottom_H, bottom_W, [&](int h, int w) {
for (int anchor = 0; anchor < anchors_num; ++anchor) {
int a_idx = anchor_idx(h, w, anchor, 0);
float x0 = anchors[a_idx + 0];
float y0 = anchors[a_idx + 1];
float x1 = anchors[a_idx + 2];
float y1 = anchors[a_idx + 3];
const float dx = deltas[delta_idx(anchor, 0, h, w)];
const float dy = deltas[delta_idx(anchor, 1, h, w)];
const float d_log_w = deltas[delta_idx(anchor, 2, h, w)];
const float d_log_h = deltas[delta_idx(anchor, 3, h, w)];
const float score = scores[score_idx(anchor, 0, h, w)];
// width & height of box
const float ww = x1 - x0 + coordinates_offset;
const float hh = y1 - y0 + coordinates_offset;
// center location of box
const float ctr_x = x0 + 0.5f * ww;
const float ctr_y = y0 + 0.5f * hh;
// new center location according to deltas (dx, dy)
const float pred_ctr_x = dx * ww + ctr_x;
const float pred_ctr_y = dy * hh + ctr_y;
// new width & height according to deltas d(log w), d(log h)
const float pred_w = std::exp(std::min(d_log_w, max_delta_log_wh)) * ww;
const float pred_h = std::exp(std::min(d_log_h, max_delta_log_wh)) * hh;
// update upper-left corner location
x0 = pred_ctr_x - 0.5f * pred_w;
y0 = pred_ctr_y - 0.5f * pred_h;
// update lower-right corner location
x1 = pred_ctr_x + 0.5f * pred_w - coordinates_offset;
y1 = pred_ctr_y + 0.5f * pred_h - coordinates_offset;
// adjust new corner locations to be within the image region,
x0 = std::max<float>(0.0f, std::min<float>(x0, img_W - coordinates_offset));
y0 = std::max<float>(0.0f, std::min<float>(y0, img_H - coordinates_offset));
x1 = std::max<float>(0.0f, std::min<float>(x1, img_W - coordinates_offset));
y1 = std::max<float>(0.0f, std::min<float>(y1, img_H - coordinates_offset));
// recompute new width & height
const float box_w = x1 - x0 + coordinates_offset;
const float box_h = y1 - y0 + coordinates_offset;
int p_idx = proposal_idx(h, w, anchor, 0);
proposals[p_idx + 0] = x0;
proposals[p_idx + 1] = y0;
proposals[p_idx + 2] = x1;
proposals[p_idx + 3] = y1;
proposals[p_idx + 4] = score;
proposals[p_idx + 5] = (min_box_W <= box_w) * (min_box_H <= box_h) * 1.0;
}
});
}
void unpack_boxes(const float* p_proposals, float* unpacked_boxes, int* is_dead, int pre_nms_topn) {
parallel_for(pre_nms_topn, [&](size_t i) {
unpacked_boxes[0*pre_nms_topn + i] = p_proposals[6*i + 0];
unpacked_boxes[1*pre_nms_topn + i] = p_proposals[6*i + 1];
unpacked_boxes[2*pre_nms_topn + i] = p_proposals[6*i + 2];
unpacked_boxes[3*pre_nms_topn + i] = p_proposals[6*i + 3];
unpacked_boxes[4*pre_nms_topn + i] = p_proposals[6*i + 4];
is_dead[i] = (p_proposals[6*i + 5] == 1.0) ? 0 : 1;
});
}
void nms_cpu(const int num_boxes, int is_dead[],
const float* boxes, int index_out[], size_t* const num_out,
const int base_index, const float nms_thresh, const int max_num_out,
float coordinates_offset) {
const int num_proposals = num_boxes;
size_t count = 0;
const float* x0 = boxes + 0 * num_proposals;
const float* y0 = boxes + 1 * num_proposals;
const float* x1 = boxes + 2 * num_proposals;
const float* y1 = boxes + 3 * num_proposals;
#if defined(HAVE_AVX2)
__m256 vc_fone = _mm256_set1_ps(coordinates_offset);
__m256i vc_ione = _mm256_set1_epi32(1);
__m256 vc_zero = _mm256_set1_ps(0.0f);
__m256 vc_nms_thresh = _mm256_set1_ps(nms_thresh);
#endif
for (int box = 0; box < num_boxes; ++box) {
if (is_dead[box])
continue;
index_out[count++] = base_index + box;
if (count == max_num_out)
break;
int tail = box + 1;
#if defined(HAVE_AVX2)
__m256 vx0i = _mm256_set1_ps(x0[box]);
__m256 vy0i = _mm256_set1_ps(y0[box]);
__m256 vx1i = _mm256_set1_ps(x1[box]);
__m256 vy1i = _mm256_set1_ps(y1[box]);
__m256 vA_width = _mm256_sub_ps(vx1i, vx0i);
__m256 vA_height = _mm256_sub_ps(vy1i, vy0i);
__m256 vA_area = _mm256_mul_ps(_mm256_add_ps(vA_width, vc_fone), _mm256_add_ps(vA_height, vc_fone));
for (; tail <= num_boxes - 8; tail += 8) {
__m256i *pdst = reinterpret_cast<__m256i*>(is_dead + tail);
__m256i vdst = _mm256_loadu_si256(pdst);
__m256 vx0j = _mm256_loadu_ps(x0 + tail);
__m256 vy0j = _mm256_loadu_ps(y0 + tail);
__m256 vx1j = _mm256_loadu_ps(x1 + tail);
__m256 vy1j = _mm256_loadu_ps(y1 + tail);
__m256 vx0 = _mm256_max_ps(vx0i, vx0j);
__m256 vy0 = _mm256_max_ps(vy0i, vy0j);
__m256 vx1 = _mm256_min_ps(vx1i, vx1j);
__m256 vy1 = _mm256_min_ps(vy1i, vy1j);
__m256 vwidth = _mm256_add_ps(_mm256_sub_ps(vx1, vx0), vc_fone);
__m256 vheight = _mm256_add_ps(_mm256_sub_ps(vy1, vy0), vc_fone);
__m256 varea = _mm256_mul_ps(_mm256_max_ps(vc_zero, vwidth), _mm256_max_ps(vc_zero, vheight));
__m256 vB_width = _mm256_sub_ps(vx1j, vx0j);
__m256 vB_height = _mm256_sub_ps(vy1j, vy0j);
__m256 vB_area = _mm256_mul_ps(_mm256_add_ps(vB_width, vc_fone), _mm256_add_ps(vB_height, vc_fone));
__m256 vdivisor = _mm256_sub_ps(_mm256_add_ps(vA_area, vB_area), varea);
__m256 vintersection_area = _mm256_div_ps(varea, vdivisor);
__m256 vcmp_0 = _mm256_cmp_ps(vx0i, vx1j, _CMP_LE_OS);
__m256 vcmp_1 = _mm256_cmp_ps(vy0i, vy1j, _CMP_LE_OS);
__m256 vcmp_2 = _mm256_cmp_ps(vx0j, vx1i, _CMP_LE_OS);
__m256 vcmp_3 = _mm256_cmp_ps(vy0j, vy1i, _CMP_LE_OS);
__m256 vcmp_4 = _mm256_cmp_ps(vc_nms_thresh, vintersection_area, _CMP_LT_OS);
vcmp_0 = _mm256_and_ps(vcmp_0, vcmp_1);
vcmp_2 = _mm256_and_ps(vcmp_2, vcmp_3);
vcmp_4 = _mm256_and_ps(vcmp_4, vcmp_0);
vcmp_4 = _mm256_and_ps(vcmp_4, vcmp_2);
_mm256_storeu_si256(pdst, _mm256_blendv_epi8(vdst, vc_ione, _mm256_castps_si256(vcmp_4)));
}
#endif
for (; tail < num_boxes; ++tail) {
float res = 0.0f;
const float x0i = x0[box];
const float y0i = y0[box];
const float x1i = x1[box];
const float y1i = y1[box];
const float x0j = x0[tail];
const float y0j = y0[tail];
const float x1j = x1[tail];
const float y1j = y1[tail];
if (x0i <= x1j && y0i <= y1j && x0j <= x1i && y0j <= y1i) {
// overlapped region (= box)
const float x0 = std::max<float>(x0i, x0j);
const float y0 = std::max<float>(y0i, y0j);
const float x1 = std::min<float>(x1i, x1j);
const float y1 = std::min<float>(y1i, y1j);
// intersection area
const float width = std::max<float>(0.0f, x1 - x0 + coordinates_offset);
const float height = std::max<float>(0.0f, y1 - y0 + coordinates_offset);
const float area = width * height;
// area of A, B
const float A_area = (x1i - x0i + coordinates_offset) * (y1i - y0i + coordinates_offset);
const float B_area = (x1j - x0j + coordinates_offset) * (y1j - y0j + coordinates_offset);
// IoU
res = area / (A_area + B_area - area);
}
if (nms_thresh < res)
is_dead[tail] = 1;
}
}
*num_out = count;
}
void fill_output_blobs(const float* proposals, const int* roi_indices,
float* rois, float* scores, uint8_t* roi_num,
const int num_proposals, const size_t num_rois, const int post_nms_topn,
Precision roi_num_type) {
const float *src_x0 = proposals + 0 * num_proposals;
const float *src_y0 = proposals + 1 * num_proposals;
const float *src_x1 = proposals + 2 * num_proposals;
const float *src_y1 = proposals + 3 * num_proposals;
const float *src_score = proposals + 4 * num_proposals;
parallel_for(num_rois, [&](size_t i) {
int index = roi_indices[i];
rois[i * 4 + 0] = src_x0[index];
rois[i * 4 + 1] = src_y0[index];
rois[i * 4 + 2] = src_x1[index];
rois[i * 4 + 3] = src_y1[index];
scores[i] = src_score[index];
});
if (roi_num_type == Precision::I32) {
int32_t num = static_cast<int32_t>(num_rois);
memcpy(roi_num, &num, sizeof(int32_t));
} else if (roi_num_type == Precision::I64) {
int64_t num = static_cast<int64_t>(num_rois);
memcpy(roi_num, &num, sizeof(int64_t));
} else {
IE_THROW() << "Incorrect element type of roi_num!";
}
}
} // namespace
bool GenerateProposals::isSupportedOperation
(const std::shared_ptr<const ngraph::Node>& op, std::string& errorMessage) noexcept {
try {
if (!ngraph::as_type_ptr<const ngraph::op::v9::GenerateProposals>(op)) {
errorMessage = "Node is not an instance of the Proposal from the operations set v0.";
return false;
}
} catch (...) {
return false;
}
return true;
}
GenerateProposals::GenerateProposals
(const std::shared_ptr<ngraph::Node>& op, const dnnl::engine& eng,
WeightsSharing::Ptr &cache) : Node(op, eng, cache) {
std::string errorMessage;
if (!isSupportedOperation(op, errorMessage)) {
IE_THROW(NotImplemented) << errorMessage;
}
if (auto proposalOp = ngraph::as_type_ptr<const ngraph::op::v9::GenerateProposals>(op)) {
auto proposalAttrs = proposalOp->get_attrs();
min_size_ = proposalAttrs.min_size;
nms_thresh_ = proposalAttrs.nms_threshold;
pre_nms_topn_ = proposalAttrs.pre_nms_count;
post_nms_topn_ = proposalAttrs.post_nms_count;
coordinates_offset_ = proposalAttrs.normalized ? 0 : 1.0;
}
roi_indices_.resize(post_nms_topn_);
}
void GenerateProposals::initSupportedPrimitiveDescriptors() {
if (!supportedPrimitiveDescriptors.empty())
return;
auto roiNumPrecision = getOriginalOutputPrecisionAtPort(OUTPUT_ROI_NUM);
addSupportedPrimDesc({{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32}},
{{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, roiNumPrecision}},
impl_desc_type::ref_any);
}
void GenerateProposals::executeDynamicImpl(dnnl::stream strm) {
execute(strm);
}
void GenerateProposals::execute(dnnl::stream strm) {
try {
if (inputShapes.size() != 4 || outputShapes.size() != 3) {
IE_THROW() << "Incorrect number of input or output edges!";
}
size_t anchor_dims_size = 1;
const auto &anchorDims = getParentEdgeAt(INPUT_ANCHORS)->getMemory().getStaticDims();
for (size_t i = 0; i < anchorDims.size(); i++) {
anchor_dims_size *= anchorDims[i];
}
size_t deltas_dims_size = 1;
const auto &deltaDims = getParentEdgeAt(INPUT_DELTAS)->getMemory().getStaticDims();
for (size_t i = 1; i < deltaDims.size(); i++) {
deltas_dims_size *= deltaDims[i];
}
if (anchor_dims_size != deltas_dims_size)
IE_THROW() << "'Anchors' blob size for GenerateProposals is incompatible with 'deltas' blob size!";
size_t score_dims_size = 1;
const auto &scoreDims = getParentEdgeAt(INPUT_SCORES)->getMemory().getStaticDims();
for (size_t i = 1; i < scoreDims.size(); i++) {
score_dims_size *= scoreDims[i];
}
if (deltas_dims_size != (4 * score_dims_size))
IE_THROW() << "'Deltas' blob size for GenerateProposals is incompatible with 'scores' blob size!";
size_t im_info_dims_size = 1;
const auto &infoDims = getParentEdgeAt(INPUT_IM_INFO)->getMemory().getStaticDims();
for (size_t i = 1; i < infoDims.size(); i++) {
im_info_dims_size *= infoDims[i];
}
// Prepare memory
const float *p_deltas_item = reinterpret_cast<const float *>(getParentEdgeAt(INPUT_DELTAS)->getMemoryPtr()->GetPtr());
const float *p_scores_item = reinterpret_cast<const float *>(getParentEdgeAt(INPUT_SCORES)->getMemoryPtr()->GetPtr());
const float *p_anchors_item = reinterpret_cast<const float *>(getParentEdgeAt(INPUT_ANCHORS)->getMemoryPtr()->GetPtr());
const float *p_img_info_cpu = reinterpret_cast<const float *>(getParentEdgeAt(INPUT_IM_INFO)->getMemoryPtr()->GetPtr());
const int anchors_num = scoreDims[1];
// bottom shape: N x (num_anchors) x H x W
const int bottom_H = deltaDims[2];
const int bottom_W = deltaDims[3];
// number of all proposals = num_anchors * H * W
const int num_proposals = anchors_num * bottom_H * bottom_W;
// number of top-n proposals before NMS
const int pre_nms_topn = std::min<int>(num_proposals, pre_nms_topn_);
// number of final RoIs
size_t num_rois = 0;
// enumerate all proposals
// num_proposals = num_anchors * H * W
// (x1, y1, x2, y2, score) for each proposal
// NOTE: for bottom, only foreground scores are passed
struct ProposalBox {
float x0;
float y0;
float x1;
float y1;
float score;
float keep;
};
std::vector<ProposalBox> proposals_(num_proposals);
std::vector<float> unpacked_boxes(5 * pre_nms_topn);
std::vector<int> is_dead(pre_nms_topn);
// Execute
size_t batch_size = scoreDims[0];
size_t total_num_rois = 0;
std::vector<float> roi_item, score_item;
std::vector<int64_t> roi_num(batch_size);
uint8_t* p_roi_num = reinterpret_cast<uint8_t*>(&roi_num[0]);
auto roi_num_type = getOriginalOutputPrecisionAtPort(OUTPUT_ROI_NUM);
const auto roi_num_item_size = roi_num_type == Precision::I32 ? sizeof(int32_t) : sizeof(int64_t);
for (size_t n = 0; n < batch_size; ++n) {
// input image height & width
const float img_H = p_img_info_cpu[0];
const float img_W = p_img_info_cpu[1];
// scale factor for height & width
float scale_h = 1.0;
float scale_w = 1.0;
if (im_info_dims_size == 3) {
scale_h = p_img_info_cpu[2];
scale_w = p_img_info_cpu[2];
} else if (im_info_dims_size == 4) {
scale_h = p_img_info_cpu[2];
scale_w = p_img_info_cpu[3];
}
// minimum box width & height
const float min_box_H = min_size_ * scale_h;
const float min_box_W = min_size_ * scale_w;
refine_anchors(p_deltas_item, p_scores_item, p_anchors_item,
reinterpret_cast<float *>(&proposals_[0]), anchors_num, bottom_H,
bottom_W, img_H, img_W,
min_box_H, min_box_W,
static_cast<const float>(log(1000. / 16.)),
coordinates_offset_);
std::partial_sort(proposals_.begin(), proposals_.begin() + pre_nms_topn, proposals_.end(),
[](const ProposalBox &struct1, const ProposalBox &struct2) {
return (struct1.score > struct2.score);
});
unpack_boxes(reinterpret_cast<float *>(&proposals_[0]), &unpacked_boxes[0], &is_dead[0], pre_nms_topn);
nms_cpu(pre_nms_topn, &is_dead[0], &unpacked_boxes[0], &roi_indices_[0], &num_rois, 0,
nms_thresh_, post_nms_topn_, coordinates_offset_);
size_t new_num_rois = total_num_rois + num_rois;
roi_item.resize(new_num_rois * 4);
score_item.resize(new_num_rois);
fill_output_blobs(&unpacked_boxes[0], &roi_indices_[0], &roi_item[total_num_rois * 4], &score_item[total_num_rois],
p_roi_num, pre_nms_topn, num_rois, post_nms_topn_, roi_num_type);
p_deltas_item += deltas_dims_size;
p_scores_item += score_dims_size;
p_img_info_cpu += im_info_dims_size;
total_num_rois = new_num_rois;
p_roi_num += roi_num_item_size;
}
// copy to out memory
redefineOutputMemory({VectorDims{total_num_rois, 4}, VectorDims{total_num_rois}, VectorDims{batch_size}});
float *p_roi_item = reinterpret_cast<float *>(getChildEdgesAtPort(OUTPUT_ROIS)[0]->getMemoryPtr()->GetPtr());
float *p_roi_score_item = reinterpret_cast<float *>(getChildEdgesAtPort(OUTPUT_SCORES)[0]->getMemoryPtr()->GetPtr());
uint8_t* p_roi_num_item = reinterpret_cast<uint8_t *>(getChildEdgesAtPort(OUTPUT_ROI_NUM)[0]->getMemoryPtr()->GetPtr());
memcpy(p_roi_item, &roi_item[0], roi_item.size() * sizeof(float));
memcpy(p_roi_score_item, &score_item[0], score_item.size() * sizeof(float));
memcpy(p_roi_num_item, &roi_num[0], getChildEdgesAtPort(OUTPUT_ROI_NUM)[0]->getMemoryPtr()->GetSize());
} catch (const std::exception &e) {
std::string errorMsg = e.what();
IE_THROW() << errorMsg;
}
}
bool GenerateProposals::created() const {
return getType() == Type::GenerateProposals;
}
bool GenerateProposals::needShapeInfer() const {
return false;
}
bool GenerateProposals::needPrepareParams() const {
return false;
}
} // namespace node
} // namespace intel_cpu
} // namespace ov

View File

@@ -0,0 +1,59 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <ie_common.h>
#include <node.h>
namespace ov {
namespace intel_cpu {
namespace node {
class GenerateProposals : public Node {
public:
GenerateProposals(const std::shared_ptr<ngraph::Node>& op,
const dnnl::engine& eng, WeightsSharing::Ptr &cache);
void getSupportedDescriptors() override {};
void initSupportedPrimitiveDescriptors() override;
void execute(dnnl::stream strm) override;
bool created() const override;
bool needShapeInfer() const override;
bool needPrepareParams() const override;
void executeDynamicImpl(dnnl::stream strm) override;
static bool isSupportedOperation(const std::shared_ptr<const ngraph::Node>& op, std::string& errorMessage) noexcept;
private:
// Inputs:
// im_info, shape [N, 3] or [N, 4]
// anchors, shape [H, W, A, 4]
// deltas, shape [N, A * 4, H, W]
// scores, shape [N, A, H, W]
// Outputs:
// rois, shape [rois_num, 4]
// scores, shape [rois_num]
// roi_num, shape [N]
const int INPUT_IM_INFO {0};
const int INPUT_ANCHORS {1};
const int INPUT_DELTAS {2};
const int INPUT_SCORES {3};
const int OUTPUT_ROIS {0};
const int OUTPUT_SCORES {1};
const int OUTPUT_ROI_NUM {2};
float min_size_;
int pre_nms_topn_;
int post_nms_topn_;
float nms_thresh_;
float coordinates_offset_;
std::vector<int> roi_indices_;
};
} // namespace node
} // namespace intel_cpu
} // namespace ov

View File

@@ -76,6 +76,7 @@
#include "nodes/depth_to_space.h"
#include "nodes/input.h"
#include "nodes/experimental_detectron_generate_proposals_single_image.h"
#include "nodes/generate_proposals.h"
#include "nodes/embedding_bag_packed_sum.h"
#include "nodes/reduce.h"
#include "nodes/if.h"
@@ -132,6 +133,7 @@ Node::NodesFactory::NodesFactory()
INTEL_CPU_NODE(Select, Type::Select);
INTEL_CPU_NODE(ShapeOf, Type::ShapeOf);
INTEL_CPU_NODE(ExperimentalDetectronGenerateProposalsSingleImage, Type::ExperimentalDetectronGenerateProposalsSingleImage);
INTEL_CPU_NODE(GenerateProposals, Type::GenerateProposals);
INTEL_CPU_NODE(ReverseSequence, Type::ReverseSequence);
INTEL_CPU_NODE(FakeQuantize, Type::FakeQuantize);
INTEL_CPU_NODE(NonMaxSuppression, Type::NonMaxSuppression);

View File

@@ -930,6 +930,142 @@ TEST_F(NGraphReshapeTests, ReshapeEDGenerateProposalsSingleImage_opset6) {
ASSERT_NO_THROW(network.reshape(newShapes));
}
TEST_F(NGraphReshapeTests, ReshapeGenerateProposals) {
std::string model = R"V0G0N(
<net name="GenerateProposals" version="10">
<layers>
<layer name="in0" type="Parameter" id="0" version="opset1">
<data shape="8,3" element_type="f32"/>
<output>
<port id="0" precision="FP32">
<dim>8</dim>
<dim>3</dim>
</port>
</output>
</layer>
<layer name="in1" type="Parameter" id="1" version="opset1">
<data shape="50,84,3,4" element_type="f32"/>
<output>
<port id="0" precision="FP32">
<dim>50</dim>
<dim>84</dim>
<dim>3</dim>
<dim>4</dim>
</port>
</output>
</layer>
<layer name="in2" type="Parameter" id="2" version="opset1">
<data shape="8,12,50,84" element_type="f32"/>
<output>
<port id="0" precision="FP32">
<dim>8</dim>
<dim>12</dim>
<dim>50</dim>
<dim>84</dim>
</port>
</output>
</layer>
<layer name="in3" type="Parameter" id="3" version="opset1">
<data shape="8,3,50,84" element_type="f32"/>
<output>
<port id="0" precision="FP32">
<dim>8</dim>
<dim>3</dim>
<dim>50</dim>
<dim>84</dim>
</port>
</output>
</layer>
<layer id="4" name="1133" type="GenerateProposals" version="opset9">
<data min_size="0.0" nms_threshold="0.699999988079071" post_nms_count="1000" pre_nms_count="1000" roi_num_type="i32"/>
<input>
<port id="0">
<dim>8</dim>
<dim>3</dim>
</port>
<port id="1">
<dim>50</dim>
<dim>84</dim>
<dim>3</dim>
<dim>4</dim>
</port>
<port id="2">
<dim>8</dim>
<dim>12</dim>
<dim>50</dim>
<dim>84</dim>
</port>
<port id="3">
<dim>8</dim>
<dim>3</dim>
<dim>50</dim>
<dim>84</dim>
</port>
</input>
<output>
<port id="4" precision="FP32">
<dim>-1</dim>
<dim>4</dim>
</port>
<port id="5" precision="FP32">
<dim>-1</dim>
</port>
<port id="6" precision="I32">
<dim>8</dim>
</port>
</output>
</layer>
<layer name="out_0" type="Result" id="5" version="opset1">
<input>
<port id="0" precision="FP32">
<dim>-1</dim>
<dim>4</dim>
</port>
</input>
</layer>
<layer name="out_1" type="Result" id="6" version="opset1">
<input>
<port id="0" precision="FP32">
<dim>-1</dim>
</port>
</input>
</layer>
<layer name="out_2" type="Result" id="7" version="opset1">
<input>
<port id="0" precision="I32">
<dim>8</dim>
</port>
</input>
</layer>
</layers>
<edges>
<edge from-layer="0" from-port="0" to-layer="4" to-port="0"/>
<edge from-layer="1" from-port="0" to-layer="4" to-port="1"/>
<edge from-layer="2" from-port="0" to-layer="4" to-port="2"/>
<edge from-layer="3" from-port="0" to-layer="4" to-port="3"/>
<edge from-layer="4" from-port="4" to-layer="5" to-port="0"/>
<edge from-layer="4" from-port="5" to-layer="6" to-port="0"/>
<edge from-layer="4" from-port="6" to-layer="7" to-port="0"/>
</edges>
</net>
)V0G0N";
InferenceEngine::Core ie;
Blob::Ptr weights;
auto network = ie.ReadNetwork(model, weights);
InferenceEngine::ICNNNetwork::InputShapes newShapes;
newShapes["in1"] = {100, 100, 4, 4};
newShapes["in2"] = {8, 16, 100, 100};
newShapes["in3"] = {8, 4, 100, 100};
ASSERT_NO_THROW(network.reshape(newShapes));
InferenceEngine::ICNNNetwork::InputShapes newShapes2;
newShapes2["in0"] = {2, 4};
newShapes2["in1"] = {100, 100, 4, 4};
newShapes2["in2"] = {2, 16, 100, 100};
newShapes2["in3"] = {2, 4, 100, 100};
ASSERT_NO_THROW(network.reshape(newShapes2));
}
TEST_F(NGraphReshapeTests, ReshapeEDROIFeatureExtractor) {
std::string model = R"V0G0N(
<net name="ExperimentalDetectronROIFeatureExtractor" version="10">

View File

@@ -0,0 +1,234 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <vector>
#include "single_layer_tests/generate_proposals.hpp"
#include "common_test_utils/ov_tensor_utils.hpp"
using namespace ov::test;
using namespace ov::test::subgraph;
namespace {
const std::vector<float> min_size = { 1 };
const std::vector<float> nms_threshold = { 0.699999988079071 };
const std::vector<int64_t> post_nms_count = { 6 };
const std::vector<int64_t> pre_nms_count = { 1000 };
const std::vector<std::pair<std::string, std::vector<ov::Tensor>>> inputTensors = {
{
"empty",
{
// 3
ov::test::utils::create_tensor<float>(ov::element::f32, ov::Shape{2, 3}, {1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f}),
// 2 x 6 x 3 x 4 = 144
ov::test::utils::create_tensor<float>(ov::element::f32, ov::Shape{2, 6, 3, 4}, std::vector<float>(144, 1.0f)),
// 2 x 12 x 2 x 6 = 144 * 2
ov::test::utils::create_tensor<float>(ov::element::f32, ov::Shape{2, 12, 2, 6}, std::vector<float>(288, 1.0f)),
// {2 x 3 x 2 x 6} = 36 * 2
ov::test::utils::create_tensor<float>(ov::element::f32, ov::Shape{2, 3, 2, 6}, {
5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 4.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 8.0f, 1.0f,
5.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 4.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 8.0f, 1.0f})
}
},
{
"filled",
{
ov::test::utils::create_tensor<float>(ov::element::f32, ov::Shape{2, 3}, {150.0, 150.0, 0.0, 150.0, 150.0, 0.0}),
ov::test::utils::create_tensor<float>(ov::element::f32, ov::Shape{2, 6, 3, 4}, {
12.0, 68.0, 102.0, 123.0, 46.0, 80.0, 79.0, 128.0, 33.0, 71.0, 127.0, 86.0, 33.0, 56.0, 150.0, 73.0,
5.0, 41.0, 93.0, 150.0, 74.0, 66.0, 106.0, 115.0, 17.0, 37.0, 87.0, 150.0, 31.0, 27.0, 150.0, 39.0,
29.0, 23.0, 112.0, 123.0, 41.0, 37.0, 103.0, 150.0, 8.0, 46.0, 98.0, 111.0, 7.0, 69.0, 114.0, 150.0,
70.0, 21.0, 150.0, 125.0, 54.0, 19.0, 132.0, 68.0, 62.0, 8.0, 150.0, 101.0, 57.0, 81.0, 150.0, 97.0,
79.0, 29.0, 109.0, 130.0, 12.0, 63.0, 100.0, 150.0, 17.0, 33.0, 113.0, 150.0, 90.0, 78.0, 150.0, 111.0,
47.0, 68.0, 150.0, 71.0, 66.0, 103.0, 111.0, 150.0, 4.0, 17.0, 112.0, 94.0, 12.0, 8.0, 119.0, 98.0,
54.0, 56.0, 120.0, 150.0, 56.0, 29.0, 150.0, 31.0, 42.0, 3.0, 139.0, 92.0, 41.0, 65.0, 150.0, 130.0,
49.0, 13.0, 143.0, 30.0, 40.0, 60.0, 150.0, 150.0, 23.0, 73.0, 24.0, 115.0, 56.0, 84.0, 107.0, 108.0,
63.0, 8.0, 142.0, 125.0, 78.0, 37.0, 93.0, 144.0, 40.0, 34.0, 150.0, 46.0, 30.0, 21.0, 150.0, 120.0}),
ov::test::utils::create_tensor<float>(ov::element::f32, ov::Shape{2, 12, 2, 6}, {
9.062256, 10.883133, 9.8441105, 12.694285, 0.41781136, 8.749107, 14.990341, 6.587644, 1.4206103,
13.299262, 12.432549, 2.736371, 0.22732796, 6.3361835, 12.268727, 2.1009045, 4.771589, 2.5131326,
5.610736, 9.3604145, 4.27379, 8.317948, 0.60510135, 6.7446275, 1.0207708, 1.1352817, 1.5785321,
1.718335, 1.8093798, 0.99247587, 1.3233583, 1.7432803, 1.8534478, 1.2593061, 1.7394226, 1.7686696,
1.647999, 1.7611449, 1.3119122, 0.03007332, 1.1106564, 0.55669737, 0.2546148, 1.9181818, 0.7134989,
2.0407224, 1.7211134, 1.8565536, 14.562747, 2.8786168, 0.5927796, 0.2064463, 7.6794515, 8.672126,
10.139171, 8.002429, 7.002932, 12.6314945, 10.550842, 0.15784842, 0.3194304, 10.752157, 3.709805,
11.628928, 0.7136225, 14.619964, 15.177284, 2.2824087, 15.381494, 0.16618137, 7.507227, 11.173228,
0.4923559, 1.8227729, 1.4749299, 1.7833921, 1.2363617, -0.23659119, 1.5737582, 1.779316, 1.9828427,
1.0482665, 1.4900246, 1.3563544, 1.5341306, 0.7634312, 4.6216766e-05, 1.6161222, 1.7512476, 1.9363779,
0.9195784, 1.4906164, -0.03244795, 0.681073, 0.6192401, 1.8033613, 14.146055, 3.4043705, 15.292292,
3.5295358, 11.138999, 9.952057, 5.633434, 12.114562, 9.427372, 12.384038, 9.583308, 8.427233,
15.293704, 3.288159, 11.64898, 9.350885, 2.0037227, 13.523184, 4.4176426, 6.1057625, 14.400079,
8.248259, 11.815807, 15.713364, 1.0023532, 1.3203261, 1.7100681, 0.7407832, 1.09448, 1.7188418,
1.4412547, 1.4862992, 0.74790007, 0.31571656, 0.6398838, 2.0236106, 1.1869069, 1.7265586, 1.2624544,
0.09934269, 1.3508598, 0.85212964, -0.38968498, 1.7059708, 1.6533034, 1.7400402, 1.8123854, -0.43063712,
9.062256, 10.883133, 9.8441105, 12.694285, 0.41781136, 8.749107, 14.990341, 6.587644, 1.4206103,
13.299262, 12.432549, 2.736371, 0.22732796, 6.3361835, 12.268727, 2.1009045, 4.771589, 2.5131326,
5.610736, 9.3604145, 4.27379, 8.317948, 0.60510135, 6.7446275, 1.0207708, 1.1352817, 1.5785321,
1.718335, 1.8093798, 0.99247587, 1.3233583, 1.7432803, 1.8534478, 1.2593061, 1.7394226, 1.7686696,
1.647999, 1.7611449, 1.3119122, 0.03007332, 1.1106564, 0.55669737, 0.2546148, 1.9181818, 0.7134989,
2.0407224, 1.7211134, 1.8565536, 14.562747, 2.8786168, 0.5927796, 0.2064463, 7.6794515, 8.672126,
10.139171, 8.002429, 7.002932, 12.6314945, 10.550842, 0.15784842, 0.3194304, 10.752157, 3.709805,
11.628928, 0.7136225, 14.619964, 15.177284, 2.2824087, 15.381494, 0.16618137, 7.507227, 11.173228,
0.4923559, 1.8227729, 1.4749299, 1.7833921, 1.2363617, -0.23659119, 1.5737582, 1.779316, 1.9828427,
1.0482665, 1.4900246, 1.3563544, 1.5341306, 0.7634312, 4.6216766e-05, 1.6161222, 1.7512476, 1.9363779,
0.9195784, 1.4906164, -0.03244795, 0.681073, 0.6192401, 1.8033613, 14.146055, 3.4043705, 15.292292,
3.5295358, 11.138999, 9.952057, 5.633434, 12.114562, 9.427372, 12.384038, 9.583308, 8.427233,
15.293704, 3.288159, 11.64898, 9.350885, 2.0037227, 13.523184, 4.4176426, 6.1057625, 14.400079,
8.248259, 11.815807, 15.713364, 1.0023532, 1.3203261, 1.7100681, 0.7407832, 1.09448, 1.7188418,
1.4412547, 1.4862992, 0.74790007, 0.31571656, 0.6398838, 2.0236106, 1.1869069, 1.7265586, 1.2624544,
0.09934269, 1.3508598, 0.85212964, -0.38968498, 1.7059708, 1.6533034, 1.7400402, 1.8123854, -0.43063712}),
ov::test::utils::create_tensor<float>(ov::element::f32, ov::Shape{2, 3, 2, 6}, {
0.7719922, 0.35906568, 0.29054508, 0.18124384, 0.5604661, 0.84750974, 0.98948747, 0.009793862, 0.7184191,
0.5560748, 0.6952493, 0.6732593, 0.3306898, 0.6790913, 0.41128764, 0.34593266, 0.94296855, 0.7348507,
0.24478768, 0.94024557, 0.05405676, 0.06466125, 0.36244348, 0.07942984, 0.10619422, 0.09412837, 0.9053611,
0.22870538, 0.9237487, 0.20986171, 0.5067282, 0.29709867, 0.53138554, 0.189101, 0.4786443, 0.88421875,
0.7719922, 0.35906568, 0.29054508, 0.18124384, 0.5604661, 0.84750974, 0.98948747, 0.009793862, 0.7184191,
0.5560748, 0.6952493, 0.6732593, 0.3306898, 0.6790913, 0.41128764, 0.34593266, 0.94296855, 0.7348507,
0.24478768, 0.94024557, 0.05405676, 0.06466125, 0.36244348, 0.07942984, 0.10619422, 0.09412837, 0.9053611,
0.22870538, 0.9237487, 0.20986171, 0.5067282, 0.29709867, 0.53138554, 0.189101, 0.4786443, 0.88421875}),
}
},
{
"filled2",
{
ov::test::utils::create_tensor<float>(ov::element::f32, ov::Shape{2, 3}, {200.0, 200.0, 4.0, 200.0, 200.0, 4.0}),
ov::test::utils::create_tensor<float>(ov::element::f32, ov::Shape{2, 6, 3, 4}, {0.0f, 1.0f, 2.0f, 3.0f,
4.0f, 5.0f, 6.0f, 7.0f,
8.0f, 9.0f, 10.0f, 11.0f,
12.0f, 13.0f, 14.0f, 15.0f,
16.0f, 17.0f, 18.0f, 19.0f,
20.0f, 21.0f, 22.0f, 23.0f,
24.0f, 25.0f, 26.0f, 27.0f,
28.0f, 29.0f, 30.0f, 31.0f,
32.0f, 33.0f, 34.0f, 35.0f,
36.0f, 37.0f, 38.0f, 39.0f,
40.0f, 41.0f, 42.0f, 43.0f,
44.0f, 45.0f, 46.0f, 47.0f,
48.0f, 49.0f, 50.0f, 51.0f,
52.0f, 53.0f, 54.0f, 55.0f,
56.0f, 57.0f, 58.0f, 59.0f,
60.0f, 61.0f, 62.0f, 63.0f,
64.0f, 65.0f, 66.0f, 67.0f,
68.0f, 69.0f, 70.0f, 71.0f,
72.0f, 73.0f, 74.0f, 75.0f,
76.0f, 77.0f, 78.0f, 79.0f,
80.0f, 81.0f, 82.0f, 83.0f,
84.0f, 85.0f, 86.0f, 87.0f,
88.0f, 89.0f, 90.0f, 91.0f,
92.0f, 93.0f, 94.0f, 95.0f,
96.0f, 97.0f, 98.0f, 99.0f,
100.0f, 101.0f, 102.0f, 103.0f,
104.0f, 105.0f, 106.0f, 107.0f,
108.0f, 109.0f, 110.0f, 111.0f,
112.0f, 113.0f, 114.0f, 115.0f,
116.0f, 117.0f, 118.0f, 119.0f,
120.0f, 121.0f, 122.0f, 123.0f,
124.0f, 125.0f, 126.0f, 127.0f,
128.0f, 129.0f, 130.0f, 131.0f,
132.0f, 133.0f, 134.0f, 135.0f,
136.0f, 137.0f, 138.0f, 139.0f,
140.0f, 141.0f, 142.0f, 143.0f}),
ov::test::utils::create_tensor<float>(ov::element::f32, ov::Shape{2, 12, 2, 6}, {
0.5337073, 0.86607957, 0.55151343, 0.21626699, 0.4462629, 0.03985678,
0.5157072, 0.9932138, 0.7565954, 0.43803605, 0.802818, 0.14834064,
0.53932905, 0.14314, 0.3817048, 0.95075196, 0.05516243, 0.2567484,
0.25508744, 0.77438325, 0.43561, 0.2094628, 0.8299043, 0.44982538,
0.95615596, 0.5651084, 0.11801951, 0.05352486, 0.9774733, 0.14439464,
0.62644225, 0.14370479, 0.54161614, 0.557915, 0.53102225, 0.0840179,
0.7249888, 0.9843559, 0.5490522, 0.53788143, 0.822474, 0.3278008,
0.39688024, 0.3286012, 0.5117038, 0.04743988, 0.9408995, 0.29885054,
0.81039643, 0.85277915, 0.06807619, 0.86430097, 0.36225632, 0.16606331,
0.5401001, 0.7541649, 0.11998601, 0.5131829, 0.40606487, 0.327888,
0.27721855, 0.6378373, 0.22795396, 0.4961256, 0.3215895, 0.15607187,
0.14782153, 0.8908137, 0.8835288, 0.834191, 0.29907143, 0.7983525,
0.755875, 0.30837986, 0.0839176, 0.26624718, 0.04371626, 0.09472824,
0.20689541, 0.37622106, 0.1083321, 0.1342548, 0.05815459, 0.7676379,
0.8105144, 0.92348766, 0.26761323, 0.7183306, 0.8947588, 0.19020908,
0.42731014, 0.7473663, 0.85775334, 0.9340091, 0.3278848, 0.755993,
0.05307213, 0.39705503, 0.21003333, 0.5625373, 0.66188884, 0.80521655,
0.6125863, 0.44678232, 0.97802377, 0.0204936, 0.02686367, 0.7390654,
0.74631, 0.58399844, 0.5988792, 0.37413648, 0.5946692, 0.6955776,
0.36377597, 0.7891322, 0.40900692, 0.99139464, 0.50169915, 0.41435778,
0.17142445, 0.26761186, 0.31591868, 0.14249913, 0.12919712, 0.5418711,
0.6523203, 0.50259084, 0.7379765, 0.01171071, 0.94423133, 0.00841132,
0.97486794, 0.2921785, 0.7633071, 0.88477814, 0.03563205, 0.50833166,
0.01354555, 0.535081, 0.41366324, 0.0694767, 0.9944055, 0.9981207,
0.5337073, 0.86607957, 0.55151343, 0.21626699, 0.4462629, 0.03985678,
0.5157072, 0.9932138, 0.7565954, 0.43803605, 0.802818, 0.14834064,
0.53932905, 0.14314, 0.3817048, 0.95075196, 0.05516243, 0.2567484,
0.25508744, 0.77438325, 0.43561, 0.2094628, 0.8299043, 0.44982538,
0.95615596, 0.5651084, 0.11801951, 0.05352486, 0.9774733, 0.14439464,
0.62644225, 0.14370479, 0.54161614, 0.557915, 0.53102225, 0.0840179,
0.7249888, 0.9843559, 0.5490522, 0.53788143, 0.822474, 0.3278008,
0.39688024, 0.3286012, 0.5117038, 0.04743988, 0.9408995, 0.29885054,
0.81039643, 0.85277915, 0.06807619, 0.86430097, 0.36225632, 0.16606331,
0.5401001, 0.7541649, 0.11998601, 0.5131829, 0.40606487, 0.327888,
0.27721855, 0.6378373, 0.22795396, 0.4961256, 0.3215895, 0.15607187,
0.14782153, 0.8908137, 0.8835288, 0.834191, 0.29907143, 0.7983525,
0.755875, 0.30837986, 0.0839176, 0.26624718, 0.04371626, 0.09472824,
0.20689541, 0.37622106, 0.1083321, 0.1342548, 0.05815459, 0.7676379,
0.8105144, 0.92348766, 0.26761323, 0.7183306, 0.8947588, 0.19020908,
0.42731014, 0.7473663, 0.85775334, 0.9340091, 0.3278848, 0.755993,
0.05307213, 0.39705503, 0.21003333, 0.5625373, 0.66188884, 0.80521655,
0.6125863, 0.44678232, 0.97802377, 0.0204936, 0.02686367, 0.7390654,
0.74631, 0.58399844, 0.5988792, 0.37413648, 0.5946692, 0.6955776,
0.36377597, 0.7891322, 0.40900692, 0.99139464, 0.50169915, 0.41435778,
0.17142445, 0.26761186, 0.31591868, 0.14249913, 0.12919712, 0.5418711,
0.6523203, 0.50259084, 0.7379765, 0.01171071, 0.94423133, 0.00841132,
0.97486794, 0.2921785, 0.7633071, 0.88477814, 0.03563205, 0.50833166,
0.01354555, 0.535081, 0.41366324, 0.0694767, 0.9944055, 0.9981207}),
ov::test::utils::create_tensor<float>(ov::element::f32, ov::Shape{2, 3, 2, 6}, {
0.56637216, 0.90457034, 0.69827306, 0.4353543, 0.47985056, 0.42658508,
0.14516132, 0.08081771, 0.1799732, 0.9229515, 0.42420176, 0.50857586,
0.82664067, 0.4972319, 0.3752427, 0.56731623, 0.18241242, 0.33252355,
0.30608943, 0.6572437, 0.69185436, 0.88646156, 0.36985755, 0.5590753,
0.5256446, 0.03342898, 0.1344396, 0.68642473, 0.37953874, 0.32575172,
0.21108444, 0.5661886, 0.45378175, 0.62126315, 0.26799858, 0.37272978,
0.56637216, 0.90457034, 0.69827306, 0.4353543, 0.47985056, 0.42658508,
0.14516132, 0.08081771, 0.1799732, 0.9229515, 0.42420176, 0.50857586,
0.82664067, 0.4972319, 0.3752427, 0.56731623, 0.18241242, 0.33252355,
0.30608943, 0.6572437, 0.69185436, 0.88646156, 0.36985755, 0.5590753,
0.5256446, 0.03342898, 0.1344396, 0.68642473, 0.37953874, 0.32575172,
0.21108444, 0.5661886, 0.45378175, 0.62126315, 0.26799858, 0.37272978}),
}
}
};
const std::vector<std::vector<InputShape>> dynamicInputShape = {
// im_info / anchors / deltas / scores
static_shapes_to_test_representation({{2, 3}, {2, 6, 3, 4}, {2, 12, 2, 6}, {2, 3, 2, 6}}),
{
{{-1, -1}, {{2, 3}}},
{{-1, -1, -1, -1}, {{2, 6, 3, 4}}},
{{-1, -1, -1, -1}, {{2, 12, 2, 6}}},
{{-1, -1, -1, -1}, {{2, 3, 2, 6}}}
},
{
{{{1, 3}, {3, 6}}, {{2, 3}}},
{{{2, 4}, {6, 12}, {3, 6}, {4, 8}}, {{2, 6, 3, 4}}},
{{{1, 3}, {12, 24}, {2, 4}, {6, 12}}, {{2, 12, 2, 6}}},
{{{1, 3}, {3, 6}, {2, 4}, {6, 12}}, {{2, 3, 2, 6}}}
}
};
INSTANTIATE_TEST_SUITE_P(
smoke_GenerateProposalsLayerTest,
GenerateProposalsLayerTest,
::testing::Combine(
::testing::ValuesIn(dynamicInputShape),
::testing::ValuesIn(min_size),
::testing::ValuesIn(nms_threshold),
::testing::ValuesIn(post_nms_count),
::testing::ValuesIn(pre_nms_count),
::testing::ValuesIn(inputTensors),
::testing::Values(ov::element::Type_t::f32),
::testing::Values(ov::element::Type_t::i32),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
GenerateProposalsLayerTest::getTestCaseName);
} // namespace

View File

@@ -0,0 +1,19 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <shared_test_classes/single_layer/generate_proposals.hpp>
namespace ov {
namespace test {
namespace subgraph {
TEST_P(GenerateProposalsLayerTest, GenerateProposalsLayerTests) {
run();
}
} // namespace subgraph
} // namespace test
} // namespace ov

View File

@@ -0,0 +1,37 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "ngraph_functions/utils/ngraph_helpers.hpp"
#include "common_test_utils/common_utils.hpp"
#include "shared_test_classes/base/ov_subgraph.hpp"
namespace ov {
namespace test {
namespace subgraph {
typedef std::tuple<
std::vector<InputShape>, // Input shapes
float, // min_size: minimum box width & height
float, // nms_threshold: specifies NMS threshold
int64_t, // post_nms_count: number of top-n proposals after NMS
int64_t, // pre_nms_count: number of top-n proposals after NMS
std::pair<std::string, std::vector<ov::Tensor>>, // input tensors
ElementType, // Network precision
ElementType, // roi_num precision
std::string // Device name>;
> GenerateProposalsTestParams;
class GenerateProposalsLayerTest :
public testing::WithParamInterface<GenerateProposalsTestParams>,
virtual public SubgraphBaseTest {
protected:
void SetUp() override;
void generate_inputs(const std::vector<ngraph::Shape>& targetInputStaticShapes) override;
public:
static std::string getTestCaseName(const testing::TestParamInfo<GenerateProposalsTestParams>& obj);
};
} // namespace subgraph
} // namespace test
} // namespace ov

View File

@@ -0,0 +1,115 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "shared_test_classes/single_layer/generate_proposals.hpp"
#include "ngraph_functions/builders.hpp"
#include "common_test_utils/ov_tensor_utils.hpp"
namespace ov {
namespace test {
namespace subgraph {
namespace {
std::ostream& operator <<(
std::ostream& ss,
const ov::op::v9::GenerateProposals::Attributes& attributes) {
ss << "score_threshold=" << attributes.min_size << "_";
ss << "nms_threshold=" << attributes.nms_threshold << "_";
ss << "max_delta_log_wh=" << attributes.post_nms_count << "_";
ss << "num_classes=" << attributes.pre_nms_count;
return ss;
}
} // namespace
std::string GenerateProposalsLayerTest::getTestCaseName(
const testing::TestParamInfo<GenerateProposalsTestParams>& obj) {
std::vector<InputShape> inputShapes;
ov::op::v9::GenerateProposals::Attributes attributes;
std::pair<std::string, std::vector<ov::Tensor>> inputTensors;
ElementType netPrecision;
ElementType roiNumPrecision;
std::string targetName;
std::tie(
inputShapes,
attributes.min_size,
attributes.nms_threshold,
attributes.post_nms_count,
attributes.pre_nms_count,
inputTensors,
netPrecision,
roiNumPrecision,
targetName) = obj.param;
std::ostringstream result;
using ov::test::operator<<;
result << "im_info=" << inputShapes[0] << "_";
result << "anchors=" << inputShapes[1] << "_";
result << "deltas=" << inputShapes[2] << "_";
result << "scores=" << inputShapes[3] << "_";
using ov::test::subgraph::operator<<;
result << "attributes={" << attributes << "}_";
result << "inputTensors=" << inputTensors.first << "_";
result << "netPRC=" << netPrecision << "_";
result << "roiNumPRC=" << roiNumPrecision << "_";
result << "trgDev=" << targetName;
return result.str();
}
void GenerateProposalsLayerTest::SetUp() {
std::vector<InputShape> inputShapes;
ov::op::v9::GenerateProposals::Attributes attributes;
std::pair<std::string, std::vector<ov::Tensor>> inputTensors;
ElementType netPrecision;
ElementType roiNumPrecision;
std::string targetName;
std::tie(
inputShapes,
attributes.min_size,
attributes.nms_threshold,
attributes.post_nms_count,
attributes.pre_nms_count,
inputTensors,
netPrecision,
roiNumPrecision,
targetName) = this->GetParam();
inType = outType = netPrecision;
targetDevice = targetName;
init_input_shapes(inputShapes);
auto params = ngraph::builder::makeDynamicParams(netPrecision, {inputDynamicShapes});
auto paramsOuts = ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes<ngraph::op::Parameter>(params));
auto generateProposals = std::make_shared<ov::op::v9::GenerateProposals>(
params[0], // im_info
params[1], // anchors
params[2], // deltas
params[3], // scores
attributes,
roiNumPrecision);
function = std::make_shared<ov::Model>(
ov::OutputVector{generateProposals->output(0),
generateProposals->output(1),
generateProposals->output(2)},
"GenerateProposals");
}
void GenerateProposalsLayerTest::generate_inputs(const std::vector<ngraph::Shape>& targetInputStaticShapes) {
auto inputTensors = std::get<5>(GetParam());
inputs.clear();
const auto& funcInputs = function->inputs();
for (auto i = 0ul; i < funcInputs.size(); ++i) {
if (targetInputStaticShapes[i] != inputTensors.second[i].get_shape()) {
throw Exception("input shape is different from tensor shape");
}
inputs.insert({funcInputs[i].get_node_shared_ptr(), inputTensors.second[i]});
}
}
} // namespace subgraph
} // namespace test
} // namespace ov