From a23a398dc0f49e7b3d035dd9f8a182701aeb5422 Mon Sep 17 00:00:00 2001 From: Steve Yoo Date: Thu, 13 Jan 2022 18:42:56 +0900 Subject: [PATCH] Add SLT to Template Plugin: NonMaxSuppression-4,3,1 (#9511) * Add SLT to Template Plugin: NonMaxSuppression-4 * Add SLT to Template Plugin: NonMaxSuppression-4,3,1 --- .../template_plugin/backend/evaluates_map.cpp | 514 ++++- .../template_plugin/backend/opset_int_tbl.hpp | 3 + .../op_reference/non_max_suppression.cpp | 1645 ++++++++++++++--- .../tests/functional/skip_tests_config.cpp | 6 + 4 files changed, 1899 insertions(+), 269 deletions(-) diff --git a/docs/template_plugin/backend/evaluates_map.cpp b/docs/template_plugin/backend/evaluates_map.cpp index 0d5fcf27d19..ae5c5ed2dff 100644 --- a/docs/template_plugin/backend/evaluates_map.cpp +++ b/docs/template_plugin/backend/evaluates_map.cpp @@ -828,7 +828,6 @@ InfoForNMS5 get_info_for_nms5_eval(const std::shared_ptr @@ -867,6 +866,519 @@ bool evaluate(const shared_ptr& op, return true; } +namespace nms_v4 { +using V4BoxEncoding = op::v4::NonMaxSuppression::BoxEncodingType; + +struct InfoForNMS4 { + int64_t max_output_boxes_per_class; + float iou_threshold; + float score_threshold; + float soft_nms_sigma; + Shape out_shape; + Shape boxes_shape; + Shape scores_shape; + std::vector boxes_data; + std::vector scores_data; + size_t out_shape_size; + bool sort_result_descending; + ngraph::element::Type output_type; +}; + +constexpr size_t boxes_port = 0; +constexpr size_t scores_port = 1; + +PartialShape infer_selected_indices_shape(const std::vector>& inputs, + int64_t max_output_boxes_per_class) { + const auto boxes_ps = inputs[boxes_port]->get_partial_shape(); + const auto scores_ps = inputs[scores_port]->get_partial_shape(); + + // NonMaxSuppression produces triplets + // that have the following format: [batch_index, class_index, box_index] + PartialShape result = {Dimension::dynamic(), 3}; + + if (boxes_ps.rank().is_static() && scores_ps.rank().is_static()) { + const auto num_boxes_boxes = boxes_ps[1]; + if (num_boxes_boxes.is_static() && scores_ps[0].is_static() && scores_ps[1].is_static()) { + const auto num_boxes = num_boxes_boxes.get_length(); + const auto num_classes = scores_ps[1].get_length(); + + result[0] = std::min(num_boxes, max_output_boxes_per_class) * num_classes * scores_ps[0].get_length(); + } + } + return result; +} + +void normalize_corner(float* boxes, const Shape& boxes_shape) { + size_t total_num_of_boxes = shape_size(boxes_shape) / 4; + for (size_t i = 0; i < total_num_of_boxes; ++i) { + float* current_box = boxes + 4 * i; + + float y1 = current_box[0]; + float x1 = current_box[1]; + float y2 = current_box[2]; + float x2 = current_box[3]; + + float ymin = std::min(y1, y2); + float ymax = std::max(y1, y2); + float xmin = std::min(x1, x2); + float xmax = std::max(x1, x2); + + current_box[0] = ymin; + current_box[1] = xmin; + current_box[2] = ymax; + current_box[3] = xmax; + } +} + +void normalize_center(float* boxes, const Shape& boxes_shape) { + size_t total_num_of_boxes = shape_size(boxes_shape) / 4; + for (size_t i = 0; i < total_num_of_boxes; ++i) { + float* current_box = boxes + 4 * i; + + float x_center = current_box[0]; + float y_center = current_box[1]; + float width = current_box[2]; + float height = current_box[3]; + + float y1 = y_center - height / 2.0; + float x1 = x_center - width / 2.0; + float y2 = y_center + height / 2.0; + float x2 = x_center + width / 2.0; + + current_box[0] = y1; + current_box[1] = x1; + current_box[2] = y2; + current_box[3] = x2; + } +} + +void normalize_box_encoding(float* boxes, const Shape& boxes_shape, const V4BoxEncoding box_encoding) { + if (box_encoding == V4BoxEncoding::CORNER) { + normalize_corner(boxes, boxes_shape); + } else { + normalize_center(boxes, boxes_shape); + } +} + +std::vector prepare_boxes_data(const std::shared_ptr& boxes, + const Shape& boxes_shape, + const V4BoxEncoding box_encoding) { + auto result = get_floats(boxes, boxes_shape); + normalize_box_encoding(result.data(), boxes_shape, box_encoding); + return result; +} + +std::vector prepare_scores_data(const std::shared_ptr& scores, const Shape& scores_shape) { + auto result = get_floats(scores, scores_shape); + return result; +} + +InfoForNMS4 get_info_for_nms4_eval(const std::shared_ptr& nms4, + const std::vector>& inputs) { + InfoForNMS4 result; + + result.max_output_boxes_per_class = inputs.size() > 2 ? get_integers(inputs[2], Shape({}))[0] : 0; + result.iou_threshold = inputs.size() > 3 ? get_floats(inputs[3], Shape({}))[0] : 0.0f; + result.score_threshold = inputs.size() > 4 ? get_floats(inputs[4], Shape({}))[0] : 0.0f; + result.soft_nms_sigma = inputs.size() > 5 ? get_floats(inputs[5], Shape({}))[0] : 0.0f; + + auto selected_indices_shape = infer_selected_indices_shape(inputs, result.max_output_boxes_per_class); + result.out_shape = selected_indices_shape.to_shape(); + + result.boxes_shape = inputs[boxes_port]->get_shape(); + result.scores_shape = inputs[scores_port]->get_shape(); + + result.boxes_data = prepare_boxes_data(inputs[boxes_port], result.boxes_shape, nms4->get_box_encoding()); + result.scores_data = prepare_scores_data(inputs[scores_port], result.scores_shape); + + result.out_shape_size = shape_size(result.out_shape); + + result.sort_result_descending = nms4->get_sort_result_descending(); + + result.output_type = nms4->get_output_type(); + + return result; +} +} // namespace nms_v4 + +template +bool evaluate(const shared_ptr& op, + const HostTensorVector& outputs, + const HostTensorVector& inputs) { + auto info = nms_v4::get_info_for_nms4_eval(op, inputs); + + std::vector selected_indices(info.out_shape_size); + std::vector selected_scores(info.out_shape_size); + int64_t valid_outputs = 0; + + runtime::reference::non_max_suppression(info.boxes_data.data(), + info.boxes_shape, + info.scores_data.data(), + info.scores_shape, + info.max_output_boxes_per_class, + info.iou_threshold, + info.score_threshold, + info.soft_nms_sigma, + selected_indices.data(), + info.out_shape, + selected_scores.data(), + info.out_shape, + &valid_outputs, + info.sort_result_descending); + + auto selected_scores_type = (inputs.size() < 4) ? element::f32 : inputs[3]->get_element_type(); + + runtime::reference::nms5_postprocessing(outputs, + info.output_type, + selected_indices, + selected_scores, + valid_outputs, + selected_scores_type); + return true; +} + +namespace nms_v3 { +using V3BoxEncoding = op::v3::NonMaxSuppression::BoxEncodingType; + +struct InfoForNMS3 { + int64_t max_output_boxes_per_class; + float iou_threshold; + float score_threshold; + float soft_nms_sigma; + Shape out_shape; + Shape boxes_shape; + Shape scores_shape; + std::vector boxes_data; + std::vector scores_data; + size_t out_shape_size; + bool sort_result_descending; + ngraph::element::Type output_type; +}; + +constexpr size_t boxes_port = 0; +constexpr size_t scores_port = 1; + +PartialShape infer_selected_indices_shape(const std::vector>& inputs, + int64_t max_output_boxes_per_class) { + const auto boxes_ps = inputs[boxes_port]->get_partial_shape(); + const auto scores_ps = inputs[scores_port]->get_partial_shape(); + + // NonMaxSuppression produces triplets + // that have the following format: [batch_index, class_index, box_index] + PartialShape result = {Dimension::dynamic(), 3}; + + if (boxes_ps.rank().is_static() && scores_ps.rank().is_static()) { + const auto num_boxes_boxes = boxes_ps[1]; + if (num_boxes_boxes.is_static() && scores_ps[0].is_static() && scores_ps[1].is_static()) { + const auto num_boxes = num_boxes_boxes.get_length(); + const auto num_classes = scores_ps[1].get_length(); + + result[0] = std::min(num_boxes, max_output_boxes_per_class * num_classes); + } + } + return result; +} + +void normalize_corner(float* boxes, const Shape& boxes_shape) { + size_t total_num_of_boxes = shape_size(boxes_shape) / 4; + for (size_t i = 0; i < total_num_of_boxes; ++i) { + float* current_box = boxes + 4 * i; + + float y1 = current_box[0]; + float x1 = current_box[1]; + float y2 = current_box[2]; + float x2 = current_box[3]; + + float ymin = std::min(y1, y2); + float ymax = std::max(y1, y2); + float xmin = std::min(x1, x2); + float xmax = std::max(x1, x2); + + current_box[0] = ymin; + current_box[1] = xmin; + current_box[2] = ymax; + current_box[3] = xmax; + } +} + +void normalize_center(float* boxes, const Shape& boxes_shape) { + size_t total_num_of_boxes = shape_size(boxes_shape) / 4; + for (size_t i = 0; i < total_num_of_boxes; ++i) { + float* current_box = boxes + 4 * i; + + float x_center = current_box[0]; + float y_center = current_box[1]; + float width = current_box[2]; + float height = current_box[3]; + + float y1 = y_center - height / 2.0; + float x1 = x_center - width / 2.0; + float y2 = y_center + height / 2.0; + float x2 = x_center + width / 2.0; + + current_box[0] = y1; + current_box[1] = x1; + current_box[2] = y2; + current_box[3] = x2; + } +} + +void normalize_box_encoding(float* boxes, const Shape& boxes_shape, const V3BoxEncoding box_encoding) { + if (box_encoding == V3BoxEncoding::CORNER) { + normalize_corner(boxes, boxes_shape); + } else { + normalize_center(boxes, boxes_shape); + } +} + +std::vector prepare_boxes_data(const std::shared_ptr& boxes, + const Shape& boxes_shape, + const V3BoxEncoding box_encoding) { + auto result = get_floats(boxes, boxes_shape); + normalize_box_encoding(result.data(), boxes_shape, box_encoding); + return result; +} + +std::vector prepare_scores_data(const std::shared_ptr& scores, const Shape& scores_shape) { + auto result = get_floats(scores, scores_shape); + return result; +} + +InfoForNMS3 get_info_for_nms3_eval(const std::shared_ptr& nms3, + const std::vector>& inputs) { + InfoForNMS3 result; + + result.max_output_boxes_per_class = inputs.size() > 2 ? get_integers(inputs[2], Shape({}))[0] : 0; + result.iou_threshold = inputs.size() > 3 ? get_floats(inputs[3], Shape({}))[0] : 0.0f; + result.score_threshold = inputs.size() > 4 ? get_floats(inputs[4], Shape({}))[0] : 0.0f; + result.soft_nms_sigma = inputs.size() > 5 ? get_floats(inputs[5], Shape({}))[0] : 0.0f; + + auto selected_indices_shape = infer_selected_indices_shape(inputs, result.max_output_boxes_per_class); + result.out_shape = selected_indices_shape.to_shape(); + + result.boxes_shape = inputs[boxes_port]->get_shape(); + result.scores_shape = inputs[scores_port]->get_shape(); + + result.boxes_data = prepare_boxes_data(inputs[boxes_port], result.boxes_shape, nms3->get_box_encoding()); + result.scores_data = prepare_scores_data(inputs[scores_port], result.scores_shape); + + result.out_shape_size = shape_size(result.out_shape); + + result.sort_result_descending = nms3->get_sort_result_descending(); + + result.output_type = nms3->get_output_type(); + + return result; +} +} // namespace nms_v3 + +template +bool evaluate(const shared_ptr& op, + const HostTensorVector& outputs, + const HostTensorVector& inputs) { + auto info = nms_v3::get_info_for_nms3_eval(op, inputs); + + std::vector selected_indices(info.out_shape_size); + std::vector selected_scores(info.out_shape_size); + int64_t valid_outputs = 0; + + runtime::reference::non_max_suppression(info.boxes_data.data(), + info.boxes_shape, + info.scores_data.data(), + info.scores_shape, + info.max_output_boxes_per_class, + info.iou_threshold, + info.score_threshold, + info.soft_nms_sigma, + selected_indices.data(), + info.out_shape, + selected_scores.data(), + info.out_shape, + &valid_outputs, + info.sort_result_descending); + + auto selected_scores_type = (inputs.size() < 4) ? element::f32 : inputs[3]->get_element_type(); + + runtime::reference::nms5_postprocessing(outputs, + info.output_type, + selected_indices, + selected_scores, + valid_outputs, + selected_scores_type); + return true; +} + +namespace nms_v1 { +using V1BoxEncoding = op::v1::NonMaxSuppression::BoxEncodingType; + +struct InfoForNMS1 { + int64_t max_output_boxes_per_class; + float iou_threshold; + float score_threshold; + float soft_nms_sigma; + Shape out_shape; + Shape boxes_shape; + Shape scores_shape; + std::vector boxes_data; + std::vector scores_data; + size_t out_shape_size; + bool sort_result_descending; + ngraph::element::Type output_type; +}; + +constexpr size_t boxes_port = 0; +constexpr size_t scores_port = 1; + +PartialShape infer_selected_indices_shape(const std::vector>& inputs, + int64_t max_output_boxes_per_class) { + const auto boxes_ps = inputs[boxes_port]->get_partial_shape(); + const auto scores_ps = inputs[scores_port]->get_partial_shape(); + + // NonMaxSuppression produces triplets + // that have the following format: [batch_index, class_index, box_index] + PartialShape result = {Dimension::dynamic(), 3}; + + if (boxes_ps.rank().is_static() && scores_ps.rank().is_static()) { + const auto num_boxes_boxes = boxes_ps[1]; + if (num_boxes_boxes.is_static() && scores_ps[0].is_static() && scores_ps[1].is_static()) { + const auto num_boxes = num_boxes_boxes.get_length(); + const auto num_classes = scores_ps[1].get_length(); + + result[0] = std::min(num_boxes, max_output_boxes_per_class * num_classes); + } + } + return result; +} + +void normalize_corner(float* boxes, const Shape& boxes_shape) { + size_t total_num_of_boxes = shape_size(boxes_shape) / 4; + for (size_t i = 0; i < total_num_of_boxes; ++i) { + float* current_box = boxes + 4 * i; + + float y1 = current_box[0]; + float x1 = current_box[1]; + float y2 = current_box[2]; + float x2 = current_box[3]; + + float ymin = std::min(y1, y2); + float ymax = std::max(y1, y2); + float xmin = std::min(x1, x2); + float xmax = std::max(x1, x2); + + current_box[0] = ymin; + current_box[1] = xmin; + current_box[2] = ymax; + current_box[3] = xmax; + } +} + +void normalize_center(float* boxes, const Shape& boxes_shape) { + size_t total_num_of_boxes = shape_size(boxes_shape) / 4; + for (size_t i = 0; i < total_num_of_boxes; ++i) { + float* current_box = boxes + 4 * i; + + float x_center = current_box[0]; + float y_center = current_box[1]; + float width = current_box[2]; + float height = current_box[3]; + + float y1 = y_center - height / 2.0; + float x1 = x_center - width / 2.0; + float y2 = y_center + height / 2.0; + float x2 = x_center + width / 2.0; + + current_box[0] = y1; + current_box[1] = x1; + current_box[2] = y2; + current_box[3] = x2; + } +} + +void normalize_box_encoding(float* boxes, const Shape& boxes_shape, const V1BoxEncoding box_encoding) { + if (box_encoding == V1BoxEncoding::CORNER) { + normalize_corner(boxes, boxes_shape); + } else { + normalize_center(boxes, boxes_shape); + } +} + +std::vector prepare_boxes_data(const std::shared_ptr& boxes, + const Shape& boxes_shape, + const V1BoxEncoding box_encoding) { + auto result = get_floats(boxes, boxes_shape); + normalize_box_encoding(result.data(), boxes_shape, box_encoding); + return result; +} + +std::vector prepare_scores_data(const std::shared_ptr& scores, const Shape& scores_shape) { + auto result = get_floats(scores, scores_shape); + return result; +} + +InfoForNMS1 get_info_for_nms1_eval(const std::shared_ptr& nms1, + const std::vector>& inputs) { + InfoForNMS1 result; + + result.max_output_boxes_per_class = inputs.size() > 2 ? get_integers(inputs[2], Shape({}))[0] : 0; + result.iou_threshold = inputs.size() > 3 ? get_floats(inputs[3], Shape({}))[0] : 0.0f; + result.score_threshold = inputs.size() > 4 ? get_floats(inputs[4], Shape({}))[0] : 0.0f; + result.soft_nms_sigma = inputs.size() > 5 ? get_floats(inputs[5], Shape({}))[0] : 0.0f; + + auto selected_indices_shape = infer_selected_indices_shape(inputs, result.max_output_boxes_per_class); + result.out_shape = selected_indices_shape.to_shape(); + + result.boxes_shape = inputs[boxes_port]->get_shape(); + result.scores_shape = inputs[scores_port]->get_shape(); + + result.boxes_data = prepare_boxes_data(inputs[boxes_port], result.boxes_shape, nms1->get_box_encoding()); + result.scores_data = prepare_scores_data(inputs[scores_port], result.scores_shape); + + result.out_shape_size = shape_size(result.out_shape); + + result.sort_result_descending = nms1->get_sort_result_descending(); + + result.output_type = ov::element::i64; + + return result; +} +} // namespace nms_v1 + +template +bool evaluate(const shared_ptr& op, + const HostTensorVector& outputs, + const HostTensorVector& inputs) { + auto info = nms_v1::get_info_for_nms1_eval(op, inputs); + + std::vector selected_indices(info.out_shape_size); + std::vector selected_scores(info.out_shape_size); + int64_t valid_outputs = 0; + + runtime::reference::non_max_suppression(info.boxes_data.data(), + info.boxes_shape, + info.scores_data.data(), + info.scores_shape, + info.max_output_boxes_per_class, + info.iou_threshold, + info.score_threshold, + info.soft_nms_sigma, + selected_indices.data(), + info.out_shape, + selected_scores.data(), + info.out_shape, + &valid_outputs, + info.sort_result_descending); + + auto selected_scores_type = (inputs.size() < 4) ? element::f32 : inputs[3]->get_element_type(); + + runtime::reference::nms5_postprocessing(outputs, + info.output_type, + selected_indices, + selected_scores, + valid_outputs, + selected_scores_type); + return true; +} + namespace matrix_nms_v8 { using SortResultType = op::v8::MatrixNms::SortResultType; struct InfoForNMS { diff --git a/docs/template_plugin/backend/opset_int_tbl.hpp b/docs/template_plugin/backend/opset_int_tbl.hpp index f7630515d7b..0b04eaef39e 100644 --- a/docs/template_plugin/backend/opset_int_tbl.hpp +++ b/docs/template_plugin/backend/opset_int_tbl.hpp @@ -53,6 +53,7 @@ NGRAPH_OP(LogicalXor, op::v1) NGRAPH_OP(LogicalNot, op::v1) NGRAPH_OP(MaxPool, op::v1) NGRAPH_OP(Mod, op::v1) +NGRAPH_OP(NonMaxSuppression, op::v1) NGRAPH_OP(OneHot, op::v1) NGRAPH_OP(Pad, op::v1) NGRAPH_OP(Split, op::v1) @@ -66,12 +67,14 @@ NGRAPH_OP(EmbeddingBagPackedSum, ngraph::op::v3) NGRAPH_OP(ExtractImagePatches, op::v3) NGRAPH_OP(EmbeddingSegmentsSum, ngraph::op::v3) NGRAPH_OP(GRUCell, ngraph::op::v3) +NGRAPH_OP(NonMaxSuppression, op::v3) NGRAPH_OP(NonZero, op::v3) NGRAPH_OP(ScatterNDUpdate, op::v3) NGRAPH_OP(ShapeOf, op::v3) NGRAPH_OP(CTCLoss, op::v4) NGRAPH_OP(LSTMCell, op::v4) +NGRAPH_OP(NonMaxSuppression, op::v4) NGRAPH_OP(Proposal, op::v4) NGRAPH_OP(BatchNormInference, op::v5) diff --git a/docs/template_plugin/tests/functional/op_reference/non_max_suppression.cpp b/docs/template_plugin/tests/functional/op_reference/non_max_suppression.cpp index fd4dec2149e..3ba8067c965 100644 --- a/docs/template_plugin/tests/functional/op_reference/non_max_suppression.cpp +++ b/docs/template_plugin/tests/functional/op_reference/non_max_suppression.cpp @@ -4,8 +4,10 @@ #include -#include "openvino/op/non_max_suppression.hpp" -#include "openvino/op/constant.hpp" +#include "openvino/opsets/opset5.hpp" +#include "openvino/opsets/opset4.hpp" +#include "openvino/opsets/opset3.hpp" +#include "openvino/opsets/opset1.hpp" #include "base_reference_test.hpp" using namespace reference_tests; @@ -13,31 +15,33 @@ using namespace ov; namespace { struct NonMaxSuppressionParams { - NonMaxSuppressionParams( - const Tensor& boxes, const Tensor& scores, - const Tensor& maxOutputBoxesPerClass, const Tensor& iouThreshold, const Tensor& scoreThreshold, - const Tensor& softNmsSigma, const op::v5::NonMaxSuppression::BoxEncodingType boxEncoding, - const Tensor& expectedSelectedIndices, const Tensor& expectedSelectedScores, - const Tensor& expectedValidOutputs, const std::string& testcaseName = "") : - boxes(boxes), scores(scores), - maxOutputBoxesPerClass(maxOutputBoxesPerClass), iouThreshold(iouThreshold), scoreThreshold(scoreThreshold), - softNmsSigma(softNmsSigma), boxEncoding(boxEncoding), - expectedSelectedIndices(expectedSelectedIndices), expectedSelectedScores(expectedSelectedScores), - expectedValidOutputs(expectedValidOutputs), testcaseName(testcaseName) {} - Tensor boxes; Tensor scores; Tensor maxOutputBoxesPerClass; Tensor iouThreshold; Tensor scoreThreshold; Tensor softNmsSigma; - op::v5::NonMaxSuppression::BoxEncodingType boxEncoding; + opset5::NonMaxSuppression::BoxEncodingType boxEncoding; Tensor expectedSelectedIndices; Tensor expectedSelectedScores; Tensor expectedValidOutputs; std::string testcaseName; }; +struct Builder : ParamsBuilder { + REFERENCE_TESTS_ADD_SET_PARAM(Builder, boxes); + REFERENCE_TESTS_ADD_SET_PARAM(Builder, scores); + REFERENCE_TESTS_ADD_SET_PARAM(Builder, maxOutputBoxesPerClass); + REFERENCE_TESTS_ADD_SET_PARAM(Builder, iouThreshold); + REFERENCE_TESTS_ADD_SET_PARAM(Builder, scoreThreshold); + REFERENCE_TESTS_ADD_SET_PARAM(Builder, softNmsSigma); + REFERENCE_TESTS_ADD_SET_PARAM(Builder, boxEncoding); + REFERENCE_TESTS_ADD_SET_PARAM(Builder, expectedSelectedIndices); + REFERENCE_TESTS_ADD_SET_PARAM(Builder, expectedSelectedScores); + REFERENCE_TESTS_ADD_SET_PARAM(Builder, expectedValidOutputs); + REFERENCE_TESTS_ADD_SET_PARAM(Builder, testcaseName); +}; + class ReferenceNonMaxSuppressionTest : public testing::TestWithParam, public CommonReferenceTest { public: void SetUp() override { @@ -56,33 +60,31 @@ public: result << "_bShape=" << param.boxes.shape; result << "_sType=" << param.scores.type; result << "_sShape=" << param.scores.shape; - result << "_escType=" << param.expectedSelectedScores.type; - result << "_escShape=" << param.expectedSelectedScores.shape; result << "_esiType=" << param.expectedSelectedIndices.type; result << "_esiShape=" << param.expectedSelectedIndices.shape; + result << "_escType=" << param.expectedSelectedScores.type; + result << "_escShape=" << param.expectedSelectedScores.shape; result << "_evoType=" << param.expectedValidOutputs.type; + result << "_evoShape=" << param.expectedValidOutputs.shape; if (param.testcaseName != "") { - result << "_evoShape=" << param.expectedValidOutputs.shape; result << "_=" << param.testcaseName; - } else { - result << "_evoShape=" << param.expectedValidOutputs.shape; } return result.str(); } private: static std::shared_ptr CreateFunction(const NonMaxSuppressionParams& params) { - const auto boxes = std::make_shared(params.boxes.type, params.boxes.shape); - const auto scores = std::make_shared(params.scores.type, params.scores.shape); - const auto max_output_boxes_per_class = std::make_shared( + const auto boxes = std::make_shared(params.boxes.type, params.boxes.shape); + const auto scores = std::make_shared(params.scores.type, params.scores.shape); + const auto max_output_boxes_per_class = std::make_shared( params.maxOutputBoxesPerClass.type, params.maxOutputBoxesPerClass.shape, params.maxOutputBoxesPerClass.data.data()); - const auto iou_threshold = std::make_shared( + const auto iou_threshold = std::make_shared( params.iouThreshold.type, params.iouThreshold.shape, params.iouThreshold.data.data()); - const auto score_threshold = std::make_shared( + const auto score_threshold = std::make_shared( params.scoreThreshold.type, params.scoreThreshold.shape, params.scoreThreshold.data.data()); - const auto soft_nms_sigma = std::make_shared( + const auto soft_nms_sigma = std::make_shared( params.softNmsSigma.type, params.softNmsSigma.shape, params.softNmsSigma.data.data()); - const auto nms = std::make_shared(boxes, + const auto nms = std::make_shared(boxes, scores, max_output_boxes_per_class, iou_threshold, @@ -107,40 +109,19 @@ public: params.expectedValidOutputs.data}; } - static std::string getTestCaseName(const testing::TestParamInfo& obj) { - auto param = obj.param; - std::ostringstream result; - result << "bType=" << param.boxes.type; - result << "_bShape=" << param.boxes.shape; - result << "_sType=" << param.scores.type; - result << "_sShape=" << param.scores.shape; - result << "_escType=" << param.expectedSelectedScores.type; - result << "_escShape=" << param.expectedSelectedScores.shape; - result << "_esiType=" << param.expectedSelectedIndices.type; - result << "_esiShape=" << param.expectedSelectedIndices.shape; - result << "_evoType=" << param.expectedValidOutputs.type; - if (param.testcaseName != "") { - result << "_evoShape=" << param.expectedValidOutputs.shape; - result << "_=" << param.testcaseName; - } else { - result << "_evoShape=" << param.expectedValidOutputs.shape; - } - return result.str(); - } - private: static std::shared_ptr CreateFunction(const NonMaxSuppressionParams& params) { - const auto boxes = std::make_shared(params.boxes.type, params.boxes.shape); - const auto scores = std::make_shared(params.scores.type, params.scores.shape); - const auto max_output_boxes_per_class = std::make_shared( + const auto boxes = std::make_shared(params.boxes.type, params.boxes.shape); + const auto scores = std::make_shared(params.scores.type, params.scores.shape); + const auto max_output_boxes_per_class = std::make_shared( params.maxOutputBoxesPerClass.type, params.maxOutputBoxesPerClass.shape); - const auto iou_threshold = std::make_shared( + const auto iou_threshold = std::make_shared( params.iouThreshold.type, params.iouThreshold.shape); - const auto score_threshold = std::make_shared( + const auto score_threshold = std::make_shared( params.scoreThreshold.type, params.scoreThreshold.shape); - const auto soft_nms_sigma = std::make_shared( + const auto soft_nms_sigma = std::make_shared( params.softNmsSigma.type, params.softNmsSigma.shape); - const auto nms = std::make_shared(boxes, + const auto nms = std::make_shared(boxes, scores, max_output_boxes_per_class, iou_threshold, @@ -149,8 +130,8 @@ private: params.boxEncoding, false); const auto f = std::make_shared(nms->outputs(), - ParameterVector{boxes, scores, max_output_boxes_per_class, - iou_threshold, score_threshold, soft_nms_sigma}); + ParameterVector{boxes, scores, max_output_boxes_per_class, + iou_threshold, score_threshold, soft_nms_sigma}); return f; } }; @@ -170,243 +151,260 @@ std::vector generateParams() { using T_TH = typename element_type_traits::value_type; using T_IND = typename element_type_traits::value_type; std::vector params { - NonMaxSuppressionParams( - // boxes + Builder {} + .boxes( Tensor(ET, {1, 6, 4}, std::vector{ 0.5, 0.5, 1.0, 1.0, 0.5, 0.6, 1.0, 1.0, 0.5, 0.4, 1.0, 1.0, - 0.5, 10.5, 1.0, 1.0, 0.5, 10.6, 1.0, 1.0, 0.5, 100.5, 1.0, 1.0}), - // scores + 0.5, 10.5, 1.0, 1.0, 0.5, 10.6, 1.0, 1.0, 0.5, 100.5, 1.0, 1.0})) + .scores( Tensor(ET, {1, 1, 6}, std::vector{ - 0.9, 0.75, 0.6, 0.95, 0.5, 0.3}), - // max_output_boxes_per_class - Tensor(ET_BOX, {}, std::vector{3}), - // iou_threshold - Tensor(ET_TH, {}, std::vector{0.5f}), - // score_threshold - Tensor(ET_TH, {}, std::vector{0.0f}), - // soft_nms_sigma - Tensor(ET_TH, {}, std::vector{0.0f}), - // box_encoding - op::v5::NonMaxSuppression::BoxEncodingType::CENTER, - // selected_indices + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{3})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .softNmsSigma( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset5::NonMaxSuppression::BoxEncodingType::CENTER) + .expectedSelectedIndices( Tensor(ET_IND, {3, 3}, std::vector{ - 0, 0, 3, 0, 0, 0, 0, 0, 5}), - // selected_scores + 0, 0, 3, 0, 0, 0, 0, 0, 5})) + .expectedSelectedScores( Tensor(ET_TH, {3, 3}, std::vector{ - 0.0, 0.0, 0.95, 0.0, 0.0, 0.9, 0.0, 0.0, 0.3}), - // valid_outputs - Tensor(ET_IND, {1}, std::vector{3}), + 0.0, 0.0, 0.95, 0.0, 0.0, 0.9, 0.0, 0.0, 0.3})) + .expectedValidOutputs( + Tensor(ET_IND, {1}, std::vector{3})) + .testcaseName( "nonmaxsuppression_center_point_box_format"), - NonMaxSuppressionParams( - // boxes + + Builder {} + .boxes( Tensor(ET, {1, 6, 4}, std::vector{ 1.0, 1.0, 0.0, 0.0, 0.0, 0.1, 1.0, 1.1, 0.0, 0.9, 1.0, -0.1, - 0.0, 10.0, 1.0, 11.0, 1.0, 10.1, 0.0, 11.1, 1.0, 101.0, 0.0, 100.0}), - // scores + 0.0, 10.0, 1.0, 11.0, 1.0, 10.1, 0.0, 11.1, 1.0, 101.0, 0.0, 100.0})) + .scores( Tensor(ET, {1, 1, 6}, std::vector{ - 0.9, 0.75, 0.6, 0.95, 0.5, 0.3}), - // max_output_boxes_per_class - Tensor(ET_BOX, {}, std::vector{3}), - // iou_threshold - Tensor(ET_TH, {}, std::vector{0.5f}), - // score_threshold - Tensor(ET_TH, {}, std::vector{0.0f}), - // soft_nms_sigma - Tensor(ET_TH, {}, std::vector{0.0f}), - // box_encoding - op::v5::NonMaxSuppression::BoxEncodingType::CORNER, - // selected_indices + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{3})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .softNmsSigma( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset5::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( Tensor(ET_IND, {3, 3}, std::vector{ - 0, 0, 3, 0, 0, 0, 0, 0, 5}), - // selected_scores + 0, 0, 3, 0, 0, 0, 0, 0, 5})) + .expectedSelectedScores( Tensor(ET_TH, {3, 3}, std::vector{ - 0.0, 0.0, 0.95, 0.0, 0.0, 0.9, 0.0, 0.0, 0.3}), - // valid_outputs - Tensor(ET_IND, {1}, std::vector{3}), + 0.0, 0.0, 0.95, 0.0, 0.0, 0.9, 0.0, 0.0, 0.3})) + .expectedValidOutputs( + Tensor(ET_IND, {1}, std::vector{3})) + .testcaseName( "nonmaxsuppression_flipped_coordinates"), - NonMaxSuppressionParams( - // boxes + + Builder {} + .boxes( Tensor(ET, {1, 10, 4}, std::vector{ 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, - 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0}), - // scores + 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0})) + .scores( Tensor(ET, {1, 1, 10}, std::vector{ - 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9}), - // max_output_boxes_per_class - Tensor(ET_BOX, {}, std::vector{3}), - // iou_threshold - Tensor(ET_TH, {}, std::vector{0.5f}), - // score_threshold - Tensor(ET_TH, {}, std::vector{0.0f}), - // soft_nms_sigma - Tensor(ET_TH, {}, std::vector{0.0f}), - // box_encoding - op::v5::NonMaxSuppression::BoxEncodingType::CORNER, - // selected_indices - Tensor(ET_IND, {1, 3}, std::vector{0, 0, 0}), - // selected_scores - Tensor(ET_TH, {1, 3}, std::vector{0.0, 0.0, 0.9}), - // valid_outputs - Tensor(ET_IND, {1}, std::vector{1}), + 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{3})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .softNmsSigma( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset5::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {1, 3}, std::vector{0, 0, 0})) + .expectedSelectedScores( + Tensor(ET_TH, {1, 3}, std::vector{0.0, 0.0, 0.9})) + .expectedValidOutputs( + Tensor(ET_IND, {1}, std::vector{1})) + .testcaseName( "nonmaxsuppression_identical_boxes"), - NonMaxSuppressionParams( - // boxes + + Builder {} + .boxes( Tensor(ET, {1, 6, 4}, std::vector{ 0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, 0.0, -0.1, 1.0, 0.9, - 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0}), - // scores + 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0})) + .scores( Tensor(ET, {1, 1, 6}, std::vector{ - 0.9, 0.75, 0.6, 0.95, 0.5, 0.3}), - // max_output_boxes_per_class - Tensor(ET_BOX, {}, std::vector{2}), - // iou_threshold - Tensor(ET_TH, {}, std::vector{0.5f}), - // score_threshold - Tensor(ET_TH, {}, std::vector{0.0f}), - // soft_nms_sigma - Tensor(ET_TH, {}, std::vector{0.0f}), - // box_encoding - op::v5::NonMaxSuppression::BoxEncodingType::CORNER, - // selected_indices - Tensor(ET_IND, {2, 3}, std::vector{0, 0, 3, 0, 0, 0}), - // selected_scores + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{2})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .softNmsSigma( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset5::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {2, 3}, std::vector{0, 0, 3, 0, 0, 0})) + .expectedSelectedScores( Tensor(ET_TH, {2, 3}, std::vector{ - 0.0, 0.0, 0.95, 0.0, 0.0, 0.9}), - // valid_outputs - Tensor(ET_IND, {1}, std::vector{2}), + 0.0, 0.0, 0.95, 0.0, 0.0, 0.9})) + .expectedValidOutputs( + Tensor(ET_IND, {1}, std::vector{2})) + .testcaseName( "nonmaxsuppression_limit_output_size"), - NonMaxSuppressionParams( - // boxes - Tensor(ET, {1, 1, 4}, std::vector{0.0, 0.0, 1.0, 1.0}), - // scores - Tensor(ET, {1, 1, 1}, std::vector{0.9}), - // max_output_boxes_per_class - Tensor(ET_BOX, {}, std::vector{3}), - // iou_threshold - Tensor(ET_TH, {}, std::vector{0.5f}), - // score_threshold - Tensor(ET_TH, {}, std::vector{0.0f}), - // soft_nms_sigma - Tensor(ET_TH, {}, std::vector{0.0f}), - // box_encoding - op::v5::NonMaxSuppression::BoxEncodingType::CORNER, - // selected_indices - Tensor(ET_IND, {1, 3}, std::vector{0, 0, 0}), - // selected_scores - Tensor(ET_TH, {1, 3}, std::vector{0.0, 0.0, 0.9}), - // valid_outputs - Tensor(ET_IND, {1}, std::vector{1}), + + Builder {} + .boxes( + Tensor(ET, {1, 1, 4}, std::vector{0.0, 0.0, 1.0, 1.0})) + .scores( + Tensor(ET, {1, 1, 1}, std::vector{0.9})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{3})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .softNmsSigma( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset5::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {1, 3}, std::vector{0, 0, 0})) + .expectedSelectedScores( + Tensor(ET_TH, {1, 3}, std::vector{0.0, 0.0, 0.9})) + .expectedValidOutputs( + Tensor(ET_IND, {1}, std::vector{1})) + .testcaseName( "nonmaxsuppression_single_box"), - NonMaxSuppressionParams( - // boxes + + Builder {} + .boxes( Tensor(ET, {1, 6, 4}, std::vector{ 0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, 0.0, -0.1, 1.0, 0.9, - 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0}), - // scores + 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0})) + .scores( Tensor(ET, {1, 1, 6}, std::vector{ - 0.9, 0.75, 0.6, 0.95, 0.5, 0.3}), - // max_output_boxes_per_class - Tensor(ET_BOX, {}, std::vector{3}), - // iou_threshold - Tensor(ET_TH, {}, std::vector{0.5f}), - // score_threshold - Tensor(ET_TH, {}, std::vector{0.0f}), - // soft_nms_sigma - Tensor(ET_TH, {}, std::vector{0.0f}), - // box_encoding - op::v5::NonMaxSuppression::BoxEncodingType::CORNER, - // selected_indices + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{3})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .softNmsSigma( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset5::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( Tensor(ET_IND, {3, 3}, std::vector{ - 0, 0, 3, 0, 0, 0, 0, 0, 5}), - // selected_scores + 0, 0, 3, 0, 0, 0, 0, 0, 5})) + .expectedSelectedScores( Tensor(ET_TH, {3, 3}, std::vector{ - 0.0, 0.0, 0.95, 0.0, 0.0, 0.9, 0.0, 0.0, 0.3}), - // valid_outputs - Tensor(ET_IND, {1}, std::vector{3}), + 0.0, 0.0, 0.95, 0.0, 0.0, 0.9, 0.0, 0.0, 0.3})) + .expectedValidOutputs( + Tensor(ET_IND, {1}, std::vector{3})) + .testcaseName( "nonmaxsuppression_suppress_by_IOU"), - NonMaxSuppressionParams( - // boxes + + Builder {} + .boxes( Tensor(ET, {1, 6, 4}, std::vector{ 0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, 0.0, -0.1, 1.0, 0.9, - 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0}), - // scores + 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0})) + .scores( Tensor(ET, {1, 1, 6}, std::vector{ - 0.9, 0.75, 0.6, 0.95, 0.5, 0.3}), - // max_output_boxes_per_class - Tensor(ET_BOX, {}, std::vector{3}), - // iou_threshold - Tensor(ET_TH, {}, std::vector{0.5f}), - // score_threshold - Tensor(ET_TH, {}, std::vector{0.4f}), - // soft_nms_sigma - Tensor(ET_TH, {}, std::vector{0.0f}), - // box_encoding - op::v5::NonMaxSuppression::BoxEncodingType::CORNER, - // selected_indices + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{3})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.4f})) + .softNmsSigma( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset5::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( Tensor(ET_IND, {2, 3}, std::vector{ - 0, 0, 3, 0, 0, 0}), - // selected_scores + 0, 0, 3, 0, 0, 0})) + .expectedSelectedScores( Tensor(ET_TH, {2, 3}, std::vector{ - 0.0, 0.0, 0.95, 0.0, 0.0, 0.9}), - // valid_outputs - Tensor(ET_IND, {1}, std::vector{2}), + 0.0, 0.0, 0.95, 0.0, 0.0, 0.9})) + .expectedValidOutputs( + Tensor(ET_IND, {1}, std::vector{2})) + .testcaseName( "nonmaxsuppression_suppress_by_IOU_and_scores"), - NonMaxSuppressionParams( - // boxes + + Builder {} + .boxes( Tensor(ET, {2, 6, 4}, std::vector{ 0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, 0.0, -0.1, 1.0, 0.9, 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, 0.0, -0.1, 1.0, 0.9, - 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0}), - // scores + 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0})) + .scores( Tensor(ET, {2, 1, 6}, std::vector{ - 0.9, 0.75, 0.6, 0.95, 0.5, 0.3, 0.9, 0.75, 0.6, 0.95, 0.5, 0.3}), - // max_output_boxes_per_class - Tensor(ET_BOX, {}, std::vector{2}), - // iou_threshold - Tensor(ET_TH, {}, std::vector{0.5f}), - // score_threshold - Tensor(ET_TH, {}, std::vector{0.0f}), - // soft_nms_sigma - Tensor(ET_TH, {}, std::vector{0.0f}), - // box_encoding - op::v5::NonMaxSuppression::BoxEncodingType::CORNER, - // selected_indices + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3, 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{2})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .softNmsSigma( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset5::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( Tensor(ET_IND, {4, 3}, std::vector{ - 0, 0, 3, 0, 0, 0, 1, 0, 3, 1, 0, 0}), - // selected_scores + 0, 0, 3, 0, 0, 0, 1, 0, 3, 1, 0, 0})) + .expectedSelectedScores( Tensor(ET_TH, {4, 3}, std::vector{ - 0.0, 0.0, 0.95, 0.0, 0.0, 0.9, 1.0, 0.0, 0.95, 1.0, 0.0, 0.9}), - // valid_outputs - Tensor(ET_IND, {1}, std::vector{4}), + 0.0, 0.0, 0.95, 0.0, 0.0, 0.9, 1.0, 0.0, 0.95, 1.0, 0.0, 0.9})) + .expectedValidOutputs( + Tensor(ET_IND, {1}, std::vector{4})) + .testcaseName( "nonmaxsuppression_two_batches"), - NonMaxSuppressionParams( - // boxes + + Builder {} + .boxes( Tensor(ET, {1, 6, 4}, std::vector{ 0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, 0.0, -0.1, 1.0, 0.9, - 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0}), - // scores + 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0})) + .scores( Tensor(ET, {1, 2, 6}, std::vector{ - 0.9, 0.75, 0.6, 0.95, 0.5, 0.3, 0.9, 0.75, 0.6, 0.95, 0.5, 0.3}), - // max_output_boxes_per_class - Tensor(ET_BOX, {}, std::vector{2}), - // iou_threshold - Tensor(ET_TH, {}, std::vector{0.5f}), - // score_threshold - Tensor(ET_TH, {}, std::vector{0.0f}), - // soft_nms_sigma - Tensor(ET_TH, {}, std::vector{0.0f}), - // box_encoding - op::v5::NonMaxSuppression::BoxEncodingType::CORNER, - // selected_indices + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3, 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{2})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .softNmsSigma( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset5::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( Tensor(ET_IND, {4, 3}, std::vector{ - 0, 0, 3, 0, 0, 0, 0, 1, 3, 0, 1, 0}), - // selected_scores + 0, 0, 3, 0, 0, 0, 0, 1, 3, 0, 1, 0})) + .expectedSelectedScores( Tensor(ET_TH, {4, 3}, std::vector{ - 0.0, 0.0, 0.95, 0.0, 0.0, 0.9, 0.0, 1.0, 0.95, 0.0, 1.0, 0.9}), - // valid_outputs - Tensor(ET_IND, {1}, std::vector{4}), + 0.0, 0.0, 0.95, 0.0, 0.0, 0.9, 0.0, 1.0, 0.95, 0.0, 1.0, 0.9})) + .expectedValidOutputs( + Tensor(ET_IND, {1}, std::vector{4})) + .testcaseName( "nonmaxsuppression_two_classes"), }; return params; @@ -436,30 +434,31 @@ std::vector generateParamsWithoutConstants() { using T_TH = typename element_type_traits::value_type; using T_IND = typename element_type_traits::value_type; std::vector params { - NonMaxSuppressionParams( - // boxes + Builder {} + .boxes( Tensor(ET, {1, 6, 4}, std::vector{ 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}), - // scores + 0.0f, 10.0f, 1.0f, 11.0f, 0.0f, 10.1f, 1.0f, 11.1f, 0.0f, 100.0f, 1.0f, 101.0f})) + .scores( Tensor(ET, {1, 1, 6}, std::vector{ - 0.9f, 0.75f, 0.6f, 0.95f, 0.5f, 0.3f}), - // max_output_boxes_per_class - Tensor(ET_BOX, {1}, std::vector{1}), - // iou_threshold - Tensor(ET_TH, {1}, std::vector{0.4f}), - // score_threshold - Tensor(ET_TH, {1}, std::vector{0.2f}), - // soft_nms_sigma - Tensor(ET_TH, {1}, std::vector{0.0f}), - // box_encoding - op::v5::NonMaxSuppression::BoxEncodingType::CORNER, - // selected_indices - Tensor(ET_IND, {1, 3}, std::vector{0, 0, 3}), - // selected_scores - Tensor(ET_TH, {1, 3}, std::vector{0.0f, 0.0f, 0.95f}), - // valid_outputs - Tensor(ET_IND, {1}, std::vector{1}), + 0.9f, 0.75f, 0.6f, 0.95f, 0.5f, 0.3f})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {1}, std::vector{1})) + .iouThreshold( + Tensor(ET_TH, {1}, std::vector{0.4f})) + .scoreThreshold( + Tensor(ET_TH, {1}, std::vector{0.2f})) + .softNmsSigma( + Tensor(ET_TH, {1}, std::vector{0.0f})) + .boxEncoding( + opset5::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {1, 3}, std::vector{0, 0, 3})) + .expectedSelectedScores( + Tensor(ET_TH, {1, 3}, std::vector{0.0f, 0.0f, 0.95f})) + .expectedValidOutputs( + Tensor(ET_IND, {1}, std::vector{1})) + .testcaseName( "nonmaxsuppression_suppress_by_IOU_and_scores_without_constants"), }; return params; @@ -485,5 +484,1115 @@ std::vector generateCombinedParamsWithoutConstants() { INSTANTIATE_TEST_SUITE_P(smoke_NonMaxSuppression_With_Hardcoded_Refs, ReferenceNonMaxSuppressionTest, testing::ValuesIn(generateCombinedParams()), ReferenceNonMaxSuppressionTest::getTestCaseName); INSTANTIATE_TEST_SUITE_P(smoke_NonMaxSuppression_With_Hardcoded_Refs, ReferenceNonMaxSuppressionTestWithoutConstants, - testing::ValuesIn(generateCombinedParamsWithoutConstants()), ReferenceNonMaxSuppressionTest::getTestCaseName); + testing::ValuesIn(generateCombinedParamsWithoutConstants()), ReferenceNonMaxSuppressionTestWithoutConstants::getTestCaseName); + + +struct NonMaxSuppression4Params { + Tensor boxes; + Tensor scores; + Tensor maxOutputBoxesPerClass; + Tensor iouThreshold; + Tensor scoreThreshold; + opset4::NonMaxSuppression::BoxEncodingType boxEncoding; + Tensor expectedSelectedIndices; + std::string testcaseName; +}; + +struct Builder4 : ParamsBuilder { + REFERENCE_TESTS_ADD_SET_PARAM(Builder4, boxes); + REFERENCE_TESTS_ADD_SET_PARAM(Builder4, scores); + REFERENCE_TESTS_ADD_SET_PARAM(Builder4, maxOutputBoxesPerClass); + REFERENCE_TESTS_ADD_SET_PARAM(Builder4, iouThreshold); + REFERENCE_TESTS_ADD_SET_PARAM(Builder4, scoreThreshold); + REFERENCE_TESTS_ADD_SET_PARAM(Builder4, boxEncoding); + REFERENCE_TESTS_ADD_SET_PARAM(Builder4, expectedSelectedIndices); + REFERENCE_TESTS_ADD_SET_PARAM(Builder4, testcaseName); +}; + +class ReferenceNonMaxSuppression4Test : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.boxes.data, params.scores.data}; + refOutData = {params.expectedSelectedIndices.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "bType=" << param.boxes.type; + result << "_bShape=" << param.boxes.shape; + result << "_sType=" << param.scores.type; + result << "_sShape=" << param.scores.shape; + result << "_esiType=" << param.expectedSelectedIndices.type; + result << "_esiShape=" << param.expectedSelectedIndices.shape; + if (param.testcaseName != "") { + result << "_=" << param.testcaseName; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const NonMaxSuppression4Params& params) { + const auto boxes = std::make_shared(params.boxes.type, params.boxes.shape); + const auto scores = std::make_shared(params.scores.type, params.scores.shape); + const auto max_output_boxes_per_class = std::make_shared( + params.maxOutputBoxesPerClass.type, params.maxOutputBoxesPerClass.shape, params.maxOutputBoxesPerClass.data.data()); + const auto iou_threshold = std::make_shared( + params.iouThreshold.type, params.iouThreshold.shape, params.iouThreshold.data.data()); + const auto score_threshold = std::make_shared( + params.scoreThreshold.type, params.scoreThreshold.shape, params.scoreThreshold.data.data()); + const auto nms = std::make_shared(boxes, + scores, + max_output_boxes_per_class, + iou_threshold, + score_threshold, + params.boxEncoding, + false); + const auto f = std::make_shared(nms->outputs(), ParameterVector{boxes, scores}); + return f; + } +}; + +class ReferenceNonMaxSuppression4TestWithoutConstants : public ReferenceNonMaxSuppression4Test { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.boxes.data, params.scores.data, params.maxOutputBoxesPerClass.data, + params.iouThreshold.data, params.scoreThreshold.data}; + refOutData = {params.expectedSelectedIndices.data}; + } + +private: + static std::shared_ptr CreateFunction(const NonMaxSuppression4Params& params) { + const auto boxes = std::make_shared(params.boxes.type, params.boxes.shape); + const auto scores = std::make_shared(params.scores.type, params.scores.shape); + const auto max_output_boxes_per_class = std::make_shared( + params.maxOutputBoxesPerClass.type, params.maxOutputBoxesPerClass.shape); + const auto iou_threshold = std::make_shared( + params.iouThreshold.type, params.iouThreshold.shape); + const auto score_threshold = std::make_shared( + params.scoreThreshold.type, params.scoreThreshold.shape); + const auto nms = std::make_shared(boxes, + scores, + max_output_boxes_per_class, + iou_threshold, + score_threshold, + params.boxEncoding, + false); + const auto f = std::make_shared(nms->outputs(), + ParameterVector{boxes, scores, max_output_boxes_per_class, + iou_threshold, score_threshold}); + return f; + } +}; + +TEST_P(ReferenceNonMaxSuppression4Test, CompareWithRefs) { + Exec(); +} + +TEST_P(ReferenceNonMaxSuppression4TestWithoutConstants, CompareWithRefs) { + Exec(); +} + +template +std::vector generateParams4() { + using T = typename element_type_traits::value_type; + using T_BOX = typename element_type_traits::value_type; + using T_TH = typename element_type_traits::value_type; + using T_IND = typename element_type_traits::value_type; + std::vector params { + Builder4 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 0.5, 0.5, 1.0, 1.0, 0.5, 0.6, 1.0, 1.0, 0.5, 0.4, 1.0, 1.0, + 0.5, 10.5, 1.0, 1.0, 0.5, 10.6, 1.0, 1.0, 0.5, 100.5, 1.0, 1.0})) + .scores( + Tensor(ET, {1, 1, 6}, std::vector{ + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{3})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset4::NonMaxSuppression::BoxEncodingType::CENTER) + .expectedSelectedIndices( + Tensor(ET_IND, {3, 3}, std::vector{ + 0, 0, 3, 0, 0, 0, 0, 0, 5})) + .testcaseName( + "nonmaxsuppression_center_point_box_format"), + + Builder4 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 1.0, 1.0, 0.0, 0.0, 0.0, 0.1, 1.0, 1.1, 0.0, 0.9, 1.0, -0.1, + 0.0, 10.0, 1.0, 11.0, 1.0, 10.1, 0.0, 11.1, 1.0, 101.0, 0.0, 100.0})) + .scores( + Tensor(ET, {1, 1, 6}, std::vector{ + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{3})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset4::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {3, 3}, std::vector{ + 0, 0, 3, 0, 0, 0, 0, 0, 5})) + .testcaseName( + "nonmaxsuppression_flipped_coordinates"), + + Builder4 {} + .boxes( + Tensor(ET, {1, 10, 4}, std::vector{ + 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, + 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, + 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0})) + .scores( + Tensor(ET, {1, 1, 10}, std::vector{ + 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{1})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset4::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {1, 3}, std::vector{0, 0, 0})) + .testcaseName( + "nonmaxsuppression_identical_boxes"), + + Builder4 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, 0.0, -0.1, 1.0, 0.9, + 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0})) + .scores( + Tensor(ET, {1, 1, 6}, std::vector{ + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{2})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset4::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {2, 3}, std::vector{0, 0, 3, 0, 0, 0})) + .testcaseName( + "nonmaxsuppression_limit_output_size"), + + Builder4 {} + .boxes( + Tensor(ET, {1, 1, 4}, std::vector{0.0, 0.0, 1.0, 1.0})) + .scores( + Tensor(ET, {1, 1, 1}, std::vector{0.9})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{3})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset4::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {1, 3}, std::vector{0, 0, 0})) + .testcaseName( + "nonmaxsuppression_single_box"), + + Builder4 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, 0.0, -0.1, 1.0, 0.9, + 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0})) + .scores( + Tensor(ET, {1, 1, 6}, std::vector{ + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{3})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset4::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {3, 3}, std::vector{ + 0, 0, 3, 0, 0, 0, 0, 0, 5})) + .testcaseName( + "nonmaxsuppression_suppress_by_IOU"), + + Builder4 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, 0.0, -0.1, 1.0, 0.9, + 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0})) + .scores( + Tensor(ET, {1, 1, 6}, std::vector{ + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{2})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.4f})) + .boxEncoding( + opset4::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {2, 3}, std::vector{ + 0, 0, 3, 0, 0, 0})) + .testcaseName( + "nonmaxsuppression_suppress_by_IOU_and_scores"), + + Builder4 {} + .boxes( + Tensor(ET, {2, 6, 4}, std::vector{ + 0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, 0.0, -0.1, 1.0, 0.9, + 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0, + 0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, 0.0, -0.1, 1.0, 0.9, + 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0})) + .scores( + Tensor(ET, {2, 1, 6}, std::vector{ + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3, 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{2})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset4::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {4, 3}, std::vector{ + 0, 0, 3, 0, 0, 0, 1, 0, 3, 1, 0, 0})) + .testcaseName( + "nonmaxsuppression_two_batches"), + + Builder4 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, 0.0, -0.1, 1.0, 0.9, + 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0})) + .scores( + Tensor(ET, {1, 2, 6}, std::vector{ + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3, 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{2})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset4::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {4, 3}, std::vector{ + 0, 0, 3, 0, 0, 0, 0, 1, 3, 0, 1, 0})) + .testcaseName( + "nonmaxsuppression_two_classes"), + }; + return params; +} + +std::vector generateCombinedParams4() { + const std::vector> generatedParams { + generateParams4(), + generateParams4(), + generateParams4(), + generateParams4(), + generateParams4(), + generateParams4(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +template +std::vector generateParams4WithoutConstants() { + using T = typename element_type_traits::value_type; + using T_BOX = typename element_type_traits::value_type; + using T_TH = typename element_type_traits::value_type; + using T_IND = typename element_type_traits::value_type; + std::vector params { + Builder4 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 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})) + .scores( + Tensor(ET, {1, 1, 6}, std::vector{ + 0.9f, 0.75f, 0.6f, 0.95f, 0.5f, 0.3f})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{1})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.4f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.2f})) + .boxEncoding( + opset4::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {1, 3}, std::vector{0, 0, 3})) + .testcaseName( + "nonmaxsuppression_suppress_by_IOU_and_scores_without_constants"), + }; + return params; +} + +std::vector generateCombinedParams4WithoutConstants() { + const std::vector> generatedParams { + generateParams4WithoutConstants(), + generateParams4WithoutConstants(), + generateParams4WithoutConstants(), + generateParams4WithoutConstants(), + generateParams4WithoutConstants(), + generateParams4WithoutConstants(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_NonMaxSuppression_With_Hardcoded_Refs, ReferenceNonMaxSuppression4Test, + testing::ValuesIn(generateCombinedParams4()), ReferenceNonMaxSuppression4Test::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_NonMaxSuppression_With_Hardcoded_Refs, ReferenceNonMaxSuppression4TestWithoutConstants, + testing::ValuesIn(generateCombinedParams4WithoutConstants()), ReferenceNonMaxSuppression4TestWithoutConstants::getTestCaseName); + + +struct NonMaxSuppression3Params { + Tensor boxes; + Tensor scores; + Tensor maxOutputBoxesPerClass; + Tensor iouThreshold; + Tensor scoreThreshold; + opset3::NonMaxSuppression::BoxEncodingType boxEncoding; + Tensor expectedSelectedIndices; + std::string testcaseName; +}; + +struct Builder3 : ParamsBuilder { + REFERENCE_TESTS_ADD_SET_PARAM(Builder3, boxes); + REFERENCE_TESTS_ADD_SET_PARAM(Builder3, scores); + REFERENCE_TESTS_ADD_SET_PARAM(Builder3, maxOutputBoxesPerClass); + REFERENCE_TESTS_ADD_SET_PARAM(Builder3, iouThreshold); + REFERENCE_TESTS_ADD_SET_PARAM(Builder3, scoreThreshold); + REFERENCE_TESTS_ADD_SET_PARAM(Builder3, boxEncoding); + REFERENCE_TESTS_ADD_SET_PARAM(Builder3, expectedSelectedIndices); + REFERENCE_TESTS_ADD_SET_PARAM(Builder3, testcaseName); +}; + +class ReferenceNonMaxSuppression3Test : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.boxes.data, params.scores.data}; + refOutData = {params.expectedSelectedIndices.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "bType=" << param.boxes.type; + result << "_bShape=" << param.boxes.shape; + result << "_sType=" << param.scores.type; + result << "_sShape=" << param.scores.shape; + result << "_esiType=" << param.expectedSelectedIndices.type; + result << "_esiShape=" << param.expectedSelectedIndices.shape; + if (param.testcaseName != "") { + result << "_=" << param.testcaseName; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const NonMaxSuppression3Params& params) { + const auto boxes = std::make_shared(params.boxes.type, params.boxes.shape); + const auto scores = std::make_shared(params.scores.type, params.scores.shape); + const auto max_output_boxes_per_class = std::make_shared( + params.maxOutputBoxesPerClass.type, params.maxOutputBoxesPerClass.shape, params.maxOutputBoxesPerClass.data.data()); + const auto iou_threshold = std::make_shared( + params.iouThreshold.type, params.iouThreshold.shape, params.iouThreshold.data.data()); + const auto score_threshold = std::make_shared( + params.scoreThreshold.type, params.scoreThreshold.shape, params.scoreThreshold.data.data()); + const auto nms = std::make_shared(boxes, + scores, + max_output_boxes_per_class, + iou_threshold, + score_threshold, + params.boxEncoding, + false); + const auto f = std::make_shared(nms->outputs(), ParameterVector{boxes, scores}); + return f; + } +}; + +class ReferenceNonMaxSuppression3TestWithoutConstants : public ReferenceNonMaxSuppression3Test { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.boxes.data, params.scores.data, params.maxOutputBoxesPerClass.data, + params.iouThreshold.data, params.scoreThreshold.data}; + refOutData = {params.expectedSelectedIndices.data}; + } + +private: + static std::shared_ptr CreateFunction(const NonMaxSuppression3Params& params) { + const auto boxes = std::make_shared(params.boxes.type, params.boxes.shape); + const auto scores = std::make_shared(params.scores.type, params.scores.shape); + const auto max_output_boxes_per_class = std::make_shared( + params.maxOutputBoxesPerClass.type, params.maxOutputBoxesPerClass.shape); + const auto iou_threshold = std::make_shared( + params.iouThreshold.type, params.iouThreshold.shape); + const auto score_threshold = std::make_shared( + params.scoreThreshold.type, params.scoreThreshold.shape); + const auto nms = std::make_shared(boxes, + scores, + max_output_boxes_per_class, + iou_threshold, + score_threshold, + params.boxEncoding, + false); + const auto f = std::make_shared(nms->outputs(), + ParameterVector{boxes, scores, max_output_boxes_per_class, + iou_threshold, score_threshold}); + return f; + } +}; + +TEST_P(ReferenceNonMaxSuppression3Test, CompareWithRefs) { + Exec(); +} + +TEST_P(ReferenceNonMaxSuppression3TestWithoutConstants, CompareWithRefs) { + Exec(); +} + +template +std::vector generateParams3() { + using T = typename element_type_traits::value_type; + using T_BOX = typename element_type_traits::value_type; + using T_TH = typename element_type_traits::value_type; + using T_IND = typename element_type_traits::value_type; + std::vector params { + Builder3 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 0.5, 0.5, 1.0, 1.0, 0.5, 0.6, 1.0, 1.0, 0.5, 0.4, 1.0, 1.0, + 0.5, 10.5, 1.0, 1.0, 0.5, 10.6, 1.0, 1.0, 0.5, 100.5, 1.0, 1.0})) + .scores( + Tensor(ET, {1, 1, 6}, std::vector{ + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{3})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset3::NonMaxSuppression::BoxEncodingType::CENTER) + .expectedSelectedIndices( + Tensor(ET_IND, {3, 3}, std::vector{ + 0, 0, 3, 0, 0, 0, 0, 0, 5})) + .testcaseName( + "nonmaxsuppression_center_point_box_format"), + + Builder3 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 1.0, 1.0, 0.0, 0.0, 0.0, 0.1, 1.0, 1.1, 0.0, 0.9, 1.0, -0.1, + 0.0, 10.0, 1.0, 11.0, 1.0, 10.1, 0.0, 11.1, 1.0, 101.0, 0.0, 100.0})) + .scores( + Tensor(ET, {1, 1, 6}, std::vector{ + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{3})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset3::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {3, 3}, std::vector{ + 0, 0, 3, 0, 0, 0, 0, 0, 5})) + .testcaseName( + "nonmaxsuppression_flipped_coordinates"), + + Builder3 {} + .boxes( + Tensor(ET, {1, 10, 4}, std::vector{ + 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, + 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, + 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0})) + .scores( + Tensor(ET, {1, 1, 10}, std::vector{ + 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{1})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset3::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {1, 3}, std::vector{0, 0, 0})) + .testcaseName( + "nonmaxsuppression_identical_boxes"), + + Builder3 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, 0.0, -0.1, 1.0, 0.9, + 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0})) + .scores( + Tensor(ET, {1, 1, 6}, std::vector{ + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{2})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset3::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {2, 3}, std::vector{0, 0, 3, 0, 0, 0})) + .testcaseName( + "nonmaxsuppression_limit_output_size"), + + Builder3 {} + .boxes( + Tensor(ET, {1, 1, 4}, std::vector{0.0, 0.0, 1.0, 1.0})) + .scores( + Tensor(ET, {1, 1, 1}, std::vector{0.9})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{3})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset3::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {1, 3}, std::vector{0, 0, 0})) + .testcaseName( + "nonmaxsuppression_single_box"), + + Builder3 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, 0.0, -0.1, 1.0, 0.9, + 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0})) + .scores( + Tensor(ET, {1, 1, 6}, std::vector{ + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{3})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset3::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {3, 3}, std::vector{ + 0, 0, 3, 0, 0, 0, 0, 0, 5})) + .testcaseName( + "nonmaxsuppression_suppress_by_IOU"), + + Builder3 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, 0.0, -0.1, 1.0, 0.9, + 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0})) + .scores( + Tensor(ET, {1, 1, 6}, std::vector{ + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{2})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.4f})) + .boxEncoding( + opset3::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {2, 3}, std::vector{ + 0, 0, 3, 0, 0, 0})) + .testcaseName( + "nonmaxsuppression_suppress_by_IOU_and_scores"), + + Builder3 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, 0.0, -0.1, 1.0, 0.9, + 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0})) + .scores( + Tensor(ET, {1, 2, 6}, std::vector{ + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3, 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{2})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset3::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {4, 3}, std::vector{ + 0, 0, 3, 0, 0, 0, 0, 1, 3, 0, 1, 0})) + .testcaseName( + "nonmaxsuppression_two_classes"), + }; + return params; +} + +std::vector generateCombinedParams3() { + const std::vector> generatedParams { + generateParams3(), + generateParams3(), + generateParams3(), + generateParams3(), + generateParams3(), + generateParams3(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +template +std::vector generateParams3WithoutConstants() { + using T = typename element_type_traits::value_type; + using T_BOX = typename element_type_traits::value_type; + using T_TH = typename element_type_traits::value_type; + using T_IND = typename element_type_traits::value_type; + std::vector params { + Builder3 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 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})) + .scores( + Tensor(ET, {1, 1, 6}, std::vector{ + 0.9f, 0.75f, 0.6f, 0.95f, 0.5f, 0.3f})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{1})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.4f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.2f})) + .boxEncoding( + opset3::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {1, 3}, std::vector{0, 0, 3})) + .testcaseName( + "nonmaxsuppression_suppress_by_IOU_and_scores_without_constants"), + }; + return params; +} + +std::vector generateCombinedParams3WithoutConstants() { + const std::vector> generatedParams { + generateParams3WithoutConstants(), + generateParams3WithoutConstants(), + generateParams3WithoutConstants(), + generateParams3WithoutConstants(), + generateParams3WithoutConstants(), + generateParams3WithoutConstants(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_NonMaxSuppression_With_Hardcoded_Refs, ReferenceNonMaxSuppression3Test, + testing::ValuesIn(generateCombinedParams3()), ReferenceNonMaxSuppression3Test::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_NonMaxSuppression_With_Hardcoded_Refs, ReferenceNonMaxSuppression3TestWithoutConstants, + testing::ValuesIn(generateCombinedParams3WithoutConstants()), ReferenceNonMaxSuppression3TestWithoutConstants::getTestCaseName); + + +struct NonMaxSuppression1Params { + Tensor boxes; + Tensor scores; + Tensor maxOutputBoxesPerClass; + Tensor iouThreshold; + Tensor scoreThreshold; + opset1::NonMaxSuppression::BoxEncodingType boxEncoding; + Tensor expectedSelectedIndices; + std::string testcaseName; +}; + +struct Builder1 : ParamsBuilder { + REFERENCE_TESTS_ADD_SET_PARAM(Builder1, boxes); + REFERENCE_TESTS_ADD_SET_PARAM(Builder1, scores); + REFERENCE_TESTS_ADD_SET_PARAM(Builder1, maxOutputBoxesPerClass); + REFERENCE_TESTS_ADD_SET_PARAM(Builder1, iouThreshold); + REFERENCE_TESTS_ADD_SET_PARAM(Builder1, scoreThreshold); + REFERENCE_TESTS_ADD_SET_PARAM(Builder1, boxEncoding); + REFERENCE_TESTS_ADD_SET_PARAM(Builder1, expectedSelectedIndices); + REFERENCE_TESTS_ADD_SET_PARAM(Builder1, testcaseName); +}; + +class ReferenceNonMaxSuppression1Test : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.boxes.data, params.scores.data}; + refOutData = {params.expectedSelectedIndices.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "bType=" << param.boxes.type; + result << "_bShape=" << param.boxes.shape; + result << "_sType=" << param.scores.type; + result << "_sShape=" << param.scores.shape; + result << "_esiType=" << param.expectedSelectedIndices.type; + result << "_esiShape=" << param.expectedSelectedIndices.shape; + if (param.testcaseName != "") { + result << "_=" << param.testcaseName; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const NonMaxSuppression1Params& params) { + const auto boxes = std::make_shared(params.boxes.type, params.boxes.shape); + const auto scores = std::make_shared(params.scores.type, params.scores.shape); + const auto max_output_boxes_per_class = std::make_shared( + params.maxOutputBoxesPerClass.type, params.maxOutputBoxesPerClass.shape, params.maxOutputBoxesPerClass.data.data()); + const auto iou_threshold = std::make_shared( + params.iouThreshold.type, params.iouThreshold.shape, params.iouThreshold.data.data()); + const auto score_threshold = std::make_shared( + params.scoreThreshold.type, params.scoreThreshold.shape, params.scoreThreshold.data.data()); + const auto nms = std::make_shared(boxes, + scores, + max_output_boxes_per_class, + iou_threshold, + score_threshold, + params.boxEncoding, + false); + const auto f = std::make_shared(nms->outputs(), ParameterVector{boxes, scores}); + return f; + } +}; + +class ReferenceNonMaxSuppression1TestWithoutConstants : public ReferenceNonMaxSuppression1Test { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.boxes.data, params.scores.data, params.maxOutputBoxesPerClass.data, + params.iouThreshold.data, params.scoreThreshold.data}; + refOutData = {params.expectedSelectedIndices.data}; + } + +private: + static std::shared_ptr CreateFunction(const NonMaxSuppression1Params& params) { + const auto boxes = std::make_shared(params.boxes.type, params.boxes.shape); + const auto scores = std::make_shared(params.scores.type, params.scores.shape); + const auto max_output_boxes_per_class = std::make_shared( + params.maxOutputBoxesPerClass.type, params.maxOutputBoxesPerClass.shape); + const auto iou_threshold = std::make_shared( + params.iouThreshold.type, params.iouThreshold.shape); + const auto score_threshold = std::make_shared( + params.scoreThreshold.type, params.scoreThreshold.shape); + const auto nms = std::make_shared(boxes, + scores, + max_output_boxes_per_class, + iou_threshold, + score_threshold, + params.boxEncoding, + false); + const auto f = std::make_shared(nms->outputs(), + ParameterVector{boxes, scores, max_output_boxes_per_class, + iou_threshold, score_threshold}); + return f; + } +}; + +TEST_P(ReferenceNonMaxSuppression1Test, CompareWithRefs) { + Exec(); +} + +TEST_P(ReferenceNonMaxSuppression1TestWithoutConstants, CompareWithRefs) { + Exec(); +} + +template +std::vector generateParams1() { + using T = typename element_type_traits::value_type; + using T_BOX = typename element_type_traits::value_type; + using T_TH = typename element_type_traits::value_type; + using T_IND = typename element_type_traits::value_type; + std::vector params { + Builder1 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 0.5, 0.5, 1.0, 1.0, 0.5, 0.6, 1.0, 1.0, 0.5, 0.4, 1.0, 1.0, + 0.5, 10.5, 1.0, 1.0, 0.5, 10.6, 1.0, 1.0, 0.5, 100.5, 1.0, 1.0})) + .scores( + Tensor(ET, {1, 1, 6}, std::vector{ + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{3})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset1::NonMaxSuppression::BoxEncodingType::CENTER) + .expectedSelectedIndices( + Tensor(ET_IND, {3, 3}, std::vector{ + 0, 0, 3, 0, 0, 0, 0, 0, 5})) + .testcaseName( + "nonmaxsuppression_center_point_box_format"), + + Builder1 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 1.0, 1.0, 0.0, 0.0, 0.0, 0.1, 1.0, 1.1, 0.0, 0.9, 1.0, -0.1, + 0.0, 10.0, 1.0, 11.0, 1.0, 10.1, 0.0, 11.1, 1.0, 101.0, 0.0, 100.0})) + .scores( + Tensor(ET, {1, 1, 6}, std::vector{ + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{3})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset1::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {3, 3}, std::vector{ + 0, 0, 3, 0, 0, 0, 0, 0, 5})) + .testcaseName( + "nonmaxsuppression_flipped_coordinates"), + + Builder1 {} + .boxes( + Tensor(ET, {1, 10, 4}, std::vector{ + 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, + 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, + 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0})) + .scores( + Tensor(ET, {1, 1, 10}, std::vector{ + 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{1})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset1::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {1, 3}, std::vector{0, 0, 0})) + .testcaseName( + "nonmaxsuppression_identical_boxes"), + + Builder1 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, 0.0, -0.1, 1.0, 0.9, + 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0})) + .scores( + Tensor(ET, {1, 1, 6}, std::vector{ + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{2})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset1::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {2, 3}, std::vector{0, 0, 3, 0, 0, 0})) + .testcaseName( + "nonmaxsuppression_limit_output_size"), + + Builder1 {} + .boxes( + Tensor(ET, {1, 1, 4}, std::vector{0.0, 0.0, 1.0, 1.0})) + .scores( + Tensor(ET, {1, 1, 1}, std::vector{0.9})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{3})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset1::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {1, 3}, std::vector{0, 0, 0})) + .testcaseName( + "nonmaxsuppression_single_box"), + + Builder1 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, 0.0, -0.1, 1.0, 0.9, + 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0})) + .scores( + Tensor(ET, {1, 1, 6}, std::vector{ + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{3})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset1::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {3, 3}, std::vector{ + 0, 0, 3, 0, 0, 0, 0, 0, 5})) + .testcaseName( + "nonmaxsuppression_suppress_by_IOU"), + + Builder1 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, 0.0, -0.1, 1.0, 0.9, + 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0})) + .scores( + Tensor(ET, {1, 1, 6}, std::vector{ + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{2})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.4f})) + .boxEncoding( + opset1::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {2, 3}, std::vector{ + 0, 0, 3, 0, 0, 0})) + .testcaseName( + "nonmaxsuppression_suppress_by_IOU_and_scores"), + + Builder1 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, 0.0, -0.1, 1.0, 0.9, + 0.0, 10.0, 1.0, 11.0, 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0})) + .scores( + Tensor(ET, {1, 2, 6}, std::vector{ + 0.9, 0.75, 0.6, 0.95, 0.5, 0.3, 0.9, 0.75, 0.6, 0.95, 0.5, 0.3})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{2})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.5f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.0f})) + .boxEncoding( + opset1::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {4, 3}, std::vector{ + 0, 0, 3, 0, 0, 0, 0, 1, 3, 0, 1, 0})) + .testcaseName( + "nonmaxsuppression_two_classes"), + }; + return params; +} + +std::vector generateCombinedParams1() { + const std::vector> generatedParams { + generateParams1(), + generateParams1(), + generateParams1(), + generateParams1(), + generateParams1(), + generateParams1(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +template +std::vector generateParams1WithoutConstants() { + using T = typename element_type_traits::value_type; + using T_BOX = typename element_type_traits::value_type; + using T_TH = typename element_type_traits::value_type; + using T_IND = typename element_type_traits::value_type; + std::vector params { + Builder1 {} + .boxes( + Tensor(ET, {1, 6, 4}, std::vector{ + 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})) + .scores( + Tensor(ET, {1, 1, 6}, std::vector{ + 0.9f, 0.75f, 0.6f, 0.95f, 0.5f, 0.3f})) + .maxOutputBoxesPerClass( + Tensor(ET_BOX, {}, std::vector{1})) + .iouThreshold( + Tensor(ET_TH, {}, std::vector{0.4f})) + .scoreThreshold( + Tensor(ET_TH, {}, std::vector{0.2f})) + .boxEncoding( + opset1::NonMaxSuppression::BoxEncodingType::CORNER) + .expectedSelectedIndices( + Tensor(ET_IND, {1, 3}, std::vector{0, 0, 3})) + .testcaseName( + "nonmaxsuppression_suppress_by_IOU_and_scores_without_constants"), + }; + return params; +} + +std::vector generateCombinedParams1WithoutConstants() { + const std::vector> generatedParams { + generateParams1WithoutConstants(), + generateParams1WithoutConstants(), + generateParams1WithoutConstants(), + generateParams1WithoutConstants(), + generateParams1WithoutConstants(), + generateParams1WithoutConstants(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_NonMaxSuppression_With_Hardcoded_Refs, ReferenceNonMaxSuppression1Test, + testing::ValuesIn(generateCombinedParams1()), ReferenceNonMaxSuppression1Test::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_NonMaxSuppression_With_Hardcoded_Refs, ReferenceNonMaxSuppression1TestWithoutConstants, + testing::ValuesIn(generateCombinedParams1WithoutConstants()), ReferenceNonMaxSuppression1TestWithoutConstants::getTestCaseName); } // namespace diff --git a/docs/template_plugin/tests/functional/skip_tests_config.cpp b/docs/template_plugin/tests/functional/skip_tests_config.cpp index 155ff86f14d..64c181e0918 100644 --- a/docs/template_plugin/tests/functional/skip_tests_config.cpp +++ b/docs/template_plugin/tests/functional/skip_tests_config.cpp @@ -106,6 +106,12 @@ std::vector disabledTestPatterns() { R"(.*ReferenceMulticlassNmsTest.*esiType=i64.*evoType=i64.*)", // CVS-64096 R"(.*ReferenceNonMaxSuppressionTest.*esiType=i32.*evoType=i32.*)", + // CVS-64081 + R"(.*ReferenceNonMaxSuppression4Test.*esiType=i32.*)", + // CVS-64067 + R"(.*ReferenceNonMaxSuppression3Test.*esiType=i32.*)", + // CVS-64034 + R"(.*ReferenceNonMaxSuppression1Test.*esiType=i32.*)", // CVS-64102 R"(.*ReferenceExperimentalPGGLayerTest.*iType=bf16.*stride_x=(32|64).*)", // CVS-72215