Files
openvino/ngraph/core/src/op/roi_align.cpp
T
Ilya Churaev b78f228fa5 Moved op utils to ov namespace (#7274)
* Moved ngraph::Node to ov namespace

* Fixed code style

* Fixed VPU

* Fixed GNA

* Fixed tests

* Added aliases for backward compatibility

* Fix clDNN

* Try to fix build

* Fixed comment

* Renamed RTTI macros

* Moved op utils to ov namespace

* Fixed ngraph library build

* Fixed unit-tests

* Changed src folder

* Fixed recurrent_sequence

* Changed low latency

* Fixed serialize

* Fixed ieFuncTests

* Try to fix windows

* Remove custom operator<< from tests

* Fixed build
2021-09-03 00:58:26 +03:00

292 lines
12 KiB
C++

// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "ngraph/op/roi_align.hpp"
#include "itt.hpp"
#include "ngraph/runtime/host_tensor.hpp"
#include "ngraph/runtime/reference/roi_align.hpp"
#include "ngraph/util.hpp" // for host_tensor_2_vector
using namespace std;
using namespace ngraph;
constexpr NodeTypeInfo op::v3::ROIAlign::type_info;
op::v3::ROIAlign::ROIAlign(const Output<Node>& input,
const Output<Node>& rois,
const Output<Node>& batch_indices,
const int pooled_h,
const int pooled_w,
const int sampling_ratio,
const float spatial_scale,
const string& mode)
: Op{{input, rois, batch_indices}},
m_pooled_h{pooled_h},
m_pooled_w{pooled_w},
m_sampling_ratio{sampling_ratio},
m_spatial_scale{spatial_scale},
m_mode{EnumNames<ROIAlign::PoolingMode>::as_enum(mode)} {
constructor_validate_and_infer_types();
}
op::v3::ROIAlign::ROIAlign(const Output<Node>& input,
const Output<Node>& rois,
const Output<Node>& batch_indices,
const int pooled_h,
const int pooled_w,
const int sampling_ratio,
const float spatial_scale,
const PoolingMode mode)
: Op{{input, rois, batch_indices}},
m_pooled_h{pooled_h},
m_pooled_w{pooled_w},
m_sampling_ratio{sampling_ratio},
m_spatial_scale{spatial_scale},
m_mode{mode} {
constructor_validate_and_infer_types();
}
void op::v3::ROIAlign::validate_and_infer_types() {
NGRAPH_OP_SCOPE(v3_ROIAlign_validate_and_infer_types);
NODE_VALIDATION_CHECK(this,
get_input_element_type(0).is_real() && get_input_element_type(1).is_real(),
"The data type for input and ROIs is expected to be a floating point type. Got: ",
get_input_element_type(0),
" and: ",
get_input_element_type(1));
NODE_VALIDATION_CHECK(this,
get_input_element_type(0) == get_input_element_type(1),
"Type of feature maps (inputs) and rois is expected to be the same. Got: ",
get_input_element_type(0),
" and: ",
get_input_element_type(1));
NODE_VALIDATION_CHECK(this,
get_input_element_type(2).is_integral_number(),
"The data type for batch indices is expected to be an integer. Got: ",
get_input_element_type(2));
const auto& input_ps = get_input_partial_shape(0);
NODE_VALIDATION_CHECK(this,
input_ps.rank().compatible(4),
"Expected a 4D tensor for the input data. Got: ",
input_ps);
const auto& rois_ps = get_input_partial_shape(1);
NODE_VALIDATION_CHECK(this,
rois_ps.rank().compatible(2),
"Expected a 2D tensor for the ROIs input. Got: ",
rois_ps);
const auto& batch_indices_ps = get_input_partial_shape(2);
NODE_VALIDATION_CHECK(this,
batch_indices_ps.rank().compatible(1),
"Expected a 1D tensor for the batch indices input. Got: ",
batch_indices_ps);
if (rois_ps.rank().is_static()) {
const auto rois_second_dim = rois_ps[1];
NODE_VALIDATION_CHECK(this,
rois_second_dim.compatible(4),
"The second dimension of ROIs input should contain box coordinates. ",
"This dimension is expected to be equal to 4. Got: ",
rois_second_dim);
if (batch_indices_ps.rank().is_static()) {
NODE_VALIDATION_CHECK(this,
rois_ps[0].compatible(batch_indices_ps[0]),
"The first dimension of ROIs input must be equal to the first dimension ",
"of the batch indices input. Got: ",
rois_ps[0],
" and: ",
batch_indices_ps[0]);
}
}
// the output shape should have the following format [NUM_ROIS, C, pooled_h, pooled_w]
auto output_shape = PartialShape{{Dimension::dynamic(),
input_ps[1],
Dimension{static_cast<int64_t>(m_pooled_h)},
Dimension{static_cast<int64_t>(m_pooled_w)}}};
// if either of those 2 dimensions is static its value will be used
// for the first dimension of the output shape - 'NUM_ROIS'
if (rois_ps.rank().is_static() && rois_ps[0].is_static()) {
output_shape[0] = rois_ps[0];
} else if (batch_indices_ps.rank().is_static() && batch_indices_ps[0].is_static()) {
output_shape[0] = batch_indices_ps[0];
}
set_output_size(1);
set_output_type(0, get_input_element_type(0), output_shape);
// if the channels dimension is not known
// the first input should be used during the function specialization
if (input_ps.rank().is_static() && input_ps[1].is_dynamic()) {
set_input_is_relevant_to_shape(0);
}
// if the 'NUM_ROIS' value is not known
// the last 2 inputs should be used during the function specialization
if (output_shape[0].is_dynamic()) {
set_input_is_relevant_to_shape(1);
set_input_is_relevant_to_shape(2);
}
}
bool op::v3::ROIAlign::visit_attributes(AttributeVisitor& visitor) {
NGRAPH_OP_SCOPE(v3_ROIAlign_visit_attributes);
visitor.on_attribute("pooled_h", m_pooled_h);
visitor.on_attribute("pooled_w", m_pooled_w);
visitor.on_attribute("sampling_ratio", m_sampling_ratio);
visitor.on_attribute("spatial_scale", m_spatial_scale);
visitor.on_attribute("mode", m_mode);
return true;
}
shared_ptr<Node> op::v3::ROIAlign::clone_with_new_inputs(const OutputVector& new_args) const {
NGRAPH_OP_SCOPE(v3_ROIAlign_clone_with_new_inputs);
check_new_args_count(this, new_args);
return make_shared<ROIAlign>(new_args.at(0),
new_args.at(1),
new_args.at(2),
m_pooled_h,
m_pooled_w,
m_sampling_ratio,
m_spatial_scale,
m_mode);
}
namespace ov {
constexpr DiscreteTypeInfo AttributeAdapter<ngraph::op::v3::ROIAlign::PoolingMode>::type_info;
template <>
NGRAPH_API EnumNames<ngraph::op::v3::ROIAlign::PoolingMode>& EnumNames<ngraph::op::v3::ROIAlign::PoolingMode>::get() {
static auto enum_names = EnumNames<ngraph::op::v3::ROIAlign::PoolingMode>(
"op::v3::ROIAlign::PoolingMode",
{{"avg", ngraph::op::v3::ROIAlign::PoolingMode::AVG}, {"max", ngraph::op::v3::ROIAlign::PoolingMode::MAX}});
return enum_names;
}
} // namespace ov
std::ostream& operator<<(std::ostream& s, const op::v3::ROIAlign::PoolingMode& type) {
return s << as_string(type);
}
namespace roi_alinop {
template <element::Type_t ET>
bool evaluate(const HostTensorPtr& feature_maps,
const HostTensorPtr& rois,
const std::vector<int64_t>& batch_indices_vec_scaled_up,
const HostTensorPtr& out,
const int pooled_height,
const int pooled_width,
const int sampling_ratio,
const float spatial_scale,
const op::v3::ROIAlign::PoolingMode& pooling_mode,
const Shape& batch_indices_shape) {
using T = typename element_type_traits<ET>::value_type;
runtime::reference::roi_align<T>(feature_maps->get_data_ptr<ET>(),
rois->get_data_ptr<ET>(),
batch_indices_vec_scaled_up.data(),
out->get_data_ptr<ET>(),
feature_maps->get_shape(),
rois->get_shape(),
batch_indices_shape,
out->get_shape(),
pooled_height,
pooled_width,
sampling_ratio,
spatial_scale,
pooling_mode);
return true;
}
bool evaluate_roi_align(const HostTensorVector& args,
const HostTensorPtr& out,
const int pooled_height,
const int pooled_width,
const int sampling_ratio,
const float spatial_scale,
const op::v3::ROIAlign::PoolingMode& pooling_mode) {
auto feature_maps = args[0];
auto rois = args[1];
auto batch_indices = args[2];
std::vector<int64_t> batch_indices_vec_scaled_up = host_tensor_2_vector<int64_t>(batch_indices);
bool rc = true;
switch (feature_maps->get_element_type()) {
NGRAPH_TYPE_CASE(evaluate_roi_align,
bf16,
feature_maps,
rois,
batch_indices_vec_scaled_up,
out,
pooled_height,
pooled_width,
sampling_ratio,
spatial_scale,
pooling_mode,
batch_indices->get_shape());
NGRAPH_TYPE_CASE(evaluate_roi_align,
f16,
feature_maps,
rois,
batch_indices_vec_scaled_up,
out,
pooled_height,
pooled_width,
sampling_ratio,
spatial_scale,
pooling_mode,
batch_indices->get_shape());
NGRAPH_TYPE_CASE(evaluate_roi_align,
f32,
feature_maps,
rois,
batch_indices_vec_scaled_up,
out,
pooled_height,
pooled_width,
sampling_ratio,
spatial_scale,
pooling_mode,
batch_indices->get_shape());
default:
rc = false;
break;
}
return rc;
}
} // namespace roi_alinop
bool op::v3::ROIAlign::evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const {
NGRAPH_OP_SCOPE(v3_ROIAlign_evaluate);
return roi_alinop::evaluate_roi_align(inputs,
outputs[0],
m_pooled_h,
m_pooled_w,
m_sampling_ratio,
m_spatial_scale,
m_mode);
}
bool op::v3::ROIAlign::has_evaluate() const {
NGRAPH_OP_SCOPE(v3_ROIAlign_has_evaluate);
switch (get_input_element_type(0)) {
case ngraph::element::bf16:
case ngraph::element::f16:
case ngraph::element::f32:
return true;
default:
break;
}
return false;
}