[IE][VPU][GT][DTS]: Update MyriadPlugin to work with dynamic NMS-5 (#2698)

* [VPU][GT][NGraph] Get rid of DynamicNMS and transformation
* [VPU][NGraph] Update DTS for NMS
* [VPU][NGraph] Update StaticShapeNMS to be inherrited from NMS-5
* [VPU][GT] Update StaticShapeNMS stage to work with updated NGraph op
* [VPU][Tests] Update tests
* [VPU][GT] Fix StaticShapeNMS to be inherited from NonMaxSuppressionIE3
* [VPU][GT] Remove unused NonMaxSuppression
This commit is contained in:
Andrew Bakalin 2020-10-23 17:04:36 +03:00 committed by GitHub
parent c4e0b74fb1
commit cab7a77cba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 253 additions and 1098 deletions

View File

@ -1,61 +0,0 @@
// Copyright (C) 2020 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "ngraph/op/non_max_suppression.hpp"
namespace ngraph { namespace vpu { namespace op {
class DynamicNonMaxSuppression : public ngraph::op::v4::NonMaxSuppression {
public:
static constexpr NodeTypeInfo type_info{"DynamicNonMaxSuppression", 0};
const NodeTypeInfo& get_type_info() const override { return type_info; }
DynamicNonMaxSuppression() = default;
/// \brief Constructs a DynamicNonMaxSuppression operation.
///
/// \param boxes Node producing the box coordinates
/// \param scores Node producing the box scores
/// \param max_output_boxes_per_class Node producing maximum number of boxes to be
/// selected per class
/// \param iou_threshold Node producing intersection over union threshold
/// \param score_threshold Node producing minimum score threshold
/// \param box_encoding Specifies the format of boxes data encoding
/// \param sort_result_descending Specifies whether it is necessary to sort selected
/// boxes across batches
/// \param output_type Specifies the output tensor type
DynamicNonMaxSuppression(const Output<Node>& boxes,
const Output<Node>& scores,
const Output<Node>& max_output_boxes_per_class,
const Output<Node>& iou_threshold,
const Output<Node>& score_threshold,
const BoxEncodingType box_encoding = BoxEncodingType::CORNER,
const bool sort_result_descending = true,
const ngraph::element::Type& output_type = ngraph::element::i64);
/// \brief Constructs a DynamicNonMaxSuppression operation with default values for the last
/// 3 inputs
///
/// \param boxes Node producing the box coordinates
/// \param scores Node producing the box coordinates
/// \param box_encoding Specifies the format of boxes data encoding
/// \param sort_result_descending Specifies whether it is necessary to sort selected
/// boxes across batches
/// \param output_type Specifies the output tensor type
DynamicNonMaxSuppression(const Output<Node>& boxes,
const Output<Node>& scores,
const BoxEncodingType box_encoding = BoxEncodingType::CORNER,
const bool sort_result_descending = true,
const ngraph::element::Type& output_type = ngraph::element::i64);
void validate_and_infer_types() override;
std::shared_ptr<Node>
clone_with_new_inputs(const OutputVector& new_args) const override;
};
} // namespace op
} // namespace vpu
} // namespace ngraph

View File

@ -5,33 +5,27 @@
#pragma once
#include <ngraph/node.hpp>
#include <ngraph/op/op.hpp>
#include <legacy/ngraph_ops/nms_ie.hpp>
#include <memory>
#include <vector>
namespace ngraph { namespace vpu { namespace op {
class StaticShapeNonMaxSuppression : public ngraph::op::v4::NonMaxSuppression {
class StaticShapeNonMaxSuppression : public ngraph::op::NonMaxSuppressionIE3 {
public:
static constexpr NodeTypeInfo type_info{"StaticShapeNonMaxSuppression", 0};
const NodeTypeInfo& get_type_info() const override { return type_info; }
StaticShapeNonMaxSuppression() = default;
StaticShapeNonMaxSuppression(const Output<Node>& boxes,
const Output<Node>& scores,
const Output<Node>& max_output_boxes_per_class,
const Output<Node>& iou_threshold,
const Output<Node>& score_threshold,
const BoxEncodingType box_encoding = BoxEncodingType::CORNER,
const bool sort_result_descending = true,
const ngraph::element::Type& output_type = ngraph::element::i64);
StaticShapeNonMaxSuppression(const Output<Node>& boxes,
const Output<Node>& scores,
const BoxEncodingType box_encoding = BoxEncodingType::CORNER,
const bool sort_result_descending = true,
const ngraph::element::Type& output_type = ngraph::element::i64);
const Output<Node>& scores,
const Output<Node>& maxOutputBoxesPerClass,
const Output<Node>& iouThreshold,
const Output<Node>& scoreThreshold,
const Output<Node>& softNmsSigma,
int centerPointBox = 0,
bool sortResultDescending = true,
const ngraph::element::Type& outputType = ngraph::element::i64);
void validate_and_infer_types() override;
std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override;

View File

@ -1,21 +0,0 @@
// Copyright (C) 2018-2020 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <ngraph/pass/graph_rewrite.hpp>
namespace vpu {
class UpgradeNMS4ToNMSDynamic : public ngraph::pass::GraphRewrite {
public:
UpgradeNMS4ToNMSDynamic() : GraphRewrite() {
upgrade_nms4_to_nms_dynamic();
}
private:
void upgrade_nms4_to_nms_dynamic();
};
} // namespace vpu

View File

@ -1,89 +0,0 @@
// Copyright (C) 2020 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "vpu/ngraph/operations/dynamic_non_max_suppression.hpp"
#include "vpu/utils/error.hpp"
#include "ngraph/opsets/opset3.hpp"
#include "ngraph/evaluator.hpp"
namespace ngraph { namespace vpu { namespace op {
constexpr NodeTypeInfo DynamicNonMaxSuppression::type_info;
DynamicNonMaxSuppression::DynamicNonMaxSuppression(
const Output<Node>& boxes,
const Output<Node>& scores,
const Output<Node>& max_output_boxes_per_class,
const Output<Node>& iou_threshold,
const Output<Node>& score_threshold,
const BoxEncodingType box_encoding,
const bool sort_result_descending,
const element::Type& output_type)
: ngraph::op::v4::NonMaxSuppression(boxes,
scores,
max_output_boxes_per_class,
iou_threshold,
score_threshold,
box_encoding,
sort_result_descending,
output_type) {
constructor_validate_and_infer_types();
}
DynamicNonMaxSuppression::DynamicNonMaxSuppression(
const Output<Node>& boxes,
const Output<Node>& scores,
const BoxEncodingType box_encoding,
const bool sort_result_descending,
const element::Type& output_type)
: ngraph::op::v4::NonMaxSuppression(boxes,
scores,
ngraph::op::Constant::create(element::i64, Shape{}, {0}),
ngraph::op::Constant::create(element::f32, Shape{}, {.0f}),
ngraph::op::Constant::create(element::f32, Shape{}, {.0f}),
box_encoding,
sort_result_descending,
output_type) {
constructor_validate_and_infer_types();
}
std::shared_ptr<Node> DynamicNonMaxSuppression::clone_with_new_inputs(const OutputVector& new_args) const {
check_new_args_count(this, new_args);
NODE_VALIDATION_CHECK(this,
new_args.size() >= 2 && new_args.size() <= 5,
"Number of inputs must be 2, 3, 4 or 5");
const auto& arg2 = new_args.size() > 2
? new_args.at(2)
: ngraph::op::Constant::create(element::i32, Shape{}, {0});
const auto& arg3 = new_args.size() > 3
? new_args.at(3)
: ngraph::op::Constant::create(element::f32, Shape{}, {.0f});
const auto& arg4 = new_args.size() > 4
? new_args.at(4)
: ngraph::op::Constant::create(element::f32, Shape{}, {.0f});
return std::make_shared<DynamicNonMaxSuppression>(new_args.at(0),
new_args.at(1),
arg2,
arg3,
arg4,
m_box_encoding,
m_sort_result_descending,
m_output_type);
}
void DynamicNonMaxSuppression::validate_and_infer_types() {
ngraph::op::v4::NonMaxSuppression::validate_and_infer_types();
// NonMaxSuppression produces triplets
// that have the following format: [batch_index, class_index, box_index]
set_output_type(0, m_output_type, PartialShape{Dimension::dynamic(), 3});
}
} // namespace op
} // namespace vpu
} // namespace ngraph

View File

@ -3,6 +3,7 @@
//
#include <ngraph/opsets/opset3.hpp>
#include <ngraph/opsets/opset5.hpp>
#include "vpu/ngraph/operations/static_shape_non_maximum_suppression.hpp"
#include "ngraph/runtime/host_tensor.hpp"
@ -14,65 +15,40 @@ constexpr NodeTypeInfo StaticShapeNonMaxSuppression::type_info;
StaticShapeNonMaxSuppression::StaticShapeNonMaxSuppression(
const Output<Node>& boxes,
const Output<Node>& scores,
const Output<Node>& max_output_boxes_per_class,
const Output<Node>& iou_threshold,
const Output<Node>& score_threshold,
const StaticShapeNonMaxSuppression::BoxEncodingType box_encoding,
const bool sort_result_descending,
const element::Type& output_type)
: ngraph::op::v4::NonMaxSuppression(
boxes, scores, max_output_boxes_per_class, iou_threshold, score_threshold,
box_encoding, sort_result_descending, output_type) {
constructor_validate_and_infer_types();
}
StaticShapeNonMaxSuppression::StaticShapeNonMaxSuppression(
const Output<Node>& boxes,
const Output<Node>& scores,
const StaticShapeNonMaxSuppression::BoxEncodingType box_encoding,
const bool sort_result_descending,
const element::Type& output_type)
: ngraph::op::v4::NonMaxSuppression(boxes,
scores,
ngraph::opset3::Constant::create(element::i64, Shape{}, {0}),
ngraph::opset3::Constant::create(element::f32, Shape{}, {.0f}),
ngraph::opset3::Constant::create(element::f32, Shape{}, {.0f}),
box_encoding, sort_result_descending, output_type) {
const Output<Node>& maxOutputBoxesPerClass,
const Output<Node>& iouThreshold,
const Output<Node>& scoreThreshold,
const Output<Node>& softNmsSigma,
int centerPointBox,
const bool sortResultDescending,
const element::Type& outputType)
: ngraph::op::NonMaxSuppressionIE3(
boxes, scores, maxOutputBoxesPerClass, iouThreshold, scoreThreshold,
softNmsSigma, centerPointBox, sortResultDescending, outputType) {
constructor_validate_and_infer_types();
}
std::shared_ptr<Node>
StaticShapeNonMaxSuppression::clone_with_new_inputs(const OutputVector& new_args) const {
check_new_args_count(this, new_args);
NODE_VALIDATION_CHECK(this,
new_args.size() >= 2 && new_args.size() <= 5,
"Number of inputs must be 2, 3, 4 or 5");
const auto& arg2 = new_args.size() > 2 ? new_args.at(2) : ngraph::opset3::Constant::create(element::i32, Shape{}, {0});
const auto& arg3 = new_args.size() > 3 ? new_args.at(3) : ngraph::opset3::Constant::create(element::f32, Shape{}, {.0f});
const auto& arg4 = new_args.size() > 4 ? new_args.at(4) : ngraph::opset3::Constant::create(element::f32, Shape{}, {.0f});
return std::make_shared<StaticShapeNonMaxSuppression>(
new_args.at(0),
new_args.at(1),
arg2,
arg3,
arg4,
m_box_encoding,
m_sort_result_descending,
m_output_type);
return std::make_shared<StaticShapeNonMaxSuppression>(new_args.at(0), new_args.at(1), new_args.at(2), new_args.at(3),
new_args.at(4), new_args.at(5), m_center_point_box, m_sort_result_descending,
m_output_type);
}
void StaticShapeNonMaxSuppression::validate_and_infer_types() {
ngraph::op::v4::NonMaxSuppression::validate_and_infer_types();
ngraph::op::NonMaxSuppressionIE3::validate_and_infer_types();
const auto out_shape = this->get_output_partial_shape(0);
NODE_VALIDATION_CHECK(this, out_shape.is_static(),
"StaticShapeNonMaxSuppression output shape is not fully defined: ", out_shape);
auto outIndicesShape = get_output_partial_shape(0);
auto outScoresShape = get_output_partial_shape(1);
set_output_size(2);
set_output_type(0, m_output_type, out_shape);
set_output_type(1, m_output_type, Shape{2});
NODE_VALIDATION_CHECK(this, outIndicesShape.is_static(),
"StaticShapeNonMaxSuppression output shape is not fully defined: ", outIndicesShape);
NODE_VALIDATION_CHECK(this, outScoresShape.is_static(),
"StaticShapeNonMaxSuppression output shape is not fully defined: ", outScoresShape);
// Replace valid outputs with the shape of selected_indices and selected_scores outputs
set_output_type(2, m_output_type, Shape{2});
}
} // namespace op

View File

@ -1,55 +0,0 @@
// Copyright (C) 2018-2020 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "vpu/ngraph/transformations/convert_nms_4_to_nms_dynamic.hpp"
#include <vpu/ngraph/operations/dynamic_non_max_suppression.hpp>
#include <ngraph/graph_util.hpp>
#include <ngraph/opsets/opset4.hpp>
#include <ngraph/rt_info.hpp>
#include <transformations/utils/utils.hpp>
#include <memory>
#include <vector>
void vpu::UpgradeNMS4ToNMSDynamic::upgrade_nms4_to_nms_dynamic() {
auto boxes = std::make_shared<ngraph::pattern::op::Label>(ngraph::element::f32, ngraph::Shape{1, 1000, 4});
auto scores = std::make_shared<ngraph::pattern::op::Label>(ngraph::element::f32, ngraph::Shape{1, 1, 1000});
auto max_output_boxes_per_class = ngraph::opset4::Constant::create(ngraph::element::i64, ngraph::Shape{}, {10});
auto iou_threshold = ngraph::opset4::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.75});
auto score_threshold = ngraph::opset4::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.7});
auto nms = std::make_shared<ngraph::opset4::NonMaxSuppression>(boxes, scores, max_output_boxes_per_class,
iou_threshold, score_threshold);
ngraph::graph_rewrite_callback callback = [](ngraph::pattern::Matcher &m) {
auto nms_4 = std::dynamic_pointer_cast<ngraph::opset4::NonMaxSuppression>(m.get_match_root());
if (!nms_4) {
return false;
}
const auto box_encoding = nms_4->get_box_encoding();
const auto new_args = nms_4->input_values();
const auto& arg2 = new_args.size() > 2 ? new_args.at(2) : ngraph::opset4::Constant::create(ngraph::element::i32, ngraph::Shape{}, {0});
const auto& arg3 = new_args.size() > 3 ? new_args.at(3) : ngraph::opset4::Constant::create(ngraph::element::f32, ngraph::Shape{}, {.0f});
const auto& arg4 = new_args.size() > 4 ? new_args.at(4) : ngraph::opset4::Constant::create(ngraph::element::f32, ngraph::Shape{}, {.0f});
const auto nms_dynamic = std::make_shared<ngraph::vpu::op::DynamicNonMaxSuppression>(
new_args.at(0),
new_args.at(1),
arg2,
arg3,
arg4,
box_encoding,
nms_4->get_sort_result_descending(),
nms_4->get_output_type());
nms_dynamic->set_friendly_name(nms_4->get_friendly_name());
ngraph::copy_runtime_info(nms_4, nms_dynamic);
ngraph::replace_node(nms_4, nms_dynamic);
return true;
};
auto m = std::make_shared<ngraph::pattern::Matcher>(nms, "UpgradeNMS4ToDynamic");
this->add_matcher(m, callback, ngraph::pass::PassProperty::CHANGE_DYNAMIC_STATE);
}

