GridSample operator (#11770)

This commit is contained in:
Tomasz Dołbniak authored and GitHub committed 2022-06-09 14:21:53 +00:00
1 parent 5fa669785c
commit 0932c74ff8
25 files changed
+678 -2

No files matched your search

@@ -78,6 +78,7 @@ from ngraph.opset9 import gelu
from ngraph.opset9 import generate_proposals
from ngraph.opset9 import greater
from ngraph.opset9 import greater_equal
from ngraph.opset9 import grid_sample
from ngraph.opset9 import grn
from ngraph.opset9 import group_convolution
from ngraph.opset9 import group_convolution_backprop_data
@@ -62,6 +62,7 @@ from ngraph.opset7.ops import gelu
from ngraph.opset9.ops import generate_proposals
from ngraph.opset1.ops import greater
from ngraph.opset1.ops import greater_equal
from ngraph.opset9.ops import grid_sample
from ngraph.opset1.ops import grn
from ngraph.opset1.ops import group_convolution
from ngraph.opset1.ops import group_convolution_backprop_data
@@ -298,3 +298,34 @@ def generate_proposals(
}
return _get_node_factory_opset9().create("GenerateProposals", inputs, attributes)
def grid_sample(
data: NodeInput,
grid: NodeInput,
attributes: dict,
name: Optional[str] = None
) -> Node:
"""Return a node which performs GridSample operation.
:param data: The input image.
:param grid: Grid values (normalized input coordinates).
:param attributes: A dictionary containing GridSample's attributes.
:param name: Optional name of the node.
Available attributes:
* align_corners A flag which specifies whether to align the grid extrema values
with the borders or center points of the input tensor's border pixels.
Range of values: true, false
Default value: false
Required: no
* mode Specifies the type of interpolation.
Range of values: bilinear, bicubic, nearest
Default value: bilinear
Required: no
* padding_mode Specifies how the out-of-bounds coordinates should be handled.
Range of values: zeros, border, reflection
Default value: zeros
Required: no
:return: A new GridSample node.
"""
return _get_node_factory_opset9().create("GridSample", as_nodes(data, grid), attributes)
@@ -62,6 +62,7 @@ from openvino.runtime.opset7.ops import gelu
from openvino.runtime.opset9.ops import generate_proposals
from openvino.runtime.opset1.ops import greater
from openvino.runtime.opset1.ops import greater_equal
from openvino.runtime.opset9.ops import grid_sample
from openvino.runtime.opset1.ops import grn
from openvino.runtime.opset1.ops import group_convolution
from openvino.runtime.opset1.ops import group_convolution_backprop_data
@@ -298,3 +298,34 @@ def generate_proposals(
}
return _get_node_factory_opset9().create("GenerateProposals", inputs, attributes)
def grid_sample(
data: NodeInput,
grid: NodeInput,
attributes: dict,
name: Optional[str] = None
) -> Node:
"""Return a node which performs GridSample operation.
:param data: The input image.
:param grid: Grid values (normalized input coordinates).
:param attributes: A dictionary containing GridSample's attributes.
:param name: Optional name of the node.
Available attributes:
* align_corners A flag which specifies whether to align the grid extrema values
with the borders or center points of the input tensor's border pixels.
Range of values: true, false
Default value: false
Required: no
* mode Specifies the type of interpolation.
Range of values: bilinear, bicubic, nearest
Default value: bilinear
Required: no
* padding_mode Specifies how the out-of-bounds coordinates should be handled.
Range of values: zeros, border, reflection
Default value: zeros
Required: no
:return: A new GridSample node.
"""
return _get_node_factory_opset9().create("GridSample", as_nodes(data, grid), attributes)
@@ -2136,3 +2136,38 @@ def test_generate_proposals():
assert node.get_output_element_type(0) == Type.f32
assert node.get_output_element_type(1) == Type.f32
assert node.get_output_element_type(2) == Type.i32
def test_grid_sample_default():
img = ov.parameter([1, 3, 100, 100], dtype=np.int32, name="image")
grid = ov.parameter([1, 10, 10, 2], dtype=np.float32, name="grid")
node = ov.grid_sample(img, grid, {})
assert node.get_type_name() == "GridSample"
assert node.get_output_size() == 1
assert list(node.get_output_shape(0)) == [1, 3, 10, 10]
assert node.get_output_element_type(0) == Type.i32
def test_grid_sample_custom_attributes():
img = ov.parameter([1, 3, 100, 100], dtype=np.int32, name="image")
grid = ov.parameter([1, 5, 6, 2], dtype=np.float32, name="grid")
attributes = {
"align_corners": True,
"mode": "nearest",
"padding_mode": "reflection"
}
node = ov.grid_sample(img, grid, attributes)
assert node.get_type_name() == "GridSample"
assert node.get_output_size() == 1
assert list(node.get_output_shape(0)) == [1, 3, 5, 6]
assert node.get_output_element_type(0) == Type.i32
node_attributes = node.get_attributes()
assert node_attributes["align_corners"] is True
assert node_attributes["mode"] == "nearest"
assert node_attributes["padding_mode"] == "reflection"
@@ -2203,3 +2203,38 @@ def test_generate_proposals():
assert node.get_output_element_type(0) == Type.f32
assert node.get_output_element_type(1) == Type.f32
assert node.get_output_element_type(2) == Type.i32
def test_grid_sample_default():
img = ng.parameter([1, 3, 100, 100], dtype=np.int32, name="image")
grid = ng.parameter([1, 10, 10, 2], dtype=np.float32, name="grid")
node = ng.grid_sample(img, grid, {})
assert node.get_type_name() == "GridSample"
assert node.get_output_size() == 1
assert list(node.get_output_shape(0)) == [1, 3, 10, 10]
assert node.get_output_element_type(0) == Type.i32
def test_grid_sample_custom_attributes():
img = ng.parameter([1, 3, 100, 100], dtype=np.int32, name="image")
grid = ng.parameter([1, 5, 6, 2], dtype=np.float32, name="grid")
attributes = {
"align_corners": True,
"mode": "nearest",
"padding_mode": "reflection"
}
node = ng.grid_sample(img, grid, attributes)
assert node.get_type_name() == "GridSample"
assert node.get_output_size() == 1
assert list(node.get_output_shape(0)) == [1, 3, 5, 6]
assert node.get_output_element_type(0) == Type.i32
node_attributes = node.get_attributes()
assert node_attributes["align_corners"] is True
assert node_attributes["mode"] == "nearest"
assert node_attributes["padding_mode"] == "reflection"
@@ -0,0 +1,16 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "ngraph/op/op.hpp"
#include "openvino/op/grid_sample.hpp"
namespace ngraph {
namespace op {
namespace v9 {
using ov::op::v9::GridSample;
} // namespace v9
} // namespace op
} // namespace ngraph
+1
View File
@@ -69,6 +69,7 @@
#include "ngraph/op/generate_proposals.hpp"
#include "ngraph/op/greater.hpp"
#include "ngraph/op/greater_eq.hpp"
#include "ngraph/op/grid_sample.hpp"
#include "ngraph/op/grn.hpp"
#include "ngraph/op/group_conv.hpp"
#include "ngraph/op/gru_cell.hpp"
@@ -0,0 +1,82 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "openvino/core/attribute_adapter.hpp"
#include "openvino/op/op.hpp"
#include "openvino/op/util/attr_types.hpp"
namespace ov {
namespace op {
namespace v9 {
/// \brief Operator performing interpolated sampling of the input tensor
/// \ingroup ov_ops_cpp_api
class OPENVINO_API GridSample : public Op {
public:
OPENVINO_OP("GridSample", "opset9");
enum class InterpolationMode { BILINEAR, BICUBIC, NEAREST };
enum class PaddingMode { ZEROS, BORDER, REFLECTION };
/// \brief A Structure which contains all GridSample attributes
struct Attributes {
// A flag which specifies whether to align the grid extrema values with the borders or center points
// of the input tensor's border pixels.
bool align_corners = false;
// Specifies the type of interpolation: `bilinear`, `bicubic`, `nearest`
InterpolationMode mode = InterpolationMode::BILINEAR;
// Specifies how the out-of-bounds coordinates should be handled: `zeros`, `border`, `reflection`
PaddingMode padding_mode = PaddingMode::ZEROS;
};
GridSample() = default;
/// \brief Constructs a GridSample operation
///
/// \param data Input data tensor (input image)
/// \param grid Normalized interpolation coordinates
/// \param attrs GridSample attributes
GridSample(const Output<Node>& data, const Output<Node>& grid, const Attributes& attributes);
bool visit_attributes(AttributeVisitor& visitor) override;
void validate_and_infer_types() override;
std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override;
const Attributes& get_attributes() const {
return m_attributes;
}
private:
Attributes m_attributes = {};
};
} // namespace v9
} // namespace op
OPENVINO_API
std::ostream& operator<<(std::ostream& s, const op::v9::GridSample::InterpolationMode& type);
OPENVINO_API
std::ostream& operator<<(std::ostream& s, const op::v9::GridSample::PaddingMode& type);
template <>
class OPENVINO_API AttributeAdapter<op::v9::GridSample::InterpolationMode>
: public EnumAttributeAdapterBase<op::v9::GridSample::InterpolationMode> {
public:
AttributeAdapter(op::v9::GridSample::InterpolationMode& value)
: EnumAttributeAdapterBase<op::v9::GridSample::InterpolationMode>(value) {}
OPENVINO_RTTI("AttributeAdapter<ov::op::v9::GridSample::InterpolationMode>");
};
template <>
class OPENVINO_API AttributeAdapter<op::v9::GridSample::PaddingMode>
: public EnumAttributeAdapterBase<op::v9::GridSample::PaddingMode> {
public:
AttributeAdapter(op::v9::GridSample::PaddingMode& value)
: EnumAttributeAdapterBase<op::v9::GridSample::PaddingMode>(value) {}
OPENVINO_RTTI("AttributeAdapter<ov::op::v9::GridSample::PaddingMode>");
};
} // namespace ov
+1
View File
@@ -68,6 +68,7 @@
#include "openvino/op/generate_proposals.hpp"
#include "openvino/op/greater.hpp"
#include "openvino/op/greater_eq.hpp"
#include "openvino/op/grid_sample.hpp"
#include "openvino/op/grn.hpp"
#include "openvino/op/group_conv.hpp"
#include "openvino/op/gru_cell.hpp"
@@ -43,6 +43,7 @@ _OPENVINO_OP_REG(FloorMod, ov::op::v1)
_OPENVINO_OP_REG(GatherTree, ov::op::v1)
_OPENVINO_OP_REG(Greater, ov::op::v1)
_OPENVINO_OP_REG(GreaterEqual, ov::op::v1)
_OPENVINO_OP_REG(GridSample, ov::op::v9)
_OPENVINO_OP_REG(GroupConvolution, ov::op::v1)
_OPENVINO_OP_REG(GroupConvolutionBackpropData, ov::op::v1)
_OPENVINO_OP_REG(GRN, ov::op::v0)
@@ -0,0 +1,65 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <ngraph/validation_util.hpp>
#include <openvino/op/grid_sample.hpp>
#include <vector>
namespace ov {
namespace op {
namespace v9 {
template <class shape_t>
void shape_infer(const GridSample* op, const std::vector<shape_t>& input_shapes, std::vector<shape_t>& output_shapes) {
NODE_VALIDATION_CHECK(op,
input_shapes.size() == 2 && output_shapes.size() == 1,
"Incorrect number of input/output shapes in GridSample's shape inference function");
const auto& data_shape = input_shapes[0];
NODE_VALIDATION_CHECK(op, data_shape.rank().compatible(4), "The supported shape of the input data tensor is 4D.");
const auto& grid_shape = input_shapes[1];
NODE_VALIDATION_CHECK(op, grid_shape.rank().compatible(4), "The supported shape of the grid tensor is 4D.");
shape_t output_shape;
output_shape.resize(4);
auto& batch_dim = output_shape[0];
auto& channel_dim = output_shape[1];
auto& H_out_dim = output_shape[2];
auto& W_out_dim = output_shape[3];
if (grid_shape.rank().is_static()) {
NODE_VALIDATION_CHECK(op,
grid_shape[3].compatible(2),
"The last dimension of grid tensor's shape has to be equal to 2.");
batch_dim = grid_shape[0];
H_out_dim = grid_shape[1];
W_out_dim = grid_shape[2];
if (data_shape.rank().is_static()) {
NODE_VALIDATION_CHECK(
op,
data_shape[0].compatible(grid_shape[0]),
"The batch dimension in the input data tensor's shape doesn't match the batch dimension in "
"the grid tensor's shape.");
// both dimensions should match but use the one which is (possibly) static for the output shape
if (data_shape[0].is_static()) {
batch_dim = data_shape[0];
}
channel_dim = data_shape[1];
}
} else if (data_shape.rank().is_static()) {
batch_dim = data_shape[0];
channel_dim = data_shape[1];
}
output_shapes[0] = std::move(output_shape);
}
} // namespace v9
} // namespace op
} // namespace ov
+65
View File
@@ -0,0 +1,65 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "openvino/op/grid_sample.hpp"
#include "grid_sample_shape_inference.hpp"
#include "itt.hpp"
namespace ov {
op::v9::GridSample::GridSample(const Output<Node>& data, const Output<Node>& grid, const Attributes& attributes)
: op::Op{{data, grid}},
m_attributes{attributes} {
constructor_validate_and_infer_types();
}
bool op::v9::GridSample::visit_attributes(AttributeVisitor& visitor) {
NGRAPH_OP_SCOPE(v9_GridSample_visit_attributes);
visitor.on_attribute("align_corners", m_attributes.align_corners);
visitor.on_attribute("mode", m_attributes.mode);
visitor.on_attribute("padding_mode", m_attributes.padding_mode);
return true;
}
void op::v9::GridSample::validate_and_infer_types() {
NGRAPH_OP_SCOPE(v9_GridSample_validate_and_infer_types);
NODE_VALIDATION_CHECK(this,
get_input_element_type(1).is_real(),
"The element type of the grid input tensor must be a floating point type.");
std::vector<PartialShape> out_shapes(1);
shape_infer(this, {get_input_partial_shape(0), get_input_partial_shape(1)}, out_shapes);
set_output_type(0, get_input_element_type(0), out_shapes[0]);
}
std::shared_ptr<Node> op::v9::GridSample::clone_with_new_inputs(const OutputVector& new_args) const {
NGRAPH_OP_SCOPE(v9_GridSample_clone_with_new_inputs);
check_new_args_count(this, new_args);
return std::make_shared<op::v9::GridSample>(new_args.at(0), new_args.at(1), this->get_attributes());
}
std::ostream& operator<<(std::ostream& s, const op::v9::GridSample::InterpolationMode& mode) {
return s << as_string(mode);
}
template <>
NGRAPH_API EnumNames<op::v9::GridSample::InterpolationMode>& EnumNames<op::v9::GridSample::InterpolationMode>::get() {
static auto enum_names =
EnumNames<op::v9::GridSample::InterpolationMode>("op::v9::GridSample::InterpolationMode",
{{"bilinear", op::v9::GridSample::InterpolationMode::BILINEAR},
{"bicubic", op::v9::GridSample::InterpolationMode::BICUBIC},
{"nearest", op::v9::GridSample::InterpolationMode::NEAREST}});
return enum_names;
}
template <>
NGRAPH_API EnumNames<op::v9::GridSample::PaddingMode>& EnumNames<op::v9::GridSample::PaddingMode>::get() {
static auto enum_names =
EnumNames<op::v9::GridSample::PaddingMode>("op::v9::GridSample::PaddingMode",
{{"zeros", op::v9::GridSample::PaddingMode::ZEROS},
{"border", op::v9::GridSample::PaddingMode::BORDER},
{"reflection", op::v9::GridSample::PaddingMode::REFLECTION}});
return enum_names;
}
} // namespace ov
+2
View File
@@ -148,6 +148,7 @@ set(SRC
type_prop/gather_nd.cpp
type_prop/gather_tree.cpp
type_prop/gelu.cpp
type_prop/grid_sample.cpp
type_prop/grn.cpp
type_prop/group_convolution.cpp
type_prop/group_convolution_backprop_data.cpp
@@ -300,6 +301,7 @@ set(SRC
visitors/op/experimental_detectron_detection_output.cpp
visitors/op/experimental_detectron_generate_proposals.cpp
visitors/op/generate_proposals.cpp
visitors/op/grid_sample.cpp
visitors/op/experimental_detectron_prior_grid_generator.cpp
visitors/op/experimental_detectron_topkrois.cpp
visitors/op/eye.cpp
@@ -0,0 +1,95 @@
ir_version: 8
producer_name: "onnx"
graph {
node {
input: "X"
input: "Grid"
output: "Y"
op_type: "GridSample"
attribute {
name: "align_corners"
i: 0
type: INT
}
attribute {
name: "mode"
s: "bilinear"
type: STRING
}
attribute {
name: "padding_mode"
s: "zeros"
type: STRING
}
}
name: "test_gridsample"
input {
name: "X"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 1
}
dim {
dim_value: 1
}
dim {
dim_value: 4
}
dim {
dim_value: 4
}
}
}
}
}
input {
name: "Grid"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 1
}
dim {
dim_value: 6
}
dim {
dim_value: 6
}
dim {
dim_value: 2
}
}
}
}
}
output {
name: "Y"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 1
}
dim {
dim_value: 1
}
dim {
dim_value: 6
}
dim {
dim_value: 6
}
}
}
}
}
}
opset_import {
version: 16
}
+1 -1
View File
@@ -158,7 +158,7 @@ TEST(opset, opset9_dump) {
std::cout << t.name << " ";
}
std::cout << std::endl;
ASSERT_EQ(172, opset.get_types_info().size());
ASSERT_EQ(173, opset.get_types_info().size());
}
class MyOpOld : public ov::op::Op {
+104
View File
@@ -0,0 +1,104 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "gtest/gtest.h"
#include "openvino/opsets/opset9.hpp"
#include "util/type_prop.hpp"
using namespace std;
using namespace ov;
TEST(type_prop, grid_sample_default) {
const auto data = make_shared<opset9::Parameter>(element::i32, PartialShape{1, 3, 224, 224});
const auto grid = make_shared<opset9::Parameter>(element::f32, PartialShape{1, 10, 10, 2});
const auto grid_sample = make_shared<opset9::GridSample>(data, grid, opset9::GridSample::Attributes{});
EXPECT_EQ(grid_sample->get_element_type(), data->get_element_type())
<< "The output element type of GridSample doesn't match the input data element type";
EXPECT_TRUE(grid_sample->get_output_partial_shape(0).same_scheme(PartialShape{1, 3, 10, 10}))
<< "The output shape of GridSample is incorrect";
}
TEST(type_prop, grid_sample_dynamic_batch) {
const auto data = make_shared<opset9::Parameter>(element::i32, PartialShape{Dimension::dynamic(), 3, 224, 224});
const auto grid = make_shared<opset9::Parameter>(element::f32, PartialShape{Dimension::dynamic(), 10, 10, 2});
const auto grid_sample = make_shared<opset9::GridSample>(data, grid, opset9::GridSample::Attributes{});
EXPECT_TRUE(grid_sample->get_output_partial_shape(0).same_scheme(PartialShape{Dimension::dynamic(), 3, 10, 10}))
<< "The output shape of GridSample is incorrect";
}
TEST(type_prop, grid_sample_dynamic_output_spatials) {
const auto data = make_shared<opset9::Parameter>(element::i32, PartialShape{2, 3, 224, 224});
const auto grid =
make_shared<opset9::Parameter>(element::f64, PartialShape{2, Dimension::dynamic(), Dimension::dynamic(), 2});
const auto grid_sample = make_shared<opset9::GridSample>(data, grid, opset9::GridSample::Attributes{});
EXPECT_TRUE(grid_sample->get_output_partial_shape(0).same_scheme(
PartialShape{2, 3, Dimension::dynamic(), Dimension::dynamic()}))
<< "The output shape of GridSample is incorrect";
}
TEST(type_prop, grid_sample_unsupported_grid_rank) {
const auto data = make_shared<opset9::Parameter>(element::i32, PartialShape{1, 3, 224, 224});
const auto grid = make_shared<opset9::Parameter>(element::f64, PartialShape{1, 2, 3, 4, 5});
EXPECT_THROW(opset9::GridSample(data, grid, opset9::GridSample::Attributes{}), ov::NodeValidationFailure);
}
TEST(type_prop, grid_sample_unsupported_data_rank) {
const auto data = make_shared<opset9::Parameter>(element::i32, PartialShape{1, 3, 224, 224, 224});
const auto grid = make_shared<opset9::Parameter>(element::f64, PartialShape{1, 5, 5, 2});
EXPECT_THROW(opset9::GridSample(data, grid, opset9::GridSample::Attributes{}), ov::NodeValidationFailure);
}
TEST(type_prop, grid_sample_unsupported_grid_element_type) {
const auto data = make_shared<opset9::Parameter>(element::i32, PartialShape{1, 3, 224, 224});
const auto grid = make_shared<opset9::Parameter>(element::i64, PartialShape{1, 5, 5, 2});
EXPECT_THROW(opset9::GridSample(data, grid, opset9::GridSample::Attributes{}), ov::NodeValidationFailure);
}
TEST(type_prop, grid_sample_incorrect_last_dim_in_grid) {
const auto data = make_shared<opset9::Parameter>(element::i32, PartialShape{1, 3, 224, 224});
const auto grid = make_shared<opset9::Parameter>(element::f32, PartialShape{1, 5, 5, 5});
EXPECT_THROW(opset9::GridSample(data, grid, opset9::GridSample::Attributes{}), ov::NodeValidationFailure);
}
TEST(type_prop, grid_sample_all_dimensions_dynamic_in_grid) {
const auto data = make_shared<opset9::Parameter>(element::i32, PartialShape{1, 3, 224, 224});
const auto grid = make_shared<opset9::Parameter>(
element::f32,
PartialShape{Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic()});
const auto grid_sample = make_shared<opset9::GridSample>(data, grid, opset9::GridSample::Attributes{});
EXPECT_TRUE(grid_sample->get_output_partial_shape(0).same_scheme(
PartialShape{1, 3, Dimension::dynamic(), Dimension::dynamic()}))
<< "The output shape of GridSample is incorrect";
}
TEST(type_prop, grid_sample_all_dimensions_dynamic_in_data) {
const auto data = make_shared<opset9::Parameter>(
element::f16,
PartialShape{Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic()});
const auto grid = make_shared<opset9::Parameter>(element::f32, PartialShape{Dimension::dynamic(), 3, 5, 2});
const auto grid_sample = make_shared<opset9::GridSample>(data, grid, opset9::GridSample::Attributes{});
EXPECT_TRUE(grid_sample->get_output_partial_shape(0).same_scheme(
PartialShape{Dimension::dynamic(), Dimension::dynamic(), 3, 5}))
<< "The output shape of GridSample is incorrect";
}
TEST(type_prop, grid_sample_dynamic_input_rank) {
const auto data = make_shared<opset9::Parameter>(element::f16, PartialShape::dynamic());
const auto grid = make_shared<opset9::Parameter>(element::f32, PartialShape{1, 5, 5, 2});
const auto grid_sample = make_shared<opset9::GridSample>(data, grid, opset9::GridSample::Attributes{});
EXPECT_TRUE(grid_sample->get_output_partial_shape(0).same_scheme(PartialShape{1, Dimension::dynamic(), 5, 5}))
<< "The output shape of GridSample is incorrect";
}
TEST(type_prop, grid_sample_dynamic_rank_of_data_and_grid) {
const auto data = make_shared<opset9::Parameter>(element::f16, PartialShape::dynamic());
const auto grid = make_shared<opset9::Parameter>(element::f32, PartialShape::dynamic());
const auto grid_sample = make_shared<opset9::GridSample>(data, grid, opset9::GridSample::Attributes{});
EXPECT_TRUE(grid_sample->get_output_partial_shape(0).same_scheme(
PartialShape{Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic()}))
<< "The output shape of GridSample is incorrect";
}
@@ -0,0 +1,25 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "gtest/gtest.h"
#include "ngraph/ngraph.hpp"
#include "ngraph/op/util/attr_types.hpp"
#include "openvino/opsets/opset9.hpp"
#include "util/visitor.hpp"
using namespace std;
using namespace ov;
using ngraph::test::NodeBuilder;
TEST(attributes, grid_sample_defaults) {
NodeBuilder::get_ops().register_factory<opset9::GridSample>();
const auto data = make_shared<opset9::Parameter>(element::f32, Shape{1, 3, 10, 10});
const auto grid = make_shared<opset9::Parameter>(element::f32, Shape{1, 5, 5, 2});
const auto op = make_shared<opset9::GridSample>(data, grid, opset9::GridSample::Attributes{});
NodeBuilder builder(op);
const auto expected_attr_count = 3;
EXPECT_EQ(builder.get_value_map_size(), expected_attr_count);
}
@@ -0,0 +1,31 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "op/grid_sample.hpp"
#include "openvino/opsets/opset9.hpp"
namespace ngraph {
namespace onnx_import {
namespace op {
namespace set_1 {
OutputVector grid_sample(const Node& node) {
const auto data = node.get_ng_inputs().at(0);
const auto grid = node.get_ng_inputs().at(1);
ov::opset9::GridSample::Attributes attributes{};
attributes.align_corners = node.get_attribute_value<int64_t>("align_corners", 0);
attributes.mode = EnumNames<ov::opset9::GridSample::InterpolationMode>::as_enum(
node.get_attribute_value<std::string>("mode", "bilinear"));
attributes.padding_mode = EnumNames<ov::opset9::GridSample::PaddingMode>::as_enum(
node.get_attribute_value<std::string>("padding_mode", "zeros"));
return {std::make_shared<ov::opset9::GridSample>(data, grid, attributes)};
}
} // namespace set_1
} // namespace op
} // namespace onnx_import
} // namespace ngraph
@@ -0,0 +1,22 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "ngraph/node.hpp"
#include "onnx_import/core/node.hpp"
namespace ngraph {
namespace onnx_import {
namespace op {
namespace set_1 {
OutputVector grid_sample(const Node& node);
} // namespace set_1
} // namespace op
} // namespace onnx_import
} // namespace ngraph
@@ -69,6 +69,7 @@
#include "op/global_average_pool.hpp"
#include "op/global_max_pool.hpp"
#include "op/greater.hpp"
#include "op/grid_sample.hpp"
#include "op/gru.hpp"
#include "op/hard_sigmoid.hpp"
#include "op/hard_swish.hpp"
@@ -344,6 +345,7 @@ OperatorsBridge::OperatorsBridge() {
REGISTER_OPERATOR("GlobalLpPool", 1, global_lp_pool);
REGISTER_OPERATOR("GlobalMaxPool", 1, global_max_pool);
REGISTER_OPERATOR("Greater", 1, greater);
REGISTER_OPERATOR("GridSample", 1, grid_sample);
REGISTER_OPERATOR("GRU", 1, gru);
REGISTER_OPERATOR("Hardmax", 1, hardmax);
REGISTER_OPERATOR("Hardmax", 13, hardmax);
@@ -5154,3 +5154,28 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_model_softsign) {
test_case.add_expected_output(output);
test_case.run();
}
NGRAPH_TEST(${BACKEND_NAME}, onnx_grid_sample) {
const auto function = onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/grid_sample.onnx"));
auto test_case = test::TestCase(function, s_device);
test_case.add_input<float>(Shape{1, 1, 4, 4}, gen_range<float>(16));
test_case.add_input<float>(
Shape{1, 6, 6, 2},
{-1.0000f, -1.0000f, -0.6000f, -1.0000f, -0.2000f, -1.0000f, 0.2000f, -1.0000f, 0.6000f, -1.0000f, 1.0000f,
-1.0000f, -1.0000f, -0.6000f, -0.6000f, -0.6000f, -0.2000f, -0.6000f, 0.2000f, -0.6000f, 0.6000f, -0.6000f,
1.0000f, -0.6000f, -1.0000f, -0.2000f, -0.6000f, -0.2000f, -0.2000f, -0.2000f, 0.2000f, -0.2000f, 0.6000f,
-0.2000f, 1.0000f, -0.2000f, -1.0000f, 0.2000f, -0.6000f, 0.2000f, -0.2000f, 0.2000f, 0.2000f, 0.2000f,
0.6000f, 0.2000f, 1.0000f, 0.2000f, -1.0000f, 0.6000f, -0.6000f, 0.6000f, -0.2000f, 0.6000f, 0.2000f,
0.6000f, 0.6000f, 0.6000f, 1.0000f, 0.6000f, -1.0000f, 1.0000f, -0.6000f, 1.0000f, -0.2000f, 1.0000f,
0.2000f, 1.0000f, 0.6000f, 1.0000f, 1.0000f, 1.0000});
test_case.add_expected_output<float>(
Shape{1, 1, 6, 6},
{0.0000f, 0.1500f, 0.5500f, 0.9500f, 1.3500f, 0.7500f, 0.6000f, 1.5000f, 2.3000f,
3.1000f, 3.9000f, 2.1000f, 2.2000f, 4.7000f, 5.5000f, 6.3000f, 7.1000f, 3.7000f,
3.8000f, 7.9000f, 8.7000f, 9.5000f, 10.3000f, 5.3000f, 5.4000f, 11.1000f, 11.9000f,
12.7000f, 13.5000f, 6.9000f, 3.0000f, 6.1500f, 6.5500f, 6.9500f, 7.3500f, 3.7500});
test_case.run();
}
@@ -424,4 +424,6 @@ IE_CPU.onnx_expand_context_dependent_function
IE_CPU.onnx_softmax_crossentropy_loss_mean
# Cannot find blob with name: Y
IE_CPU.onnx_bool_init_and
IE_CPU.onnx_bool_init_and
onnx_grid_sample
@@ -82,3 +82,5 @@ onnx_clip_no_min_no_max_int64
# z node not found in graph cache - ticket: 81976
INTERPRETER.onnx_expand_context_dependent_function
INTERPRETER.onnx_softmax_crossentropy_loss_mean
onnx_grid_sample