Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FrontEnd]Paddle_Op_Conversion_prior_box #7639

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions ngraph/frontend/paddlepaddle/src/op/prior_box.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#include "ngraph/op/prior_box.hpp"

#include <node_context.hpp>

#include "default_opset.hpp"

namespace ngraph {
namespace frontend {
namespace pdpd {
namespace op {
using namespace default_opset;
using namespace element;
namespace detail {
namespace {
std::shared_ptr<StridedSlice> make_slice(const std::shared_ptr<ngraph::Node>& node, int64_t start, int64_t end) {
return std::make_shared<StridedSlice>(node,
Constant::create(i64, Shape{1}, std::vector<int64_t>{start}),
Constant::create(i64, Shape{1}, std::vector<int64_t>{end}),
std::vector<int64_t>{0}, // begin mask
std::vector<int64_t>{0}); // end mask
}
} // namespace
} // namespace detail
NamedOutputs prior_box(const NodeContext& node) {
auto input = node.get_ng_input("Input");
auto Image = node.get_ng_input("Image");
const auto input_shape = std::make_shared<ShapeOf>(input);
const auto Image_shape = std::make_shared<ShapeOf>(Image);
const auto output_shape_slice = detail::make_slice(input_shape, 2, 4);
const auto image_shape_slice = detail::make_slice(Image_shape, 2, 4);

ngraph::op::PriorBoxAttrs attrs;
attrs.min_size = node.get_attribute<std::vector<float>>("min_sizes", {});
attrs.max_size = node.get_attribute<std::vector<float>>("max_sizes", {});
attrs.aspect_ratio = node.get_attribute<std::vector<float>>("aspect_ratios", {1.0});
attrs.flip = node.get_attribute<bool>("flip", false);
attrs.clip = node.get_attribute<bool>("clip", false);
attrs.step = node.get_attribute<float>("step_w", 0);

attrs.offset = node.get_attribute<float>("offset", 0.5);
attrs.variance = node.get_attribute<std::vector<float>>("variances", {0.1, 0.1, 0.2, 0.2});

bool min_max_aspect_ratios_order = node.get_attribute<bool>("min_max_aspect_ratios_order", false);

const auto ov_prior_box_node = std::make_shared<PriorBox>(output_shape_slice, image_shape_slice, attrs);

const auto split_axis_node = Constant::create(i64, ngraph::Shape{}, {0});
const auto node_prior_box_split = std::make_shared<Split>(ov_prior_box_node, split_axis_node, 2);

const auto node_boxes_origin = node_prior_box_split->output(0);
const auto node_variances_origin = node_prior_box_split->output(1);

const auto out_shape =
std::make_shared<Concat>(NodeVector{output_shape_slice, Constant::create<int64_t>(i64, {2}, {-1, 4})}, 0);

auto node_boxes_reshape = std::make_shared<Reshape>(node_boxes_origin, out_shape, true);
const auto node_variances_reshape = std::make_shared<Reshape>(node_variances_origin, out_shape, true);

int64_t total_aspect_ratios = ngraph::op::PriorBox::normalized_aspect_ratio(attrs.aspect_ratio, attrs.flip).size();
if ((total_aspect_ratios > 1) && !attrs.min_size.empty() && !attrs.max_size.empty() &&
!min_max_aspect_ratios_order) {
std::vector<int64_t> mask{1, 1, 1, 0, 1};
int64_t min_size_len = static_cast<int64_t>(attrs.min_size.size());

const auto out_shape_div_numpri = std::make_shared<Concat>(
NodeVector{output_shape_slice, Constant::create<int64_t>(i64, {3}, {min_size_len, -1, 4})},
0);
const auto node_boxes_div_numpri = std::make_shared<Reshape>(node_boxes_reshape, out_shape_div_numpri, true);

const auto slice_begin_min = Constant::create(i64, Shape{5}, std::vector<int64_t>{0, 0, 0, 0, 0});
const auto slice_end_min = std::make_shared<Concat>(
NodeVector{output_shape_slice, Constant::create<int64_t>(i64, {3}, {min_size_len, 1, 4})},
0);
const auto slice_min_node =
std::make_shared<StridedSlice>(node_boxes_div_numpri, slice_begin_min, slice_end_min, mask, mask);

const auto slice_begin_max = Constant::create(i64, Shape{5}, std::vector<int64_t>{0, 0, 0, 1, 0});
const auto slice_end_max = std::make_shared<Concat>(
NodeVector{output_shape_slice, Constant::create<int64_t>(i64, {3}, {min_size_len, 2, 4})},
0);
const auto slice_max_node =
std::make_shared<StridedSlice>(node_boxes_div_numpri, slice_begin_max, slice_end_max, mask, mask);

const auto slice_begin_aspect_ratios = Constant::create(i64, Shape{5}, std::vector<int64_t>{0, 0, 0, 2, 0});
const auto slice_end_aspect_ratios = std::make_shared<Concat>(
NodeVector{output_shape_slice,
Constant::create<int64_t>(i64, {3}, {min_size_len, 2 + (total_aspect_ratios - 1), 4})},
0);
const auto slice_aspect_ratios_node = std::make_shared<StridedSlice>(node_boxes_div_numpri,
slice_begin_aspect_ratios,
slice_end_aspect_ratios,
mask,
mask);

const auto node_boxes_div_numpri_reorder =
std::make_shared<Concat>(NodeVector{slice_min_node, slice_aspect_ratios_node, slice_max_node}, 3);
node_boxes_reshape = std::make_shared<Reshape>(node_boxes_div_numpri_reorder, out_shape, true);
}

NamedOutputs outputs;
outputs["Boxes"] = {node_boxes_reshape};
outputs["Variances"] = {node_variances_reshape};
return outputs;
}
} // namespace op
} // namespace pdpd
} // namespace frontend
} // namespace ngraph
2 changes: 2 additions & 0 deletions ngraph/frontend/paddlepaddle/src/op_table.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ OP_CONVERTER(nearest_interp_v2);
OP_CONVERTER(pad3d);
OP_CONVERTER(pow);
OP_CONVERTER(pool2d);
OP_CONVERTER(prior_box);
OP_CONVERTER(range);
OP_CONVERTER(relu);
OP_CONVERTER(relu6);
Expand Down Expand Up @@ -126,6 +127,7 @@ std::map<std::string, CreatorFunction> get_supported_ops() {
{"pad3d", op::pad3d},
{"pow", op::pow},
{"pool2d", op::pool2d},
{"prior_box", op::prior_box},
{"range", op::range},
{"relu", op::relu},
{"relu6", op::relu6},
Expand Down
4 changes: 4 additions & 0 deletions ngraph/test/frontend/paddlepaddle/op_fuzzy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ static const std::vector<std::string> models{std::string("argmax"),
std::string("pow_int64"),
// pow_int64_out_of_range(out of range of OV int64),
std::string("pow_y_tensor"),
std::string("prior_box_attrs_mmar_order_true"),
std::string("prior_box_default"),
std::string("prior_box_flip_clip_false"),
std::string("prior_box_max_sizes_none"),
std::string("range0"),
std::string("range1"),
std::string("range2"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#
# prior_box paddle model generator
#
import numpy as np
from save_model import saveModel
import sys


def prior_box(name: str, input_data, image_data, attrs: dict):
import paddle as pdpd
pdpd.enable_static()

with pdpd.static.program_guard(pdpd.static.Program(), pdpd.static.Program()):
Input = pdpd.static.data(
name='Input', shape=input_data.shape, dtype=input_data.dtype)
Image = pdpd.static.data(
name='Image', shape=image_data.shape, dtype=image_data.dtype)

box, var = pdpd.fluid.layers.prior_box(Input,
Image,
min_sizes=attrs['min_sizes'],
max_sizes=attrs['max_sizes'],
aspect_ratios=attrs['aspect_ratios'],
variance=attrs['variance'],
flip=attrs['flip'],
clip=attrs['clip'],
steps=attrs['steps'],
offset=attrs['offset'],
name=None,
min_max_aspect_ratios_order=attrs['min_max_aspect_ratios_order'])

liubo-intel marked this conversation as resolved.
Show resolved Hide resolved
cpu = pdpd.static.cpu_places(1)
exe = pdpd.static.Executor(cpu[0])
# startup program will call initializer to initialize the parameters.
exe.run(pdpd.static.default_startup_program())

outs = exe.run(
feed={'Input': input_data, 'Image': image_data},
fetch_list=[box, var])

# Save inputs in order of ngraph function, to facilite Fuzzy test,
# which accepts inputs and outputs in this order as well.
saveModel(name, exe, feedkeys=['Input', 'Image'], fetchlist=[box, var],
inputs=[input_data, image_data], outputs=outs, target_dir=sys.argv[1])
return outs


if __name__ == "__main__":

prior_box_attrs_default = {
'name': "prior_box_default",
'min_sizes': np.array([2, 4]).astype('float32').tolist(),
'max_sizes': np.array([5, 10]).astype('float32').tolist(),
'aspect_ratios': [2.0, 3.0],
'flip': True,
'clip': True,
'steps': np.array([1.25, 1.25]).astype('float32').tolist(),
'offset': 0.5,
'variance': np.array([0.1, 0.1, 0.2, 0.2], dtype=np.float).flatten(),
'min_max_aspect_ratios_order': False
}

prior_box_max_sizes_none = {
'name': "prior_box_max_sizes_none",
'min_sizes': np.array([2, 4]).astype('float32').tolist(),
'max_sizes': None,
'aspect_ratios': [2.0, 3.0],
'flip': True,
'clip': True,
'steps': np.array([1.25, 1.25]).astype('float32').tolist(),
'offset': 0.5,
'variance': np.array([0.1, 0.1, 0.2, 0.2], dtype=np.float).flatten(),
'min_max_aspect_ratios_order': False
}

prior_box_flip_clip_false = {
'name': "prior_box_flip_clip_false",
'min_sizes': np.array([2, 4]).astype('float32').tolist(),
'max_sizes': np.array([5, 10]).astype('float32').tolist(),
'aspect_ratios': [2.0, 3.0],
'flip': False,
'clip': False,
'steps': np.array([1.25, 1.25]).astype('float32').tolist(),
'offset': 0.5,
'variance': np.array([0.1, 0.1, 0.2, 0.2], dtype=np.float).flatten(),
'min_max_aspect_ratios_order': False
}

prior_box_attrs_mmar_order_true = {
'name': "prior_box_attrs_mmar_order_true",
'min_sizes': np.array([2, 4]).astype('float32').tolist(),
'max_sizes': np.array([5, 10]).astype('float32').tolist(),
'aspect_ratios': [2.0, 3.0],
'flip': True,
'clip': True,
'steps': np.array([1.25, 1.25]).astype('float32').tolist(),
'offset': 0.5,
'variance': np.array([0.1, 0.1, 0.2, 0.2], dtype=np.float).flatten(),
'min_max_aspect_ratios_order': True
}

prior_box_attrs_list = [prior_box_attrs_default,
prior_box_max_sizes_none, prior_box_flip_clip_false, prior_box_attrs_mmar_order_true]

layer_w = 32
layer_h = 32

image_w = 40
image_h = 40

input_channels = 2
image_channels = 3
batch_size = 10

input_data = np.random.random(
(batch_size, input_channels, layer_w,
layer_h)).astype('float32')

image_data = np.random.random(
(batch_size, image_channels, image_w,
image_h)).astype('float32')

for item in prior_box_attrs_list:
pred_pdpd = prior_box(item['name'], input_data, image_data, item)