View File

@ -28,7 +28,6 @@
#include "ngraph/opsets/opset3.hpp"
#include "ngraph/opsets/opset5.hpp"
#include "vpu/ngraph/operations/dynamic_non_max_suppression.hpp"
namespace vpu {
@ -71,42 +70,42 @@ bool propagateUpperBoundFromExistingDSR(std::shared_ptr<ngraph::Function>& funct
const Transformations& getDefaultTransformations() {
static const Transformations transformations = {
{ngraph::opset3::Add::type_info, dynamicToStaticShapeBinaryEltwise},
{ngraph::opset3::Multiply::type_info, dynamicToStaticShapeBinaryEltwise},
{ngraph::opset3::Subtract::type_info, dynamicToStaticShapeBinaryEltwise},
{ngraph::opset3::VariadicSplit::type_info, dynamicToStaticShapeVariadicSplit},
{ngraph::opset3::Divide::type_info, dynamicToStaticShapeBinaryEltwise},
{ngraph::opset3::Equal::type_info, dynamicToStaticShapeBinaryEltwise},
{ngraph::opset3::Greater::type_info, dynamicToStaticShapeBinaryEltwise},
{ngraph::opset3::Power::type_info, dynamicToStaticShapeBinaryEltwise},
{ngraph::opset3::Maximum::type_info, dynamicToStaticShapeBinaryEltwise},
{ngraph::opset3::Minimum::type_info, dynamicToStaticShapeBinaryEltwise},
{ngraph::opset3::Less::type_info, dynamicToStaticShapeBinaryEltwise},
{ngraph::vpu::op::DynamicNonMaxSuppression::type_info, dynamicToStaticNonMaxSuppression},
{ngraph::opset3::NonZero::type_info, dynamicToStaticShapeNonZero},
{ngraph::opset3::TopK::type_info, dynamicToStaticShapeTopK},
{ngraph::opset3::Transpose::type_info, dynamicToStaticShapeTranspose},
{ngraph::opset3::Concat::type_info, dynamicToStaticShapeConcat},
{ngraph::opset3::Convert::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::Clamp::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::Floor::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::Log::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::Relu::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::ScatterUpdate::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::Sigmoid::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::Softmax::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::Exp::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::Sqrt::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::LogicalNot::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::StridedSlice::type_info, dynamicToStaticShapeStridedSlice},
{ngraph::opset3::Squeeze::type_info, dynamicToStaticShapeSqueeze},
{ngraph::opset3::Gather::type_info, dynamicToStaticShapeGather},
{ngraph::opset3::Unsqueeze::type_info, dynamicToStaticShapeUnsqueeze},
{ngraph::opset3::ROIAlign::type_info, dynamicToStaticShapeROIAlign},
{ngraph::opset3::Reshape::type_info, dynamicToStaticShapeReshape},
{ngraph::opset3::Broadcast::type_info, dynamicToStaticShapeBroadcast},
{ngraph::opset3::MatMul::type_info, dynamicToStaticShapeMatMul},
{ngraph::opset5::Split::type_info, dynamicToStaticShapeSplit},
{ngraph::opset3::Add::type_info, dynamicToStaticShapeBinaryEltwise},
{ngraph::opset3::Multiply::type_info, dynamicToStaticShapeBinaryEltwise},
{ngraph::opset3::Subtract::type_info, dynamicToStaticShapeBinaryEltwise},
{ngraph::opset3::VariadicSplit::type_info, dynamicToStaticShapeVariadicSplit},
{ngraph::opset3::Divide::type_info, dynamicToStaticShapeBinaryEltwise},
{ngraph::opset3::Equal::type_info, dynamicToStaticShapeBinaryEltwise},
{ngraph::opset3::Greater::type_info, dynamicToStaticShapeBinaryEltwise},
{ngraph::opset3::Power::type_info, dynamicToStaticShapeBinaryEltwise},
{ngraph::opset3::Maximum::type_info, dynamicToStaticShapeBinaryEltwise},
{ngraph::opset3::Minimum::type_info, dynamicToStaticShapeBinaryEltwise},
{ngraph::opset3::Less::type_info, dynamicToStaticShapeBinaryEltwise},
{ngraph::opset5::NonMaxSuppression::type_info, dynamicToStaticNonMaxSuppression},
{ngraph::opset3::NonZero::type_info, dynamicToStaticShapeNonZero},
{ngraph::opset3::TopK::type_info, dynamicToStaticShapeTopK},
{ngraph::opset3::Transpose::type_info, dynamicToStaticShapeTranspose},
{ngraph::opset3::Concat::type_info, dynamicToStaticShapeConcat},
{ngraph::opset3::Convert::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::Clamp::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::Floor::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::Log::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::Relu::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::ScatterUpdate::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::Sigmoid::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::Softmax::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::Exp::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::Sqrt::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::LogicalNot::type_info, dynamicToStaticUnaryElementwise},
{ngraph::opset3::StridedSlice::type_info, dynamicToStaticShapeStridedSlice},
{ngraph::opset3::Squeeze::type_info, dynamicToStaticShapeSqueeze},
{ngraph::opset3::Gather::type_info, dynamicToStaticShapeGather},
{ngraph::opset3::Unsqueeze::type_info, dynamicToStaticShapeUnsqueeze},
{ngraph::opset3::ROIAlign::type_info, dynamicToStaticShapeROIAlign},
{ngraph::opset3::Reshape::type_info, dynamicToStaticShapeReshape},
{ngraph::opset3::Broadcast::type_info, dynamicToStaticShapeBroadcast},
{ngraph::opset3::MatMul::type_info, dynamicToStaticShapeMatMul},
{ngraph::opset5::Split::type_info, dynamicToStaticShapeSplit},
// reduction
{ngraph::opset3::ReduceLogicalAnd::type_info, dynamicToStaticShapeReduce},

View File

@ -4,39 +4,50 @@
#include "vpu/ngraph/transformations/dynamic_to_static_shape_non_max_suppression.hpp"
#include <vpu/ngraph/operations/static_shape_non_maximum_suppression.hpp>
#include "vpu/ngraph/operations/dynamic_shape_resolver.hpp"
#include "vpu/ngraph/operations/dynamic_non_max_suppression.hpp"
#include "vpu/ngraph/utilities.hpp"
#include <vpu/utils/error.hpp>
#include <vpu/utils/error.hpp>
#include "ngraph/graph_util.hpp"
#include "ngraph/opsets/opset3.hpp"
#include "ngraph/opsets/opset5.hpp"
#include <memory>
#include <vpu/ngraph/operations/static_shape_non_maximum_suppression.hpp>
namespace vpu {
void dynamicToStaticNonMaxSuppression(std::shared_ptr<ngraph::Node> node) {
auto nms_dynamic = std::dynamic_pointer_cast<ngraph::vpu::op::DynamicNonMaxSuppression>(node);
VPU_THROW_UNLESS(nms_dynamic, "dynamicToStaticNonMaxSuppression transformation for {} of type {} expects {} as node for replacement",
node->get_friendly_name(), node->get_type_info(), ngraph::vpu::op::DynamicNonMaxSuppression::type_info);
auto nms = std::dynamic_pointer_cast<ngraph::opset5::NonMaxSuppression>(node);
VPU_THROW_UNLESS(nms, "dynamicToStaticNonMaxSuppression transformation for {} of type {} expects {} as node for replacement",
node->get_friendly_name(), node->get_type_info(), ngraph::opset5::NonMaxSuppression::type_info);
auto staticShapeNMS = std::make_shared<ngraph::vpu::op::StaticShapeNonMaxSuppression>(
nms_dynamic->input_value(0),
nms_dynamic->input_value(1),
nms_dynamic->input_value(2),
nms_dynamic->input_value(3),
nms_dynamic->input_value(4),
nms_dynamic->get_box_encoding(),
nms_dynamic->get_sort_result_descending(),
nms_dynamic->get_output_type());
nms->input_value(0),
nms->input_value(1),
nms->input_value(2),
nms->input_value(3),
nms->input_value(4),
nms->input_value(5),
nms->get_box_encoding() == ngraph::opset5::NonMaxSuppression::BoxEncodingType::CENTER ? 1 : 0,
nms->get_sort_result_descending(),
nms->get_output_type());
auto dynamicShapeResolver = std::make_shared<ngraph::vpu::op::DynamicShapeResolver>(
staticShapeNMS->output(0), staticShapeNMS->output(1));
dynamicShapeResolver->set_friendly_name(nms_dynamic->get_friendly_name());
auto dsrIndices = std::make_shared<ngraph::vpu::op::DynamicShapeResolver>(
staticShapeNMS->output(0), staticShapeNMS->output(2));
auto dsrScores = std::make_shared<ngraph::vpu::op::DynamicShapeResolver>(
staticShapeNMS->output(1), staticShapeNMS->output(2));
dsrIndices->set_friendly_name(nms->output(0).get_node_shared_ptr()->get_friendly_name());
dsrScores->set_friendly_name(nms->output(1).get_node_shared_ptr()->get_friendly_name());
ngraph::replace_node(std::move(nms_dynamic), std::move(dynamicShapeResolver));
const auto gatherValidOutputs = std::make_shared<ngraph::opset5::Gather>(
staticShapeNMS->output(2),
ngraph::opset5::Constant::create(staticShapeNMS->output(2).get_element_type(), ngraph::Shape{1}, {0}),
ngraph::opset5::Constant::create(staticShapeNMS->output(2).get_element_type(), ngraph::Shape{1}, {0}));
gatherValidOutputs->set_friendly_name(nms->output(2).get_node_shared_ptr()->get_friendly_name());
nms->output(0).replace(dsrIndices);
nms->output(1).replace(dsrScores);
nms->output(2).replace(gatherValidOutputs);
}
} // namespace vpu

View File

@ -136,7 +136,6 @@ public:
void parseTopK(const Model& model, const ie::CNNLayerPtr& layer, const DataVector& inputs, const DataVector& outputs) const;
void parseSelect(const Model& model, const ie::CNNLayerPtr& layer, const DataVector& inputs, const DataVector& outputs) const;
void parseExpDetectionOutput(const Model& model, const ie::CNNLayerPtr& layer, const DataVector& inputs, const DataVector& outputs) const;
void parseNonMaxSuppression(const Model& model, const ie::CNNLayerPtr& layer, const DataVector& inputs, const DataVector& outputs) const;
void parseROIFeatureExtractor(const Model& model, const ie::CNNLayerPtr& layer, const DataVector& inputs, const DataVector& outputs) const;
void parseConvert(const Model& model, const ie::CNNLayerPtr& layer, const DataVector& inputs, const DataVector& outputs) const;
void parseErf(const Model& model, const ie::CNNLayerPtr& layer, const DataVector& inputs, const DataVector& outputs) const;

View File

@ -144,7 +144,6 @@ VPU_DECLARE_ENUM(StageType,
ScatterUpdate = 103,
ReduceMin = 105,
ExpDetectionOutput = 106, // ExperimentalDetectronDetectionOutput
NonMaxSuppression = 107,
ROIFeatureExtractor = 108,
SCRelu = 109,
Erf = 110,

View File

@ -1,34 +0,0 @@
// Copyright (C) 2020 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <vpu/model/stage.hpp>
namespace vpu {
class NonMaxSuppression : public StageNode {
protected:
StagePtr cloneImpl() const override;
void propagateDataOrderImpl(StageDataInfo<DimsOrder>& orderInfo) override;
void getDataStridesRequirementsImpl(StageDataInfo<StridesRequirement>& stridesInfo) override;
void finalizeDataLayoutImpl() override;
void getBatchSupportInfoImpl(StageDataInfo<BatchSupport>& batchInfo) override;
StageSHAVEsRequirements getSHAVEsRequirementsImpl() const override;
void initialCheckImpl() const override;
void finalCheckImpl() const override;
void serializeParamsImpl(BlobSerializer& serializer) const override;
void serializeDataImpl(BlobSerializer& serializer) const override;
};
} // namespace vpu

View File

@ -32,7 +32,6 @@
#include <transformations/common_optimizations/common_optimizations.hpp>
#include <transformations/init_node_info.hpp>
#include <vpu/ngraph/transformations/merge_subsequent_dsr_operations.hpp>
#include <vpu/ngraph/transformations/convert_nms_4_to_nms_dynamic.hpp>
#include "vpu/ngraph/transformations/dynamic_to_static_shape.hpp"
#include "vpu/ngraph/transformations/eliminate_shapeof_after_dsr.hpp"
#include <vpu/ngraph/operations/dynamic_shape_resolver.hpp>
@ -105,7 +104,6 @@ FrontEnd::FrontEnd(StageBuilder::Ptr stageBuilder, const ie::ICore* core)
{"Select", LAYER_PARSER(parseSelect)},
{"Erf", LAYER_PARSER(parseErf)},
{"ExperimentalDetectronDetectionOutput", LAYER_PARSER(parseExpDetectionOutput)},
{"NonMaxSuppression", LAYER_PARSER(parseNonMaxSuppression)},
{"ExperimentalDetectronROIFeatureExtractor", LAYER_PARSER(parseROIFeatureExtractor)},
{"Convert", LAYER_PARSER(parseConvert)},
{"ReduceMax", LAYER_PARSER(parseReduce)},
@ -173,7 +171,6 @@ ie::ICNNNetwork::Ptr FrontEnd::convertNetwork(ie::ICNNNetwork& network) {
manager.register_pass<::ngraph::pass::InitNodeInfo>();
// WA: ConvertPriorBox must be executed before the 1st ConstantFolding pass
manager.register_pass<::ngraph::pass::ConvertPriorBox>();
manager.register_pass<vpu::UpgradeNMS4ToNMSDynamic>();
manager.register_pass<ngraph::pass::CommonOptimizations>();
manager.register_pass<vpu::DynamicToStaticShape>();
manager.register_pass<vpu::EliminateShapeOfAfterDSR>();

View File

@ -1,97 +0,0 @@
// Copyright (C) 2018-2020 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <vpu/stages/nms.hpp>
#include <vpu/frontend/frontend.hpp>
#include <memory>
#include <set>
namespace vpu {
StagePtr NonMaxSuppression::cloneImpl() const {
return std::make_shared<NonMaxSuppression>(*this);
}
void NonMaxSuppression::propagateDataOrderImpl(StageDataInfo<DimsOrder>& orderInfo) {
}
void NonMaxSuppression::getDataStridesRequirementsImpl(StageDataInfo<StridesRequirement>& stridesInfo) {
}
void NonMaxSuppression::finalizeDataLayoutImpl() {
}
void NonMaxSuppression::getBatchSupportInfoImpl(StageDataInfo<BatchSupport>& batchInfo) {
}
StageSHAVEsRequirements NonMaxSuppression::getSHAVEsRequirementsImpl() const {
// Current NMS implementation doesn't allow calculation of `> boxesThreshold` boxes using one SHAVE
constexpr int boxesThreshold = 3650;
const auto& inDesc = input(0)->desc();
const auto& maxBoxesNum = inDesc.dim(Dim::H);
if (maxBoxesNum > boxesThreshold) {
return StageSHAVEsRequirements::NeedMax;
} else {
return StageSHAVEsRequirements::OnlyOne;
}
}
void NonMaxSuppression::initialCheckImpl() const {
assertInputsOutputsTypes(this,
{{DataType::FP16},
{DataType::FP16},
{DataType::S32},
{DataType::FP16},
{DataType::FP16}},
{{DataType::S32}});
}
void NonMaxSuppression::finalCheckImpl() const {
}
void NonMaxSuppression::serializeParamsImpl(BlobSerializer& serializer) const {
bool center_point_box = attrs().get<bool>("center_point_box");
serializer.append(static_cast<int32_t>(center_point_box));
}
void NonMaxSuppression::serializeDataImpl(BlobSerializer& serializer) const {
IE_ASSERT(inputEdges().size() >= 2 && inputEdges().size() <= 5);
IE_ASSERT(outputEdges().size() == 1);
auto input1 = inputEdges()[0]->input();
auto input2 = inputEdges()[1]->input();
auto input3 = inputEdges()[2]->input();
auto input4 = inputEdges()[3]->input();
auto input5 = inputEdges()[4]->input();
auto output = outputEdges()[0]->output();
input1->serializeBuffer(serializer);
input2->serializeBuffer(serializer);
output->serializeBuffer(serializer);
input3->serializeBuffer(serializer);
input4->serializeBuffer(serializer);
input5->serializeBuffer(serializer);
}
void FrontEnd::parseNonMaxSuppression(const Model& model, const ie::CNNLayerPtr& _layer, const DataVector& inputs, const DataVector& outputs) const {
auto layer = std::dynamic_pointer_cast<ie::NonMaxSuppressionLayer>(_layer);
IE_ASSERT(layer != nullptr);
IE_ASSERT(inputs.size() >= 2 && inputs.size() <= 5);
IE_ASSERT(outputs.size() == 1);
DataVector tempInputs = inputs;
for (size_t fake = inputs.size(); fake < 5; fake++) {
tempInputs.push_back(model->addFakeData());
}
auto stage = model->addNewStage<NonMaxSuppression>(layer->name, StageType::NonMaxSuppression, layer, tempInputs, outputs);
stage->attrs().set<bool>("center_point_box", layer->center_point_box);
}
} // namespace vpu

View File

@ -2,10 +2,9 @@
// SPDX-License-Identifier: Apache-2.0
//
#include <vpu/stages/nms.hpp>
#include <vpu/frontend/frontend.hpp>
#include <ngraph/op/non_max_suppression.hpp>
#include <precision_utils.h>
#include <memory>
#include <set>
@ -14,12 +13,34 @@ namespace vpu {
namespace {
class StaticShapeNMS final : public NonMaxSuppression {
class StaticShapeNMS final : public StageNode {
private:
StagePtr cloneImpl() const override {
return std::make_shared<StaticShapeNMS>(*this);
}
void propagateDataOrderImpl(StageDataInfo<DimsOrder>& orderInfo) override {
}
void getDataStridesRequirementsImpl(StageDataInfo<StridesRequirement>& stridesInfo) override {
}
void finalizeDataLayoutImpl() override {
}
void getBatchSupportInfoImpl(StageDataInfo<BatchSupport>& batchInfo) override {
}
StageSHAVEsRequirements getSHAVEsRequirementsImpl() const override {
// Current NMS implementation doesn't allow calculation of `> boxesThreshold` boxes using one SHAVE
constexpr int boxesThreshold = 3650;
const auto& inDesc = input(0)->desc();
const auto& maxBoxesNum = inDesc.dim(Dim::H);
return maxBoxesNum <= boxesThreshold ? StageSHAVEsRequirements::OnlyOne : StageSHAVEsRequirements::NeedMax;
}
void initialCheckImpl() const override {
assertInputsOutputsTypes(this,
{{DataType::FP16},
@ -31,6 +52,12 @@ private:
{DataType::S32}});
}
void serializeParamsImpl(BlobSerializer& serializer) const override {
const auto center_point_box = attrs().get<bool>("center_point_box");
serializer.append(static_cast<int32_t>(center_point_box));
}
void serializeDataImpl(BlobSerializer& serializer) const override {
auto input1 = inputEdges()[0]->input();
auto input2 = inputEdges()[1]->input();
@ -53,29 +80,45 @@ private:
} // namespace
void FrontEnd::parseStaticShapeNMS(const Model& model, const ie::CNNLayerPtr& layer, const DataVector& inputs, const DataVector& outputs) const {
VPU_THROW_UNLESS(inputs.size() >= 2 && inputs.size() <= 5,
"StaticShapeNMS parsing failed, expected number of input is in range [2, 5], but {} provided",
inputs.size());
VPU_THROW_UNLESS(outputs.size() == 2,
"StaticShapeNMS parsing failed, expected number of outputs: 2, but {} provided",
outputs.size());
VPU_THROW_UNLESS(inputs.size() == 6,
"StaticShapeNMS with name {} parsing failed, expected number of inputs: 6, but {} provided",
layer->name, inputs.size());
VPU_THROW_UNLESS(outputs.size() == 3,
"StaticShapeNMS with name {} parsing failed, expected number of outputs: 4, but {} provided",
layer->name, outputs.size());
const auto softNMSSigmaData = inputs[5];
VPU_THROW_UNLESS(softNMSSigmaData->usage() == DataUsage::Const,
"StaticShapeNMS with name {} parsing failed: softNMSSigma should have usage {} while it actually has {}",
layer->type, DataUsage::Const, softNMSSigmaData->usage());
VPU_THROW_UNLESS(softNMSSigmaData->desc().totalDimSize() == 1,
"StaticShapeNMS with name {} parsing failed: softNMSSigma input should contain 1 value, while it has {} values",
layer->type, softNMSSigmaData->desc().totalDimSize());
const auto softNMSSigma = InferenceEngine::PrecisionUtils::f16tof32(softNMSSigmaData->content()->get<InferenceEngine::ie_fp16>()[0]);
VPU_THROW_UNLESS(softNMSSigma == 0,
"StaticShapeNMS with name {} parsing failed: the only supported value for softNMSSigma is 0, while it actually equal to {}",
layer->name, softNMSSigma);
auto usedInputs = inputs;
// Erase unused softNMSSigma input
usedInputs.pop_back();
const auto& outIndices = outputs[0];
const auto& outScores = outputs[1];
const auto& outShape = outputs[2];
VPU_THROW_UNLESS(outScores == nullptr,
"StaticShapeNMS with name {} parsing failed: selected_scores output is not supported {}",
layer->name);
const auto sortResultDescending = layer->GetParamAsBool("sort_result_descending");
const auto boxEncoding = layer->GetParamAsString("box_encoding");
const auto centerPointBox = layer->GetParamAsBool("center_point_box");
VPU_THROW_UNLESS(sortResultDescending == false,
"StaticShapeNMS: parameter sortResultDescending=true is not supported on VPU");
VPU_THROW_UNLESS(boxEncoding == "corner" || boxEncoding == "center",
"StaticShapeNMS: boxEncoding currently supports only two values: \"corner\" and \"center\" "
"while {} was provided", boxEncoding);
"StaticShapeNMS with name {}: parameter sortResultDescending=true is not supported on VPU", layer->name);
DataVector tempInputs = inputs;
for (auto fake = inputs.size(); fake < 5; fake++) {
tempInputs.push_back(model->addFakeData());
}
auto stage = model->addNewStage<StaticShapeNMS>(layer->name, StageType::StaticShapeNMS, layer, tempInputs, outputs);
stage->attrs().set<bool>("center_point_box", boxEncoding == "center");
auto stage = model->addNewStage<StaticShapeNMS>(layer->name, StageType::StaticShapeNMS, layer, usedInputs, DataVector{outIndices, outShape});
stage->attrs().set<bool>("center_point_box", centerPointBox);
}
} // namespace vpu

View File

@ -5,13 +5,16 @@
#include <common_test_utils/test_common.hpp>
#include <ngraph_functions/utils/ngraph_helpers.hpp>
#include <ngraph/opsets/opset3.hpp>
#include <ngraph/opsets/opset5.hpp>
#include <ngraph/op/non_max_suppression.hpp>
#include <ngraph/output_vector.hpp>
#include <vpu/ngraph/operations/dynamic_shape_resolver.hpp>
#include <vpu/ngraph/operations/dynamic_non_max_suppression.hpp>
#include <vpu/ngraph/transformations/dynamic_to_static_shape.hpp>
#include <vpu/ngraph/transformations/dynamic_to_static_shape_non_max_suppression.hpp>
#include <vpu/ngraph/operations/static_shape_non_maximum_suppression.hpp>
#include <vpu/utils/error.hpp>
#include <numeric>
#include <queue>
#include <random>
@ -22,50 +25,48 @@ using DataType = ngraph::element::Type_t;
using DataDims = ngraph::Shape;
struct NonMaxSuppressionTestCase {
int64_t num_batches, num_boxes, num_classes, max_output_boxes_per_class;
float iou_threshold, score_threshold;
int64_t numBatches, numBoxes, numClasses, maxOutputBoxesPerClass;
float iouThreshold, scoreThreshold, softNMSSigma;
};
class DynamicToStaticShapeNonMaxSuppression : public CommonTestUtils::TestsCommon,
public testing::WithParamInterface<std::tuple<DataType, DataType, NonMaxSuppressionTestCase>> {
public:
void SetUp() override {
const auto& parameters = GetParam();
const auto& float_type = std::get<0>(parameters);
const auto& integer_type = std::get<1>(parameters);
const auto& nms_setup = std::get<2>(parameters);
const auto& floatType = std::get<0>(parameters);
const auto& integerType = std::get<1>(parameters);
const auto& nmsSetup = std::get<2>(parameters);
ngraph::helpers::CompareFunctions(*transform(float_type, integer_type, nms_setup),
*reference(float_type, integer_type, nms_setup));
ngraph::helpers::CompareFunctions(*transform(floatType, integerType, nmsSetup),
*reference(floatType, integerType, nmsSetup));
}
protected:
std::shared_ptr<const ngraph::Function> transform(
const ngraph::element::Type_t& float_type,
const ngraph::element::Type_t& integer_type,
const NonMaxSuppressionTestCase& nms_setup) const {
const ngraph::element::Type_t& floatType,
const ngraph::element::Type_t& integerType,
const NonMaxSuppressionTestCase& nmsSetup) const {
const auto boxes = std::make_shared<ngraph::opset3::Parameter>(
float_type, ngraph::PartialShape{nms_setup.num_batches, nms_setup.num_boxes, 4});
floatType, ngraph::PartialShape{nmsSetup.numBatches, nmsSetup.numBoxes, 4});
const auto scores = std::make_shared<ngraph::opset3::Parameter>(
float_type, ngraph::PartialShape{nms_setup.num_batches, nms_setup.num_classes, nms_setup.num_boxes});
const auto max_output_boxes_per_class = ngraph::opset3::Constant::create(integer_type, {}, std::vector<int64_t>{nms_setup.max_output_boxes_per_class});
const auto iou_threshold = ngraph::opset3::Constant::create(float_type, ngraph::Shape{}, std::vector<float>{nms_setup.iou_threshold});
const auto score_threshold = ngraph::opset3::Constant::create(float_type, ngraph::Shape{}, std::vector<float>{nms_setup.score_threshold});
floatType, ngraph::PartialShape{nmsSetup.numBatches, nmsSetup.numClasses, nmsSetup.numBoxes});
const auto maxOutputBoxesPerClass = ngraph::opset3::Constant::create(integerType, {}, std::vector<int64_t>{nmsSetup.maxOutputBoxesPerClass});
const auto iouThreshold = ngraph::opset3::Constant::create(floatType, ngraph::Shape{}, std::vector<float>{nmsSetup.iouThreshold});
const auto scoreThreshold = ngraph::opset3::Constant::create(floatType, ngraph::Shape{}, std::vector<float>{nmsSetup.scoreThreshold});
const auto softNMSSigma = ngraph::opset3::Constant::create(floatType, ngraph::Shape{}, std::vector<float>{nmsSetup.softNMSSigma});
const auto dims = std::make_shared<ngraph::opset3::Parameter>(ngraph::element::i64, ngraph::Shape{3});
const auto dsr = std::make_shared<ngraph::vpu::op::DynamicShapeResolver>(scores, dims);
const auto node = std::make_shared<ngraph::vpu::op::DynamicNonMaxSuppression>(
boxes, dsr, max_output_boxes_per_class, iou_threshold, score_threshold);
const auto node = std::make_shared<ngraph::op::v5::NonMaxSuppression>(
boxes, dsr, maxOutputBoxesPerClass, iouThreshold, scoreThreshold, softNMSSigma);
auto outputShape = node->get_output_partial_shape(0);
const auto function = std::make_shared<ngraph::Function>(
ngraph::NodeVector{node},
ngraph::OutputVector{node->outputs()},
ngraph::ParameterVector{boxes, scores, dims},
"Actual");
node->set_output_type(0, dsr->get_input_element_type(0), ngraph::PartialShape::dynamic(outputShape.rank()));
const auto transformations = vpu::Transformations{{node->type_info, vpu::dynamicToStaticNonMaxSuppression}};
vpu::DynamicToStaticShape(transformations).run_on_function(function);
@ -73,27 +74,35 @@ protected:
}
std::shared_ptr<const ngraph::Function> reference(
const ngraph::element::Type_t& float_type,
const ngraph::element::Type_t& integer_type,
const NonMaxSuppressionTestCase& nms_setup) const {
const ngraph::element::Type_t& floatType,
const ngraph::element::Type_t& integerType,
const NonMaxSuppressionTestCase& nmsSetup) const {
const auto boxes = std::make_shared<ngraph::opset3::Parameter>(
float_type, ngraph::PartialShape{nms_setup.num_batches, nms_setup.num_boxes, 4});
floatType, ngraph::PartialShape{nmsSetup.numBatches, nmsSetup.numBoxes, 4});
const auto scores = std::make_shared<ngraph::opset3::Parameter>(
float_type, ngraph::PartialShape{nms_setup.num_batches, nms_setup.num_classes, nms_setup.num_boxes});
const auto max_output_boxes_per_class = ngraph::opset3::Constant::create(integer_type, {}, std::vector<int64_t>{nms_setup.max_output_boxes_per_class});
const auto iou_threshold = ngraph::opset3::Constant::create(float_type, {}, std::vector<float>{nms_setup.iou_threshold});
const auto score_threshold = ngraph::opset3::Constant::create(float_type, {}, std::vector<float>{nms_setup.score_threshold});
floatType, ngraph::PartialShape{nmsSetup.numBatches, nmsSetup.numClasses, nmsSetup.numBoxes});
const auto maxOutputBoxesPerClass = ngraph::opset3::Constant::create(integerType, {}, std::vector<int64_t>{nmsSetup.maxOutputBoxesPerClass});
const auto iouThreshold = ngraph::opset3::Constant::create(floatType, {}, std::vector<float>{nmsSetup.iouThreshold});
const auto scoreThreshold = ngraph::opset3::Constant::create(floatType, {}, std::vector<float>{nmsSetup.scoreThreshold});
const auto softNMSSigma = ngraph::opset3::Constant::create(floatType, ngraph::Shape{}, std::vector<float>{nmsSetup.softNMSSigma});
const auto dims = std::make_shared<ngraph::opset3::Parameter>(ngraph::element::i64, ngraph::Shape{3});
const auto dsr = std::make_shared<ngraph::vpu::op::DynamicShapeResolver>(scores, dims);
const auto dsrInput = std::make_shared<ngraph::vpu::op::DynamicShapeResolver>(scores, dims);
const auto node = std::make_shared<ngraph::vpu::op::StaticShapeNonMaxSuppression>(
boxes, dsr, max_output_boxes_per_class, iou_threshold, score_threshold);
boxes, dsrInput, maxOutputBoxesPerClass, iouThreshold, scoreThreshold, softNMSSigma);
const auto validOutputs = std::make_shared<ngraph::opset5::Gather>(
node->output(2),
ngraph::opset5::Constant::create(dims->get_element_type(), ngraph::Shape{1}, {0}),
ngraph::opset5::Constant::create(dims->get_element_type(), ngraph::Shape{1}, {0}));
const auto dsrIndices = std::make_shared<ngraph::vpu::op::DynamicShapeResolver>(node->output(0), node->output(2));
const auto dsrScores = std::make_shared<ngraph::vpu::op::DynamicShapeResolver>(node->output(1), node->output(2));
const auto dsr1 = std::make_shared<ngraph::vpu::op::DynamicShapeResolver>(node->output(0), node->output(1));
return std::make_shared<ngraph::Function>(
ngraph::NodeVector{dsr1},
ngraph::NodeVector{dsrIndices, dsrScores, validOutputs},
ngraph::ParameterVector{boxes, scores, dims},
"Expected");
}
@ -111,10 +120,10 @@ INSTANTIATE_TEST_CASE_P(smoke_NGraph, DynamicToStaticShapeNonMaxSuppression, tes
ngraph::element::i64,
ngraph::element::u8),
testing::Values(
// num_batches, num_boxes, num_classes, max_output_boxes_per_class, iou_threshold, score_threshold
NonMaxSuppressionTestCase{1, 10, 5, 10, 0., 0.},
NonMaxSuppressionTestCase{2, 100, 5, 10, 0., 0.},
NonMaxSuppressionTestCase{3, 10, 5, 2, 0.5, 0.},
NonMaxSuppressionTestCase{1, 1000, 1, 2000, 0.5, 0.})));
// numBatches, numBoxes, numClasses, maxOutputBoxesPerClass, iouThreshold, scoreThreshold, softNMSSigma
NonMaxSuppressionTestCase{1, 10, 5, 10, 0., 0., 0.},
NonMaxSuppressionTestCase{2, 100, 5, 10, 0., 0., 0.},
NonMaxSuppressionTestCase{3, 10, 5, 2, 0.5, 0., 0.},
NonMaxSuppressionTestCase{1, 1000, 1, 2000, 0.5, 0., 0.})));
} // namespace

