[Core] GridSample operator reference implementation (#11841)
This commit is contained in:
1 parent
39981bf2b8
commit
f8c4e736b4
10 files changed
+897
-36
No files matched your search
@@ -0,0 +1,519 @@
|
||||
// Copyright (C) 2022 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "openvino/op/grid_sample.hpp"
|
||||
|
||||
#include "base_reference_test.hpp"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace ov;
|
||||
using namespace reference_tests;
|
||||
|
||||
namespace {
|
||||
struct GridSampleParams {
|
||||
GridSampleParams(const reference_tests::Tensor& data,
|
||||
const reference_tests::Tensor& grid,
|
||||
const op::v9::GridSample::Attributes& attrs,
|
||||
const reference_tests::Tensor& expected,
|
||||
const std::string& name)
|
||||
: data_tensor{data},
|
||||
grid_tensor{grid},
|
||||
attributes{attrs},
|
||||
expected_tensor{expected},
|
||||
test_case_name{name} {}
|
||||
|
||||
reference_tests::Tensor data_tensor;
|
||||
reference_tests::Tensor grid_tensor;
|
||||
op::v9::GridSample::Attributes attributes;
|
||||
reference_tests::Tensor expected_tensor;
|
||||
std::string test_case_name;
|
||||
};
|
||||
|
||||
class ReferenceGridSample : public testing::TestWithParam<GridSampleParams>, public CommonReferenceTest {
|
||||
public:
|
||||
void SetUp() override {
|
||||
const auto& params = GetParam();
|
||||
function = CreateFunction(params.data_tensor, params.grid_tensor, params.attributes);
|
||||
inputData = {params.data_tensor.data, params.grid_tensor.data};
|
||||
refOutData = {params.expected_tensor.data};
|
||||
}
|
||||
|
||||
static std::string getTestCaseName(const testing::TestParamInfo<GridSampleParams>& obj) {
|
||||
return obj.param.test_case_name;
|
||||
}
|
||||
|
||||
private:
|
||||
static std::shared_ptr<Model> CreateFunction(const reference_tests::Tensor& data,
|
||||
const reference_tests::Tensor& grid,
|
||||
const op::v9::GridSample::Attributes& attributes) {
|
||||
const auto in1 = std::make_shared<op::v0::Parameter>(data.type, data.shape);
|
||||
const auto in2 = std::make_shared<op::v0::Parameter>(grid.type, grid.shape);
|
||||
const auto grid_sample = std::make_shared<op::v9::GridSample>(in1, in2, attributes);
|
||||
return std::make_shared<Model>(NodeVector{grid_sample}, ParameterVector{in1, in2});
|
||||
}
|
||||
};
|
||||
|
||||
constexpr auto GS_BICUBIC{op::v9::GridSample::InterpolationMode::BICUBIC};
|
||||
constexpr auto GS_BILINEAR{op::v9::GridSample::InterpolationMode::BILINEAR};
|
||||
constexpr auto GS_NEAREST{op::v9::GridSample::InterpolationMode::NEAREST};
|
||||
|
||||
constexpr auto GS_BORDER{op::v9::GridSample::PaddingMode::BORDER};
|
||||
constexpr auto GS_REFLECTION{op::v9::GridSample::PaddingMode::REFLECTION};
|
||||
constexpr auto GS_ZEROS{op::v9::GridSample::PaddingMode::ZEROS};
|
||||
|
||||
constexpr std::array<op::v9::GridSample::PaddingMode, 3> padding_modes{GS_ZEROS, GS_BORDER, GS_REFLECTION};
|
||||
constexpr std::array<bool, 2> align_corners_modes{false, true};
|
||||
|
||||
std::vector<GridSampleParams> generateNearestParamsOddDimensionsInnerGrids() {
|
||||
std::vector<GridSampleParams> params;
|
||||
|
||||
reference_tests::Tensor data_odd_dims{{1, 1, 3, 5},
|
||||
element::f32,
|
||||
std::vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}};
|
||||
reference_tests::Tensor grid_inner{
|
||||
{1, 3, 4, 2},
|
||||
element::f32,
|
||||
std::vector<float>{-0.1, -0.1, -0.1, 0.1, 0.1, -0.1, 0.1, 0.1, -0.5, -0.5, -0.5, 0.5,
|
||||
0.5, -0.5, 0.5, 0.5, -1., -1., -1., 1., 1., -1., 1., 1.}};
|
||||
reference_tests::Tensor output{{1, 1, 3, 4},
|
||||
element::f32,
|
||||
std::vector<float>{8, 8, 8, 8, 2, 12, 4, 14, 1, 11, 5, 15}};
|
||||
for (const auto& padding : padding_modes) {
|
||||
for (const auto align : align_corners_modes) {
|
||||
std::stringstream name;
|
||||
name << "nearest_" << padding << (align ? "_align" : "_noalign") << "_odd_dims_inner";
|
||||
params.emplace_back(data_odd_dims,
|
||||
grid_inner,
|
||||
op::v9::GridSample::Attributes{align, GS_NEAREST, padding},
|
||||
output,
|
||||
name.str());
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
std::vector<GridSampleParams> generateNearestParamsOddDimensionsOuterGrids() {
|
||||
std::vector<GridSampleParams> params;
|
||||
reference_tests::Tensor data_odd_dims{{1, 1, 3, 5},
|
||||
element::f32,
|
||||
std::vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}};
|
||||
reference_tests::Tensor grid_outer{
|
||||
{1, 1, 7, 2},
|
||||
element::f32,
|
||||
std::vector<float>{-10.1, -9.7, -7.55, 0.37, -77., 11.56, 0.5, 2.55, 1.7, 1.1, 3., -0.17, 1.301, -1.001}};
|
||||
|
||||
params.emplace_back(data_odd_dims,
|
||||
grid_outer,
|
||||
op::v9::GridSample::Attributes{false, GS_NEAREST, GS_ZEROS},
|
||||
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{0, 0, 0, 0, 0, 0, 0}},
|
||||
"nearest_zeros_noalign_odd_dims_outer");
|
||||
|
||||
params.emplace_back(data_odd_dims,
|
||||
grid_outer,
|
||||
op::v9::GridSample::Attributes{true, GS_NEAREST, GS_ZEROS},
|
||||
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{0, 0, 0, 0, 0, 0, 0}},
|
||||
"nearest_zeros_align_odd_dims_outer");
|
||||
|
||||
params.emplace_back(
|
||||
data_odd_dims,
|
||||
grid_outer,
|
||||
op::v9::GridSample::Attributes{false, GS_NEAREST, GS_BORDER},
|
||||
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{1, 11, 11, 14, 15, 10, 5}},
|
||||
"nearest_border_noalign_odd_dims_outer");
|
||||
|
||||
params.emplace_back(
|
||||
data_odd_dims,
|
||||
grid_outer,
|
||||
op::v9::GridSample::Attributes{true, GS_NEAREST, GS_BORDER},
|
||||
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{1, 6, 11, 14, 15, 10, 5}},
|
||||
"nearest_border_align_odd_dims_outer");
|
||||
|
||||
params.emplace_back(data_odd_dims,
|
||||
grid_outer,
|
||||
op::v9::GridSample::Attributes{false, GS_NEAREST, GS_REFLECTION},
|
||||
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{8, 14, 1, 4, 14, 6, 5}},
|
||||
"nearest_reflection_noalign_odd_dims_outer");
|
||||
|
||||
params.emplace_back(data_odd_dims,
|
||||
grid_outer,
|
||||
op::v9::GridSample::Attributes{true, GS_NEAREST, GS_REFLECTION},
|
||||
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{8, 9, 6, 4, 14, 6, 4}},
|
||||
"nearest_reflection_align_odd_dims_outer");
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
std::vector<GridSampleParams> generateNearestParamsEvenDimensions() {
|
||||
std::vector<GridSampleParams> params;
|
||||
reference_tests::Tensor data_even_dims{
|
||||
{1, 1, 4, 6},
|
||||
element::f32,
|
||||
std::vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}};
|
||||
reference_tests::Tensor grid_inner{
|
||||
{1, 1, 8, 2},
|
||||
element::f32,
|
||||
std::vector<float>{-0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -1, 1, 1, -1, -0.1, -0.1, 0.1, 0.1}};
|
||||
|
||||
reference_tests::Tensor output_align{{1, 1, 1, 8}, element::f32, std::vector<float>{8, 14, 11, 17, 19, 6, 9, 16}};
|
||||
reference_tests::Tensor output_noalign{{1, 1, 1, 8}, element::f32, std::vector<float>{2, 14, 5, 17, 19, 6, 9, 16}};
|
||||
reference_tests::Tensor output_zeros_noalign{{1, 1, 1, 8},
|
||||
element::f32,
|
||||
std::vector<float>{2, 14, 5, 17, 0, 0, 9, 16}};
|
||||
|
||||
for (const auto& padding : padding_modes) {
|
||||
std::stringstream name1, name2;
|
||||
name1 << "nearest_" << padding << "_noalign"
|
||||
<< "_even_dims_inner";
|
||||
params.emplace_back(data_even_dims,
|
||||
grid_inner,
|
||||
op::v9::GridSample::Attributes{false, GS_NEAREST, padding},
|
||||
padding == GS_ZEROS ? output_zeros_noalign : output_noalign,
|
||||
name1.str());
|
||||
|
||||
name2 << "nearest_" << padding << "_align"
|
||||
<< "_even_dims_inner";
|
||||
params.emplace_back(data_even_dims,
|
||||
grid_inner,
|
||||
op::v9::GridSample::Attributes{true, GS_NEAREST, padding},
|
||||
output_align,
|
||||
name2.str());
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
std::vector<GridSampleParams> generateBilinearParamsOddDimensionsInnerGrids() {
|
||||
std::vector<GridSampleParams> params;
|
||||
reference_tests::Tensor data_odd_dims{{1, 1, 3, 5},
|
||||
element::f32,
|
||||
std::vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}};
|
||||
reference_tests::Tensor grid_inner{
|
||||
{1, 3, 4, 2},
|
||||
element::f32,
|
||||
std::vector<float>{-0.1, -0.1, -0.1, 0.1, 0.1, -0.1, 0.1, 0.1, -0.5, -0.5, -0.5, 0.5,
|
||||
0.5, -0.5, 0.5, 0.5, -1., -1., -1., 1., 1., -1., 1., 1.}};
|
||||
|
||||
reference_tests::Tensor output_align{{1, 1, 3, 4},
|
||||
element::f32,
|
||||
std::vector<float>{7.3, 8.3, 7.7, 8.7, 4.5, 9.5, 6.5, 11.5, 1, 11, 5, 15}};
|
||||
reference_tests::Tensor output_noalign{{1, 1, 3, 4},
|
||||
element::f32,
|
||||
std::vector<float>{7, 8.5, 7.5, 9, 3, 10.5, 5.5, 13, 1, 11, 5, 15}};
|
||||
reference_tests::Tensor output_zeros_noalign{
|
||||
{1, 1, 3, 4},
|
||||
element::f32,
|
||||
std::vector<float>{7, 8.5, 7.5, 9, 3, 10.5, 5.5, 13, 0.25, 2.75, 1.25, 3.75}};
|
||||
|
||||
params.emplace_back(data_odd_dims,
|
||||
grid_inner,
|
||||
op::v9::GridSample::Attributes{false, GS_BILINEAR, GS_ZEROS},
|
||||
output_zeros_noalign,
|
||||
"bilinear_zeros_noalign_odd_dims_inner");
|
||||
|
||||
params.emplace_back(data_odd_dims,
|
||||
grid_inner,
|
||||
op::v9::GridSample::Attributes{true, GS_BILINEAR, GS_ZEROS},
|
||||
output_align,
|
||||
"bilinear_zeros_align_odd_dims_inner");
|
||||
|
||||
params.emplace_back(data_odd_dims,
|
||||
grid_inner,
|
||||
op::v9::GridSample::Attributes{false, GS_BILINEAR, GS_BORDER},
|
||||
output_noalign,
|
||||
"bilinear_border_noalign_odd_dims_inner");
|
||||
|
||||
params.emplace_back(data_odd_dims,
|
||||
grid_inner,
|
||||
op::v9::GridSample::Attributes{true, GS_BILINEAR, GS_BORDER},
|
||||
output_align,
|
||||
"bilinear_border_align_odd_dims_inner");
|
||||
|
||||
params.emplace_back(data_odd_dims,
|
||||
grid_inner,
|
||||
op::v9::GridSample::Attributes{false, GS_BILINEAR, GS_REFLECTION},
|
||||
output_noalign,
|
||||
"bilinear_reflection_noalign_odd_dims_inner");
|
||||
|
||||
params.emplace_back(data_odd_dims,
|
||||
grid_inner,
|
||||
op::v9::GridSample::Attributes{true, GS_BILINEAR, GS_REFLECTION},
|
||||
output_align,
|
||||
"bilinear_reflection_align_odd_dims_inner");
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
std::vector<GridSampleParams> generateBilinearParamsOddDimensionsOuterGrids() {
|
||||
std::vector<GridSampleParams> params;
|
||||
|
||||
reference_tests::Tensor data_odd_dims{{1, 1, 3, 5},
|
||||
element::f32,
|
||||
std::vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}};
|
||||
|
||||
reference_tests::Tensor grid_outer{
|
||||
{1, 1, 7, 2},
|
||||
element::f32,
|
||||
std::vector<float>{-10.1, -9.7, -7.55, 0.37, -77., 11.56, 0.5, 2.55, 1.7, 1.1, 3., -0.17, 1.301, -1.001}};
|
||||
|
||||
params.emplace_back(data_odd_dims,
|
||||
grid_outer,
|
||||
op::v9::GridSample::Attributes{false, GS_BILINEAR, GS_ZEROS},
|
||||
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{0, 0, 0, 0, 0, 0, 0}},
|
||||
"bilinear_zeros_noalign_odd_dims_outer");
|
||||
|
||||
params.emplace_back(
|
||||
data_odd_dims,
|
||||
grid_outer,
|
||||
op::v9::GridSample::Attributes{true, GS_BILINEAR, GS_ZEROS},
|
||||
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{0, 0, 0, 0, 0, 0, 1.9880099}},
|
||||
"bilinear_zeros_align_odd_dims_outer");
|
||||
|
||||
params.emplace_back(
|
||||
data_odd_dims,
|
||||
grid_outer,
|
||||
op::v9::GridSample::Attributes{false, GS_BILINEAR, GS_BORDER},
|
||||
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{1, 8.775, 11, 14.25, 15, 8.725, 5}},
|
||||
"bilinear_border_noalign_odd_dims_outer");
|
||||
|
||||
params.emplace_back(
|
||||
data_odd_dims,
|
||||
grid_outer,
|
||||
op::v9::GridSample::Attributes{true, GS_BILINEAR, GS_BORDER},
|
||||
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{1, 7.85, 11, 14, 15, 9.15, 5}},
|
||||
"bilinear_border_align_odd_dims_outer");
|
||||
|
||||
params.emplace_back(
|
||||
data_odd_dims,
|
||||
grid_outer,
|
||||
op::v9::GridSample::Attributes{false, GS_BILINEAR, GS_REFLECTION},
|
||||
reference_tests::Tensor{{1, 1, 1, 7},
|
||||
element::f32,
|
||||
std::vector<float>{5.9999995, 11.9, 2.7000031, 5.1250005, 13.75, 4.725, 4.7475}},
|
||||
"bilinear_reflection_noalign_odd_dims_outer");
|
||||
|
||||
params.emplace_back(
|
||||
data_odd_dims,
|
||||
grid_outer,
|
||||
op::v9::GridSample::Attributes{true, GS_BILINEAR, GS_REFLECTION},
|
||||
reference_tests::Tensor{{1, 1, 1, 7},
|
||||
element::f32,
|
||||
std::vector<float>{6.7, 10.75, 3.800002, 6.25, 13.099999, 5.15, 4.4030004}},
|
||||
"bilinear_reflection_align_odd_dims_outer");
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
std::vector<GridSampleParams> generateBilinearParamsEvenDimensions() {
|
||||
std::vector<GridSampleParams> params;
|
||||
reference_tests::Tensor data_even_dims{
|
||||
{1, 1, 4, 6},
|
||||
element::f32,
|
||||
std::vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}};
|
||||
reference_tests::Tensor grid_inner{
|
||||
{1, 1, 8, 2},
|
||||
element::f32,
|
||||
std::vector<float>{-0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -1, 1, 1, -1, -0.1, -0.1, 0.1, 0.1}};
|
||||
|
||||
params.emplace_back(
|
||||
data_even_dims,
|
||||
grid_inner,
|
||||
op::v9::GridSample::Attributes{false, GS_BILINEAR, GS_ZEROS},
|
||||
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{5, 17, 8, 20, 4.75, 1.5, 11, 14}},
|
||||
"bilinear_zeros_noalign_even_dims_inner");
|
||||
|
||||
params.emplace_back(data_even_dims,
|
||||
grid_inner,
|
||||
op::v9::GridSample::Attributes{true, GS_BILINEAR, GS_ZEROS},
|
||||
reference_tests::Tensor{{1, 1, 1, 7},
|
||||
element::f32,
|
||||
std::vector<float>{6.75, 15.75, 9.25, 18.25, 19, 6, 11.35, 13.65}},
|
||||
"bilinear_zeros_align_even_dims_inner");
|
||||
|
||||
params.emplace_back(
|
||||
data_even_dims,
|
||||
grid_inner,
|
||||
op::v9::GridSample::Attributes{false, GS_BILINEAR, GS_BORDER},
|
||||
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{5, 17, 8, 20, 19, 6, 11, 14}},
|
||||
"bilinear_border_noalign_even_dims_inner");
|
||||
|
||||
params.emplace_back(data_even_dims,
|
||||
grid_inner,
|
||||
op::v9::GridSample::Attributes{true, GS_BILINEAR, GS_BORDER},
|
||||
reference_tests::Tensor{{1, 1, 1, 7},
|
||||
element::f32,
|
||||
std::vector<float>{6.75, 15.75, 9.25, 18.25, 19, 6, 11.35, 13.65}},
|
||||
"bilinear_border_align_even_dims_inner");
|
||||
|
||||
params.emplace_back(
|
||||
data_even_dims,
|
||||
grid_inner,
|
||||
op::v9::GridSample::Attributes{false, GS_BILINEAR, GS_REFLECTION},
|
||||
reference_tests::Tensor{{1, 1, 1, 7}, element::f32, std::vector<float>{5, 17, 8, 20, 19, 6, 11, 14}},
|
||||
"bilinear_reflection_noalign_even_dims_inner");
|
||||
|
||||
params.emplace_back(data_even_dims,
|
||||
grid_inner,
|
||||
op::v9::GridSample::Attributes{true, GS_BILINEAR, GS_REFLECTION},
|
||||
reference_tests::Tensor{{1, 1, 1, 7},
|
||||
element::f32,
|
||||
std::vector<float>{6.75, 15.75, 9.25, 18.25, 19, 6, 11.35, 13.65}},
|
||||
"bilinear_reflection_align_even_dims_inner");
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
std::vector<GridSampleParams> generateBicubicParams() {
|
||||
std::vector<GridSampleParams> params;
|
||||
|
||||
// clang-format off
|
||||
reference_tests::Tensor data_even_dims{{1, 1, 4, 7}, element::f32,
|
||||
std::vector<float>{ 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 2, 2, 2, 2, 2, 1,
|
||||
1, 2, 3, 5, 3, 2, 1,
|
||||
1, 2, 5, 9, 5, 2, 1}};
|
||||
reference_tests::Tensor grid{
|
||||
{1, 4, 4, 2},
|
||||
element::f32,
|
||||
std::vector<float>{ -0.1, -0.1, -0.1, 0.1, 0.1, -0.1, 0.1, 0.1,
|
||||
-0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5,
|
||||
-0.9, -0.9, -0.9, 0.9, 0.9, -0.9, 0.9, 0.9,
|
||||
-1.75, 0.7, 1.33, -1.11, 0.965, 1.007, 21, 37}};
|
||||
|
||||
params.emplace_back(data_even_dims,
|
||||
grid,
|
||||
op::v9::GridSample::Attributes{false, GS_BICUBIC, GS_ZEROS},
|
||||
reference_tests::Tensor{{1, 1, 4, 4},
|
||||
element::f32,
|
||||
std::vector<float>{2.6663566, 3.527928, 2.6663566, 3.527928,
|
||||
1.6318359, 2.7156982, 1.6318359, 2.7156982,
|
||||
0.6378987, 0.57033366, 0.6378987, 0.57033366,
|
||||
0, -0.01507522, 0.25528803, 0 }},
|
||||
"bicubic_zeros_noalign");
|
||||
|
||||
params.emplace_back(data_even_dims,
|
||||
grid,
|
||||
op::v9::GridSample::Attributes{true, GS_BICUBIC, GS_ZEROS},
|
||||
reference_tests::Tensor{{1, 1, 4, 4},
|
||||
element::f32,
|
||||
std::vector<float>{ 2.7887204, 3.4506166, 2.7887204, 3.4506166,
|
||||
1.8481445, 2.7364502, 1.8481445, 2.7364502,
|
||||
1.2367951, 1.3602872, 1.2367951, 1.3602872,
|
||||
0, 0.00650583, 1.1182348, 0 }},
|
||||
"bicubic_zeros_align");
|
||||
|
||||
params.emplace_back(data_even_dims,
|
||||
grid,
|
||||
op::v9::GridSample::Attributes{false, GS_BICUBIC, GS_BORDER},
|
||||
reference_tests::Tensor{{1, 1, 4, 4},
|
||||
element::f32,
|
||||
std::vector<float>{ 2.6663566, 3.527928, 2.6663566, 3.527928,
|
||||
1.5380859, 2.4677734, 1.5380859, 2.4677734,
|
||||
1.0089612, 0.91871876, 1.0089612, 0.91871876,
|
||||
1, 1, 0.8902873, 1 }},
|
||||
"bicubic_border_noalign");
|
||||
|
||||
params.emplace_back(data_even_dims,
|
||||
grid,
|
||||
op::v9::GridSample::Attributes{true, GS_BICUBIC, GS_BORDER},
|
||||
reference_tests::Tensor{{1, 1, 4, 4},
|
||||
element::f32,
|
||||
std::vector<float>{ 2.7887204, 3.4506166, 2.7887204, 3.4506166,
|
||||
1.8129883, 2.623291, 1.8129883, 2.623291,
|
||||
1.0363026, 1.1486388, 1.0363026, 1.1486388,
|
||||
1, 1.0000064, 1.0641243, 1 }},
|
||||
"bicubic_border_align");
|
||||
|
||||
params.emplace_back(data_even_dims,
|
||||
grid,
|
||||
op::v9::GridSample::Attributes{false, GS_BICUBIC, GS_REFLECTION},
|
||||
reference_tests::Tensor{{1, 1, 4, 4},
|
||||
element::f32,
|
||||
std::vector<float>{ 2.6663566, 3.527928, 2.6663566, 3.527928,
|
||||
1.5380859, 2.4677734, 1.5380859, 2.4677734,
|
||||
1.0150609, 0.904375, 1.0150609, 0.904375,
|
||||
5.48851, 0.898316, 0.8237547, 0.8125 }},
|
||||
"bicubic_reflection_noalign");
|
||||
|
||||
params.emplace_back(data_even_dims,
|
||||
grid,
|
||||
op::v9::GridSample::Attributes{true, GS_BICUBIC, GS_REFLECTION},
|
||||
reference_tests::Tensor{{1, 1, 4, 4},
|
||||
element::f32,
|
||||
std::vector<float>{ 2.7887204, 3.4506166, 2.7887204, 3.4506166,
|
||||
1.7745361, 2.6518555, 1.7745361, 2.6518555,
|
||||
1.0085088, 1.0307077, 1.0085088, 1.0307077,
|
||||
5.5649586, 1.0553409, 1.0011607, 1 }},
|
||||
"bicubic_reflection_align");
|
||||
// clang-format on
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
std::vector<GridSampleParams> generateBicubicBatchesParams() {
|
||||
std::vector<GridSampleParams> params;
|
||||
|
||||
reference_tests::Tensor data{{2, 2, 4, 3},
|
||||
element::f32,
|
||||
std::vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
|
||||
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48}};
|
||||
reference_tests::Tensor grid{{2, 2, 4, 2},
|
||||
element::f32,
|
||||
std::vector<float>{-0.1, -0.1, -0.1, 0.1, 0.1, -0.1, 0.1, 0.1, -0.5, -0.5, -0.5,
|
||||
0.5, 0.5, -0.5, 0.5, 0.5, -0.9, -0.9, -0.9, 0.9, 0.9, -0.9,
|
||||
0.9, 0.9, -1.75, 0.7, 1.33, -1.11, 0.965, 1.007, 21, 37}};
|
||||
|
||||
params.emplace_back(
|
||||
data,
|
||||
grid,
|
||||
op::v9::GridSample::Attributes{true, GS_BICUBIC, GS_BORDER},
|
||||
reference_tests::Tensor{
|
||||
{2, 2, 2, 4},
|
||||
element::f32,
|
||||
std::vector<float>{6.0096254, 6.7048755, 6.2951245, 6.9903746, 3.4101562, 8.402344, 4.5976562, 9.589844,
|
||||
18.009624, 18.704876, 18.295124, 18.990376, 15.410156, 20.402344, 16.597656, 21.589844,
|
||||
25.415281, 33.735218, 27.26478, 35.58472, 32.884, 26.852259, 35.996872, 36.,
|
||||
37.41528, 45.735218, 39.264782, 47.58472, 44.884, 38.852257, 47.996872, 48.}},
|
||||
"bicubic_border_align_batches");
|
||||
|
||||
params.emplace_back(
|
||||
data,
|
||||
grid,
|
||||
op::v9::GridSample::Attributes{false, GS_BICUBIC, GS_REFLECTION},
|
||||
reference_tests::Tensor{
|
||||
{2, 2, 2, 4},
|
||||
element::f32,
|
||||
std::vector<float>{5.8170314, 6.7650313, 6.2349687, 7.182969, 2.4101562, 8.972656, 4.0273438, 10.589844,
|
||||
17.81703, 18.765032, 18.234968, 19.18297, 14.410156, 20.972656, 16.027344, 22.589844,
|
||||
24.356874, 34.301876, 26.698126, 36.643124, 34.304035, 26.55013, 36.74749, 36.75,
|
||||
36.356876, 46.301876, 38.698124, 48.643124, 46.304035, 38.55013, 48.74749, 48.75}},
|
||||
"bicubic_reflection_noalign_batches");
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
std::vector<GridSampleParams> generateGridSampleParams() {
|
||||
std::vector<std::vector<GridSampleParams>> combo_params{generateNearestParamsOddDimensionsInnerGrids(),
|
||||
generateNearestParamsOddDimensionsOuterGrids(),
|
||||
generateNearestParamsEvenDimensions(),
|
||||
generateBilinearParamsOddDimensionsInnerGrids(),
|
||||
generateBilinearParamsOddDimensionsOuterGrids(),
|
||||
generateBilinearParamsEvenDimensions(),
|
||||
generateBicubicParams(),
|
||||
generateBicubicBatchesParams()};
|
||||
std::vector<GridSampleParams> test_params;
|
||||
for (auto& params : combo_params)
|
||||
std::move(params.begin(), params.end(), std::back_inserter(test_params));
|
||||
return test_params;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST_P(ReferenceGridSample, LayerTest) {
|
||||
Exec();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(smoke,
|
||||
ReferenceGridSample,
|
||||
::testing::ValuesIn(generateGridSampleParams()),
|
||||
ReferenceGridSample::getTestCaseName);
|
||||
@@ -127,10 +127,6 @@ xfail_issue_68212 = xfail_test(reason="Unsupported reading model with bytes stre
|
||||
|
||||
xfail_issue_78843 = xfail_test(reason="Missing reference output files for ssd mobilenet models")
|
||||
|
||||
xfail_issue_81974 = xfail_test(reason="RuntimeError: OpenVINO does not support the following ONNX "
|
||||
"operations: GridSample, Optional, SequenceConstruct, "
|
||||
"OptionalHasElement, SequenceInsert")
|
||||
|
||||
xfail_issue_81976 = xfail_test(reason="RuntimeError: z node not found in graph cache")
|
||||
xfail_issue_82038 = xfail_test(reason="ScatterElements, ScatterND, AssertionError: Result mismatch")
|
||||
xfail_issue_82039 = xfail_test(reason="Unsupported data type Optional, RuntimeError: [ NOT_IMPLEMENTED ] "
|
||||
|
||||
@@ -45,7 +45,6 @@ from tests import (
|
||||
xfail_issue_63137,
|
||||
xfail_issue_63138,
|
||||
xfail_issue_69444,
|
||||
xfail_issue_81974,
|
||||
xfail_issue_81976,
|
||||
skip_segfault,
|
||||
xfail_issue_82038,
|
||||
@@ -368,17 +367,6 @@ tests_expected_to_fail = [
|
||||
"OnnxBackendNodeModelTest.test_sce_NCd1d2d3d4d5_mean_weight_cpu", # ticket: 81976
|
||||
"OnnxBackendNodeModelTest.test_sce_NCd1d2d3d4d5_mean_weight_log_prob_cpu", # ticket: 81976
|
||||
),
|
||||
(
|
||||
xfail_issue_81974,
|
||||
"OnnxBackendNodeModelTest.test_gridsample_aligncorners_true_cpu",
|
||||
"OnnxBackendNodeModelTest.test_gridsample_bicubic_cpu",
|
||||
"OnnxBackendNodeModelTest.test_gridsample_bilinear_cpu",
|
||||
"OnnxBackendNodeModelTest.test_gridsample_border_padding_cpu",
|
||||
"OnnxBackendNodeModelTest.test_gridsample_cpu",
|
||||
"OnnxBackendNodeModelTest.test_gridsample_nearest_cpu",
|
||||
"OnnxBackendNodeModelTest.test_gridsample_reflection_padding_cpu",
|
||||
"OnnxBackendNodeModelTest.test_gridsample_zeros_padding_cpu",
|
||||
),
|
||||
(
|
||||
xfail_issue_81976, # SoftmaxCrossEntropyLoss operator
|
||||
"OnnxBackendNodeModelTest.test_sce_NCd1d2d3_none_no_weight_negative_ii_cpu",
|
||||
|
||||
@@ -138,10 +138,6 @@ xfail_issue_78843 = xfail_test(reason="Missing reference output files for ssd mo
|
||||
xfail_issue_78741 = xfail_test(reason="Cannot get dims for non-static shapes. "
|
||||
"Requires dynamism support enabled.")
|
||||
|
||||
xfail_issue_81974 = xfail_test(reason="RuntimeError: OpenVINO does not support the following ONNX "
|
||||
"operations: GridSample, Optional, SequenceConstruct, "
|
||||
"OptionalHasElement, SequenceInsert")
|
||||
|
||||
xfail_issue_81976 = xfail_test(reason="RuntimeError: z node not found in graph cache")
|
||||
xfail_issue_82038 = xfail_test(reason="ScatterElements, ScatterND, AssertionError: Result mismatch")
|
||||
xfail_issue_82039 = xfail_test(reason="Unsupported data type Optional, RuntimeError: [ NOT_IMPLEMENTED ] "
|
||||
|
||||
@@ -45,7 +45,6 @@ from tests_compatibility import (
|
||||
xfail_issue_63138,
|
||||
xfail_issue_69444,
|
||||
xfail_issue_78741,
|
||||
xfail_issue_81974,
|
||||
xfail_issue_81976,
|
||||
skip_segfault,
|
||||
xfail_issue_82038,
|
||||
@@ -450,17 +449,6 @@ tests_expected_to_fail = [
|
||||
"OnnxBackendNodeModelTest.test_sce_NCd1d2d3d4d5_mean_weight_cpu", # ticket: 81976
|
||||
"OnnxBackendNodeModelTest.test_sce_NCd1d2d3d4d5_mean_weight_log_prob_cpu", # ticket: 81976
|
||||
),
|
||||
(
|
||||
xfail_issue_81974,
|
||||
"OnnxBackendNodeModelTest.test_gridsample_aligncorners_true_cpu",
|
||||
"OnnxBackendNodeModelTest.test_gridsample_bicubic_cpu",
|
||||
"OnnxBackendNodeModelTest.test_gridsample_bilinear_cpu",
|
||||
"OnnxBackendNodeModelTest.test_gridsample_border_padding_cpu",
|
||||
"OnnxBackendNodeModelTest.test_gridsample_cpu",
|
||||
"OnnxBackendNodeModelTest.test_gridsample_nearest_cpu",
|
||||
"OnnxBackendNodeModelTest.test_gridsample_reflection_padding_cpu",
|
||||
"OnnxBackendNodeModelTest.test_gridsample_zeros_padding_cpu",
|
||||
),
|
||||
(
|
||||
xfail_issue_81976, # SoftmaxCrossEntropyLoss operator
|
||||
"OnnxBackendNodeModelTest.test_sce_NCd1d2d3_none_no_weight_negative_ii_cpu",
|
||||
|
||||
@@ -30,6 +30,12 @@ public:
|
||||
InterpolationMode mode = InterpolationMode::BILINEAR;
|
||||
// Specifies how the out-of-bounds coordinates should be handled: `zeros`, `border`, `reflection`
|
||||
PaddingMode padding_mode = PaddingMode::ZEROS;
|
||||
|
||||
Attributes() = default;
|
||||
Attributes(bool align_corners, InterpolationMode mode, PaddingMode padding_mode)
|
||||
: align_corners{align_corners},
|
||||
mode{mode},
|
||||
padding_mode{padding_mode} {}
|
||||
};
|
||||
|
||||
GridSample() = default;
|
||||
@@ -49,6 +55,11 @@ public:
|
||||
return m_attributes;
|
||||
}
|
||||
|
||||
OPENVINO_SUPPRESS_DEPRECATED_START
|
||||
bool evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const override;
|
||||
OPENVINO_SUPPRESS_DEPRECATED_END
|
||||
bool has_evaluate() const override;
|
||||
|
||||
private:
|
||||
Attributes m_attributes = {};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,295 @@
|
||||
// Copyright (C) 2022 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cfenv>
|
||||
#include <cmath>
|
||||
|
||||
#include "ngraph/shape.hpp"
|
||||
#include "openvino/op/grid_sample.hpp"
|
||||
|
||||
namespace ngraph {
|
||||
namespace runtime {
|
||||
namespace reference {
|
||||
namespace {
|
||||
|
||||
using index_4D_t = typename std::array<size_t, 4>;
|
||||
|
||||
template <typename GRID_ET>
|
||||
using denormalize_fn_t = typename std::function<GRID_ET(GRID_ET, size_t)>;
|
||||
|
||||
template <typename DATA_ET>
|
||||
using get_padded_fn_t = typename std::function<DATA_ET(const DATA_ET*, const Shape&, size_t, size_t, long, long)>;
|
||||
|
||||
template <typename T>
|
||||
T& get_single_value(T* buffer, const Shape& shape, const index_4D_t& index) {
|
||||
// In this context below assertion is guaranteed by grid_sample(..) function.
|
||||
// assert(shape.size() == index.size());
|
||||
auto sx = shape.back();
|
||||
auto offset = index.back();
|
||||
for (auto i = index.size() - 2; i > 0; --i) {
|
||||
offset += index[i] * sx;
|
||||
sx *= shape[i];
|
||||
}
|
||||
offset += index[0] * sx;
|
||||
return buffer[offset];
|
||||
}
|
||||
|
||||
template <typename GRID_ET>
|
||||
GRID_ET rescale_align(GRID_ET value, size_t range) {
|
||||
return (value + 1) * (static_cast<GRID_ET>(range) - 1) / 2;
|
||||
}
|
||||
|
||||
template <typename GRID_ET>
|
||||
GRID_ET rescale_noalign(GRID_ET value, size_t range) {
|
||||
return ((value + 1) * static_cast<GRID_ET>(range) - 1) / 2;
|
||||
}
|
||||
|
||||
template <typename DATA_ET>
|
||||
DATA_ET zeros_padding(const DATA_ET* data,
|
||||
const Shape& data_shape,
|
||||
const size_t n,
|
||||
const size_t c,
|
||||
const long y_d,
|
||||
const long x_d) {
|
||||
const auto H = static_cast<long>(data_shape[2]);
|
||||
const auto W = static_cast<long>(data_shape[3]);
|
||||
if (y_d < 0 || x_d < 0 || y_d >= H || x_d >= W) {
|
||||
return 0;
|
||||
} else {
|
||||
const auto y = static_cast<size_t>(y_d);
|
||||
const auto x = static_cast<size_t>(x_d);
|
||||
return get_single_value(data, data_shape, index_4D_t{n, c, y, x});
|
||||
}
|
||||
}
|
||||
|
||||
template <typename DATA_ET>
|
||||
DATA_ET border_padding(const DATA_ET* data,
|
||||
const Shape& data_shape,
|
||||
const size_t n,
|
||||
const size_t c,
|
||||
const long y_d,
|
||||
const long x_d) {
|
||||
const auto H = static_cast<long>(data_shape[2]);
|
||||
const auto W = static_cast<long>(data_shape[3]);
|
||||
const auto y = static_cast<size_t>(std::min(std::max(y_d, 0l), H - 1));
|
||||
const auto x = static_cast<size_t>(std::min(std::max(x_d, 0l), W - 1));
|
||||
return get_single_value(data, data_shape, index_4D_t{n, c, y, x});
|
||||
}
|
||||
|
||||
template <typename DATA_ET>
|
||||
DATA_ET reflection_data_no_align(const DATA_ET* data,
|
||||
const Shape& data_shape,
|
||||
const size_t n,
|
||||
const size_t c,
|
||||
long y_d,
|
||||
long x_d) {
|
||||
const auto H = static_cast<long>(data_shape[2]);
|
||||
const auto W = static_cast<long>(data_shape[3]);
|
||||
const auto H_2 = static_cast<long>(data_shape[2]) * 2l;
|
||||
const auto W_2 = static_cast<long>(data_shape[3]) * 2l;
|
||||
y_d = (y_d % H_2 + H_2) % H_2;
|
||||
x_d = (x_d % W_2 + W_2) % W_2;
|
||||
const auto y = static_cast<size_t>(y_d >= H ? H_2 - 1 - y_d : y_d);
|
||||
const auto x = static_cast<size_t>(x_d >= W ? W_2 - 1 - x_d : x_d);
|
||||
return get_single_value(data, data_shape, index_4D_t{n, c, y, x});
|
||||
}
|
||||
|
||||
template <typename DATA_ET>
|
||||
DATA_ET reflection_data_with_align(const DATA_ET* data,
|
||||
const Shape& data_shape,
|
||||
const size_t n,
|
||||
const size_t c,
|
||||
long y_d,
|
||||
long x_d) {
|
||||
const auto H = static_cast<long>(data_shape[2]);
|
||||
const auto W = static_cast<long>(data_shape[3]);
|
||||
const auto H_2_2 = 2 * (H - 1);
|
||||
const auto W_2_2 = 2 * (W - 1);
|
||||
y_d = std::abs(y_d) % H_2_2;
|
||||
x_d = std::abs(x_d) % W_2_2;
|
||||
const auto y = static_cast<size_t>(y_d >= H ? H_2_2 - y_d : y_d);
|
||||
const auto x = static_cast<size_t>(x_d >= W ? W_2_2 - x_d : x_d);
|
||||
return get_single_value(data, data_shape, index_4D_t{n, c, y, x});
|
||||
}
|
||||
|
||||
template <typename DATA_ET, typename GRID_ET>
|
||||
DATA_ET bilinear(const DATA_ET* data,
|
||||
const Shape& data_shape,
|
||||
const size_t n,
|
||||
const size_t c,
|
||||
const GRID_ET y_n,
|
||||
const GRID_ET x_n,
|
||||
const get_padded_fn_t<DATA_ET>& get_padded,
|
||||
const denormalize_fn_t<GRID_ET>& denormalize) {
|
||||
const auto y_d = denormalize(y_n, data_shape[2]);
|
||||
const auto x_d = denormalize(x_n, data_shape[3]);
|
||||
const auto y_topleft = std::floor(y_d);
|
||||
const auto x_topleft = std::floor(x_d);
|
||||
const auto dy = y_d - y_topleft;
|
||||
const auto dx = x_d - x_topleft;
|
||||
const auto v00 = get_padded(data, data_shape, n, c, y_topleft, x_topleft);
|
||||
const auto v01 = get_padded(data, data_shape, n, c, y_topleft, x_topleft + 1);
|
||||
const auto v10 = get_padded(data, data_shape, n, c, y_topleft + 1, x_topleft);
|
||||
const auto v11 = get_padded(data, data_shape, n, c, y_topleft + 1, x_topleft + 1);
|
||||
|
||||
const auto q0 = (1 - dx) * v00 + dx * v01;
|
||||
const auto q1 = (1 - dx) * v10 + dx * v11;
|
||||
return dy * q1 + (1 - dy) * q0;
|
||||
}
|
||||
|
||||
template <typename DATA_ET, typename GRID_ET>
|
||||
DATA_ET nearest(const DATA_ET* data,
|
||||
const Shape& data_shape,
|
||||
const size_t n,
|
||||
const size_t c,
|
||||
const GRID_ET y_n,
|
||||
const GRID_ET x_n,
|
||||
const get_padded_fn_t<DATA_ET>& get_padded,
|
||||
const denormalize_fn_t<GRID_ET>& denormalize) {
|
||||
const auto y_nearest = std::lrint(denormalize(y_n, data_shape[2]));
|
||||
const auto x_nearest = std::lrint(denormalize(x_n, data_shape[3]));
|
||||
return get_padded(data, data_shape, n, c, y_nearest, x_nearest);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
using vector_4_t = typename std::array<T, 4>;
|
||||
template <typename T>
|
||||
using matrix_4x4_t = typename std::array<vector_4_t<T>, 4>;
|
||||
|
||||
// formula taken from
|
||||
// https://github.com/onnx/onnx/blob/a92870cdf359297495a118184dca2eaecee4b717/onnx/backend/test/case/node/resize.py#L201-L207
|
||||
template <typename T>
|
||||
vector_4_t<T> cubic_coeffs(const T r, const T A = -0.75) {
|
||||
vector_4_t<T> v;
|
||||
v[0] = ((A * (r + 1) - 5 * A) * (r + 1) + 8 * A) * (r + 1) - 4 * A;
|
||||
v[1] = ((A + 2) * r - (A + 3)) * r * r + 1;
|
||||
v[2] = ((A + 2) * (1 - r) - (A + 3)) * (1 - r) * (1 - r) + 1;
|
||||
v[3] = ((A * (2 - r) - 5 * A) * (2 - r) + 8 * A) * (2 - r) - 4 * A;
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename DATA_ET>
|
||||
matrix_4x4_t<DATA_ET> gather_4x4(const DATA_ET* data,
|
||||
const Shape& data_shape,
|
||||
const size_t n,
|
||||
const size_t c,
|
||||
const long y_topleft,
|
||||
const long x_topleft,
|
||||
const get_padded_fn_t<DATA_ET>& get_padded) {
|
||||
matrix_4x4_t<DATA_ET> s;
|
||||
for (int j = 0; j < 4; ++j)
|
||||
for (int i = 0; i < 4; ++i)
|
||||
s[j][i] = get_padded(data, data_shape, n, c, y_topleft + j, x_topleft + i);
|
||||
return s;
|
||||
}
|
||||
|
||||
template <typename DATA_ET, typename GRID_ET>
|
||||
DATA_ET bicubic(const DATA_ET* data,
|
||||
const Shape& data_shape,
|
||||
const size_t n,
|
||||
const size_t c,
|
||||
const GRID_ET y_n,
|
||||
const GRID_ET x_n,
|
||||
const get_padded_fn_t<DATA_ET>& get_padded,
|
||||
const denormalize_fn_t<GRID_ET>& denormalize) {
|
||||
const auto y_d = denormalize(y_n, data_shape[2]);
|
||||
const auto x_d = denormalize(x_n, data_shape[3]);
|
||||
const auto y_topleft = std::floor(y_d);
|
||||
const auto x_topleft = std::floor(x_d);
|
||||
const auto dy = y_d - y_topleft;
|
||||
const auto dx = x_d - x_topleft;
|
||||
const auto s = gather_4x4(data, data_shape, n, c, y_topleft - 1, x_topleft - 1, get_padded);
|
||||
|
||||
const auto cy = cubic_coeffs(dy);
|
||||
const auto cx = cubic_coeffs(dx);
|
||||
vector_4_t<DATA_ET> p;
|
||||
std::transform(s.begin(), s.end(), p.begin(), [&cx](const vector_4_t<DATA_ET>& v) {
|
||||
return std::inner_product(cx.begin(), cx.end(), v.begin(), static_cast<DATA_ET>(0));
|
||||
});
|
||||
return std::inner_product(cy.begin(), cy.end(), p.begin(), static_cast<DATA_ET>(0));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template <typename DATA_ET, typename GRID_ET>
|
||||
void grid_sample(DATA_ET* output,
|
||||
const DATA_ET* data,
|
||||
const GRID_ET* grid,
|
||||
const Shape& data_shape,
|
||||
const Shape& grid_shape,
|
||||
const bool align_corners,
|
||||
const ov::op::v9::GridSample::InterpolationMode interpolation_mode,
|
||||
const ov::op::v9::GridSample::PaddingMode padding_mode) {
|
||||
assert(data_shape.size() == 4 && grid_shape.size() == 4);
|
||||
assert(data_shape[0] == grid_shape[0] and grid_shape[3] == 2);
|
||||
|
||||
const auto N = data_shape[0];
|
||||
const auto C = data_shape[1];
|
||||
const auto H_out = grid_shape[1];
|
||||
const auto W_out = grid_shape[2];
|
||||
const Shape output_shape{N, C, H_out, W_out};
|
||||
|
||||
const auto prev_rounding_mode = std::fegetround();
|
||||
std::fesetround(FE_TONEAREST);
|
||||
|
||||
get_padded_fn_t<DATA_ET> get_padded_fn;
|
||||
switch (padding_mode) {
|
||||
default:
|
||||
case ov::op::v9::GridSample::PaddingMode::ZEROS:
|
||||
get_padded_fn = zeros_padding<DATA_ET>;
|
||||
break;
|
||||
case ov::op::v9::GridSample::PaddingMode::BORDER:
|
||||
get_padded_fn = border_padding<DATA_ET>;
|
||||
break;
|
||||
case ov::op::v9::GridSample::PaddingMode::REFLECTION:
|
||||
if (align_corners)
|
||||
get_padded_fn = reflection_data_with_align<DATA_ET>;
|
||||
else
|
||||
get_padded_fn = reflection_data_no_align<DATA_ET>;
|
||||
break;
|
||||
}
|
||||
|
||||
denormalize_fn_t<GRID_ET> denormalize_fn;
|
||||
if (align_corners)
|
||||
denormalize_fn = rescale_align<GRID_ET>;
|
||||
else
|
||||
denormalize_fn = rescale_noalign<GRID_ET>;
|
||||
|
||||
for (size_t n = 0; n < N; ++n) {
|
||||
for (size_t c = 0; c < C; ++c) {
|
||||
for (size_t y = 0; y < H_out; ++y) {
|
||||
for (size_t x = 0; x < W_out; ++x) {
|
||||
const auto y_n = get_single_value(grid, grid_shape, index_4D_t{n, y, x, 1});
|
||||
const auto x_n = get_single_value(grid, grid_shape, index_4D_t{n, y, x, 0});
|
||||
|
||||
auto& out = get_single_value(output, output_shape, index_4D_t{n, c, y, x});
|
||||
|
||||
switch (interpolation_mode) {
|
||||
case ov::op::v9::GridSample::InterpolationMode::BILINEAR:
|
||||
out =
|
||||
bilinear<DATA_ET, GRID_ET>(data, data_shape, n, c, y_n, x_n, get_padded_fn, denormalize_fn);
|
||||
break;
|
||||
case ov::op::v9::GridSample::InterpolationMode::NEAREST:
|
||||
out =
|
||||
nearest<DATA_ET, GRID_ET>(data, data_shape, n, c, y_n, x_n, get_padded_fn, denormalize_fn);
|
||||
break;
|
||||
case ov::op::v9::GridSample::InterpolationMode::BICUBIC:
|
||||
out =
|
||||
bicubic<DATA_ET, GRID_ET>(data, data_shape, n, c, y_n, x_n, get_padded_fn, denormalize_fn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::fesetround(prev_rounding_mode);
|
||||
}
|
||||
} // namespace reference
|
||||
} // namespace runtime
|
||||
} // namespace ngraph
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
#include "grid_sample_shape_inference.hpp"
|
||||
#include "itt.hpp"
|
||||
#include "ngraph/runtime/reference/grid_sample.hpp"
|
||||
#include "ngraph/validation_util.hpp"
|
||||
|
||||
namespace ov {
|
||||
op::v9::GridSample::GridSample(const Output<Node>& data, const Output<Node>& grid, const Attributes& attributes)
|
||||
@@ -43,6 +45,10 @@ std::ostream& operator<<(std::ostream& s, const op::v9::GridSample::Interpolatio
|
||||
return s << as_string(mode);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& s, const op::v9::GridSample::PaddingMode& padding_mode) {
|
||||
return s << as_string(padding_mode);
|
||||
}
|
||||
|
||||
template <>
|
||||
NGRAPH_API EnumNames<op::v9::GridSample::InterpolationMode>& EnumNames<op::v9::GridSample::InterpolationMode>::get() {
|
||||
static auto enum_names =
|
||||
@@ -62,4 +68,70 @@ NGRAPH_API EnumNames<op::v9::GridSample::PaddingMode>& EnumNames<op::v9::GridSam
|
||||
{"reflection", op::v9::GridSample::PaddingMode::REFLECTION}});
|
||||
return enum_names;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
template <element::Type_t DATA_ET, element::Type_t GRID_ET>
|
||||
bool evaluate_exec(const HostTensorPtr& output,
|
||||
const HostTensorPtr& data,
|
||||
const HostTensorPtr& grid,
|
||||
const op::v9::GridSample::Attributes& attributes) {
|
||||
ngraph::runtime::reference::grid_sample(output->get_data_ptr<DATA_ET>(),
|
||||
data->get_data_ptr<DATA_ET>(),
|
||||
grid->get_data_ptr<GRID_ET>(),
|
||||
data->get_shape(),
|
||||
grid->get_shape(),
|
||||
attributes.align_corners,
|
||||
attributes.mode,
|
||||
attributes.padding_mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define GRID_SAMPLE_TYPE_CASE(a, ...) \
|
||||
case element::Type_t::a: { \
|
||||
NGRAPH_OP_SCOPE(OV_PP_CAT3(evaluate_exec_grid_sample, _, a)); \
|
||||
rc = evaluate_exec<DATA_ET, element::Type_t::a>(__VA_ARGS__); \
|
||||
} break
|
||||
|
||||
template <element::Type_t DATA_ET>
|
||||
bool evaluate(const HostTensorPtr& output,
|
||||
const HostTensorPtr& data,
|
||||
const HostTensorPtr& grid,
|
||||
const op::v9::GridSample::Attributes& attributes) {
|
||||
auto rc = true;
|
||||
switch (grid->get_element_type()) {
|
||||
GRID_SAMPLE_TYPE_CASE(f32, output, data, grid, attributes);
|
||||
default:
|
||||
rc = false;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool evaluate_grid_sample(const HostTensorPtr& output,
|
||||
const HostTensorPtr& data,
|
||||
const HostTensorPtr& grid,
|
||||
const op::v9::GridSample::Attributes& attributes) {
|
||||
auto rc = true;
|
||||
switch (output->get_element_type()) {
|
||||
NGRAPH_TYPE_CASE(evaluate_grid_sample, f32, output, data, grid, attributes);
|
||||
default:
|
||||
rc = false;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool op::v9::GridSample::evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const {
|
||||
NGRAPH_OP_SCOPE(v9_GridSample_evaluate);
|
||||
OPENVINO_ASSERT(ngraph::validate_host_tensor_vector(inputs, 2), "Invalid GridSample input TensorVector.");
|
||||
OPENVINO_ASSERT(ngraph::validate_host_tensor_vector(outputs, 1), "Invalid GridSample output TensorVector.");
|
||||
|
||||
return evaluate_grid_sample(outputs[0], inputs[0], inputs[1], m_attributes);
|
||||
}
|
||||
|
||||
bool op::v9::GridSample::has_evaluate() const {
|
||||
return get_input_element_type(0) == element::f32 && get_input_element_type(1) == element::f32;
|
||||
}
|
||||
} // namespace ov
|
||||
@@ -425,5 +425,3 @@ IE_CPU.onnx_softmax_crossentropy_loss_mean
|
||||
|
||||
# Cannot find blob with name: Y
|
||||
IE_CPU.onnx_bool_init_and
|
||||
|
||||
onnx_grid_sample
|
||||
@@ -82,5 +82,3 @@ 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
|
||||
Reference in new issue
Block a user