* Commit.
* Moved the preprocessing functions for NMS-5 to Interpreter backend.
* Code style fix.
{
namespace reference
{
- struct InfoForNMS5
- {
- int64_t max_output_boxes_per_class;
- float iou_threshold;
- float score_threshold;
- float soft_nms_sigma;
- Shape out_shape;
- Shape boxes_shape;
- Shape scores_shape;
- std::vector<float> boxes_data;
- std::vector<float> scores_data;
- size_t out_shape_size;
- bool sort_result_descending;
- ngraph::element::Type output_type;
- };
-
- InfoForNMS5 get_info_for_nms5_evaluation(const op::v5::NonMaxSuppression* nms5,
- const HostTensorVector& inputs);
-
void non_max_suppression(const float* boxes_data,
const Shape& boxes_data_shape,
const float* scores_data,
float score = 0.0f;
};
-using V5BoxEncoding = op::v5::NonMaxSuppression::BoxEncodingType;
-
-namespace
-{
- constexpr size_t boxes_port = 0;
- constexpr size_t scores_port = 1;
- constexpr size_t max_output_boxes_port = 2;
- constexpr size_t iou_threshold_port = 3;
- constexpr size_t score_threshold_port = 4;
- constexpr size_t soft_nms_sigma_port = 5;
-
- PartialShape
- infer_selected_indices_shape(const std::vector<std::shared_ptr<HostTensor>>& inputs,
- int64_t max_output_boxes_per_class)
- {
- const auto boxes_ps = inputs[boxes_port]->get_partial_shape();
- const auto scores_ps = inputs[scores_port]->get_partial_shape();
-
- // NonMaxSuppression produces triplets
- // that have the following format: [batch_index, class_index, box_index]
- PartialShape result = {Dimension::dynamic(), 3};
-
- if (boxes_ps.rank().is_static() && scores_ps.rank().is_static())
- {
- const auto num_boxes_boxes = boxes_ps[1];
- if (num_boxes_boxes.is_static() && scores_ps[0].is_static() && scores_ps[1].is_static())
- {
- const auto num_boxes = num_boxes_boxes.get_length();
- const auto num_classes = scores_ps[1].get_length();
-
- result[0] = std::min(num_boxes, max_output_boxes_per_class) * num_classes *
- scores_ps[0].get_length();
- }
- }
-
- return result;
- }
-
- void normalize_corner(float* boxes, const Shape& boxes_shape)
- {
- size_t total_num_of_boxes = shape_size(boxes_shape) / 4;
- for (size_t i = 0; i < total_num_of_boxes; ++i)
- {
- float* current_box = boxes + 4 * i;
-
- float y1 = current_box[0];
- float x1 = current_box[1];
- float y2 = current_box[2];
- float x2 = current_box[3];
-
- float ymin = std::min(y1, y2);
- float ymax = std::max(y1, y2);
- float xmin = std::min(x1, x2);
- float xmax = std::max(x1, x2);
-
- current_box[0] = ymin;
- current_box[1] = xmin;
- current_box[2] = ymax;
- current_box[3] = xmax;
- }
- }
-
- void normalize_center(float* boxes, const Shape& boxes_shape)
- {
- size_t total_num_of_boxes = shape_size(boxes_shape) / 4;
- for (size_t i = 0; i < total_num_of_boxes; ++i)
- {
- float* current_box = boxes + 4 * i;
-
- float x_center = current_box[0];
- float y_center = current_box[1];
- float width = current_box[2];
- float height = current_box[3];
-
- float y1 = y_center - height / 2.0;
- float x1 = x_center - width / 2.0;
- float y2 = y_center + height / 2.0;
- float x2 = x_center + width / 2.0;
-
- current_box[0] = y1;
- current_box[1] = x1;
- current_box[2] = y2;
- current_box[3] = x2;
- }
- }
-
- void normalize_box_encoding(float* boxes,
- const Shape& boxes_shape,
- const V5BoxEncoding box_encoding)
- {
- if (box_encoding == V5BoxEncoding::CORNER)
- {
- normalize_corner(boxes, boxes_shape);
- }
- else
- {
- normalize_center(boxes, boxes_shape);
- }
- }
-
- std::vector<float> get_floats(const std::shared_ptr<HostTensor>& input, const Shape& shape)
- {
- size_t input_size = shape_size(shape);
- std::vector<float> result(input_size);
-
- switch (input->get_element_type())
- {
- case element::Type_t::bf16:
- {
- bfloat16* p = input->get_data_ptr<bfloat16>();
- for (size_t i = 0; i < input_size; ++i)
- {
- result[i] = float(p[i]);
- }
- }
- break;
- case element::Type_t::f16:
- {
- float16* p = input->get_data_ptr<float16>();
- for (size_t i = 0; i < input_size; ++i)
- {
- result[i] = float(p[i]);
- }
- }
- break;
- case element::Type_t::f32:
- {
- float* p = input->get_data_ptr<float>();
- memcpy(result.data(), p, input_size * sizeof(float));
- }
- break;
- default: throw std::runtime_error("Unsupported data type in op NonMaxSuppression-5"); break;
- }
-
- return result;
- }
-
- std::vector<float> prepare_boxes_data(const std::shared_ptr<HostTensor>& boxes,
- const Shape& boxes_shape,
- const V5BoxEncoding box_encoding)
- {
- auto result = get_floats(boxes, boxes_shape);
- normalize_box_encoding(result.data(), boxes_shape, box_encoding);
- return result;
- }
-
- std::vector<float> prepare_scores_data(const std::shared_ptr<HostTensor>& scores,
- const Shape& scores_shape)
- {
- auto result = get_floats(scores, scores_shape);
- return result;
- }
-}
-
namespace ngraph
{
namespace runtime
{
namespace reference
{
- InfoForNMS5 get_info_for_nms5_evaluation(const op::v5::NonMaxSuppression* nms5,
- const HostTensorVector& inputs)
- {
- InfoForNMS5 result;
-
- result.max_output_boxes_per_class = nms5->max_boxes_output_from_input();
- result.iou_threshold = nms5->iou_threshold_from_input();
- result.score_threshold = nms5->score_threshold_from_input();
- result.soft_nms_sigma = nms5->soft_nms_sigma_from_input();
-
- auto selected_indices_shape =
- infer_selected_indices_shape(inputs, result.max_output_boxes_per_class);
- result.out_shape = selected_indices_shape.to_shape();
-
- result.boxes_shape = inputs[boxes_port]->get_shape();
- result.scores_shape = inputs[scores_port]->get_shape();
-
- result.boxes_data = prepare_boxes_data(
- inputs[boxes_port], result.boxes_shape, nms5->get_box_encoding());
- result.scores_data = prepare_scores_data(inputs[scores_port], result.scores_shape);
-
- result.out_shape_size = shape_size(result.out_shape);
-
- result.sort_result_descending = nms5->get_sort_result_descending();
-
- result.output_type = nms5->get_output_type();
-
- return result;
- }
-
void non_max_suppression(const float* boxes_data,
const Shape& boxes_data_shape,
const float* scores_data,
NGRAPH_SUPPRESS_DEPRECATED_START
+using V5BoxEncoding = op::v5::NonMaxSuppression::BoxEncodingType;
+
+namespace
+{
+ constexpr size_t boxes_port = 0;
+ constexpr size_t scores_port = 1;
+ constexpr size_t max_output_boxes_port = 2;
+ constexpr size_t iou_threshold_port = 3;
+ constexpr size_t score_threshold_port = 4;
+ constexpr size_t soft_nms_sigma_port = 5;
+
+ PartialShape
+ infer_selected_indices_shape(const std::vector<std::shared_ptr<HostTensor>>& inputs,
+ int64_t max_output_boxes_per_class)
+ {
+ const auto boxes_ps = inputs[boxes_port]->get_partial_shape();
+ const auto scores_ps = inputs[scores_port]->get_partial_shape();
+
+ // NonMaxSuppression produces triplets
+ // that have the following format: [batch_index, class_index, box_index]
+ PartialShape result = {Dimension::dynamic(), 3};
+
+ if (boxes_ps.rank().is_static() && scores_ps.rank().is_static())
+ {
+ const auto num_boxes_boxes = boxes_ps[1];
+ if (num_boxes_boxes.is_static() && scores_ps[0].is_static() && scores_ps[1].is_static())
+ {
+ const auto num_boxes = num_boxes_boxes.get_length();
+ const auto num_classes = scores_ps[1].get_length();
+
+ result[0] = std::min(num_boxes, max_output_boxes_per_class) * num_classes *
+ scores_ps[0].get_length();
+ }
+ }
+
+ return result;
+ }
+
+ void normalize_corner(float* boxes, const Shape& boxes_shape)
+ {
+ size_t total_num_of_boxes = shape_size(boxes_shape) / 4;
+ for (size_t i = 0; i < total_num_of_boxes; ++i)
+ {
+ float* current_box = boxes + 4 * i;
+
+ float y1 = current_box[0];
+ float x1 = current_box[1];
+ float y2 = current_box[2];
+ float x2 = current_box[3];
+
+ float ymin = std::min(y1, y2);
+ float ymax = std::max(y1, y2);
+ float xmin = std::min(x1, x2);
+ float xmax = std::max(x1, x2);
+
+ current_box[0] = ymin;
+ current_box[1] = xmin;
+ current_box[2] = ymax;
+ current_box[3] = xmax;
+ }
+ }
+
+ void normalize_center(float* boxes, const Shape& boxes_shape)
+ {
+ size_t total_num_of_boxes = shape_size(boxes_shape) / 4;
+ for (size_t i = 0; i < total_num_of_boxes; ++i)
+ {
+ float* current_box = boxes + 4 * i;
+
+ float x_center = current_box[0];
+ float y_center = current_box[1];
+ float width = current_box[2];
+ float height = current_box[3];
+
+ float y1 = y_center - height / 2.0;
+ float x1 = x_center - width / 2.0;
+ float y2 = y_center + height / 2.0;
+ float x2 = x_center + width / 2.0;
+
+ current_box[0] = y1;
+ current_box[1] = x1;
+ current_box[2] = y2;
+ current_box[3] = x2;
+ }
+ }
+
+ void normalize_box_encoding(float* boxes,
+ const Shape& boxes_shape,
+ const V5BoxEncoding box_encoding)
+ {
+ if (box_encoding == V5BoxEncoding::CORNER)
+ {
+ normalize_corner(boxes, boxes_shape);
+ }
+ else
+ {
+ normalize_center(boxes, boxes_shape);
+ }
+ }
+
+ std::vector<float> get_floats(const std::shared_ptr<HostTensor>& input, const Shape& shape)
+ {
+ size_t input_size = shape_size(shape);
+ std::vector<float> result(input_size);
+
+ switch (input->get_element_type())
+ {
+ case element::Type_t::bf16:
+ {
+ bfloat16* p = input->get_data_ptr<bfloat16>();
+ for (size_t i = 0; i < input_size; ++i)
+ {
+ result[i] = float(p[i]);
+ }
+ }
+ break;
+ case element::Type_t::f16:
+ {
+ float16* p = input->get_data_ptr<float16>();
+ for (size_t i = 0; i < input_size; ++i)
+ {
+ result[i] = float(p[i]);
+ }
+ }
+ break;
+ case element::Type_t::f32:
+ {
+ float* p = input->get_data_ptr<float>();
+ memcpy(result.data(), p, input_size * sizeof(float));
+ }
+ break;
+ default: throw std::runtime_error("Unsupported data type in op NonMaxSuppression-5"); break;
+ }
+
+ return result;
+ }
+
+ std::vector<float> prepare_boxes_data(const std::shared_ptr<HostTensor>& boxes,
+ const Shape& boxes_shape,
+ const V5BoxEncoding box_encoding)
+ {
+ auto result = get_floats(boxes, boxes_shape);
+ normalize_box_encoding(result.data(), boxes_shape, box_encoding);
+ return result;
+ }
+
+ std::vector<float> prepare_scores_data(const std::shared_ptr<HostTensor>& scores,
+ const Shape& scores_shape)
+ {
+ auto result = get_floats(scores, scores_shape);
+ return result;
+ }
+}
+
+runtime::interpreter::INTExecutable::InfoForNMS5
+ runtime::interpreter::INTExecutable::get_info_for_nms5_eval(
+ const op::v5::NonMaxSuppression* nms5,
+ const std::vector<std::shared_ptr<HostTensor>>& inputs)
+{
+ InfoForNMS5 result;
+
+ result.max_output_boxes_per_class = nms5->max_boxes_output_from_input();
+ result.iou_threshold = nms5->iou_threshold_from_input();
+ result.score_threshold = nms5->score_threshold_from_input();
+ result.soft_nms_sigma = nms5->soft_nms_sigma_from_input();
+
+ auto selected_indices_shape =
+ infer_selected_indices_shape(inputs, result.max_output_boxes_per_class);
+ result.out_shape = selected_indices_shape.to_shape();
+
+ result.boxes_shape = inputs[boxes_port]->get_shape();
+ result.scores_shape = inputs[scores_port]->get_shape();
+
+ result.boxes_data =
+ prepare_boxes_data(inputs[boxes_port], result.boxes_shape, nms5->get_box_encoding());
+ result.scores_data = prepare_scores_data(inputs[scores_port], result.scores_shape);
+
+ result.out_shape_size = shape_size(result.out_shape);
+
+ result.sort_result_descending = nms5->get_sort_result_descending();
+
+ result.output_type = nms5->get_output_type();
+
+ return result;
+}
+
runtime::interpreter::OP_TYPEID runtime::interpreter::INTExecutable::get_typeid(const Node& node)
{
const NodeTypeInfo& type_info = node.get_type_info();
const std::vector<std::shared_ptr<HostTensor>>& outputs,
const std::vector<std::shared_ptr<HostTensor>>& inputs);
+ struct InfoForNMS5
+ {
+ int64_t max_output_boxes_per_class;
+ float iou_threshold;
+ float score_threshold;
+ float soft_nms_sigma;
+ Shape out_shape;
+ Shape boxes_shape;
+ Shape scores_shape;
+ std::vector<float> boxes_data;
+ std::vector<float> scores_data;
+ size_t out_shape_size;
+ bool sort_result_descending;
+ ngraph::element::Type output_type;
+ };
+
+ InfoForNMS5 get_info_for_nms5_eval(const op::v5::NonMaxSuppression* nms5,
+ const std::vector<std::shared_ptr<HostTensor>>& inputs);
+
template <typename T>
void op_engine(const Node& node,
const std::vector<std::shared_ptr<HostTensor>>& out,
const op::v5::NonMaxSuppression* nms =
static_cast<const op::v5::NonMaxSuppression*>(&node);
- auto info = reference::get_info_for_nms5_evaluation(nms, args);
+ auto info = get_info_for_nms5_eval(nms, args);
std::vector<int64_t> selected_indices(info.out_shape_size);
std::vector<float> selected_scores(info.out_shape_size);