Review ROIPooling class for shape inference aspects (#16403)
* Review ROIPooling class - check interval shape and label propagation - add template shape_infer - add shape infer into cpu plugin - add test with StaticShape * Use get_output_roi instead of get_output_size * Add missing includes
This commit is contained in:
1 parent
82a992b95d
commit
63797db257
8 files changed
+384
-156
No files matched your search
@@ -34,12 +34,30 @@ public:
|
||||
|
||||
std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override;
|
||||
|
||||
/// \brief Set the output ROI feature map (pooled_h, pooled_w).
|
||||
/// \param output_size Shape with pooling attributes pooled_h and pooled_w sizes.
|
||||
void set_output_roi(Shape output_size);
|
||||
|
||||
/// \brief Get the output ROI feature map shape (H x W)
|
||||
/// \return Shape with pooled_h and pooled_w attributes.
|
||||
const Shape& get_output_roi() const;
|
||||
|
||||
OPENVINO_DEPRECATED("Use 'get_output_roi' instead. Use of this member can be ambiguous with Node base "
|
||||
"'get_output_size' which return number of outputs.")
|
||||
const Shape& get_output_size() const {
|
||||
return m_output_size;
|
||||
}
|
||||
|
||||
/// \brief Set the spatial scale value.
|
||||
/// \param scale Scale value to set.
|
||||
void set_spatial_scale(float scale);
|
||||
float get_spatial_scale() const {
|
||||
return m_spatial_scale;
|
||||
}
|
||||
|
||||
/// \brief Set the method of pooling
|
||||
/// \param method_name Pooling method name.
|
||||
void set_method(std::string method_name);
|
||||
const std::string& get_method() const {
|
||||
return m_method;
|
||||
}
|
||||
@@ -47,7 +65,7 @@ public:
|
||||
|
||||
private:
|
||||
Shape m_output_size{0, 0};
|
||||
float m_spatial_scale{0};
|
||||
float m_spatial_scale{0.0f};
|
||||
std::string m_method = "max";
|
||||
};
|
||||
} // namespace v0
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
// Copyright (C) 2018-2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "compare.hpp"
|
||||
#include "dimension_util.hpp"
|
||||
#include "openvino/op/roi_pooling.hpp"
|
||||
|
||||
namespace ov {
|
||||
namespace op {
|
||||
namespace pooling {
|
||||
namespace validate {
|
||||
template <class TROIPooling, class TShape>
|
||||
void rois_input_shape(const TROIPooling* op, const TShape rois_shape) {
|
||||
if (rois_shape.rank().is_static()) {
|
||||
NODE_VALIDATION_CHECK(op,
|
||||
rois_shape.size() == 2,
|
||||
"Expected a 2D tensor for the ROIs input with box coordinates. Got: ",
|
||||
rois_shape);
|
||||
|
||||
NODE_VALIDATION_CHECK(op,
|
||||
rois_shape[1].compatible(5),
|
||||
"The second dimension of ROIs input should contain batch id and box coordinates. ",
|
||||
"This dimension is expected to be equal to 5. Got: ",
|
||||
rois_shape[1]);
|
||||
}
|
||||
}
|
||||
|
||||
template <class TROIPooling>
|
||||
void output_roi_attr(const TROIPooling* op) {
|
||||
const auto& out_roi = op->get_output_roi();
|
||||
|
||||
NODE_VALIDATION_CHECK(op,
|
||||
out_roi.size() == 2,
|
||||
"The dimension of pooled size is expected to be equal to 2. Got: ",
|
||||
out_roi.size());
|
||||
|
||||
NODE_VALIDATION_CHECK(op,
|
||||
std::none_of(out_roi.cbegin(), out_roi.cend(), cmp::Less<size_t>(1)),
|
||||
"Pooled size attributes pooled_h and pooled_w should should be positive integers. Got: ",
|
||||
out_roi[0],
|
||||
" and: ",
|
||||
out_roi[1],
|
||||
"respectively");
|
||||
}
|
||||
|
||||
template <class TROIPooling>
|
||||
void scale_attr(const TROIPooling* op) {
|
||||
const auto scale = op->get_spatial_scale();
|
||||
NODE_VALIDATION_CHECK(op,
|
||||
std::isnormal(scale) && !std::signbit(scale),
|
||||
"The spatial scale attribute should be a positive floating point number. Got: ",
|
||||
scale);
|
||||
}
|
||||
|
||||
template <class TROIPooling>
|
||||
void method_attr(const TROIPooling* op) {
|
||||
const auto& method = op->get_method();
|
||||
NODE_VALIDATION_CHECK(op,
|
||||
method == "max" || method == "bilinear",
|
||||
"Pooling method attribute should be either \'max\' or \'bilinear\'. Got: ",
|
||||
method);
|
||||
}
|
||||
} // namespace validate
|
||||
} // namespace pooling
|
||||
|
||||
namespace v0 {
|
||||
template <class TShape>
|
||||
std::vector<TShape> shape_infer(const ROIPooling* op, const std::vector<TShape>& input_shapes) {
|
||||
NODE_VALIDATION_CHECK(op, input_shapes.size() == 2);
|
||||
using namespace ov::util;
|
||||
|
||||
const auto& feat_shape = input_shapes[0];
|
||||
const auto& rois_shape = input_shapes[1];
|
||||
const auto& feat_rank = feat_shape.rank();
|
||||
|
||||
NODE_VALIDATION_CHECK(op,
|
||||
feat_rank.compatible(4),
|
||||
"Expected a 4D tensor for the feature maps input. Got: ",
|
||||
feat_shape);
|
||||
|
||||
pooling::validate::rois_input_shape(op, rois_shape);
|
||||
pooling::validate::output_roi_attr(op);
|
||||
pooling::validate::scale_attr(op);
|
||||
pooling::validate::method_attr(op);
|
||||
|
||||
TShape out_shape;
|
||||
out_shape.reserve(4);
|
||||
|
||||
out_shape.emplace_back(rois_shape.rank().is_static() ? rois_shape[0] : dim::inf_bound);
|
||||
out_shape.emplace_back(feat_rank.is_static() ? feat_shape[1] : dim::inf_bound);
|
||||
std::copy(op->get_output_roi().cbegin(), op->get_output_roi().cend(), std::back_inserter(out_shape));
|
||||
|
||||
return {out_shape};
|
||||
}
|
||||
|
||||
template <class TShape>
|
||||
void shape_infer(const ROIPooling* op, const std::vector<TShape>& input_shapes, std::vector<TShape>& output_shapes) {
|
||||
output_shapes = shape_infer(op, input_shapes);
|
||||
}
|
||||
} // namespace v0
|
||||
} // namespace op
|
||||
} // namespace ov
|
||||
@@ -2,18 +2,22 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "ngraph/op/roi_pooling.hpp"
|
||||
#include "openvino/op/roi_pooling.hpp"
|
||||
|
||||
#include "itt.hpp"
|
||||
#include "openvino/core/validation_util.hpp"
|
||||
#include "roi_pooling_shape_inference.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
|
||||
op::ROIPooling::ROIPooling(const Output<Node>& input,
|
||||
const Output<Node>& coords,
|
||||
const ov::Shape& output_size,
|
||||
const float spatial_scale,
|
||||
const string& method)
|
||||
namespace ov {
|
||||
namespace op {
|
||||
namespace v0 {
|
||||
ROIPooling::ROIPooling(const Output<Node>& input,
|
||||
const Output<Node>& coords,
|
||||
const ov::Shape& output_size,
|
||||
const float spatial_scale,
|
||||
const string& method)
|
||||
: Op({input, coords}),
|
||||
m_output_size(output_size),
|
||||
m_spatial_scale(spatial_scale),
|
||||
@@ -21,10 +25,10 @@ op::ROIPooling::ROIPooling(const Output<Node>& input,
|
||||
constructor_validate_and_infer_types();
|
||||
}
|
||||
|
||||
void op::ROIPooling::validate_and_infer_types() {
|
||||
void ROIPooling::validate_and_infer_types() {
|
||||
OV_OP_SCOPE(v0_ROIPooling_validate_and_infer_types);
|
||||
auto feat_maps_et = get_input_element_type(0);
|
||||
auto coords_et = get_input_element_type(1);
|
||||
const auto& feat_maps_et = get_input_element_type(0);
|
||||
const auto& coords_et = get_input_element_type(1);
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
feat_maps_et.is_real() && coords_et.is_real(),
|
||||
"The data type for input and ROIs is expected to be a floating point type. Got: ",
|
||||
@@ -34,72 +38,16 @@ void op::ROIPooling::validate_and_infer_types() {
|
||||
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
feat_maps_et == coords_et,
|
||||
"Type of feature maps (inputs) and rois is expected to be the same. Got: ",
|
||||
"Type of feature maps (inputs) and ROIs is expected to be the same. Got: ",
|
||||
feat_maps_et,
|
||||
" and: ",
|
||||
coords_et);
|
||||
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
m_output_size.size() == 2,
|
||||
"The dimension of pooled size is expected to be equal to 2. Got: ",
|
||||
m_output_size.size());
|
||||
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
m_output_size[0] > 0 && m_output_size[1] > 0,
|
||||
"Pooled size attributes pooled_h and pooled_w should should be "
|
||||
"non-negative integers. Got: ",
|
||||
m_output_size[0],
|
||||
" and: ",
|
||||
m_output_size[1],
|
||||
"respectively");
|
||||
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
m_spatial_scale > 0,
|
||||
"The spatial scale attribute should be a positive floating point number. Got: ",
|
||||
m_spatial_scale);
|
||||
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
m_method == "max" || m_method == "bilinear",
|
||||
"Pooling method attribute should be either \'max\' or \'bilinear\'. Got: ",
|
||||
m_method);
|
||||
const auto output_shapes = shape_infer(this, get_node_input_partial_shapes(*this));
|
||||
set_output_type(0, feat_maps_et, output_shapes[0]);
|
||||
|
||||
const auto& feat_maps_ps = get_input_partial_shape(0);
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
feat_maps_ps.rank().compatible(4),
|
||||
"Expected a 4D tensor for the feature maps input. Got: ",
|
||||
feat_maps_ps);
|
||||
|
||||
const auto& coords_ps = get_input_partial_shape(1);
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
coords_ps.rank().compatible(2),
|
||||
"Expected a 2D tensor for the ROIs input with box coordinates. Got: ",
|
||||
coords_ps);
|
||||
|
||||
if (coords_ps.rank().is_static()) {
|
||||
const auto coords_second_dim = coords_ps[1];
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
coords_second_dim.compatible(5),
|
||||
"The second dimension of ROIs input should contain batch id and box coordinates. ",
|
||||
"This dimension is expected to be equal to 5. Got: ",
|
||||
coords_second_dim);
|
||||
}
|
||||
|
||||
// output shape should be {NUM_ROIS, C, pooled_h, pooled_w}
|
||||
auto output_shape = ov::PartialShape{{Dimension::dynamic(),
|
||||
Dimension::dynamic(),
|
||||
Dimension{static_cast<int64_t>(m_output_size[0])},
|
||||
Dimension{static_cast<int64_t>(m_output_size[1])}}};
|
||||
|
||||
if (coords_ps.rank().is_static()) {
|
||||
output_shape[0] = coords_ps[0];
|
||||
}
|
||||
|
||||
if (feat_maps_ps.rank().is_static()) {
|
||||
output_shape[1] = feat_maps_ps[1];
|
||||
}
|
||||
|
||||
set_output_size(1);
|
||||
set_output_type(0, feat_maps_et, output_shape);
|
||||
|
||||
// if channel dimension, C, not known
|
||||
// feature maps input is used by shape specialization pass
|
||||
@@ -114,13 +62,13 @@ void op::ROIPooling::validate_and_infer_types() {
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<Node> op::ROIPooling::clone_with_new_inputs(const OutputVector& new_args) const {
|
||||
shared_ptr<Node> ROIPooling::clone_with_new_inputs(const OutputVector& new_args) const {
|
||||
OV_OP_SCOPE(v0_ROIPooling_clone_with_new_inputs);
|
||||
check_new_args_count(this, new_args);
|
||||
return make_shared<ROIPooling>(new_args.at(0), new_args.at(1), m_output_size, m_spatial_scale, m_method);
|
||||
}
|
||||
|
||||
bool op::ROIPooling::visit_attributes(AttributeVisitor& visitor) {
|
||||
bool ROIPooling::visit_attributes(AttributeVisitor& visitor) {
|
||||
OV_OP_SCOPE(v0_ROIPooling_visit_attributes);
|
||||
visitor.on_attribute("output_size", m_output_size);
|
||||
visitor.on_attribute("pooled_h", m_output_size[0]);
|
||||
@@ -129,3 +77,21 @@ bool op::ROIPooling::visit_attributes(AttributeVisitor& visitor) {
|
||||
visitor.on_attribute("method", m_method);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ROIPooling::set_output_roi(Shape output_size) {
|
||||
m_output_size = std::move(output_size);
|
||||
}
|
||||
const Shape& ROIPooling::get_output_roi() const {
|
||||
return m_output_size;
|
||||
}
|
||||
|
||||
void ROIPooling::set_spatial_scale(float scale) {
|
||||
m_spatial_scale = scale;
|
||||
}
|
||||
|
||||
void ROIPooling::set_method(std::string method_name) {
|
||||
m_method = std::move(method_name);
|
||||
}
|
||||
} // namespace v0
|
||||
} // namespace op
|
||||
} // namespace ov
|
||||
@@ -2,109 +2,171 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "common_test_utils/test_assertions.hpp"
|
||||
#include "gtest/gtest.h"
|
||||
#include "ngraph/ngraph.hpp"
|
||||
#include "openvino/opsets/opset11.hpp"
|
||||
#include "type_prop.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
using namespace ov;
|
||||
using namespace ov::opset11;
|
||||
using namespace testing;
|
||||
|
||||
TEST(type_prop, roi_pooling_basic_shape_inference) {
|
||||
const auto feat_maps = make_shared<op::Parameter>(element::f32, Shape{1, 3, 6, 6});
|
||||
const auto rois = make_shared<op::Parameter>(element::f32, Shape{4, 5});
|
||||
const auto op = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, 0.625f);
|
||||
ASSERT_EQ(op->get_method(), "max");
|
||||
ASSERT_EQ(op->get_shape(), (Shape{4, 3, 2, 2}));
|
||||
class TypePropROIPoolingV0 : public TypePropOpTest<op::v0::ROIPooling> {
|
||||
protected:
|
||||
float spatial_scale = 0.625f;
|
||||
Shape pooling_roi_2x2{2, 2};
|
||||
};
|
||||
|
||||
TEST_F(TypePropROIPoolingV0, default_ctor) {
|
||||
const auto feat_maps = make_shared<Parameter>(element::f32, PartialShape{{0, 3}, {1, 3}, {1, 6}, {1, 6}});
|
||||
const auto rois = make_shared<Parameter>(element::f32, PartialShape{{2, 4}, {1, 5}});
|
||||
|
||||
const auto op = make_op();
|
||||
op->set_arguments(OutputVector{feat_maps, rois});
|
||||
op->set_spatial_scale(spatial_scale);
|
||||
op->set_method("max");
|
||||
op->set_output_roi({3, 4});
|
||||
op->validate_and_infer_types();
|
||||
|
||||
EXPECT_FLOAT_EQ(op->get_spatial_scale(), spatial_scale);
|
||||
EXPECT_EQ(op->get_output_roi(), Shape({3, 4}));
|
||||
EXPECT_EQ(op->get_method(), "max");
|
||||
EXPECT_EQ(op->get_input_size(), 2);
|
||||
EXPECT_EQ(op->get_element_type(), element::f32);
|
||||
EXPECT_EQ(static_cast<Node*>(op.get())->get_output_size(), 1);
|
||||
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{{2, 4}, {1, 3}, 3, 4}));
|
||||
}
|
||||
|
||||
TEST(type_prop, roi_pooling_dynamic_channels_dim) {
|
||||
const auto feat_maps = make_shared<op::Parameter>(element::f32, PartialShape{1, Dimension(), 6, 6});
|
||||
const auto rois = make_shared<op::Parameter>(element::f32, Shape{4, 5});
|
||||
const auto op = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, 0.625f, "max");
|
||||
ASSERT_TRUE(op->get_output_partial_shape(0).same_scheme(PartialShape{4, Dimension(), 2, 2}));
|
||||
TEST_F(TypePropROIPoolingV0, basic_shape_inference) {
|
||||
const auto feat_maps = make_shared<Parameter>(element::f32, Shape{1, 3, 6, 6});
|
||||
const auto rois = make_shared<Parameter>(element::f32, Shape{4, 5});
|
||||
const auto op = make_op(feat_maps, rois, pooling_roi_2x2, 0.625f);
|
||||
|
||||
EXPECT_EQ(op->get_element_type(), element::f32);
|
||||
EXPECT_EQ(op->get_method(), "max");
|
||||
EXPECT_EQ(op->get_shape(), (Shape{4, 3, 2, 2}));
|
||||
}
|
||||
|
||||
TEST(type_prop, roi_pooling_dynamic_num_rois_dim) {
|
||||
const auto feat_maps = make_shared<op::Parameter>(element::f32, Shape{1, 3, 6, 6});
|
||||
const auto rois = make_shared<op::Parameter>(element::f32, PartialShape{Dimension(), 5});
|
||||
const auto op = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, 0.625f);
|
||||
ASSERT_TRUE(op->get_output_partial_shape(0).same_scheme(PartialShape{Dimension(), 3, 2, 2}));
|
||||
TEST_F(TypePropROIPoolingV0, dynamic_channels_dim) {
|
||||
auto feat_shape = PartialShape{1, -1, 6, 6};
|
||||
auto rois_shape = PartialShape{4, 5};
|
||||
set_shape_labels(feat_shape, 10);
|
||||
set_shape_labels(rois_shape, 20);
|
||||
|
||||
const auto feat_maps = make_shared<Parameter>(element::f32, feat_shape);
|
||||
const auto rois = make_shared<Parameter>(element::f32, rois_shape);
|
||||
const auto op = make_op(feat_maps, rois, pooling_roi_2x2, spatial_scale, "max");
|
||||
|
||||
EXPECT_EQ(op->get_element_type(), element::f32);
|
||||
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{4, -1, 2, 2}));
|
||||
EXPECT_THAT(get_shape_labels(op->get_output_partial_shape(0)), ElementsAre(20, 11, ov::no_label, ov::no_label));
|
||||
}
|
||||
|
||||
TEST(type_prop, roi_pooling_dynamic_rank_feat_maps) {
|
||||
const auto feat_maps = make_shared<op::Parameter>(element::f32, PartialShape::dynamic());
|
||||
const auto rois = make_shared<op::Parameter>(element::f32, Shape{4, 5});
|
||||
const auto op = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, 0.625f);
|
||||
ASSERT_TRUE(op->get_output_partial_shape(0).same_scheme(PartialShape{4, Dimension(), 2, 2}));
|
||||
TEST_F(TypePropROIPoolingV0, dynamic_num_rois_dim) {
|
||||
auto feat_shape = PartialShape{1, 3, 6, 6};
|
||||
auto rois_shape = PartialShape{-1, 5};
|
||||
set_shape_labels(feat_shape, 10);
|
||||
set_shape_labels(rois_shape, 20);
|
||||
|
||||
const auto feat_maps = make_shared<Parameter>(element::f64, feat_shape);
|
||||
const auto rois = make_shared<Parameter>(element::f64, rois_shape);
|
||||
const auto op = make_op(feat_maps, rois, pooling_roi_2x2, spatial_scale, "bilinear");
|
||||
|
||||
EXPECT_EQ(op->get_element_type(), element::f64);
|
||||
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{-1, 3, 2, 2}));
|
||||
EXPECT_THAT(get_shape_labels(op->get_output_partial_shape(0)), ElementsAre(20, 11, ov::no_label, ov::no_label));
|
||||
}
|
||||
|
||||
TEST(type_prop, roi_pooling_dynamic_rank_rois) {
|
||||
const auto feat_maps = make_shared<op::Parameter>(element::f32, Shape{1, 3, 6, 6});
|
||||
const auto rois = make_shared<op::Parameter>(element::f32, PartialShape::dynamic());
|
||||
const auto op = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, 0.625f);
|
||||
ASSERT_TRUE(op->get_output_partial_shape(0).same_scheme(PartialShape{Dimension(), 3, 2, 2}));
|
||||
TEST_F(TypePropROIPoolingV0, dynamic_rank_feat_maps) {
|
||||
const auto feat_maps = make_shared<Parameter>(element::f16, PartialShape::dynamic());
|
||||
const auto rois = make_shared<Parameter>(element::f16, Shape{4, 5});
|
||||
const auto op = make_op(feat_maps, rois, pooling_roi_2x2, spatial_scale);
|
||||
|
||||
EXPECT_EQ(op->get_element_type(), element::f16);
|
||||
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{4, -1, 2, 2}));
|
||||
EXPECT_THAT(get_shape_labels(op->get_output_partial_shape(0)), Each(ov::no_label));
|
||||
}
|
||||
|
||||
TEST(type_prop, roi_pooling_incompatible_input_rank) {
|
||||
const auto feat_maps = make_shared<op::Parameter>(element::f32, Shape{1, 3, 2, 6, 6});
|
||||
const auto rois = make_shared<op::Parameter>(element::f32, Shape{3, 5});
|
||||
// feat_maps must be of rank 4
|
||||
ASSERT_THROW(const auto unused = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, 0.625f, "max"),
|
||||
ngraph::NodeValidationFailure);
|
||||
TEST_F(TypePropROIPoolingV0, dynamic_rank_feat_rois) {
|
||||
const auto feat_maps = make_shared<Parameter>(element::f32, Shape{1, 3, 6, 6});
|
||||
const auto rois = make_shared<Parameter>(element::f32, PartialShape::dynamic());
|
||||
const auto op = make_op(feat_maps, rois, pooling_roi_2x2, spatial_scale);
|
||||
|
||||
EXPECT_EQ(op->get_element_type(), element::f32);
|
||||
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{-1, 3, 2, 2}));
|
||||
EXPECT_THAT(get_shape_labels(op->get_output_partial_shape(0)), Each(ov::no_label));
|
||||
}
|
||||
|
||||
TEST(type_prop, roi_pooling_incompatible_pooling_shape) {
|
||||
Shape pool_shape{2, 2, 2};
|
||||
const auto feat_maps = make_shared<op::Parameter>(element::f32, Shape{3, 2, 6, 6});
|
||||
const auto rois = make_shared<op::Parameter>(element::f32, Shape{3, 5});
|
||||
// pool_shape must be of rank 2 {pooled_h, pooled_w}
|
||||
ASSERT_THROW(const auto unused = make_shared<op::v0::ROIPooling>(feat_maps, rois, pool_shape, 0.625f, "max"),
|
||||
ngraph::NodeValidationFailure);
|
||||
TEST_F(TypePropROIPoolingV0, incompatible_input_rank) {
|
||||
const auto feat_maps = make_shared<Parameter>(element::f32, Shape{1, 3, 6, 6, 6});
|
||||
const auto rois = make_shared<Parameter>(element::f32, PartialShape{3, 5});
|
||||
|
||||
OV_EXPECT_THROW(const auto op = make_op(feat_maps, rois, pooling_roi_2x2, spatial_scale, "max"),
|
||||
NodeValidationFailure,
|
||||
HasSubstr("Expected a 4D tensor for the feature maps input"));
|
||||
}
|
||||
|
||||
TEST(type_prop, roi_pooling_incompatible_rois_second_dim) {
|
||||
const auto feat_maps = make_shared<op::Parameter>(element::f32, Shape{3, 2, 6, 6});
|
||||
const auto rois = make_shared<op::Parameter>(element::f32, Shape{3, 4});
|
||||
// the second dim of rois must be 5. [batch_id, x_1, y_1, x_2, y_2]
|
||||
ASSERT_THROW(const auto unused = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, 0.625f, "max"),
|
||||
ngraph::NodeValidationFailure);
|
||||
TEST_F(TypePropROIPoolingV0, incompatible_pooling_shape) {
|
||||
const auto feat_maps = make_shared<Parameter>(element::f32, Shape{3, 2, 6, 6});
|
||||
const auto rois = make_shared<Parameter>(element::f32, PartialShape{3, 5});
|
||||
|
||||
OV_EXPECT_THROW(const auto op = make_op(feat_maps, rois, Shape{2, 2, 2}, spatial_scale, "max"),
|
||||
NodeValidationFailure,
|
||||
HasSubstr("The dimension of pooled size is expected to be equal to 2"));
|
||||
}
|
||||
|
||||
TEST(type_prop, roi_pooling_incompatible_feature_maps_element_type) {
|
||||
const auto feat_maps = make_shared<op::Parameter>(element::i32, Shape{3, 2, 6, 6});
|
||||
const auto rois = make_shared<op::Parameter>(element::f32, Shape{3, 5});
|
||||
// feat_maps element type must be floating point type
|
||||
ASSERT_THROW(const auto unused = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, 0.625f, "max"),
|
||||
ngraph::NodeValidationFailure);
|
||||
TEST_F(TypePropROIPoolingV0, incompatible_rois_second_dim) {
|
||||
const auto feat_maps = make_shared<Parameter>(element::f32, Shape{3, 2, 6, 6});
|
||||
const auto rois = make_shared<Parameter>(element::f32, PartialShape{3, 4});
|
||||
|
||||
OV_EXPECT_THROW(const auto op = make_op(feat_maps, rois, pooling_roi_2x2, spatial_scale, "max"),
|
||||
NodeValidationFailure,
|
||||
HasSubstr("The second dimension of ROIs input should contain batch id and box coordinates. This "
|
||||
"dimension is expected to be equal to 5"));
|
||||
}
|
||||
|
||||
TEST(type_prop, roi_pooling_incompatible_rois_element_type) {
|
||||
const auto feat_maps = make_shared<op::Parameter>(element::f32, Shape{3, 2, 6, 6});
|
||||
const auto rois = make_shared<op::Parameter>(element::f16, Shape{3, 5});
|
||||
// rois element type must be equal to feat_maps element type (floating point type)
|
||||
ASSERT_THROW(const auto unused = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, 0.625f, "bilinear"),
|
||||
ngraph::NodeValidationFailure);
|
||||
TEST_F(TypePropROIPoolingV0, incompatible_feature_maps_element_type) {
|
||||
const auto feat_maps = make_shared<Parameter>(element::i32, Shape{3, 2, 6, 6});
|
||||
const auto rois = make_shared<Parameter>(element::f32, PartialShape{3, 5});
|
||||
|
||||
OV_EXPECT_THROW(const auto op = make_op(feat_maps, rois, pooling_roi_2x2, spatial_scale, "max"),
|
||||
NodeValidationFailure,
|
||||
HasSubstr("The data type for input and ROIs is expected to be a floating point type"));
|
||||
}
|
||||
|
||||
TEST(type_prop, roi_pooling_invalid_pooling_method) {
|
||||
const auto feat_maps = make_shared<op::Parameter>(element::f32, Shape{3, 2, 6, 6});
|
||||
const auto rois = make_shared<op::Parameter>(element::f16, Shape{3, 5});
|
||||
// ROIPooling method is invalid: not max nor bilinear
|
||||
ASSERT_THROW(const auto unused = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, 0.625f, "invalid"),
|
||||
ngraph::NodeValidationFailure);
|
||||
TEST_F(TypePropROIPoolingV0, incompatible_rois_element_type) {
|
||||
const auto feat_maps = make_shared<Parameter>(element::f32, Shape{3, 2, 6, 6});
|
||||
const auto rois = make_shared<Parameter>(element::i16, PartialShape{3, 5});
|
||||
|
||||
OV_EXPECT_THROW(const auto op = make_op(feat_maps, rois, pooling_roi_2x2, spatial_scale, "bilinear"),
|
||||
NodeValidationFailure,
|
||||
HasSubstr("The data type for input and ROIs is expected to be a floating point type"));
|
||||
}
|
||||
|
||||
TEST(type_prop, roi_pooling_invalid_spatial_scale) {
|
||||
const auto feat_maps = make_shared<op::Parameter>(element::f32, Shape{3, 2, 6, 6});
|
||||
const auto rois = make_shared<op::Parameter>(element::f16, Shape{3, 5});
|
||||
// ROIPooling spatial scale attribute must be a positive floating point number
|
||||
ASSERT_THROW(const auto unused = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, -0.625f, "max"),
|
||||
ngraph::NodeValidationFailure);
|
||||
TEST_F(TypePropROIPoolingV0, invalid_pooling_method) {
|
||||
const auto feat_maps = make_shared<Parameter>(element::f32, Shape{3, 2, 6, 6});
|
||||
const auto rois = make_shared<Parameter>(element::f32, PartialShape{3, 5});
|
||||
|
||||
OV_EXPECT_THROW(const auto op = make_op(feat_maps, rois, pooling_roi_2x2, spatial_scale, "invalid"),
|
||||
NodeValidationFailure,
|
||||
HasSubstr("Pooling method attribute should be either \'max\' or \'bilinear\'"));
|
||||
}
|
||||
|
||||
TEST(type_prop, roi_pooling_invalid_pooled_size) {
|
||||
const auto feat_maps = make_shared<op::Parameter>(element::f32, Shape{3, 2, 6, 6});
|
||||
const auto rois = make_shared<op::Parameter>(element::f16, Shape{3, 5});
|
||||
// ROIPooling pooled_h and pooled_w must be non-negative integers
|
||||
ASSERT_THROW(const auto unused = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{1, 0}, 0.625f, "max"),
|
||||
ngraph::NodeValidationFailure);
|
||||
TEST_F(TypePropROIPoolingV0, invalid_spatial_scale) {
|
||||
const auto feat_maps = make_shared<Parameter>(element::f32, Shape{3, 2, 6, 6});
|
||||
const auto rois = make_shared<Parameter>(element::f32, PartialShape{3, 5});
|
||||
|
||||
OV_EXPECT_THROW(const auto op = make_op(feat_maps, rois, pooling_roi_2x2, -1.0f),
|
||||
NodeValidationFailure,
|
||||
HasSubstr("The spatial scale attribute should be a positive floating point number"));
|
||||
}
|
||||
|
||||
TEST_F(TypePropROIPoolingV0, invalid_pooled_size) {
|
||||
const auto feat_maps = make_shared<Parameter>(element::f32, Shape{3, 2, 6, 6});
|
||||
const auto rois = make_shared<Parameter>(element::f32, PartialShape{3, 5});
|
||||
|
||||
OV_EXPECT_THROW(const auto op = make_op(feat_maps, rois, Shape{1, 0}, spatial_scale),
|
||||
NodeValidationFailure,
|
||||
HasSubstr("Pooled size attributes pooled_h and pooled_w should should be positive integers"));
|
||||
}
|
||||
@@ -25,7 +25,7 @@ TEST(attributes, roi_pooling_op) {
|
||||
NodeBuilder builder(op, {data, coords});
|
||||
const auto g_op = ov::as_type_ptr<opset3::ROIPooling>(builder.create());
|
||||
|
||||
EXPECT_EQ(g_op->get_output_size(), op->get_output_size());
|
||||
EXPECT_EQ(g_op->get_output_roi(), op->get_output_roi());
|
||||
EXPECT_EQ(g_op->get_spatial_scale(), op->get_spatial_scale());
|
||||
EXPECT_EQ(g_op->get_method(), op->get_method());
|
||||
}
|
||||
@@ -393,10 +393,10 @@ ROIPooling::ROIPooling(const std::shared_ptr<ngraph::Node>& op, const GraphConte
|
||||
std::string errorPrefix = "ROIPooling layer with name '" + getName() + "' ";
|
||||
|
||||
auto roiPooling = ngraph::as_type_ptr<const ngraph::opset2::ROIPooling>(op);
|
||||
refParams.pooled_h = roiPooling->get_output_size()[0];
|
||||
refParams.pooled_w = roiPooling->get_output_size()[1];
|
||||
refParams.pooled_h = roiPooling->get_output_roi()[0];
|
||||
refParams.pooled_w = roiPooling->get_output_roi()[1];
|
||||
refParams.spatial_scale = roiPooling->get_spatial_scale();
|
||||
std::string m = roiPooling->get_method();
|
||||
const auto& m = roiPooling->get_method();
|
||||
if (m == "max") {
|
||||
algorithm = Algorithm::ROIPoolingMax;
|
||||
} else if (m == "bilinear") {
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
#include "reverse_sequence_shape_inference.hpp"
|
||||
#include "reverse_shape_inference.hpp"
|
||||
#include "roi_align_shape_inference.hpp"
|
||||
#include "roi_pooling_shape_inference.hpp"
|
||||
#include "roll_shape_inference.hpp"
|
||||
#include "scatter_elements_update_shape_inference.hpp"
|
||||
#include "scatter_nd_base_shape_inference.hpp"
|
||||
@@ -125,9 +126,8 @@ public:
|
||||
|
||||
IShapeInferCommon::Result
|
||||
infer(const std::vector<StaticShape>& input_shapes, const std::map<size_t, HostTensorPtr>& constant_data) override {
|
||||
auto op = static_cast<OP*>(node.get());
|
||||
std::vector<StaticShape> output_shapes(op->get_output_size());
|
||||
shape_infer(op, input_shapes, output_shapes);
|
||||
std::vector<StaticShape> output_shapes(node->get_output_size());
|
||||
shape_infer(static_cast<OP*>(node.get()), input_shapes, output_shapes);
|
||||
return {std::move(output_shapes), ShapeInferStatus::success};
|
||||
}
|
||||
};
|
||||
@@ -597,6 +597,7 @@ const IShapeInferCommonFactory::TRegistry IShapeInferCommonFactory::registry{
|
||||
_OV_OP_SHAPE_INFER_REG(Reshape, entryIOC),
|
||||
_OV_OP_SHAPE_INFER_REG(ReverseSequence, entryIO),
|
||||
_OV_OP_SHAPE_INFER_REG(ROIAlign, entryIO),
|
||||
_OV_OP_SHAPE_INFER_REG(ROIPooling, entryIO),
|
||||
_OV_OP_SHAPE_INFER_REG(Roll, entryIOC),
|
||||
_OV_OP_SHAPE_INFER_REG(ScatterElementsUpdate, entryIOC),
|
||||
_OV_OP_SHAPE_INFER_REG(ScatterNDUpdate, entryIO),
|
||||
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
// Copyright (C) 2018-2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include "common_test_utils/test_assertions.hpp"
|
||||
#include "openvino/opsets/opset11.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
using namespace ov;
|
||||
using namespace ov::intel_cpu;
|
||||
using namespace testing;
|
||||
|
||||
class ROIPoolingV0StaticShapeInferenceTest : public OpStaticShapeInferenceTest<op::v0::ROIPooling> {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
output_shapes.resize(1);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(ROIPoolingV0StaticShapeInferenceTest, default_ctor) {
|
||||
op = make_op();
|
||||
op->set_output_roi({3, 3});
|
||||
op->set_method("max");
|
||||
op->set_spatial_scale(0.34f);
|
||||
|
||||
input_shapes = ShapeVector{{1, 5, 10, 10}, {2, 5}};
|
||||
auto shape_infer = make_shape_inference(op);
|
||||
shape_inference(op.get(), input_shapes, output_shapes);
|
||||
|
||||
EXPECT_EQ(output_shapes.size(), 1);
|
||||
EXPECT_EQ(output_shapes.front(), StaticShape({2, 5, 3, 3}));
|
||||
}
|
||||
|
||||
TEST_F(ROIPoolingV0StaticShapeInferenceTest, inputs_dynamic_rank) {
|
||||
const auto feat = std::make_shared<op::v0::Parameter>(element::f64, PartialShape::dynamic());
|
||||
const auto rois = std::make_shared<op::v0::Parameter>(element::f64, PartialShape::dynamic());
|
||||
|
||||
op = make_op(feat, rois, ov::Shape{5, 5}, 0.9f);
|
||||
|
||||
input_shapes = ShapeVector{{2, 3, 100, 100}, {10, 5}};
|
||||
shape_inference(op.get(), input_shapes, output_shapes);
|
||||
|
||||
EXPECT_EQ(output_shapes.size(), 1);
|
||||
EXPECT_EQ(output_shapes.front(), StaticShape({10, 3, 5, 5}));
|
||||
}
|
||||
|
||||
TEST_F(ROIPoolingV0StaticShapeInferenceTest, inputs_static_rank) {
|
||||
const auto feat = std::make_shared<op::v0::Parameter>(element::f64, PartialShape::dynamic(4));
|
||||
const auto rois = std::make_shared<op::v0::Parameter>(element::f64, PartialShape::dynamic(2));
|
||||
|
||||
op = make_op(feat, rois, ov::Shape{7, 5}, 1.9f, "max");
|
||||
|
||||
input_shapes = ShapeVector{{2, 3, 20, 100}, {10, 5}};
|
||||
shape_inference(op.get(), input_shapes, output_shapes);
|
||||
|
||||
EXPECT_EQ(output_shapes.size(), 1);
|
||||
EXPECT_EQ(output_shapes.front(), StaticShape({10, 3, 7, 5}));
|
||||
}
|
||||
|
||||
TEST_F(ROIPoolingV0StaticShapeInferenceTest, invalid_rois_batch_size) {
|
||||
const auto feat = std::make_shared<op::v0::Parameter>(element::f64, PartialShape::dynamic(4));
|
||||
const auto rois = std::make_shared<op::v0::Parameter>(element::f64, PartialShape::dynamic());
|
||||
|
||||
op = make_op(feat, rois, ov::Shape{7, 5}, 1.9f, "max");
|
||||
|
||||
input_shapes = ShapeVector{{2, 3, 20, 100}, {10, 6}};
|
||||
|
||||
OV_EXPECT_THROW(shape_inference(op.get(), input_shapes, output_shapes),
|
||||
NodeValidationFailure,
|
||||
HasSubstr("The second dimension of ROIs input should contain batch id and box coordinates. This "
|
||||
"dimension is expected to be equal to 5"));
|
||||
}
|
||||
Reference in new issue
Block a user