View File

@ -54,11 +54,12 @@ protected:
std::shared_ptr<const ngraph::Function> reference(
const TensorType& dataType,
const TensorShape& dataShape) const {
const auto data = std::make_shared<ngraph::opset3::Parameter>(dataType, dataShape);
const auto shape = std::make_shared<ngraph::opset3::Parameter>(ngraph::element::i64, ngraph::Shape{dataShape.size()});
return std::make_shared<ngraph::Function>(
ngraph::NodeVector{shape},
ngraph::ParameterVector{shape},
ngraph::ParameterVector{data, shape},
"Expected");
}
};
@ -115,13 +116,14 @@ protected:
std::shared_ptr<const ngraph::Function> reference(
const TensorType& dataType,
const TensorShape& dataShape) const {
const auto data = std::make_shared<ngraph::opset3::Parameter>(dataType, dataShape);
const auto shape = std::make_shared<ngraph::opset3::Parameter>(ngraph::element::i64, ngraph::Shape{dataShape.size()});
const auto shapeRelu = std::make_shared<ngraph::opset3::Relu>(shape);
return std::make_shared<ngraph::Function>(
ngraph::NodeVector{shapeRelu},
ngraph::ParameterVector{shape},
ngraph::ParameterVector{data, shape},
"Expected");
}
};

