[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:
parent
c4e0b74fb1
commit
cab7a77cba
@ -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
|
@ -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;
|
||||
|
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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},
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -144,7 +144,6 @@ VPU_DECLARE_ENUM(StageType,
|
||||
ScatterUpdate = 103,
|
||||
ReduceMin = 105,
|
||||
ExpDetectionOutput = 106, // ExperimentalDetectronDetectionOutput
|
||||
NonMaxSuppression = 107,
|
||||
ROIFeatureExtractor = 108,
|
||||
SCRelu = 109,
|
||||
Erf = 110,
|
||||
|
@ -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
|
@ -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>();
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
}
|
||||
};
|
||||
|
@ -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 = {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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},
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
@ -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!";
|
||||
}
|
Loading…
Reference in New Issue
Block a user