From eb82adeb3a3b378e25630baf824c1ba7f256c761 Mon Sep 17 00:00:00 2001 From: Nikolay Shchegolev Date: Wed, 11 Nov 2020 00:36:38 +0300 Subject: [PATCH] [CPU] Proposal layer. Check img info input. (#2456) --- .../src/mkldnn_plugin/nodes/proposal.cpp | 7 +- .../behavior/invalid_cases/proposal.cpp | 55 +++++++++++ .../behavior/invalid_cases/proposal.hpp | 33 +++++++ .../include/single_layer_tests/proposal.hpp | 1 + .../src/behavior/invalid_cases/proposal.cpp | 98 +++++++++++++++++++ .../src/single_layer_tests/proposal.cpp | 30 +++--- .../include/ngraph_functions/builders.hpp | 2 +- .../tests/ngraph_functions/src/proposal.cpp | 4 +- 8 files changed, 214 insertions(+), 16 deletions(-) create mode 100644 inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/invalid_cases/proposal.cpp create mode 100644 inference-engine/tests/functional/plugin/shared/include/behavior/invalid_cases/proposal.hpp create mode 100644 inference-engine/tests/functional/plugin/shared/src/behavior/invalid_cases/proposal.cpp diff --git a/inference-engine/src/mkldnn_plugin/nodes/proposal.cpp b/inference-engine/src/mkldnn_plugin/nodes/proposal.cpp index 49575363370..2b1dd1b599c 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/proposal.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/proposal.cpp @@ -163,15 +163,20 @@ public: // input image height & width const float img_H = p_img_info_cpu[0]; const float img_W = p_img_info_cpu[1]; + if (!std::isnormal(img_H) || !std::isnormal(img_W) || (img_H < 0.f) || (img_W < 0.f)) { + THROW_IE_EXCEPTION << "Proposal operation image info input must have positive image height and width."; + } // scale factor for height & width const float scale_H = p_img_info_cpu[2]; const float scale_W = img_info_size == 4 ? p_img_info_cpu[3] : scale_H; + if (!std::isfinite(scale_H) || !std::isfinite(scale_W) || (scale_H < 0.f) || (scale_W < 0.f)) { + THROW_IE_EXCEPTION << "Proposal operation image info input must have non negative scales."; + } XARCH::proposal_exec(p_bottom_item, p_d_anchor_item, dims0, {img_H, img_W, scale_H, scale_W}, anchors.data(), roi_indices.data(), p_roi_item, p_prob_item, conf); - return OK; } catch (const InferenceEngine::details::InferenceEngineException& e) { if (resp) { diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/invalid_cases/proposal.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/invalid_cases/proposal.cpp new file mode 100644 index 00000000000..cf527db9931 --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/invalid_cases/proposal.cpp @@ -0,0 +1,55 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include "behavior/invalid_cases/proposal.hpp" + +using namespace ngraph::helpers; +using namespace LayerTestsDefinitions; +using namespace BehaviorTestsDefinitions; + +namespace { + +/* ============= Proposal ============= */ +const std::vector base_size_ = {16}; +const std::vector pre_nms_topn_ = {100}; +const std::vector post_nms_topn_ = {100}; +const std::vector nms_thresh_ = {0.7f}; +const std::vector min_size_ = {1}; +const std::vector ratio_ = {{1.0f, 2.0f}}; +const std::vector scale_ = {{1.2f, 1.5f}}; +const std::vector clip_before_nms_ = {false}; +const std::vector clip_after_nms_ = {false}; +const std::vector> img_info_invalid = {{0.f, 225.f, 1.f}, + {225.f, -1.f, 1.f}, + {225.f, NAN, 1.f}, + {INFINITY, 100.f, 1.f}, + {225.f, 100.f, NAN}, + {225.f, 100.f, INFINITY}}; + +// empty string corresponds to Caffe framework +const std::vector framework_ = {""}; + +const auto proposalParams = ::testing::Combine( + ::testing::ValuesIn(base_size_), + ::testing::ValuesIn(pre_nms_topn_), + ::testing::ValuesIn(post_nms_topn_), + ::testing::ValuesIn(nms_thresh_), + ::testing::ValuesIn(min_size_), + ::testing::ValuesIn(ratio_), + ::testing::ValuesIn(scale_), + ::testing::ValuesIn(clip_before_nms_), + ::testing::ValuesIn(clip_after_nms_), + ::testing::ValuesIn(framework_) +); + +INSTANTIATE_TEST_CASE_P(invalid, ProposalBehTest, + ::testing::Combine( + proposalParams, + ::testing::ValuesIn(img_info_invalid), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + ProposalBehTest::getTestCaseName +); + +} // namespace diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/invalid_cases/proposal.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/invalid_cases/proposal.hpp new file mode 100644 index 00000000000..3f07be3acbd --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/invalid_cases/proposal.hpp @@ -0,0 +1,33 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "single_layer_tests/proposal.hpp" + +namespace BehaviorTestsDefinitions { + +typedef std::tuple< + LayerTestsDefinitions::proposalSpecificParams, + std::vector, + std::string> proposalBehTestParamsSet; + +class ProposalBehTest + : public testing::WithParamInterface, + virtual public LayerTestsUtils::LayerTestsCommon { +public: + static std::string getTestCaseName(testing::TestParamInfo obj); + InferenceEngine::Blob::Ptr GenerateInput(const InferenceEngine::InputInfo &info) const override; + +protected: + void SetUp() override; + void Validate() override {}; + + const LayerTestsDefinitions::normalize_type normalize = true; + const LayerTestsDefinitions::feat_stride_type feat_stride = 1; + const LayerTestsDefinitions::box_size_scale_type box_size_scale = 2.0f; + const LayerTestsDefinitions::box_coordinate_scale_type box_coordinate_scale = 2.0f; +}; + +} // namespace BehaviorTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/proposal.hpp b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/proposal.hpp index 33925be0eb5..c8b00f6e69d 100644 --- a/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/proposal.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/proposal.hpp @@ -56,6 +56,7 @@ class ProposalLayerTest virtual public LayerTestsUtils::LayerTestsCommon { public: static std::string getTestCaseName(testing::TestParamInfo obj); + static std::string SerializeProposalSpecificParams(proposalSpecificParams& params); InferenceEngine::Blob::Ptr GenerateInput(const InferenceEngine::InputInfo &info) const override; protected: diff --git a/inference-engine/tests/functional/plugin/shared/src/behavior/invalid_cases/proposal.cpp b/inference-engine/tests/functional/plugin/shared/src/behavior/invalid_cases/proposal.cpp new file mode 100644 index 00000000000..3ba5ed9a531 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/src/behavior/invalid_cases/proposal.cpp @@ -0,0 +1,98 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "behavior/invalid_cases/proposal.hpp" + +using namespace BehaviorTestsDefinitions; +using namespace LayerTestsDefinitions; + +std::string ProposalBehTest::getTestCaseName(testing::TestParamInfo obj) { + proposalSpecificParams proposalParams; + std::string targetDevice; + std::vector img_info; + std::tie(proposalParams, img_info, targetDevice) = obj.param; + auto proposalPramString = ProposalLayerTest::SerializeProposalSpecificParams(proposalParams); + + std::ostringstream result; + result << "targetDevice=" << targetDevice; + result << "img_info = " << CommonTestUtils::vec2str(img_info) << "_"; + + return proposalPramString + result.str(); +} + +InferenceEngine::Blob::Ptr ProposalBehTest::GenerateInput(const InferenceEngine::InputInfo &info) const { + InferenceEngine::Blob::Ptr blobPtr; + + const std::string name = info.name(); + if (name == "scores") { + blobPtr = FuncTestUtils::createAndFillBlobFloat(info.getTensorDesc(), 1, 0, 1000, 8234231); + } else if (name == "boxes") { + blobPtr = FuncTestUtils::createAndFillBlobFloatNormalDistribution(info.getTensorDesc(), 0.0f, 0.2f, 7235346); + } + + return blobPtr; +} + +void ProposalBehTest::SetUp() { + proposalSpecificParams proposalParams; + std::vector img_info; + + std::tie(proposalParams, img_info, targetDevice) = this->GetParam(); + base_size_type base_size; + pre_nms_topn_type pre_nms_topn; + post_nms_topn_type post_nms_topn; + nms_thresh_type nms_thresh; + min_size_type min_size; + ratio_type ratio; + scale_type scale; + clip_before_nms_type clip_before_nms; + clip_after_nms_type clip_after_nms; + framework_type framework; + + std::tie(base_size, pre_nms_topn, + post_nms_topn, + nms_thresh, + min_size, + ratio, + scale, + clip_before_nms, + clip_after_nms, + framework) = proposalParams; + + size_t bottom_w = base_size; + size_t bottom_h = base_size; + size_t num_anchors = ratio.size() * scale.size(); + + std::vector scoresShape = {1, 2 * num_anchors, bottom_h, bottom_w}; + std::vector boxesShape = {1, 4 * num_anchors, bottom_h, bottom_w}; + std::vector imageInfoShape = {3}; + + auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(InferenceEngine::Precision::FP16); + auto params = ngraph::builder::makeParams(ngPrc, {{"scores", scoresShape}, {"boxes", boxesShape}}); + auto paramOuts = ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)); + + auto proposal = std::dynamic_pointer_cast( + ngraph::builder::makeProposal(paramOuts[0], paramOuts[1], img_info, ngPrc, + base_size, + pre_nms_topn, + post_nms_topn, + nms_thresh, + feat_stride, + min_size, + ratio, + scale, + clip_before_nms, + clip_after_nms, + normalize, + box_size_scale, + box_coordinate_scale, + framework)); + + ngraph::ResultVector results{std::make_shared(proposal)}; + function = std::make_shared(results, params, "proposal"); +} + +TEST_P(ProposalBehTest, CompareWithRefs) { + ASSERT_THROW(Run(), InferenceEngine::details::InferenceEngineException); +} diff --git a/inference-engine/tests/functional/plugin/shared/src/single_layer_tests/proposal.cpp b/inference-engine/tests/functional/plugin/shared/src/single_layer_tests/proposal.cpp index d5cc953ff8a..5a8cdb39c11 100644 --- a/inference-engine/tests/functional/plugin/shared/src/single_layer_tests/proposal.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/single_layer_tests/proposal.cpp @@ -25,12 +25,7 @@ const feat_stride_type feat_stride = 1; const box_size_scale_type box_size_scale = 2.0f; const box_coordinate_scale_type box_coordinate_scale = 2.0f; -std::string ProposalLayerTest::getTestCaseName(testing::TestParamInfo obj) { - proposalSpecificParams proposalParams; - - std::string targetDevice; - std::tie(proposalParams, targetDevice) = obj.param; - +std::string ProposalLayerTest::SerializeProposalSpecificParams(proposalSpecificParams& params) { base_size_type base_size; pre_nms_topn_type pre_nms_topn; post_nms_topn_type post_nms_topn; @@ -49,7 +44,7 @@ std::string ProposalLayerTest::getTestCaseName(testing::TestParamInfo(params)); auto proposal = std::dynamic_pointer_cast( - ngraph::builder::makeProposal(paramOuts[0], paramOuts[1], paramOuts[2], ngPrc, + ngraph::builder::makeProposal(paramOuts[0], paramOuts[1], img_info, ngPrc, base_size, pre_nms_topn, post_nms_topn, @@ -137,9 +144,6 @@ InferenceEngine::Blob::Ptr ProposalLayerTest::GenerateInput(const InferenceEngin blobPtr = FuncTestUtils::createAndFillBlobFloat(info.getTensorDesc(), 1, 0, 1000, 8234231); } else if (name == "boxes") { blobPtr = FuncTestUtils::createAndFillBlobFloatNormalDistribution(info.getTensorDesc(), 0.0f, 0.2f, 7235346); - } else if (name == "image_info") { - const float image_info[] = {225.0f, 225.0f, 1.0f}; - blobPtr = FuncTestUtils::createAndFillBlobWithFloatArray(info.getTensorDesc(), image_info, 3); } return blobPtr; diff --git a/inference-engine/tests/ngraph_functions/include/ngraph_functions/builders.hpp b/inference-engine/tests/ngraph_functions/include/ngraph_functions/builders.hpp index ad2d450f933..35bbb631fc8 100644 --- a/inference-engine/tests/ngraph_functions/include/ngraph_functions/builders.hpp +++ b/inference-engine/tests/ngraph_functions/include/ngraph_functions/builders.hpp @@ -247,7 +247,7 @@ std::shared_ptr makeMinMax(const ngraph::Output &in1, std::shared_ptr makeProposal(const ngraph::Output &class_probs, const ngraph::Output &class_logits, - const ngraph::Output &image_shape, + const std::vector& image_info, const element::Type &type, size_t base_size, size_t pre_nms_topn, diff --git a/inference-engine/tests/ngraph_functions/src/proposal.cpp b/inference-engine/tests/ngraph_functions/src/proposal.cpp index cbcbfdaeee2..d8fbd1d3b86 100644 --- a/inference-engine/tests/ngraph_functions/src/proposal.cpp +++ b/inference-engine/tests/ngraph_functions/src/proposal.cpp @@ -13,7 +13,7 @@ namespace builder { std::shared_ptr makeProposal(const ngraph::Output &class_probs, const ngraph::Output &class_logits, - const ngraph::Output &image_shape, + const std::vector& image_info, const element::Type &type, size_t base_size, size_t pre_nms_topn, @@ -45,6 +45,8 @@ std::shared_ptr makeProposal(const ngraph::Output &class_probs, attrs.box_coordinate_scale = box_coordinate_scale; attrs.framework = framework; + auto image_shape = makeConstant(ngraph::element::Type_t::f32, {3}, image_info); + return std::make_shared(class_probs, class_logits, image_shape, attrs); }