Review shape inference of ExtractImagesPatches (#18771)
* Review shape inference of ExtractImagesPatches - Check static and dynamic shapes propagation - Check label propagation - Review template implementation of `shape_infer function - Add unit tests. * Add additional test to check padding calc
This commit is contained in:
1 parent
bb3c9aa9a7
commit
32f2868a5b
5 files changed
+382
-130
No files matched your search
@@ -2,94 +2,81 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
#pragma once
|
||||
#include <openvino/op/extractimagepatches.hpp>
|
||||
|
||||
#include "dimension_util.hpp"
|
||||
#include "openvino/op/extractimagepatches.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace ov {
|
||||
namespace op {
|
||||
namespace v3 {
|
||||
int32_t inline calc_shape_padding(const int32_t input,
|
||||
const int32_t rate,
|
||||
const int32_t stride,
|
||||
const int32_t patch_size,
|
||||
const PadType type) {
|
||||
int32_t out = 0;
|
||||
if (type == PadType::VALID) {
|
||||
out = (input - rate * (patch_size - 1) - 1) / stride + 1;
|
||||
} else {
|
||||
out = 1 + (input - 1) / stride;
|
||||
}
|
||||
return out < 0 ? 0 : out;
|
||||
}
|
||||
|
||||
template <class T, class TRShape = result_shape_t<T>>
|
||||
std::vector<TRShape> shape_infer(const ExtractImagePatches* op, const std::vector<T>& input_shapes) {
|
||||
NODE_VALIDATION_CHECK(op, input_shapes.size() == 1);
|
||||
using DimType = typename T::value_type;
|
||||
using namespace ov::util;
|
||||
using TDim = typename T::value_type;
|
||||
|
||||
constexpr size_t num_spatial_dim = 2;
|
||||
constexpr auto is_zero = cmp::Less<size_t>(1);
|
||||
|
||||
const auto& input_shape = input_shapes[0];
|
||||
auto output_shapes = std::vector<TRShape>(1);
|
||||
auto& output_shape = output_shapes[0];
|
||||
output_shape.resize(4);
|
||||
NODE_VALIDATION_CHECK(op, input_shape.rank().compatible(4), "input tensor must be 4D tensor.");
|
||||
|
||||
NODE_SHAPE_INFER_CHECK(op, input_shapes, input_shape.rank().compatible(4), "input tensor must be 4D tensor.");
|
||||
|
||||
const auto& sizes = op->get_sizes();
|
||||
NODE_VALIDATION_CHECK(op,
|
||||
op->get_sizes().size() == 2,
|
||||
sizes.size() == num_spatial_dim,
|
||||
"Attribute sizes should be in [size_rows, size_cols] format.");
|
||||
|
||||
const auto& strides = op->get_strides();
|
||||
NODE_VALIDATION_CHECK(op,
|
||||
op->get_strides().size() == 2,
|
||||
strides.size() == num_spatial_dim,
|
||||
"Attribute strides should be in [stride_rows, stride_cols] format.");
|
||||
|
||||
NODE_VALIDATION_CHECK(op,
|
||||
op->get_strides()[0] > 0 && op->get_strides()[1] > 0,
|
||||
std::none_of(strides.begin(), strides.end(), is_zero),
|
||||
"Attribute strides should be strictly greater than zeros in values.");
|
||||
|
||||
const auto& rates = op->get_rates();
|
||||
NODE_VALIDATION_CHECK(op,
|
||||
op->get_rates().size() == 2,
|
||||
rates.size() == num_spatial_dim,
|
||||
"Attribute rates should be in [rate_rows, rate_cols] format.");
|
||||
|
||||
NODE_VALIDATION_CHECK(op,
|
||||
op->get_rates()[0] > 0 && op->get_rates()[1] > 0,
|
||||
std::none_of(rates.begin(), rates.end(), is_zero),
|
||||
"Attribute rates should be strictly greater than zeros in values.");
|
||||
|
||||
NODE_VALIDATION_CHECK(op,
|
||||
op->get_auto_pad() == PadType::VALID || op->get_auto_pad() == PadType::SAME_LOWER ||
|
||||
op->get_auto_pad() == PadType::SAME_UPPER,
|
||||
"Attribute padding should be in either valid or same_lower or same_upper.");
|
||||
const auto& pad_type = op->get_auto_pad();
|
||||
NODE_VALIDATION_CHECK(
|
||||
op,
|
||||
pad_type == PadType::VALID || pad_type == PadType::SAME_LOWER || pad_type == PadType::SAME_UPPER,
|
||||
"Attribute padding should be in either valid or same_lower or same_upper.");
|
||||
|
||||
if (input_shape.rank().is_static()) {
|
||||
// Determine batch & output_depth
|
||||
output_shape[0] = input_shape[0];
|
||||
output_shape[1] = input_shape[1] * op->get_sizes()[0] * op->get_sizes()[1];
|
||||
// Determine spatial shape
|
||||
if (input_shape[2].is_static() && input_shape[3].is_static()) {
|
||||
int32_t input_rows = static_cast<int32_t>(input_shape[2].get_length());
|
||||
int32_t input_cols = static_cast<int32_t>(input_shape[3].get_length());
|
||||
int32_t out_rows(0);
|
||||
int32_t out_cols(0);
|
||||
if (input_rows == 0 || input_cols == 0) {
|
||||
output_shape = input_shape;
|
||||
return output_shapes;
|
||||
const auto num_non_spatial_dims = input_shape.size() - num_spatial_dim;
|
||||
|
||||
auto out_it = std::copy_n(input_shape.begin(), num_non_spatial_dims, std::back_inserter(output_shape));
|
||||
output_shape[1] *=
|
||||
std::accumulate(sizes.begin(), sizes.end(), static_cast<size_t>(1), std::multiplies<size_t>());
|
||||
|
||||
auto stride_it = strides.cbegin();
|
||||
|
||||
if (pad_type == PadType::VALID) {
|
||||
auto size_it = sizes.cbegin();
|
||||
auto rate_it = rates.cbegin();
|
||||
|
||||
for (size_t i = num_non_spatial_dims; i < input_shape.size(); ++i, ++stride_it, ++size_it, ++rate_it) {
|
||||
out_it = dim::ceil_div(input_shape[i] - ((*rate_it) * (*size_it - 1)), *stride_it);
|
||||
}
|
||||
|
||||
out_rows = calc_shape_padding(input_rows,
|
||||
static_cast<int32_t>(op->get_rates()[0]),
|
||||
static_cast<int32_t>(op->get_strides()[0]),
|
||||
static_cast<int32_t>(op->get_sizes()[0]),
|
||||
op->get_auto_pad());
|
||||
out_cols = calc_shape_padding(input_cols,
|
||||
static_cast<int32_t>(op->get_rates()[1]),
|
||||
static_cast<int32_t>(op->get_strides()[1]),
|
||||
static_cast<int32_t>(op->get_sizes()[1]),
|
||||
op->get_auto_pad());
|
||||
|
||||
auto out_rows_cast = static_cast<typename DimType::value_type>(out_rows);
|
||||
auto out_cols_cast = static_cast<typename DimType::value_type>(out_cols);
|
||||
|
||||
output_shape[2] = out_rows_cast;
|
||||
output_shape[3] = out_cols_cast;
|
||||
} else {
|
||||
std::transform(input_shape.begin() + num_non_spatial_dims,
|
||||
input_shape.end(),
|
||||
stride_it,
|
||||
out_it,
|
||||
&dim::ceil_div<TDim>);
|
||||
}
|
||||
} else {
|
||||
output_shape.resize(4);
|
||||
}
|
||||
return output_shapes;
|
||||
}
|
||||
|
||||
@@ -2,23 +2,20 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "ngraph/op/extractimagepatches.hpp"
|
||||
|
||||
#include <extract_image_patches_shape_inference.hpp>
|
||||
#include "openvino/op/extractimagepatches.hpp"
|
||||
|
||||
#include "extract_image_patches_shape_inference.hpp"
|
||||
#include "itt.hpp"
|
||||
#include "ngraph/attribute_visitor.hpp"
|
||||
#include "openvino/core/attribute_visitor.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
|
||||
// ExtractImagePatches v3
|
||||
|
||||
op::v3::ExtractImagePatches::ExtractImagePatches(const Output<Node>& image,
|
||||
const ov::Shape& sizes,
|
||||
const Strides& strides,
|
||||
const ov::Shape& rates,
|
||||
const PadType& auto_pad)
|
||||
namespace ov {
|
||||
namespace op {
|
||||
namespace v3 {
|
||||
ExtractImagePatches::ExtractImagePatches(const Output<Node>& image,
|
||||
const ov::Shape& sizes,
|
||||
const Strides& strides,
|
||||
const ov::Shape& rates,
|
||||
const PadType& auto_pad)
|
||||
: Op({image}),
|
||||
m_patch_sizes(sizes),
|
||||
m_patch_movement_strides(strides),
|
||||
@@ -27,16 +24,17 @@ op::v3::ExtractImagePatches::ExtractImagePatches(const Output<Node>& image,
|
||||
constructor_validate_and_infer_types();
|
||||
}
|
||||
|
||||
void op::v3::ExtractImagePatches::validate_and_infer_types() {
|
||||
void ExtractImagePatches::validate_and_infer_types() {
|
||||
OV_OP_SCOPE(v3_ExtractImagePatches_validate_and_infer_types);
|
||||
std::vector<PartialShape> input_shapes = {get_input_partial_shape(0)};
|
||||
|
||||
const auto input_shapes = std::vector<PartialShape>{get_input_partial_shape(0)};
|
||||
const auto output_shapes = shape_infer(this, input_shapes);
|
||||
if (output_shapes[0].is_dynamic())
|
||||
set_input_is_relevant_to_shape(0);
|
||||
set_output_type(0, get_input_element_type(0), output_shapes[0]);
|
||||
}
|
||||
|
||||
bool op::v3::ExtractImagePatches::visit_attributes(AttributeVisitor& visitor) {
|
||||
bool ExtractImagePatches::visit_attributes(AttributeVisitor& visitor) {
|
||||
OV_OP_SCOPE(v3_ExtractImagePatches_visit_attributes);
|
||||
visitor.on_attribute("sizes", m_patch_sizes);
|
||||
visitor.on_attribute("strides", m_patch_movement_strides);
|
||||
@@ -45,12 +43,16 @@ bool op::v3::ExtractImagePatches::visit_attributes(AttributeVisitor& visitor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
shared_ptr<Node> op::v3::ExtractImagePatches::clone_with_new_inputs(const OutputVector& new_args) const {
|
||||
std::shared_ptr<Node> ExtractImagePatches::clone_with_new_inputs(const OutputVector& new_args) const {
|
||||
OV_OP_SCOPE(v3_ExtractImagePatches_clone_with_new_inputs);
|
||||
check_new_args_count(this, new_args);
|
||||
return make_shared<op::v3::ExtractImagePatches>(new_args.at(0),
|
||||
m_patch_sizes,
|
||||
m_patch_movement_strides,
|
||||
m_patch_selection_rates,
|
||||
m_padding);
|
||||
return std::make_shared<ExtractImagePatches>(new_args.at(0),
|
||||
m_patch_sizes,
|
||||
m_patch_movement_strides,
|
||||
m_patch_selection_rates,
|
||||
m_padding);
|
||||
}
|
||||
|
||||
} // namespace v3
|
||||
} // namespace op
|
||||
} // namespace ov
|
||||
@@ -2,15 +2,36 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "openvino/op/extractimagepatches.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "common_test_utils/test_assertions.hpp"
|
||||
#include "common_test_utils/type_prop.hpp"
|
||||
#include "gtest/gtest.h"
|
||||
#include "ngraph/ngraph.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
using namespace ov;
|
||||
using namespace testing;
|
||||
|
||||
TEST(type_prop, extractimagepatches_default_ctor) {
|
||||
auto data = make_shared<op::v0::Parameter>(element::i32, Shape{64, 3, 10, 10});
|
||||
auto padtype_padding = op::PadType::VALID;
|
||||
|
||||
auto op = make_shared<op::v3::ExtractImagePatches>();
|
||||
op->set_argument(0, data);
|
||||
op->set_sizes({3, 3});
|
||||
op->set_strides({5, 5});
|
||||
op->set_rates({1, 1});
|
||||
op->set_auto_pad(padtype_padding);
|
||||
op->validate_and_infer_types();
|
||||
|
||||
EXPECT_EQ(op->get_input_size(), 1);
|
||||
EXPECT_EQ(op->get_output_element_type(0), element::i32);
|
||||
EXPECT_EQ(op->get_output_shape(0), (Shape{64, 27, 2, 2}));
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_i32) {
|
||||
auto data = make_shared<op::Parameter>(element::i32, Shape{64, 3, 10, 10});
|
||||
auto data = make_shared<op::v0::Parameter>(element::i32, Shape{64, 3, 10, 10});
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{5, 5};
|
||||
auto rates = Shape{1, 1};
|
||||
@@ -22,7 +43,7 @@ TEST(type_prop, extractimagepatches_i32) {
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_i64) {
|
||||
auto data = make_shared<op::Parameter>(element::i64, Shape{64, 3, 10, 10});
|
||||
auto data = make_shared<op::v0::Parameter>(element::i64, Shape{64, 3, 12, 12});
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{5, 5};
|
||||
auto rates = Shape{1, 1};
|
||||
@@ -34,7 +55,7 @@ TEST(type_prop, extractimagepatches_i64) {
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_rates_change) {
|
||||
auto data = make_shared<op::Parameter>(element::i32, Shape{64, 3, 10, 10});
|
||||
auto data = make_shared<op::v0::Parameter>(element::i32, Shape{64, 3, 33, 43});
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{5, 5};
|
||||
auto rates = Shape{2, 2};
|
||||
@@ -42,11 +63,13 @@ TEST(type_prop, extractimagepatches_rates_change) {
|
||||
auto extractimagepatches = make_shared<op::v3::ExtractImagePatches>(data, sizes, strides, rates, padtype_padding);
|
||||
|
||||
EXPECT_EQ(extractimagepatches->get_output_element_type(0), element::i32);
|
||||
EXPECT_EQ(extractimagepatches->get_output_shape(0), (Shape{64, 27, 2, 2}));
|
||||
EXPECT_EQ(extractimagepatches->get_output_shape(0), (Shape{64, 27, 6, 8}));
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_input_shape_change) {
|
||||
auto data = make_shared<op::Parameter>(element::i32, Shape{64, 3, 9, 9});
|
||||
auto data_shape = PartialShape{64, 3, 9, 9};
|
||||
set_shape_labels(data_shape, 10);
|
||||
auto data = make_shared<op::v0::Parameter>(element::i32, data_shape);
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{5, 5};
|
||||
auto rates = Shape{2, 2};
|
||||
@@ -55,10 +78,14 @@ TEST(type_prop, extractimagepatches_input_shape_change) {
|
||||
|
||||
EXPECT_EQ(extractimagepatches->get_output_element_type(0), element::i32);
|
||||
EXPECT_EQ(extractimagepatches->get_output_shape(0), (Shape{64, 27, 1, 1}));
|
||||
EXPECT_THAT(get_shape_labels(extractimagepatches->get_output_partial_shape(0)), ElementsAre(10, 0, 0, 0));
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_dynamic_shape) {
|
||||
auto data = make_shared<op::Parameter>(element::i32, PartialShape::dynamic(4));
|
||||
auto data_shape = PartialShape::dynamic(4);
|
||||
set_shape_labels(data_shape, 10);
|
||||
|
||||
auto data = make_shared<op::v0::Parameter>(element::i32, data_shape);
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{5, 5};
|
||||
auto rates = Shape{2, 2};
|
||||
@@ -66,11 +93,12 @@ TEST(type_prop, extractimagepatches_dynamic_shape) {
|
||||
auto extractimagepatches = make_shared<op::v3::ExtractImagePatches>(data, sizes, strides, rates, padtype_padding);
|
||||
|
||||
EXPECT_EQ(extractimagepatches->get_output_element_type(0), element::i32);
|
||||
EXPECT_TRUE(extractimagepatches->get_output_partial_shape(0).same_scheme(PartialShape::dynamic(4)));
|
||||
EXPECT_EQ(extractimagepatches->get_output_partial_shape(0), PartialShape::dynamic(4));
|
||||
EXPECT_THAT(get_shape_labels(extractimagepatches->get_output_partial_shape(0)), ElementsAre(10, 0, 0, 0));
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_dynamic_batch_shape) {
|
||||
auto data = make_shared<op::Parameter>(element::i32, PartialShape{Dimension::dynamic(), 3, 10, 10});
|
||||
auto data = make_shared<op::v0::Parameter>(element::i32, PartialShape{Dimension::dynamic(), 3, 14, 23});
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{5, 5};
|
||||
auto rates = Shape{1, 1};
|
||||
@@ -78,12 +106,26 @@ TEST(type_prop, extractimagepatches_dynamic_batch_shape) {
|
||||
auto extractimagepatches = make_shared<op::v3::ExtractImagePatches>(data, sizes, strides, rates, padtype_padding);
|
||||
|
||||
EXPECT_EQ(extractimagepatches->get_output_element_type(0), element::i32);
|
||||
EXPECT_TRUE(
|
||||
extractimagepatches->get_output_partial_shape(0).same_scheme(PartialShape{Dimension::dynamic(), 27, 2, 2}));
|
||||
EXPECT_EQ(extractimagepatches->get_output_partial_shape(0), PartialShape({-1, 27, 3, 5}));
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_interval_shape_and_labels) {
|
||||
auto data_shape = PartialShape{{1, 10}, {3, 4}, {10, 51}, {13, 71}};
|
||||
set_shape_labels(data_shape, 10);
|
||||
auto data = make_shared<op::v0::Parameter>(element::i32, data_shape);
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{5, 5};
|
||||
auto rates = Shape{1, 1};
|
||||
auto padtype_padding = op::PadType::VALID;
|
||||
auto extractimagepatches = make_shared<op::v3::ExtractImagePatches>(data, sizes, strides, rates, padtype_padding);
|
||||
|
||||
EXPECT_EQ(extractimagepatches->get_output_element_type(0), element::i32);
|
||||
EXPECT_EQ(extractimagepatches->get_output_partial_shape(0), PartialShape({{1, 10}, {27, 36}, {2, 10}, {3, 14}}));
|
||||
EXPECT_THAT(get_shape_labels(extractimagepatches->get_output_partial_shape(0)), ElementsAre(10, 0, 0, 0));
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_padding_same_lower1) {
|
||||
auto data = make_shared<op::Parameter>(element::i32, Shape{64, 3, 10, 10});
|
||||
auto data = make_shared<op::v0::Parameter>(element::i32, Shape{64, 3, 31, 27});
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{5, 5};
|
||||
auto rates = Shape{1, 1};
|
||||
@@ -91,11 +133,11 @@ TEST(type_prop, extractimagepatches_padding_same_lower1) {
|
||||
auto extractimagepatches = make_shared<op::v3::ExtractImagePatches>(data, sizes, strides, rates, padtype_padding);
|
||||
|
||||
EXPECT_EQ(extractimagepatches->get_output_element_type(0), element::i32);
|
||||
EXPECT_EQ(extractimagepatches->get_output_shape(0), (Shape{64, 27, 2, 2}));
|
||||
EXPECT_EQ(extractimagepatches->get_output_shape(0), (Shape{64, 27, 7, 6}));
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_padding_same_lower2) {
|
||||
auto data = make_shared<op::Parameter>(element::i32, Shape{64, 3, 9, 9});
|
||||
auto data = make_shared<op::v0::Parameter>(element::i32, Shape{64, 3, 9, 9});
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{5, 5};
|
||||
auto rates = Shape{1, 1};
|
||||
@@ -106,7 +148,7 @@ TEST(type_prop, extractimagepatches_padding_same_lower2) {
|
||||
EXPECT_EQ(extractimagepatches->get_output_shape(0), (Shape{64, 27, 2, 2}));
|
||||
}
|
||||
TEST(type_prop, extractimagepatches_padding_same_upper) {
|
||||
auto data = make_shared<op::Parameter>(element::i32, Shape{64, 3, 11, 11});
|
||||
auto data = make_shared<op::v0::Parameter>(element::i32, Shape{64, 3, 23, 11});
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{5, 5};
|
||||
auto rates = Shape{1, 1};
|
||||
@@ -114,11 +156,11 @@ TEST(type_prop, extractimagepatches_padding_same_upper) {
|
||||
auto extractimagepatches = make_shared<op::v3::ExtractImagePatches>(data, sizes, strides, rates, padtype_padding);
|
||||
|
||||
EXPECT_EQ(extractimagepatches->get_output_element_type(0), element::i32);
|
||||
EXPECT_EQ(extractimagepatches->get_output_shape(0), (Shape{64, 27, 3, 3}));
|
||||
EXPECT_EQ(extractimagepatches->get_output_shape(0), (Shape{64, 27, 5, 3}));
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_padding_same_upper2) {
|
||||
auto data = make_shared<op::Parameter>(element::i32, Shape{64, 3, 6, 11});
|
||||
auto data = make_shared<op::v0::Parameter>(element::i32, Shape{64, 3, 6, 11});
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{5, 5};
|
||||
auto rates = Shape{1, 1};
|
||||
@@ -130,7 +172,7 @@ TEST(type_prop, extractimagepatches_padding_same_upper2) {
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_zero_dim_inputs) {
|
||||
auto data = make_shared<op::Parameter>(element::i32, Shape{64, 0, 0, 0});
|
||||
auto data = make_shared<op::v0::Parameter>(element::i32, Shape{64, 0, 0, 0});
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{5, 5};
|
||||
auto rates = Shape{1, 1};
|
||||
@@ -142,7 +184,7 @@ TEST(type_prop, extractimagepatches_zero_dim_inputs) {
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_large_stride_valid_padding) {
|
||||
auto data = make_shared<op::Parameter>(element::i32, Shape{64, 3, 10, 10});
|
||||
auto data = make_shared<op::v0::Parameter>(element::i32, Shape{64, 3, 10, 10});
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{15, 15};
|
||||
auto rates = Shape{1, 1};
|
||||
@@ -154,7 +196,7 @@ TEST(type_prop, extractimagepatches_large_stride_valid_padding) {
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_large_stride_same_padding) {
|
||||
auto data = make_shared<op::Parameter>(element::i32, Shape{64, 3, 10, 10});
|
||||
auto data = make_shared<op::v0::Parameter>(element::i32, Shape{64, 3, 10, 10});
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{15, 15};
|
||||
auto rates = Shape{1, 1};
|
||||
@@ -166,7 +208,7 @@ TEST(type_prop, extractimagepatches_large_stride_same_padding) {
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_dyn) {
|
||||
auto data = make_shared<op::Parameter>(element::i64, PartialShape::dynamic());
|
||||
auto data = make_shared<op::v0::Parameter>(element::i64, PartialShape::dynamic());
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{5, 5};
|
||||
auto rates = Shape{1, 1};
|
||||
@@ -174,5 +216,188 @@ TEST(type_prop, extractimagepatches_dyn) {
|
||||
auto extractimagepatches = make_shared<op::v3::ExtractImagePatches>(data, sizes, strides, rates, padtype_padding);
|
||||
|
||||
EXPECT_EQ(extractimagepatches->get_output_element_type(0), element::i64);
|
||||
EXPECT_TRUE(extractimagepatches->get_output_partial_shape(0).same_scheme(PartialShape::dynamic(4)));
|
||||
EXPECT_EQ(extractimagepatches->get_output_partial_shape(0), PartialShape::dynamic(4));
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_interval_shape_and_labels_padding_same_upper) {
|
||||
auto data_shape = PartialShape{{1, 10}, {3, 4}, {10, 51}, {13, 71}};
|
||||
set_shape_labels(data_shape, 10);
|
||||
auto data = make_shared<op::v0::Parameter>(element::i32, data_shape);
|
||||
auto sizes = Shape{1, 1};
|
||||
auto strides = Strides{5, 5};
|
||||
auto rates = Shape{1, 1};
|
||||
auto padtype_padding = op::PadType::SAME_LOWER;
|
||||
auto extractimagepatches = make_shared<op::v3::ExtractImagePatches>(data, sizes, strides, rates, padtype_padding);
|
||||
|
||||
EXPECT_EQ(extractimagepatches->get_output_element_type(0), element::i32);
|
||||
EXPECT_EQ(extractimagepatches->get_output_partial_shape(0), PartialShape({{1, 10}, {3, 4}, {2, 11}, {3, 15}}));
|
||||
EXPECT_THAT(get_shape_labels(extractimagepatches->get_output_partial_shape(0)), ElementsAre(10, 11, 0, 0));
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_data_not_rank_4d) {
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{5, 5};
|
||||
auto rates = Shape{1, 1};
|
||||
auto padtype_padding = op::PadType::VALID;
|
||||
|
||||
OV_EXPECT_THROW(ignore = make_shared<op::v3::ExtractImagePatches>(
|
||||
make_shared<op::v0::Parameter>(element::i64, PartialShape::dynamic(3)),
|
||||
sizes,
|
||||
strides,
|
||||
rates,
|
||||
padtype_padding),
|
||||
NodeValidationFailure,
|
||||
HasSubstr("input tensor must be 4D tensor"));
|
||||
|
||||
OV_EXPECT_THROW(ignore = make_shared<op::v3::ExtractImagePatches>(
|
||||
make_shared<op::v0::Parameter>(element::i64, PartialShape::dynamic(5)),
|
||||
sizes,
|
||||
strides,
|
||||
rates,
|
||||
padtype_padding),
|
||||
NodeValidationFailure,
|
||||
HasSubstr("input tensor must be 4D tensor"));
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_sizes_has_no_two_elements) {
|
||||
auto data = make_shared<op::v0::Parameter>(element::i64, PartialShape::dynamic());
|
||||
auto sizes = Shape{3};
|
||||
auto strides = Strides{5, 5};
|
||||
auto rates = Shape{1, 1};
|
||||
auto padtype_padding = op::PadType::EXPLICIT;
|
||||
|
||||
OV_EXPECT_THROW(ignore = make_shared<op::v3::ExtractImagePatches>(data, sizes, strides, rates, padtype_padding),
|
||||
NodeValidationFailure,
|
||||
HasSubstr("Attribute sizes should be in [size_rows, size_cols] format"));
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_strides_has_no_two_elements) {
|
||||
auto data = make_shared<op::v0::Parameter>(element::i64, PartialShape::dynamic());
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{5, 5, 1};
|
||||
auto rates = Shape{1, 1};
|
||||
auto padtype_padding = op::PadType::EXPLICIT;
|
||||
|
||||
OV_EXPECT_THROW(ignore = make_shared<op::v3::ExtractImagePatches>(data, sizes, strides, rates, padtype_padding),
|
||||
NodeValidationFailure,
|
||||
HasSubstr("Attribute strides should be in [stride_rows, stride_cols] format"));
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_strides_has_zero_value) {
|
||||
auto data = make_shared<op::v0::Parameter>(element::i64, PartialShape::dynamic());
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{5, 0};
|
||||
auto rates = Shape{1, 1};
|
||||
auto padtype_padding = op::PadType::EXPLICIT;
|
||||
|
||||
OV_EXPECT_THROW(ignore = make_shared<op::v3::ExtractImagePatches>(data, sizes, strides, rates, padtype_padding),
|
||||
NodeValidationFailure,
|
||||
HasSubstr("Attribute strides should be strictly greater than zeros in values"));
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_rates_has_no_two_elements) {
|
||||
auto data = make_shared<op::v0::Parameter>(element::i64, PartialShape::dynamic());
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{5, 5};
|
||||
auto rates = Shape{1};
|
||||
auto padtype_padding = op::PadType::EXPLICIT;
|
||||
|
||||
OV_EXPECT_THROW(ignore = make_shared<op::v3::ExtractImagePatches>(data, sizes, strides, rates, padtype_padding),
|
||||
NodeValidationFailure,
|
||||
HasSubstr("Attribute rates should be in [rate_rows, rate_cols] format"));
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_rates_has_zero_value) {
|
||||
auto data = make_shared<op::v0::Parameter>(element::i64, PartialShape::dynamic());
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{5, 5};
|
||||
auto rates = Shape{0, 1};
|
||||
auto padtype_padding = op::PadType::EXPLICIT;
|
||||
|
||||
OV_EXPECT_THROW(ignore = make_shared<op::v3::ExtractImagePatches>(data, sizes, strides, rates, padtype_padding),
|
||||
NodeValidationFailure,
|
||||
HasSubstr("Attribute rates should be strictly greater than zeros in values"));
|
||||
}
|
||||
|
||||
TEST(type_prop, extractimagepatches_not_supported_padding) {
|
||||
auto data = make_shared<op::v0::Parameter>(element::i64, PartialShape::dynamic());
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{5, 5};
|
||||
auto rates = Shape{1, 1};
|
||||
auto padtype_padding = op::PadType::EXPLICIT;
|
||||
|
||||
OV_EXPECT_THROW(ignore = make_shared<op::v3::ExtractImagePatches>(data, sizes, strides, rates, padtype_padding),
|
||||
NodeValidationFailure,
|
||||
HasSubstr("Attribute padding should be in either valid or same_lower or same_upper"));
|
||||
}
|
||||
|
||||
using ExtractImagesPatchesParams = std::tuple<op::PadType,
|
||||
size_t, // size
|
||||
size_t, // rate
|
||||
size_t // stride
|
||||
>;
|
||||
|
||||
class ExtractImagesPatchesV3Test : public TypePropOpTest<op::v3::ExtractImagePatches>,
|
||||
public WithParamInterface<ExtractImagesPatchesParams> {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
const auto& p = GetParam();
|
||||
|
||||
pad_type = std::get<0>(p);
|
||||
sizes = Shape(2, std::get<1>(p));
|
||||
rates = Shape(2, std::get<2>(p));
|
||||
strides = Shape(2, std::get<3>(p));
|
||||
}
|
||||
|
||||
int64_t calc_shape_padding(const int64_t input,
|
||||
const int64_t rate,
|
||||
const int64_t stride,
|
||||
const int64_t patch_size,
|
||||
const op::PadType type) {
|
||||
int64_t out = 0;
|
||||
if (type == op::PadType::VALID) {
|
||||
out = (input - rate * (patch_size - 1) - 1) / stride + 1;
|
||||
} else {
|
||||
out = 1 + (input - 1) / stride;
|
||||
}
|
||||
return out < 0 ? 0 : out;
|
||||
}
|
||||
|
||||
PartialShape exp_shape() {
|
||||
auto shape = PartialShape{dim0, dim1, -1, -1};
|
||||
shape[1] *= sizes[0] * sizes[1];
|
||||
shape[2] = calc_shape_padding(100,
|
||||
static_cast<int64_t>(rates[0]),
|
||||
static_cast<int64_t>(strides[0]),
|
||||
static_cast<int64_t>(sizes[0]),
|
||||
pad_type);
|
||||
shape[3] = calc_shape_padding(100,
|
||||
static_cast<int64_t>(rates[1]),
|
||||
static_cast<int64_t>(strides[1]),
|
||||
static_cast<int64_t>(sizes[1]),
|
||||
pad_type);
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
Shape sizes, rates;
|
||||
Strides strides;
|
||||
op::PadType pad_type;
|
||||
int64_t dim0 = 64, dim1 = 2;
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(type_prop,
|
||||
ExtractImagesPatchesV3Test,
|
||||
Combine(Values(op::PadType::VALID, op::PadType::SAME_LOWER),
|
||||
Range<size_t>(1, 11),
|
||||
Range<size_t>(1, 11),
|
||||
Range<size_t>(1, 11)),
|
||||
PrintToStringParamName());
|
||||
|
||||
TEST_P(ExtractImagesPatchesV3Test, check_calc_padding) {
|
||||
auto data = make_shared<op::v0::Parameter>(element::i32, PartialShape{dim0, dim1, 100, 100});
|
||||
auto extractimagepatches = make_shared<op::v3::ExtractImagePatches>(data, sizes, strides, rates, pad_type);
|
||||
|
||||
EXPECT_EQ(extractimagepatches->get_output_element_type(0), element::i32);
|
||||
EXPECT_EQ(extractimagepatches->get_output_partial_shape(0), exp_shape());
|
||||
}
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
// Copyright (C) 2018-2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "utils.hpp"
|
||||
|
||||
using namespace ov;
|
||||
using namespace ov::intel_cpu;
|
||||
|
||||
TEST(StaticShapeInferenceTest, ExtractImagePatchesTest) {
|
||||
auto data = std::make_shared<op::v0::Parameter>(element::i32, PartialShape{-1, -1, -1, -1});
|
||||
auto sizes = Shape{3, 3};
|
||||
auto strides = Strides{5, 5};
|
||||
auto rates = Shape{1, 1};
|
||||
auto padTypePadding = op::PadType::VALID;
|
||||
auto extractImagePatches =
|
||||
std::make_shared<op::v3::ExtractImagePatches>(data, sizes, strides, rates, padTypePadding);
|
||||
// Test StaticShape
|
||||
std::vector<StaticShape> static_input_shapes = {StaticShape{64, 3, 10, 10}}, static_output_shapes = {StaticShape{}};
|
||||
|
||||
shape_inference(extractImagePatches.get(), static_input_shapes, static_output_shapes);
|
||||
ASSERT_EQ(static_output_shapes[0], (StaticShape{64, 27, 2, 2}));
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
|
||||
// Copyright (C) 2018-2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "common_test_utils/test_assertions.hpp"
|
||||
#include "extract_image_patches_shape_inference.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
using namespace ov;
|
||||
using namespace ov::intel_cpu;
|
||||
using namespace testing;
|
||||
|
||||
class StaticShapeExtractImagePatchesV3Test : public OpStaticShapeInferenceTest<op::v3::ExtractImagePatches> {};
|
||||
|
||||
TEST_F(StaticShapeExtractImagePatchesV3Test, default_ctor_no_args) {
|
||||
auto pad_type = op::PadType::VALID;
|
||||
|
||||
op = make_op();
|
||||
op->set_sizes({3, 3});
|
||||
op->set_strides({5, 5});
|
||||
op->set_rates({1, 1});
|
||||
op->set_auto_pad(pad_type);
|
||||
|
||||
input_shapes = ShapeVector{{10, 8, 12, 6}};
|
||||
shape_inference(op.get(), input_shapes, output_shapes);
|
||||
|
||||
EXPECT_EQ(output_shapes.size(), 1);
|
||||
EXPECT_EQ(output_shapes.front(), StaticShape({10, 72, 2, 1}));
|
||||
}
|
||||
|
||||
TEST_F(StaticShapeExtractImagePatchesV3Test, data_input_is_dynamic_rank) {
|
||||
const auto data = std::make_shared<op::v0::Parameter>(element::f32, ov::PartialShape::dynamic());
|
||||
op = make_op(data, ov::Shape{3, 3}, ov::Strides{5, 5}, ov::Shape{2, 2}, op::PadType::VALID);
|
||||
|
||||
input_shapes = ShapeVector{{2, 2, 23, 24}};
|
||||
shape_inference(op.get(), input_shapes, output_shapes);
|
||||
|
||||
EXPECT_EQ(output_shapes.size(), 1);
|
||||
EXPECT_EQ(output_shapes.front(), StaticShape({2, 18, 4, 4}));
|
||||
}
|
||||
|
||||
TEST_F(StaticShapeExtractImagePatchesV3Test, data_input_is_static_rank) {
|
||||
const auto data = std::make_shared<op::v0::Parameter>(element::f32, ov::PartialShape::dynamic(4));
|
||||
op = make_op(data, ov::Shape{3, 3}, ov::Strides{5, 5}, ov::Shape{1, 1}, op::PadType::SAME_UPPER);
|
||||
|
||||
input_shapes = ShapeVector{{2, 2, 43, 34}};
|
||||
shape_inference(op.get(), input_shapes, output_shapes);
|
||||
|
||||
EXPECT_EQ(output_shapes.size(), 1);
|
||||
EXPECT_EQ(output_shapes.front(), StaticShape({2, 18, 9, 7}));
|
||||
}
|
||||
|
||||
TEST_F(StaticShapeExtractImagePatchesV3Test, data_shape_not_compatible_rank_4) {
|
||||
const auto data = std::make_shared<op::v0::Parameter>(element::f32, ov::PartialShape::dynamic(4));
|
||||
op = make_op(data, ov::Shape{3, 3}, ov::Strides{5, 5}, ov::Shape{1, 1}, op::PadType::SAME_UPPER);
|
||||
|
||||
OV_EXPECT_THROW(shape_inference(op.get(), ShapeVector{{2, 20, 12, 24, 1}}, output_shapes),
|
||||
NodeValidationFailure,
|
||||
HasSubstr("input tensor must be 4D tensor"));
|
||||
}
|
||||
Reference in new issue
Block a user