[ShapeInference] DetectionOutput shape inference review (#15645)

* Add setter for attributes

* Add more type_prop tests

* Extend shape infer tests for default ctor

* Remove redundant set_output_size and update shapes init

---------

Co-authored-by: Pawel Raasz <pawel.raasz@intel.com>
This commit is contained in:
Katarzyna Mitrus
2023-02-21 11:42:47 +01:00
committed by GitHub
parent 86b50044cd
commit 94b64fed79
4 changed files with 390 additions and 107 deletions

View File

@@ -54,6 +54,9 @@ public:
const Attributes& get_attrs() const {
return m_attrs;
}
void set_attrs(const Attributes& attrs) {
m_attrs = attrs;
}
bool visit_attributes(AttributeVisitor& visitor) override;
private:
@@ -104,6 +107,9 @@ public:
const Attributes& get_attrs() const {
return m_attrs;
}
void set_attrs(const Attributes& attrs) {
m_attrs = attrs;
}
bool visit_attributes(AttributeVisitor& visitor) override;
private:

View File

@@ -4,9 +4,9 @@
#include "ngraph/op/detection_output.hpp"
#include <detection_output_shape_inference.hpp>
#include "detection_output_shape_inference.hpp"
#include "itt.hpp"
#include "openvino/core/validation_util.hpp"
using namespace std;
@@ -35,14 +35,10 @@ void ov::op::v0::DetectionOutput::validate_and_infer_types() {
OV_OP_SCOPE(v0_DetectionOutput_validate_and_infer_types);
NODE_VALIDATION_CHECK(this, m_attrs.num_classes > 0, "Number of classes must be greater than zero");
validate_base(m_attrs);
std::vector<ov::PartialShape> input_shapes;
for (size_t input_idx = 0; input_idx < get_input_size(); input_idx++)
input_shapes.push_back(get_input_partial_shape(input_idx));
std::vector<ov::PartialShape> output_shapes = {ov::PartialShape{}};
const auto input_shapes = get_node_input_partial_shapes(*this);
auto output_shapes = std::vector<ov::PartialShape>(1);
shape_infer(this, input_shapes, output_shapes);
set_output_size(1);
set_output_type(0, get_input_element_type(0), output_shapes[0]);
}
@@ -97,14 +93,10 @@ ov::op::v8::DetectionOutput::DetectionOutput(const Output<Node>& box_logits,
void ov::op::v8::DetectionOutput::validate_and_infer_types() {
OV_OP_SCOPE(v8_DetectionOutput_validate_and_infer_types);
validate_base(m_attrs);
std::vector<ov::PartialShape> input_shapes;
for (size_t input_idx = 0; input_idx < get_input_size(); input_idx++)
input_shapes.push_back(get_input_partial_shape(input_idx));
std::vector<ov::PartialShape> output_shapes = {ov::PartialShape{}};
const auto input_shapes = get_node_input_partial_shapes(*this);
auto output_shapes = std::vector<ov::PartialShape>(1);
shape_infer(this, input_shapes, output_shapes);
set_output_size(1);
set_output_type(0, get_input_element_type(0), output_shapes[0]);
}

View File

@@ -6,22 +6,36 @@
#include <memory>
#include "dimension_tracker.hpp"
#include "gtest/gtest.h"
#include "ngraph/ngraph.hpp"
#include "openvino/util/common_util.hpp"
#include "util/type_prop.hpp"
using namespace std;
using namespace ngraph;
using namespace testing;
// ------------------------------ V0 ------------------------------
std::shared_ptr<op::DetectionOutput> create_detection_output(const PartialShape& box_logits_shape,
const PartialShape& class_preds_shape,
const PartialShape& proposals_shape,
const PartialShape& aux_class_preds_shape,
const PartialShape& aux_box_preds_shape,
std::shared_ptr<op::DetectionOutput> create_detection_output(PartialShape box_logits_shape,
PartialShape class_preds_shape,
PartialShape proposals_shape,
PartialShape aux_class_preds_shape,
PartialShape aux_box_preds_shape,
const op::DetectionOutputAttrs& attrs,
element::Type input_type,
element::Type proposals_type) {
element::Type proposals_type,
bool set_labels = false) {
if (set_labels) {
// The labels are set for all of the shapes,
// but the output dimension is always a product of multiplication, so labels are not preserved
set_shape_labels(box_logits_shape, 10);
set_shape_labels(class_preds_shape, 20);
set_shape_labels(proposals_shape, 30);
set_shape_labels(aux_class_preds_shape, 40);
set_shape_labels(aux_box_preds_shape, 50);
}
auto box_logits = make_shared<op::Parameter>(input_type, box_logits_shape);
auto class_preds = make_shared<op::Parameter>(input_type, class_preds_shape);
auto proposals = make_shared<op::Parameter>(proposals_type, proposals_shape);
@@ -30,7 +44,41 @@ std::shared_ptr<op::DetectionOutput> create_detection_output(const PartialShape&
return make_shared<op::DetectionOutput>(box_logits, class_preds, proposals, aux_class_preds, aux_box_preds, attrs);
}
TEST(type_prop_layers, detection_output) {
TEST(type_prop_layers, detection_output_v0_default_ctor) {
auto op = make_shared<op::v8::DetectionOutput>();
auto input_type = element::f32;
auto box_logits = make_shared<op::Parameter>(input_type, PartialShape{4, 20});
auto class_preds = make_shared<op::Parameter>(input_type, PartialShape{4, 10});
auto proposals = make_shared<op::Parameter>(input_type, PartialShape{4, 2, 20});
auto ad_class_preds = make_shared<op::Parameter>(input_type, PartialShape{4, 10});
auto ad_box_preds = make_shared<op::Parameter>(input_type, PartialShape{4, 20});
op::DetectionOutputAttrs attrs;
attrs.keep_top_k = {-1};
attrs.top_k = 7;
attrs.num_classes = 2;
attrs.normalized = true;
op->set_attrs(attrs);
op->set_arguments(OutputVector{box_logits, class_preds, proposals, ad_class_preds, ad_box_preds});
op->validate_and_infer_types();
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{1, 1, 56, 7}));
EXPECT_EQ(op->get_element_type(), element::f32);
attrs.keep_top_k = {-1};
attrs.top_k = -1;
op->set_attrs(attrs);
op->validate_and_infer_types();
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{1, 1, 40, 7}));
EXPECT_EQ(op->get_element_type(), element::f32);
}
TEST(type_prop_layers, detection_output_basic) {
op::DetectionOutputAttrs attrs;
attrs.keep_top_k = {200};
attrs.num_classes = 2;
@@ -43,11 +91,76 @@ TEST(type_prop_layers, detection_output) {
attrs,
element::f32,
element::f32);
ASSERT_EQ(op->get_shape(), (Shape{1, 1, 800, 7}));
ASSERT_EQ(op->get_element_type(), element::f32);
EXPECT_EQ(op->get_shape(), (Shape{1, 1, 800, 7}));
EXPECT_EQ(op->get_element_type(), element::f32);
}
TEST(type_prop_layers, detection_output_f16) {
TEST(type_prop_layers, detection_output_interval_labeled_keep_top_k) {
op::DetectionOutputAttrs attrs;
attrs.keep_top_k = {60};
attrs.num_classes = 3;
attrs.normalized = true;
auto op = create_detection_output(PartialShape{{2, 4}, {1, 20}},
PartialShape{{2, 4}, {1, 10}},
PartialShape{-1, 2, 20},
PartialShape{-1, 10},
PartialShape{-1, 20},
attrs,
element::f32,
element::f32,
true); // set labels
// [1, 1, N * keep_top_k[0], 7]
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{1, 1, {120, 240}, 7}));
EXPECT_THAT(get_shape_labels(op->get_output_partial_shape(0)), Each(ov::no_label));
EXPECT_EQ(op->get_element_type(), element::f32);
}
TEST(type_prop_layers, detection_output_interval_labeled_top_k) {
op::DetectionOutputAttrs attrs;
attrs.keep_top_k = {-1};
attrs.top_k = 80;
attrs.num_classes = 3;
attrs.normalized = true;
auto op = create_detection_output(PartialShape{{2, 4}, {1, 20}},
PartialShape{{2, 4}, {1, 10}},
PartialShape{-1, 2, 20},
PartialShape{-1, 10},
PartialShape{-1, 20},
attrs,
element::f32,
element::f32,
true); // set labels
// [1, 1, N * top_k * num_classes, 7]
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{1, 1, {480, 960}, 7}));
EXPECT_THAT(get_shape_labels(op->get_output_partial_shape(0)), Each(ov::no_label));
EXPECT_EQ(op->get_element_type(), element::f32);
}
TEST(type_prop_layers, detection_output_interval_labeled_negative_both_topk) {
op::DetectionOutputAttrs attrs;
attrs.keep_top_k = {-1};
attrs.top_k = -1;
attrs.num_classes = 3;
attrs.normalized = true;
auto op = create_detection_output(PartialShape{{2, 4}, {1, 20}},
PartialShape{{2, 4}, {1, 10}},
PartialShape{-1, 2, 20},
PartialShape{-1, 10},
PartialShape{-1, 20},
attrs,
element::f32,
element::f32,
true); // set labels
// [1, 1, N * num_classes * num_prior_boxes, 7] // num_prior_boxex = 5
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{1, 1, {30, 60}, 7}));
EXPECT_THAT(get_shape_labels(op->get_output_partial_shape(0)), Each(ov::no_label));
EXPECT_EQ(op->get_element_type(), element::f32);
}
TEST(type_prop_layers, detection_output_v0_f16) {
op::DetectionOutputAttrs attrs;
attrs.keep_top_k = {200};
attrs.num_classes = 2;
@@ -60,8 +173,8 @@ TEST(type_prop_layers, detection_output_f16) {
attrs,
element::f16,
element::f16);
ASSERT_EQ(op->get_shape(), (Shape{1, 1, 800, 7}));
ASSERT_EQ(op->get_element_type(), element::f16);
EXPECT_EQ(op->get_shape(), (Shape{1, 1, 800, 7}));
EXPECT_EQ(op->get_element_type(), element::f16);
}
TEST(type_prop_layers, detection_f16_with_proposals_f32) {
@@ -77,11 +190,11 @@ TEST(type_prop_layers, detection_f16_with_proposals_f32) {
attrs,
element::f16,
element::f32);
ASSERT_EQ(op->get_shape(), (Shape{1, 1, 800, 7}));
ASSERT_EQ(op->get_element_type(), element::f16);
EXPECT_EQ(op->get_shape(), (Shape{1, 1, 800, 7}));
EXPECT_EQ(op->get_element_type(), element::f16);
}
TEST(type_prop_layers, detection_output_not_normalized) {
TEST(type_prop_layers, detection_output_v0_not_normalized) {
op::DetectionOutputAttrs attrs;
attrs.keep_top_k = {200};
attrs.num_classes = 2;
@@ -94,11 +207,11 @@ TEST(type_prop_layers, detection_output_not_normalized) {
attrs,
element::f32,
element::f32);
ASSERT_EQ(op->get_shape(), (Shape{1, 1, 800, 7}));
ASSERT_EQ(op->get_element_type(), element::f32);
EXPECT_EQ(op->get_shape(), (Shape{1, 1, 800, 7}));
EXPECT_EQ(op->get_element_type(), element::f32);
}
TEST(type_prop_layers, detection_output_negative_keep_top_k) {
TEST(type_prop_layers, detection_output_v0_negative_keep_top_k) {
op::DetectionOutputAttrs attrs;
attrs.keep_top_k = {-1};
attrs.top_k = -1;
@@ -112,11 +225,11 @@ TEST(type_prop_layers, detection_output_negative_keep_top_k) {
attrs,
element::f32,
element::f32);
ASSERT_EQ(op->get_shape(), (Shape{1, 1, 40, 7}));
ASSERT_EQ(op->get_element_type(), element::f32);
EXPECT_EQ(op->get_shape(), (Shape{1, 1, 40, 7}));
EXPECT_EQ(op->get_element_type(), element::f32);
}
TEST(type_prop_layers, detection_output_no_share_location) {
TEST(type_prop_layers, detection_output_v0_no_share_location) {
op::DetectionOutputAttrs attrs;
attrs.keep_top_k = {-1};
attrs.top_k = -1;
@@ -131,11 +244,11 @@ TEST(type_prop_layers, detection_output_no_share_location) {
attrs,
element::f32,
element::f32);
ASSERT_EQ(op->get_shape(), (Shape{1, 1, 40, 7}));
ASSERT_EQ(op->get_element_type(), element::f32);
EXPECT_EQ(op->get_shape(), (Shape{1, 1, 40, 7}));
EXPECT_EQ(op->get_element_type(), element::f32);
}
TEST(type_prop_layers, detection_output_calculated_num_prior_boxes) {
TEST(type_prop_layers, detection_output_v0_calculated_num_prior_boxes) {
op::DetectionOutputAttrs attrs;
attrs.keep_top_k = {-1};
attrs.top_k = -1;
@@ -150,11 +263,11 @@ TEST(type_prop_layers, detection_output_calculated_num_prior_boxes) {
attrs,
element::f32,
element::f32);
ASSERT_EQ(op->get_shape(), (Shape{1, 1, 80, 7}));
ASSERT_EQ(op->get_element_type(), element::f32);
EXPECT_EQ(op->get_shape(), (Shape{1, 1, 80, 7}));
EXPECT_EQ(op->get_element_type(), element::f32);
}
TEST(type_prop_layers, detection_output_top_k) {
TEST(type_prop_layers, detection_output_v0_top_k) {
op::DetectionOutputAttrs attrs;
attrs.keep_top_k = {-1};
attrs.top_k = 7;
@@ -168,11 +281,11 @@ TEST(type_prop_layers, detection_output_top_k) {
attrs,
element::f32,
element::f32);
ASSERT_EQ(op->get_shape(), (Shape{1, 1, 56, 7}));
ASSERT_EQ(op->get_element_type(), element::f32);
EXPECT_EQ(op->get_shape(), (Shape{1, 1, 56, 7}));
EXPECT_EQ(op->get_element_type(), element::f32);
}
TEST(type_prop_layers, detection_output_all_dynamic_shapes) {
TEST(type_prop_layers, detection_output_v0_all_dynamic_shapes) {
PartialShape dyn_shape = PartialShape::dynamic();
op::DetectionOutputAttrs attrs;
attrs.keep_top_k = {-1};
@@ -185,11 +298,11 @@ TEST(type_prop_layers, detection_output_all_dynamic_shapes) {
attrs,
element::f32,
element::f32);
ASSERT_EQ(op->get_output_partial_shape(0), (PartialShape{1, 1, Dimension::dynamic(), 7}));
ASSERT_EQ(op->get_element_type(), element::f32);
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{1, 1, Dimension::dynamic(), 7}));
EXPECT_EQ(op->get_element_type(), element::f32);
}
TEST(type_prop_layers, detection_output_dynamic_batch) {
TEST(type_prop_layers, detection_output_v0_dynamic_batch) {
op::DetectionOutputAttrs attrs;
attrs.keep_top_k = {200};
attrs.num_classes = 2;
@@ -202,8 +315,8 @@ TEST(type_prop_layers, detection_output_dynamic_batch) {
attrs,
element::f32,
element::f32);
ASSERT_EQ(op->get_output_partial_shape(0), (PartialShape{{1, 1, Dimension::dynamic(), 7}}));
ASSERT_EQ(op->get_element_type(), element::f32);
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{{1, 1, Dimension::dynamic(), 7}}));
EXPECT_EQ(op->get_element_type(), element::f32);
}
void detection_output_invalid_data_type_test(element::Type box_logits_et,
@@ -232,7 +345,7 @@ void detection_output_invalid_data_type_test(element::Type box_logits_et,
}
}
TEST(type_prop_layers, detection_output_invalid_data_type) {
TEST(type_prop_layers, detection_output_v0_invalid_data_type) {
detection_output_invalid_data_type_test(element::i32,
element::f32,
element::f32,
@@ -268,7 +381,7 @@ TEST(type_prop_layers, detection_output_invalid_data_type) {
"same as box logits data type (f32). Got i32");
}
TEST(type_prop_layers, detection_output_mismatched_batch_size) {
TEST(type_prop_layers, detection_output_v0_mismatched_batch_size) {
{
try {
op::DetectionOutputAttrs attrs;
@@ -316,7 +429,7 @@ TEST(type_prop_layers, detection_output_mismatched_batch_size) {
}
}
TEST(type_prop_layers, detection_output_invalid_ranks) {
TEST(type_prop_layers, detection_output_v0_invalid_ranks) {
{
try {
op::DetectionOutputAttrs attrs;
@@ -382,7 +495,7 @@ TEST(type_prop_layers, detection_output_invalid_ranks) {
}
}
TEST(type_prop_layers, detection_output_invalid_box_logits_shape) {
TEST(type_prop_layers, detection_output_v0_invalid_box_logits_shape) {
// share_location = true
{
try {
@@ -437,7 +550,7 @@ TEST(type_prop_layers, detection_output_invalid_box_logits_shape) {
}
}
TEST(type_prop_layers, detection_output_invalid_class_preds_shape) {
TEST(type_prop_layers, detection_output_v0_invalid_class_preds_shape) {
try {
op::DetectionOutputAttrs attrs;
attrs.keep_top_k = {-1};
@@ -460,7 +573,7 @@ TEST(type_prop_layers, detection_output_invalid_class_preds_shape) {
}
}
TEST(type_prop_layers, detection_output_invalid_proposals_shape) {
TEST(type_prop_layers, detection_output_v0_invalid_proposals_shape) {
// variance_encoded_in_target = false
{
try {
@@ -567,7 +680,7 @@ TEST(type_prop_layers, detection_output_invalid_proposals_shape) {
}
}
TEST(type_prop_layers, detection_output_invalid_aux_class_preds) {
TEST(type_prop_layers, detection_output_v0_invalid_aux_class_preds) {
// invalid batch size
{
try {
@@ -623,7 +736,7 @@ TEST(type_prop_layers, detection_output_invalid_aux_class_preds) {
}
}
TEST(type_prop_layers, detection_output_invalid_aux_box_preds) {
TEST(type_prop_layers, detection_output_v0_invalid_aux_box_preds) {
// invalid batch size
{
try {
@@ -680,24 +793,44 @@ TEST(type_prop_layers, detection_output_invalid_aux_box_preds) {
// ------------------------------ V8 ------------------------------
namespace {
std::shared_ptr<op::v8::DetectionOutput> create_detection_output_v8(const PartialShape& box_logits_shape,
const PartialShape& class_preds_shape,
const PartialShape& proposals_shape,
std::shared_ptr<op::v8::DetectionOutput> create_detection_output_v8(PartialShape box_logits_shape,
PartialShape class_preds_shape,
PartialShape proposals_shape,
const op::v8::DetectionOutput::Attributes& attrs,
element::Type input_type) {
element::Type input_type,
bool set_labels = false) {
if (set_labels) {
// The labels are set for all of the shapes,
// but the output dimension is always a product of multiplication, so labels are not preserved
set_shape_labels(box_logits_shape, 10);
set_shape_labels(class_preds_shape, 20);
set_shape_labels(proposals_shape, 30);
}
auto box_logits = make_shared<op::Parameter>(input_type, box_logits_shape);
auto class_preds = make_shared<op::Parameter>(input_type, class_preds_shape);
auto proposals = make_shared<op::Parameter>(input_type, proposals_shape);
return make_shared<op::v8::DetectionOutput>(box_logits, class_preds, proposals, attrs);
}
std::shared_ptr<op::v8::DetectionOutput> create_detection_output2_v8(const PartialShape& box_logits_shape,
const PartialShape& class_preds_shape,
const PartialShape& proposals_shape,
const PartialShape& aux_class_preds_shape,
const PartialShape& aux_box_preds_shape,
std::shared_ptr<op::v8::DetectionOutput> create_detection_output2_v8(PartialShape box_logits_shape,
PartialShape class_preds_shape,
PartialShape proposals_shape,
PartialShape aux_class_preds_shape,
PartialShape aux_box_preds_shape,
const op::v8::DetectionOutput::Attributes& attrs,
element::Type input_type) {
element::Type input_type,
bool set_labels = false) {
if (set_labels) {
// The labels are set for all of the shapes,
// but the output dimension is always a product of multiplication, so labels are not preserved
set_shape_labels(box_logits_shape, 10);
set_shape_labels(class_preds_shape, 20);
set_shape_labels(proposals_shape, 30);
set_shape_labels(aux_class_preds_shape, 40);
set_shape_labels(aux_box_preds_shape, 50);
}
auto box_logits = make_shared<op::Parameter>(input_type, box_logits_shape);
auto class_preds = make_shared<op::Parameter>(input_type, class_preds_shape);
auto proposals = make_shared<op::Parameter>(input_type, proposals_shape);
@@ -750,13 +883,10 @@ std::vector<op::v8::DetectionOutput::Attributes> create_attributes_vector() {
}
} // namespace
TEST(type_prop_layers, detection_outputv8_all_static) {
TEST(type_prop_layers, detection_output_v8_all_static) {
// this case covers deducing a number of classes value
// since this value is not saved in attributes
op::v8::DetectionOutput::Attributes attrs;
// initialize attributes affecting shape inference
// others remain by default
Dimension N = 5;
Dimension num_prior_boxes = 100;
Dimension priors_batch_size = N;
@@ -776,16 +906,12 @@ TEST(type_prop_layers, detection_outputv8_all_static) {
compute_reference_output_shape(attrs.keep_top_k, attrs.top_k, N, num_classes, num_prior_boxes);
auto op = create_detection_output_v8(box_logits_shape, class_preds_shape, proposals_shape, attrs, element::f32);
ASSERT_EQ(op->get_output_partial_shape(0), output_shape_reference);
ASSERT_EQ(op->get_element_type(), element::f32);
EXPECT_EQ(op->get_output_partial_shape(0), output_shape_reference);
EXPECT_EQ(op->get_element_type(), element::f32);
}
}
TEST(type_prop_layers, detection_outputv8_dynamic) {
op::v8::DetectionOutput::Attributes attrs;
// initialize attributes affecting shape inference
// others remain by default
TEST(type_prop_layers, detection_output_v8_dynamic) {
Dimension N = 13;
Dimension num_prior_boxes = 33;
Dimension priors_batch_size = 1;
@@ -804,16 +930,12 @@ TEST(type_prop_layers, detection_outputv8_dynamic) {
compute_reference_output_shape(attrs.keep_top_k, attrs.top_k, N, num_classes, num_prior_boxes);
auto op = create_detection_output_v8(box_logits_shape, class_preds_shape, proposals_shape, attrs, element::f32);
ASSERT_EQ(op->get_output_partial_shape(0), output_shape_reference);
ASSERT_EQ(op->get_element_type(), element::f32);
EXPECT_EQ(op->get_output_partial_shape(0), output_shape_reference);
EXPECT_EQ(op->get_element_type(), element::f32);
}
}
TEST(type_prop_layers, detection_outputv8_num_classes_not_deduced) {
op::v8::DetectionOutput::Attributes attrs;
// initialize attributes affecting shape inference
// others remain by default
TEST(type_prop_layers, detection_output_v8_num_classes_not_deduced) {
Dimension N = 13;
Dimension num_prior_boxes = 33;
Dimension priors_batch_size = 1;
@@ -831,17 +953,13 @@ TEST(type_prop_layers, detection_outputv8_num_classes_not_deduced) {
compute_reference_output_shape(attrs.keep_top_k, attrs.top_k, N, Dimension::dynamic(), num_prior_boxes);
auto op = create_detection_output_v8(box_logits_shape, class_preds_shape, proposals_shape, attrs, element::f32);
ASSERT_EQ(op->get_output_partial_shape(0), output_shape_reference);
ASSERT_EQ(op->get_element_type(), element::f32);
EXPECT_EQ(op->get_output_partial_shape(0), output_shape_reference);
EXPECT_EQ(op->get_element_type(), element::f32);
}
}
TEST(type_prop_layers, detection_outputv8_num_classes_no_deduction) {
TEST(type_prop_layers, detection_output_v8_num_classes_no_deduction) {
// In this case a number of classes and a number of prior boxes are not deduced
op::v8::DetectionOutput::Attributes attrs;
// initialize attributes affecting shape inference
// others remain by default
Dimension N = 3;
Dimension priors_batch_size = N;
@@ -859,18 +977,14 @@ TEST(type_prop_layers, detection_outputv8_num_classes_no_deduction) {
Dimension::dynamic());
auto op = create_detection_output_v8(box_logits_shape, class_preds_shape, proposals_shape, attrs, element::f32);
ASSERT_EQ(op->get_output_partial_shape(0), output_shape_reference);
ASSERT_EQ(op->get_element_type(), element::f32);
EXPECT_EQ(op->get_output_partial_shape(0), output_shape_reference);
EXPECT_EQ(op->get_element_type(), element::f32);
}
}
TEST(type_prop_layers, detection_outputv8_dynamic2) {
TEST(type_prop_layers, detection_output_v8_dynamic2) {
// In this case a number of prior boxes is deduced using additional input
// and after that a number of classes is deduced using the second input shape
op::v8::DetectionOutput::Attributes attrs;
// initialize attributes affecting shape inference
// others remain by default
Dimension N = 13;
Dimension num_prior_boxes = 33;
Dimension priors_batch_size = 1;
@@ -895,7 +1009,137 @@ TEST(type_prop_layers, detection_outputv8_dynamic2) {
ad_box_preds_shape,
attrs,
element::f32);
ASSERT_EQ(op->get_output_partial_shape(0), output_shape_reference);
ASSERT_EQ(op->get_element_type(), element::f32);
EXPECT_EQ(op->get_output_partial_shape(0), output_shape_reference);
EXPECT_EQ(op->get_element_type(), element::f32);
}
}
TEST(type_prop_layers, detection_output_v8_intervals_3in) {
auto N = Dimension(2, 4);
auto priors_batch_size = N;
auto num_prior_boxes = Dimension(8, 10);
auto attrs_vector = create_attributes_vector();
for (const auto& attrs : attrs_vector) {
Dimension prior_box_size = attrs.normalized ? 4 : 5;
PartialShape box_logits_shape{N, {40, 240}};
PartialShape class_preds_shape = {N, {10, 60}};
PartialShape proposals_shape = {priors_batch_size,
attrs.variance_encoded_in_target ? 1 : 2,
prior_box_size * num_prior_boxes};
PartialShape output_shape_reference = compute_reference_output_shape(attrs.keep_top_k,
attrs.top_k,
N,
Dimension::dynamic(),
Dimension::dynamic());
auto op =
create_detection_output_v8(box_logits_shape, class_preds_shape, proposals_shape, attrs, element::f32, true);
EXPECT_EQ(op->get_output_partial_shape(0), output_shape_reference)
<< "Failed for keep_top_k=" << ov::util::vector_to_string(attrs.keep_top_k) << " top_k=" << attrs.top_k
<< " and variance_encoded_in_target=" << attrs.variance_encoded_in_target << std::endl;
EXPECT_THAT(get_shape_labels(op->get_output_partial_shape(0)), Each(ov::no_label));
EXPECT_EQ(op->get_element_type(), element::f32);
}
}
TEST(type_prop_layers, detection_output_v8_interval_batch_3in) {
auto N = Dimension(2, 4);
auto priors_batch_size = N;
auto num_prior_boxes = Dimension(6);
auto num_classes = Dimension(10);
auto attrs_vector = create_attributes_vector();
for (const auto& attrs : attrs_vector) {
Dimension num_loc_classes = attrs.share_location ? 1 : num_classes;
Dimension prior_box_size = attrs.normalized ? 4 : 5;
PartialShape box_logits_shape = {N, num_prior_boxes * num_loc_classes * 4};
PartialShape class_preds_shape = {N, num_prior_boxes * num_classes};
PartialShape proposals_shape = {priors_batch_size,
attrs.variance_encoded_in_target ? 1 : 2,
num_prior_boxes * prior_box_size};
PartialShape output_shape_reference =
compute_reference_output_shape(attrs.keep_top_k, attrs.top_k, N, num_classes, num_prior_boxes);
auto op =
create_detection_output_v8(box_logits_shape, class_preds_shape, proposals_shape, attrs, element::f32, true);
EXPECT_EQ(op->get_output_partial_shape(0), output_shape_reference)
<< "Failed for keep_top_k=" << ov::util::vector_to_string(attrs.keep_top_k) << " top_k=" << attrs.top_k
<< " and variance_encoded_in_target=" << attrs.variance_encoded_in_target << std::endl;
EXPECT_THAT(get_shape_labels(op->get_output_partial_shape(0)), Each(ov::no_label));
EXPECT_EQ(op->get_element_type(), element::f32);
}
}
TEST(type_prop_layers, detection_output_v8_interval_batch_5in) {
auto N = Dimension(2, 4);
auto priors_batch_size = Dimension(1, 2);
auto num_prior_boxes = Dimension(6);
auto num_classes = Dimension(10);
auto attrs_vector = create_attributes_vector();
for (const auto& attrs : attrs_vector) {
Dimension num_loc_classes = attrs.share_location ? 1 : num_classes;
Dimension prior_box_size = attrs.normalized ? 4 : 5;
PartialShape box_logits_shape = {N, num_prior_boxes * num_loc_classes * 4};
PartialShape class_preds_shape = {N, num_prior_boxes * num_classes};
PartialShape proposals_shape = {priors_batch_size,
attrs.variance_encoded_in_target ? 1 : 2,
num_prior_boxes * prior_box_size};
PartialShape ad_class_preds_shape = {N, num_prior_boxes * 2};
PartialShape output_shape_reference =
compute_reference_output_shape(attrs.keep_top_k, attrs.top_k, N, num_classes, num_prior_boxes);
auto op =
create_detection_output_v8(box_logits_shape, class_preds_shape, proposals_shape, attrs, element::f32, true);
EXPECT_EQ(op->get_output_partial_shape(0), output_shape_reference)
<< "Failed for keep_top_k=" << ov::util::vector_to_string(attrs.keep_top_k) << " top_k=" << attrs.top_k
<< " and variance_encoded_in_target=" << attrs.variance_encoded_in_target << std::endl;
EXPECT_THAT(get_shape_labels(op->get_output_partial_shape(0)), Each(ov::no_label));
EXPECT_EQ(op->get_element_type(), element::f32);
}
}
TEST(type_prop_layers, detection_output_v8_default_ctor) {
Dimension N = 13;
Dimension num_prior_boxes = 33;
Dimension priors_batch_size = 1;
Dimension num_classes = 10;
for (const auto& attrs : create_attributes_vector()) {
Dimension num_loc_classes = attrs.share_location ? 1 : num_classes;
Dimension prior_box_size = attrs.normalized ? 4 : 5;
PartialShape box_logits_shape = {N, num_prior_boxes * num_loc_classes * 4};
PartialShape class_preds_shape = {N, num_prior_boxes * num_classes};
PartialShape proposals_shape = {priors_batch_size,
attrs.variance_encoded_in_target ? 1 : 2,
num_prior_boxes * prior_box_size};
PartialShape ad_class_preds_shape = {N, num_prior_boxes * 2};
PartialShape output_shape_reference =
compute_reference_output_shape(attrs.keep_top_k, attrs.top_k, N, num_classes, num_prior_boxes);
auto input_type = element::f32;
auto box_logits = make_shared<op::Parameter>(input_type, box_logits_shape);
auto class_preds = make_shared<op::Parameter>(input_type, class_preds_shape);
auto proposals = make_shared<op::Parameter>(input_type, proposals_shape);
auto ad_class_preds = make_shared<op::Parameter>(input_type, ad_class_preds_shape);
auto ad_box_preds = make_shared<op::Parameter>(input_type, box_logits_shape);
auto op = make_shared<op::v8::DetectionOutput>();
op->set_attrs(attrs);
op->set_arguments(OutputVector{box_logits, class_preds, proposals, ad_class_preds, ad_box_preds});
op->validate_and_infer_types();
EXPECT_EQ(op->get_output_partial_shape(0), output_shape_reference);
EXPECT_EQ(op->get_element_type(), element::f32);
}
}

View File

@@ -9,6 +9,8 @@
#include <utils/shape_inference/shape_inference.hpp>
#include "utils/shape_inference/static_shape.hpp"
#include "detection_output_shape_inference.hpp"
using namespace ov;
using namespace ov::intel_cpu;
@@ -30,7 +32,7 @@ std::shared_ptr<Node> create_detection_output(const PartialShape& box_logits_sha
return std::make_shared<T1>(box_logits, class_preds, proposals, aux_class_preds, aux_box_preds, attrs);
}
TEST(StaticShapeInferenceTest, detection_output_top_k) {
TEST(StaticShapeInferenceTest, detection_output_v0_top_k) {
op::v0::DetectionOutput::Attributes attrs;
attrs.keep_top_k = {-1};
attrs.top_k = 7;
@@ -55,7 +57,7 @@ TEST(StaticShapeInferenceTest, detection_output_top_k) {
ASSERT_EQ(output_shapes[0], StaticShape({1, 1, 56, 7}));
}
TEST(StaticShapeInferenceTest, detection_output_no_share_location) {
TEST(StaticShapeInferenceTest, detection_output_v0_no_share_location) {
op::v0::DetectionOutput::Attributes attrs;
attrs.keep_top_k = {-1};
attrs.top_k = -1;
@@ -81,7 +83,7 @@ TEST(StaticShapeInferenceTest, detection_output_no_share_location) {
ASSERT_EQ(output_shapes[0], StaticShape({1, 1, 40, 7}));
}
TEST(StaticShapeInferenceTest, detection_output) {
TEST(StaticShapeInferenceTest, detection_output_v0_basic) {
op::v0::DetectionOutput::Attributes attrs;
attrs.keep_top_k = {200};
attrs.num_classes = 2;
@@ -105,7 +107,27 @@ TEST(StaticShapeInferenceTest, detection_output) {
ASSERT_EQ(output_shapes[0], (StaticShape{1, 1, 800, 7}));
}
TEST(StaticShapeInferenceTest, detection_outputv8_top_k) {
TEST(StaticShapeInferenceTest, detection_output_v0_default_ctor) {
auto op = std::make_shared<op::v0::DetectionOutput>();
op::v0::DetectionOutput::Attributes attrs;
attrs.keep_top_k = {200};
attrs.num_classes = 2;
attrs.normalized = true;
op->set_attrs(attrs);
const std::vector<StaticShape> input_shapes = {StaticShape{4, 20},
StaticShape{4, 10},
StaticShape{4, 2, 20},
StaticShape{4, 10},
StaticShape{4, 20}};
std::vector<StaticShape> output_shapes = {StaticShape{}};
shape_infer(op.get(), input_shapes, output_shapes);
EXPECT_EQ(output_shapes[0], (StaticShape{1, 1, 800, 7}));
}
TEST(StaticShapeInferenceTest, detection_output_v8_top_k) {
op::v8::DetectionOutput::Attributes attrs;
attrs.keep_top_k = {-1};
attrs.top_k = 7;
@@ -129,7 +151,7 @@ TEST(StaticShapeInferenceTest, detection_outputv8_top_k) {
ASSERT_EQ(output_shapes[0], StaticShape({1, 1, 56, 7}));
}
TEST(StaticShapeInferenceTest, detection_outputv8_no_share_location) {
TEST(StaticShapeInferenceTest, detection_output_v8_no_share_location) {
op::v8::DetectionOutput::Attributes attrs;
attrs.keep_top_k = {-1};
attrs.top_k = -1;
@@ -154,7 +176,7 @@ TEST(StaticShapeInferenceTest, detection_outputv8_no_share_location) {
ASSERT_EQ(output_shapes[0], StaticShape({1, 1, 40, 7}));
}
TEST(StaticShapeInferenceTest, detection_output_v8) {
TEST(StaticShapeInferenceTest, detection_output_v8_basic) {
op::v8::DetectionOutput::Attributes attrs;
attrs.keep_top_k = {200};
attrs.normalized = true;
@@ -176,3 +198,22 @@ TEST(StaticShapeInferenceTest, detection_output_v8) {
shape_inference(op.get(), input_shapes, output_shapes);
ASSERT_EQ(output_shapes[0], (StaticShape{1, 1, 800, 7}));
}
TEST(StaticShapeInferenceTest, detection_output_v8_default_ctor) {
auto op = std::make_shared<op::v8::DetectionOutput>();
op::v8::DetectionOutput::Attributes attrs;
attrs.keep_top_k = {200};
attrs.normalized = true;
op->set_attrs(attrs);
const std::vector<StaticShape> input_shapes = {StaticShape{4, 20},
StaticShape{4, 10},
StaticShape{4, 2, 20},
StaticShape{4, 10},
StaticShape{4, 20}};
std::vector<StaticShape> output_shapes = {StaticShape{}};
shape_infer(op.get(), input_shapes, output_shapes);
EXPECT_EQ(output_shapes[0], (StaticShape{1, 1, 800, 7}));
}