View File

@ -6,6 +6,7 @@
#include <functional_test_utils/blob_utils.hpp>
#include <ngraph/opsets/opset3.hpp>
#include <ngraph/op/non_max_suppression.hpp>
#include "vpu/ngraph/operations/static_shape_non_maximum_suppression.hpp"
using TensorShape = InferenceEngine::SizeVector;
@ -16,7 +17,8 @@ using StaticShapeNMSParam = std::tuple<
int64_t, // Number of classes
int64_t, // Maximum output boxes per class
float, // IOU threshold
float>; // Score threshold
float, // Score threshold
float>; // Soft NMS sigma
using StaticShapeNMSTestParam = std::tuple<
StaticShapeNMSParam, // NMS params
@ -66,6 +68,7 @@ protected:
const auto maxOutputBoxesPerClass = std::get<3>(NMSParams);
const auto iouThreshold = std::get<4>(NMSParams);
const auto scoreThreshold = std::get<5>(NMSParams);
const auto softNMSSigma = std::get<6>(NMSParams);
auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(inPrc);
@ -79,10 +82,12 @@ protected:
ngraph::element::f32, ngraph::Shape{}, iouThreshold);
const auto scoreThresholdConst = std::make_shared<ngraph::opset3::Constant>(
ngraph::element::f32, ngraph::Shape{}, scoreThreshold);
const auto softNMSSigmaConst = std::make_shared<ngraph::opset3::Constant>(
ngraph::element::f32, ngraph::Shape{1}, softNMSSigma);
const auto staticShapeNMS = std::make_shared<ngraph::vpu::op::StaticShapeNonMaxSuppression>(
inputBoxes, inputScores, maxOutputBoxesPerClassConst, iouThresholdConst, scoreThresholdConst,
ngraph::opset3::NonMaxSuppression::BoxEncodingType::CORNER, false, ngraph::element::i32);
inputBoxes, inputScores, maxOutputBoxesPerClassConst, iouThresholdConst, scoreThresholdConst, softNMSSigmaConst,
0, false, ngraph::element::i32);
ngraph::ResultVector results{std::make_shared<ngraph::opset3::Result>(staticShapeNMS->output(0)),
std::make_shared<ngraph::opset3::Result>(staticShapeNMS->output(1))};
@ -95,11 +100,11 @@ TEST_P(StaticShapeNMSLayerTest, accuracy) {
}
std::vector<StaticShapeNMSParam> NMSParams = {
std::make_tuple(1, 10, 5, 10, 0., 0.),
std::make_tuple(2, 100, 5, 10, 0., 0.),
std::make_tuple(3, 10, 5, 2, 0.5, 0.),
std::make_tuple(1, 1000, 1, 2000, 0.5, 0.),
std::make_tuple(1, 8200, 1, 8200, 0.5, 0.),
std::make_tuple(1, 10, 5, 10, 0., 0., 0.),
std::make_tuple(2, 100, 5, 10, 0., 0., 0.),
std::make_tuple(3, 10, 5, 2, 0.5, 0., 0.),
std::make_tuple(1, 1000, 1, 2000, 0.5, 0., 0.),
std::make_tuple(1, 8200, 1, 8200, 0.5, 0., 0.),
};
std::vector<InferenceEngine::Precision> NMSPrecisions = {

View File

@ -5,7 +5,7 @@
#include <functional_test_utils/layer_test_utils.hpp>
#include <ngraph_functions/builders.hpp>
#include <vpu/ngraph/operations/dynamic_shape_resolver.hpp>
#include <vpu/ngraph/operations/dynamic_non_max_suppression.hpp>
#include <ngraph/op/non_max_suppression.hpp>
namespace {
@ -49,7 +49,7 @@ protected:
const auto dims = std::make_shared<ngraph::opset3::Parameter>(ngraph::element::i64, ngraph::Shape{3});
const auto dsr = std::make_shared<ngraph::vpu::op::DynamicShapeResolver>(scores, dims);
const auto node = std::make_shared<ngraph::vpu::op::DynamicNonMaxSuppression>(
const auto node = std::make_shared<ngraph::op::v5::NonMaxSuppression>(
boxes, dsr, max_output_boxes_per_class, iou_threshold, score_threshold);
const auto result = std::make_shared<ngraph::opset3::Result>(node);

View File

@ -177,8 +177,6 @@ std::vector<std::vector<std::uint8_t>> getConstData(const std::shared_ptr<Functi
namespace {
using ComparingNodesPair = std::pair<std::shared_ptr<ngraph::Node>, std::shared_ptr<ngraph::Node>>;
std::string toString(const NodeTypeInfo& typeInfo) {
return std::string(typeInfo.name) + " ver. " + std::to_string(typeInfo.version);
}
@ -195,34 +193,38 @@ void CompareNodes(const Node& actual, const Node& expected) {
const auto& numActualInputs = actual.inputs().size();
const auto& numExpectedInputs = expected.inputs().size();
NGRAPH_CHECK(numActualInputs == numExpectedInputs, "Functions compare: numbers of inputs are different: ", numActualInputs, " and ", numExpectedInputs);
const auto& numActualOutputs = actual.outputs().size();
const auto& numExpectedOutputs = expected.outputs().size();
NGRAPH_CHECK(numActualOutputs == numExpectedOutputs, "Functions compare: numbers of outputs are different: ",
numActualOutputs, " and ", numExpectedOutputs);
}
} // namespace
void CompareFunctions(const Function& actual, const Function& expected) {
const auto& actualResults = actual.get_results();
NGRAPH_CHECK(actualResults.size() == 1, "Got ", actualResults.size(), " outputs for function, but only single output functions are supported");
const auto& actualResult = actualResults.front();
const auto& actualOrderedOps = actual.get_ordered_ops();
const auto& expectedOrderedOps = expected.get_ordered_ops();
const auto& expectedResults = expected.get_results();
NGRAPH_CHECK(expectedResults.size() == 1, "Got ", expectedResults.size(), " outputs for function, but only single output functions are supported");
const auto& expectedResult = expectedResults.front();
NGRAPH_CHECK(expectedOrderedOps.size() == actualOrderedOps.size(),
"Functions compare: expected and actual ops number should be equal "
"but got ", expectedOrderedOps.size(), " and ", actualOrderedOps.size(), " respectively");
std::queue<ComparingNodesPair> nodes;
nodes.emplace(actualResult, expectedResult);
while (!nodes.empty()) {
const auto actualNode = nodes.front().first;
const auto expectedNode = nodes.front().second;
nodes.pop();
for (std::size_t i = 0; i < expectedOrderedOps.size(); i++) {
const auto& expectedOp = expectedOrderedOps[i];
const auto& actualOp = actualOrderedOps[i];
CompareNodes(*actualNode, *expectedNode);
for (std::size_t i = 0; i < actualNode->inputs().size(); ++i) {
const auto& actualShape = actualNode->input(i).get_partial_shape();
const auto& expectedShape = expectedNode->input(i).get_partial_shape();
CompareNodes(*actualOp, *expectedOp);
for (std::size_t i = 0; i < actualOp->inputs().size(); ++i) {
const auto& actualShape = actualOp->input(i).get_partial_shape();
const auto& expectedShape = expectedOp->input(i).get_partial_shape();
CompareShapes(actualShape, expectedShape);
}
nodes.emplace(actualNode->input_value(i).get_node_shared_ptr(), expectedNode->input_value(i).get_node_shared_ptr());
for (std::size_t i = 0; i < actualOp->outputs().size(); ++i) {
const auto& actualShape = actualOp->output(i).get_partial_shape();
const auto& expectedShape = expectedOp->output(i).get_partial_shape();
CompareShapes(actualShape, expectedShape);
}
}
}

View File

@ -1,260 +0,0 @@
// Copyright (C) 2018-2020 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "myriad_layers_nms_test.hpp"
INSTANTIATE_TEST_CASE_P(accuracy, myriadLayersTestsNonMaxSuppression_smoke,
::testing::Values(
MAKE_STRUCT(NMS_testParams,
{6, 1, 1}, // {spatial_dimension, num_classes, num_batches}
1,
{3},
{0.5f},
{0.f},
{ // batches
{ // spatial_dimension
{0.5f, 0.5f, 1.0f, 1.0f}, // center_point_box=0 {y1, x1, y2, x2} center_point_box=1 {y0, x0, w, h}
{0.5f, 0.6f, 1.0f, 1.0f},
{0.5f, 0.4f, 1.0f, 1.0f},
{0.5f, 10.5f, 1.0f, 1.0f},
{0.5f, 10.6f, 1.0f, 1.0f},
{0.5f, 100.5f, 1.0f, 1.0f},
},
},
{ // batches
{ // classes
{0.9f, 0.75f, 0.6f, 0.95f, 0.5f, 0.3f}, // spatial_dimension
},
},
{ // num_selected_indices
{0, 0, 3}, // {batch_index, class_index, box_index}
{0, 0, 0},
{0, 0, 5},
}
),
MAKE_STRUCT(NMS_testParams,
{6, 1, 1},
0,
{3},
{0.5f},
{0.f},
{
{
{1.0f, 1.0f, 0.0f, 0.0f},
{0.0f, 0.1f, 1.0f, 1.1f},
{0.0f, 0.9f, 1.0f, -0.1f},
{0.0f, 10.0f, 1.0f, 11.0f},
{1.0f, 10.1f, 0.0f, 11.1f},
{1.0f, 101.0f, 0.0f, 100.0f}
}
},
{
{
{0.9f, 0.75f, 0.6f, 0.95f, 0.5f, 0.3f}
}
},
{
{0, 0, 3},
{0, 0, 0},
{0, 0, 5},
}
),
MAKE_STRUCT(NMS_testParams,
{10, 1, 1},
0,
{3},
{0.5f},
{0.f},
{
{
{0.0f, 0.0f, 1.0f, 1.0f},
{0.0f, 0.0f, 1.0f, 1.0f},
{0.0f, 0.0f, 1.0f, 1.0f},
{0.0f, 0.0f, 1.0f, 1.0f},
{0.0f, 0.0f, 1.0f, 1.0f},
{0.0f, 0.0f, 1.0f, 1.0f},
{0.0f, 0.0f, 1.0f, 1.0f},
{0.0f, 0.0f, 1.0f, 1.0f},
{0.0f, 0.0f, 1.0f, 1.0f},
{0.0f, 0.0f, 1.0f, 1.0f},
}
},
{
{
{0.9f, 0.9f, 0.9f, 0.9f, 0.9f, 0.9f, 0.9f, 0.9f, 0.9f, 0.9f}
}
},
{
{0, 0, 0},
}
),
MAKE_STRUCT(NMS_testParams,
{6, 1, 1},
0,
{2},
{0.5f},
{0.f},
{
{
{0.0f, 0.0f, 1.0f, 1.0f},
{0.0f, 0.1f, 1.0f, 1.1f},
{0.0f, -0.1f, 1.0f, 0.9f},
{0.0f, 10.0f, 1.0f, 11.0f},
{0.0f, 10.1f, 1.0f, 11.1f},
{0.0f, 100.0f, 1.0f, 101.0f},
}
},
{
{
{0.9f, 0.75f, 0.6f, 0.95f, 0.5f, 0.3f}
}
},
{
{0, 0, 3},
{0, 0, 0},
}
),
MAKE_STRUCT(NMS_testParams,
{1, 1, 1},
0,
{3},
{0.5f},
{0.f},
{
{
{0.0f, 0.0f, 1.0f, 1.0f},
}
},
{
{
{0.9f}
}
},
{
{0, 0, 0},
}
),
MAKE_STRUCT(NMS_testParams,
{6, 1, 1},
0,
{3},
{0.5f},
{0.f},
{
{
{0.0f, 0.0f, 1.0f, 1.0f},
{0.0f, 0.1f, 1.0f, 1.1f},
{0.0f, -0.1f, 1.0f, 0.9f},
{0.0f, 10.0f, 1.0f, 11.0f},
{0.0f, 10.1f, 1.0f, 11.1f},
{0.0f, 100.0f, 1.0f, 101.0f},
}
},
{
{
{0.9f, 0.75f, 0.6f, 0.95f, 0.5f, 0.3f}
}
},
{
{0, 0, 3},
{0, 0, 0},
{0, 0, 5},
}
),
MAKE_STRUCT(NMS_testParams,
{6, 1, 1},
0,
{3},
{0.5f},
{0.4f},
{
{
{0.0f, 0.0f, 1.0f, 1.0f},
{0.0f, 0.1f, 1.0f, 1.1f},
{0.0f, -0.1f, 1.0f, 0.9f},
{0.0f, 10.0f, 1.0f, 11.0f},
{0.0f, 10.1f, 1.0f, 11.1f},
{0.0f, 100.0f, 1.0f, 101.0f},
}
},
{
{
{0.9f, 0.75f, 0.6f, 0.95f, 0.5f, 0.3f}
}
},
{
{0, 0, 3},
{0, 0, 0},
}
),
MAKE_STRUCT(NMS_testParams,
{6, 1, 2},
0,
{2},
{0.5f},
{0.0f},
{
{
{0.0f, 0.0f, 1.0f, 1.0f},
{0.0f, 0.1f, 1.0f, 1.1f},
{0.0f, -0.1f, 1.0f, 0.9f},
{0.0f, 10.0f, 1.0f, 11.0f},
{0.0f, 10.1f, 1.0f, 11.1f},
{0.0f, 100.0f, 1.0f, 101.0f},
},
{
{0.0f, 0.0f, 1.0f, 1.0f},
{0.0f, 0.1f, 1.0f, 1.1f},
{0.0f, -0.1f, 1.0f, 0.9f},
{0.0f, 10.0f, 1.0f, 11.0f},
{0.0f, 10.1f, 1.0f, 11.1f},
{0.0f, 100.0f, 1.0f, 101.0f},
}
},
{
{
{0.9f, 0.75f, 0.6f, 0.95f, 0.5f, 0.3f}
},
{
{0.9f, 0.75f, 0.6f, 0.95f, 0.5f, 0.3f}
}
},
{
{0, 0, 3},
{0, 0, 0},
{1, 0, 3},
{1, 0, 0},
}
),
MAKE_STRUCT(NMS_testParams,
{6, 2, 1},
0,
{2},
{0.5f},
{0.0f},
{
{
{0.0f, 0.0f, 1.0f, 1.0f},
{0.0f, 0.1f, 1.0f, 1.1f},
{0.0f, -0.1f, 1.0f, 0.9f},
{0.0f, 10.0f, 1.0f, 11.0f},
{0.0f, 10.1f, 1.0f, 11.1f},
{0.0f, 100.0f, 1.0f, 101.0f},
}
},
{
{
{0.9f, 0.75f, 0.6f, 0.95f, 0.5f, 0.3f},
{0.9f, 0.75f, 0.6f, 0.95f, 0.5f, 0.3f}
}
},
{
{0, 0, 3},
{0, 0, 0},
{0, 1, 3},
{0, 1, 0},
}
)
)
);

View File

@ -1,264 +0,0 @@
// Copyright (C) 2018-2020 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "myriad_layers_tests.hpp"
#include "tests_vpu_common.hpp"
using namespace InferenceEngine;
typedef std::vector<int> NMS_Dims;
typedef std::vector<std::vector<std::vector<float>>> init3DFloat;
typedef std::vector<int> initIntScalar;
typedef std::vector<float> initFPScalar;
typedef std::vector<std::vector<int>> refType;
struct NMS_testParams {
int dims[3]; // {spat_dim, num_classes, num_batches}
int centerPointBox;
initIntScalar MaxOutBoxesPerClass; // scalar
initFPScalar IoUThreshold; // scalar
initFPScalar ScoreThreshold; // scalar
init3DFloat boxes;
init3DFloat scores;
refType referenceOutput;
};
static std::string getModel(const int numOfInputs, const NMS_Dims &dims, const int center_point_box) {
std::string model = R"V0G0N(
<net name="testNMS" version="7">
<layers>
<layer id="0" name="boxes" precision="FP16" type="Input">
<output>
<port id="0">
<dim>__BATCHES__</dim>
<dim>__SPAT_DIM__</dim>
<dim>4</dim>
</port>
</output>
</layer>
<layer id="1" name="scores" precision="FP16" type="Input">
<output>
<port id="0">
<dim>__BATCHES__</dim>
<dim>__CLASSES__</dim>
<dim>__SPAT_DIM__</dim>
</port>
</output>
</layer>)V0G0N";
if (numOfInputs > 2)
model += R"V0G0N(
<layer id="2" name="MaxOutputBoxesPerClass" precision="I32" type="Input">
<output>
<port id="0">
<dim>1</dim>
</port>
</output>
</layer>)V0G0N";
if (numOfInputs > 3)
model += R"V0G0N(
<layer id="3" name="IoUThreshold" precision="FP16" type="Input">
<output>
<port id="0">
<dim>1</dim>
</port>
</output>
</layer>)V0G0N";
if (numOfInputs > 4)
model += R"V0G0N(
<layer id="4" name="ScoreThreshold" precision="FP16" type="Input">
<output>
<port id="0">
<dim>1</dim>
</port>
</output>
</layer>)V0G0N";
model += R"V0G0N(
<layer id="5" name="NMS" precision="I32" type="NonMaxSuppression">
<data center_point_box="__CPB__"/>
<input>
<port id="0">
<dim>__BATCHES__</dim>
<dim>__SPAT_DIM__</dim>
<dim>4</dim>
</port>
<port id="1">
<dim>__BATCHES__</dim>
<dim>__CLASSES__</dim>
<dim>__SPAT_DIM__</dim>
</port>)V0G0N";
if (numOfInputs > 2)
model += R"V0G0N(
<port id="2">
<dim>1</dim>
</port>)V0G0N";
if (numOfInputs > 3)
model += R"V0G0N(
<port id="3">
<dim>1</dim>
</port>)V0G0N";
if (numOfInputs > 4)
model += R"V0G0N(
<port id="4">
<dim>1</dim>
</port>)V0G0N";
model += R"V0G0N(
</input>
<output>
<port id="4">
<dim>__SPAT_DIM__</dim>
<dim>3</dim>
</port>
</output>
</layer>
</layers>
<edges>
<edge from-layer="0" from-port="0" to-layer="5" to-port="0"/>
<edge from-layer="1" from-port="0" to-layer="5" to-port="1"/>)V0G0N";
if (numOfInputs > 2)
model += R"V0G0N(
<edge from-layer="2" from-port="0" to-layer="5" to-port="2"/>)V0G0N";
if (numOfInputs > 3)
model += R"V0G0N(
<edge from-layer="3" from-port="0" to-layer="5" to-port="3"/>)V0G0N";
if (numOfInputs > 4)
model += R"V0G0N(
<edge from-layer="4" from-port="0" to-layer="5" to-port="4"/>)V0G0N";
model += R"V0G0N(
</edges>
</net>
)V0G0N";
REPLACE_WITH_STR(model, "__SPAT_DIM__", std::to_string(dims[0]));
REPLACE_WITH_STR(model, "__CLASSES__", std::to_string(dims[1]));
REPLACE_WITH_STR(model, "__BATCHES__", std::to_string(dims[2]));
REPLACE_WITH_STR(model, "__CPB__", std::to_string(center_point_box));
return model;
}
static void copyScalarToBlob(const Blob::Ptr& blob, const initIntScalar& scalar) {
auto *data = blob->buffer().as<int32_t *>();
data[0] = scalar[0];
}
static void copyScalarToBlob(const Blob::Ptr& blob, const initFPScalar& scalar) {
auto *data = blob->buffer().as<ie_fp16 *>();
data[0] = PrecisionUtils::f32tof16(scalar[0]);
}
static void copy3DToBlob(const Blob::Ptr& blob, const init3DFloat& src) {
auto *data = blob->buffer().as<ie_fp16 *>();
const auto dims = blob->getTensorDesc().getDims();
for (int i = 0; i < dims[0]; i++) {
for (int j = 0; j < dims[1]; j++) {
for (int k = 0; k < dims[2]; k++) {
data[i * dims[1] * dims[2] + j * dims[2] + k] = PrecisionUtils::f32tof16(src[i][j][k]);
}
}
}
}
static void copyReference(const Blob::Ptr& blob, const refType src) {
int32_t *data = blob->buffer().as<int32_t *>();
const auto dims = blob->getTensorDesc().getDims();
int boxNum = 0;
for (; boxNum < src.size(); boxNum++) {
data[boxNum * 3 + 0] = src[boxNum][0];
data[boxNum * 3 + 1] = src[boxNum][1];
data[boxNum * 3 + 2] = src[boxNum][2];
}
for (; boxNum < dims[0]; boxNum++) {
data[boxNum * 3 + 0] = -1;
data[boxNum * 3 + 1] = -1;
data[boxNum * 3 + 2] = -1;
}
}
typedef myriadLayerTestBaseWithParam<NMS_testParams> myriadLayersTestsNonMaxSuppression_smoke;
TEST_P(myriadLayersTestsNonMaxSuppression_smoke, NonMaxSuppression) {
const auto params = GetParam();
const int spatDim = params.dims[0];
const int numClasses = params.dims[1];
const int numBatches = params.dims[2];
const int center_point_box = params.centerPointBox;
int numOfInputs = 2;
if (!params.ScoreThreshold.empty())
numOfInputs = 5;
else if (!params.IoUThreshold.empty())
numOfInputs = 4;
else if (!params.MaxOutBoxesPerClass.empty())
numOfInputs = 3;
const auto model = getModel(numOfInputs, {spatDim, numClasses, numBatches}, center_point_box);
ASSERT_NO_THROW(readNetwork(model));
const auto& network = _cnnNetwork;
_inputsInfo = network.getInputsInfo();
_inputsInfo["boxes"]->setPrecision(Precision::FP16);
_inputsInfo["scores"]->setPrecision(Precision::FP16);
if (numOfInputs > 2)
_inputsInfo["MaxOutputBoxesPerClass"]->setPrecision(Precision::I32);
if (numOfInputs > 3)
_inputsInfo["IoUThreshold"]->setPrecision(Precision::FP16);
if (numOfInputs > 4)
_inputsInfo["ScoreThreshold"]->setPrecision(Precision::FP16);
_outputsInfo = network.getOutputsInfo();
_outputsInfo["NMS"]->setPrecision(Precision::I32);
StatusCode st = OK;
ASSERT_NO_THROW(st = _vpuPluginPtr->LoadNetwork(_exeNetwork, network, _config, &_resp));
ASSERT_EQ(StatusCode::OK, st) << _resp.msg;
ASSERT_NE(_exeNetwork, nullptr) << _resp.msg;
ASSERT_NO_THROW(st = _exeNetwork->CreateInferRequest(_inferRequest, &_resp));
ASSERT_EQ(StatusCode::OK, st) << _resp.msg;
Blob::Ptr boxesBlob;
ASSERT_NO_THROW(st = _inferRequest->GetBlob("boxes", boxesBlob, &_resp));
ASSERT_EQ(StatusCode::OK, st) << _resp.msg;
std::cout << CheckMyriadX() << std::endl;
copy3DToBlob(boxesBlob, params.boxes);
Blob::Ptr scoresBlob;
ASSERT_NO_THROW(st = _inferRequest->GetBlob("scores", scoresBlob, &_resp));
ASSERT_EQ(StatusCode::OK, st) << _resp.msg;
copy3DToBlob(scoresBlob, params.scores);
if (numOfInputs > 2) {
Blob::Ptr MaxOutputBoxesBlob;
ASSERT_NO_THROW(st = _inferRequest->GetBlob("MaxOutputBoxesPerClass", MaxOutputBoxesBlob, &_resp));
ASSERT_EQ(StatusCode::OK, st) << _resp.msg;
copyScalarToBlob(MaxOutputBoxesBlob, params.MaxOutBoxesPerClass);
}
if (numOfInputs > 3) {
Blob::Ptr IoUThresholdBlob;
ASSERT_NO_THROW(st = _inferRequest->GetBlob("IoUThreshold", IoUThresholdBlob, &_resp));
ASSERT_EQ(StatusCode::OK, st) << _resp.msg;
copyScalarToBlob(IoUThresholdBlob, params.IoUThreshold);
}
if (numOfInputs > 4) {
Blob::Ptr ScoreThresholdBlob;
ASSERT_NO_THROW(st = _inferRequest->GetBlob("ScoreThreshold", ScoreThresholdBlob, &_resp));
ASSERT_EQ(StatusCode::OK, st) << _resp.msg;
copyScalarToBlob(ScoreThresholdBlob, params.ScoreThreshold);
}
ASSERT_NO_THROW(st = _inferRequest->Infer(&_resp));
ASSERT_EQ(StatusCode::OK, st) << _resp.msg;
Blob::Ptr outputBlob;
ASSERT_NO_THROW(st = _inferRequest->GetBlob("NMS", outputBlob, &_resp));
ASSERT_EQ(StatusCode::OK, st) << _resp.msg;
Blob::Ptr refBlob = make_shared_blob<int32_t>(outputBlob->getTensorDesc());
refBlob->allocate();
copyReference(refBlob, params.referenceOutput);
if (memcmp(refBlob->cbuffer(), outputBlob->cbuffer(), outputBlob->byteSize()))
FAIL() << "Wrong result with compare ONNX reference!";
}