[OV20] InputTensorInfo::set_shape (#9059)
* InputTensorInfo::set_shape * Fix clang-format
This commit is contained in:
parent
f0e570b30a
commit
70b5e28979
@ -766,6 +766,36 @@ static RefPreprocessParams convert_color_i420_single_plane() {
|
||||
return res;
|
||||
}
|
||||
|
||||
static RefPreprocessParams set_shape_custom_crop() {
|
||||
RefPreprocessParams res("set_shape_custom_crop");
|
||||
res.function = []() {
|
||||
auto f = create_simple_function(element::f32, PartialShape{2, 2, 2, 2});
|
||||
auto p = PrePostProcessor(f);
|
||||
p.input().tensor().set_shape({-1, -1, -1, -1});
|
||||
p.input().preprocess().custom([](const Output<Node>& node) {
|
||||
// Add custom crop to model's dimensions using 'Slice' operation
|
||||
// Middle part 2x2x2x2 of original user's 4x4x4x4 input tensor will be extracted
|
||||
auto start = opset8::Constant::create(element::i32, {4}, {1, 1, 1, 1});
|
||||
auto stop = opset8::Constant::create(element::i32, {4}, {3, 3, 3, 3});
|
||||
auto step = opset8::Constant::create(element::i32, {4}, {1, 1, 1, 1});
|
||||
auto axis = opset8::Constant::create(element::i32, {4}, {0, 1, 2, 3});
|
||||
auto slice = std::make_shared<opset8::Slice>(node, start, stop, step, axis);
|
||||
return slice;
|
||||
});
|
||||
p.build();
|
||||
return f;
|
||||
};
|
||||
auto input_size = 4 * 4 * 4 * 4;
|
||||
std::vector<float> input_values(input_size);
|
||||
std::iota(input_values.begin(), input_values.end(), 0);
|
||||
res.inputs.emplace_back(element::f32, Shape{4, 4, 4, 4}, input_values);
|
||||
res.expected.emplace_back(Shape{2, 2, 2, 2}, element::f32, std::vector<float>{ 85, 86, 89, 90,
|
||||
101, 102, 105, 106,
|
||||
149, 150, 153, 154,
|
||||
165, 166, 169, 170});
|
||||
return res;
|
||||
}
|
||||
|
||||
static RefPreprocessParams postprocess_2_inputs_basic() {
|
||||
RefPreprocessParams res("postprocess_2_inputs_basic");
|
||||
res.function = []() {
|
||||
@ -1037,6 +1067,7 @@ std::vector<RefPreprocessParams> allPreprocessTests() {
|
||||
element_type_before_convert_color_nv12(),
|
||||
convert_color_i420_to_bgr_three_planes(),
|
||||
convert_color_i420_single_plane(),
|
||||
set_shape_custom_crop(),
|
||||
postprocess_2_inputs_basic(),
|
||||
post_convert_layout_by_dims(),
|
||||
post_convert_layout_by_dims_multi(),
|
||||
|
@ -255,7 +255,13 @@ static void regclass_graph_InputTensorInfo(py::module m) {
|
||||
});
|
||||
info.def("set_spatial_static_shape", [](ov::preprocess::InputTensorInfo& me, size_t height, size_t width) {
|
||||
return &me.set_spatial_static_shape(height, width);
|
||||
;
|
||||
});
|
||||
info.def("set_shape", [](ov::preprocess::InputTensorInfo& me, const ov::PartialShape& shape) {
|
||||
return &me.set_shape(shape);
|
||||
});
|
||||
// Allow to use set_shape([1,2,3]) in Python code, not set_shape(PartialShape([1,2,3]))
|
||||
info.def("set_shape", [](ov::preprocess::InputTensorInfo& me, const std::vector<int64_t>& shape) {
|
||||
return &me.set_shape(shape);
|
||||
});
|
||||
info.def("set_color_format",
|
||||
[](ov::preprocess::InputTensorInfo& me,
|
||||
|
@ -201,6 +201,37 @@ def test_ngraph_preprocess_spatial_static_shape():
|
||||
assert np.equal(output, expected_output).all()
|
||||
|
||||
|
||||
def test_ngraph_preprocess_set_shape():
|
||||
shape = [1, 1, 1]
|
||||
parameter_a = ops.parameter(shape, dtype=np.int32, name="A")
|
||||
model = parameter_a
|
||||
function = Function(model, [parameter_a], "TestFunction")
|
||||
|
||||
@custom_preprocess_function
|
||||
def custom_crop(out_node: Output):
|
||||
start = ops.constant(np.array([1, 1, 1]), dtype=np.int32)
|
||||
stop = ops.constant(np.array([2, 2, 2]), dtype=np.int32)
|
||||
step = ops.constant(np.array([1, 1, 1]), dtype=np.int32)
|
||||
axis = ops.constant(np.array([0, 1, 2]), dtype=np.int32)
|
||||
return ops.slice(out_node, start, stop, step, axis)
|
||||
|
||||
p = PrePostProcessor(function)
|
||||
inp = p.input()
|
||||
inp.tensor().set_shape([3, 3, 3])
|
||||
inp.preprocess().custom(custom_crop)
|
||||
function = p.build()
|
||||
|
||||
input_data = np.array([[[0, 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]]]).astype(np.int32)
|
||||
expected_output = np.array([[[13]]]).astype(np.float32)
|
||||
|
||||
runtime = get_runtime()
|
||||
computation = runtime.computation(function)
|
||||
output = computation(input_data)
|
||||
assert np.equal(output, expected_output).all()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"algorithm, color_format1, color_format2, is_failing",
|
||||
[(ResizeAlgorithm.RESIZE_LINEAR, ColorFormat.UNDEFINED, ColorFormat.BGR, True),
|
||||
|
@ -105,6 +105,19 @@ public:
|
||||
///
|
||||
/// \return Reference to 'this' to allow chaining with other calls in a builder-like manner
|
||||
InputTensorInfo& set_memory_type(const std::string& memory_type);
|
||||
|
||||
/// \brief By default, input shape is inherited from model's input shape. Use this method to specify different
|
||||
/// input data shape. If it is needed to change only input height & width of input image, consider define layout and
|
||||
/// use `set_spatial_static_shape' or 'set_spatial_dynamic_shape' instead. This method allows defining any custom
|
||||
/// input shape and can be useful for custom preprocessing operations
|
||||
///
|
||||
/// \note Methods 'set_spatial_dynamic_shape', 'set_spatial_static_shape' are also intended to modify input shape,
|
||||
/// using those methods together will throw ov::AssertFailure exception
|
||||
///
|
||||
/// \param shape New shape for input tensor.
|
||||
///
|
||||
/// \return Reference to 'this' to allow chaining with other calls in a builder-like manner.
|
||||
InputTensorInfo& set_shape(const ov::PartialShape& shape);
|
||||
};
|
||||
|
||||
} // namespace preprocess
|
||||
|
@ -69,12 +69,14 @@ public:
|
||||
}
|
||||
|
||||
void set_spatial_dynamic_shape() {
|
||||
OPENVINO_ASSERT(!m_shape_set, "'set_spatial_dynamic_shape' and 'set_shape' shall not be used together");
|
||||
m_spatial_shape_set = true;
|
||||
m_spatial_width = -1;
|
||||
m_spatial_height = -1;
|
||||
}
|
||||
|
||||
void set_spatial_static_shape(size_t height, size_t width) & {
|
||||
OPENVINO_ASSERT(!m_shape_set, "'set_spatial_static_shape' and 'set_shape' shall not be used together");
|
||||
m_spatial_shape_set = true;
|
||||
m_spatial_height = static_cast<int>(height);
|
||||
m_spatial_width = static_cast<int>(width);
|
||||
@ -122,6 +124,22 @@ public:
|
||||
return m_memory_type_set;
|
||||
}
|
||||
|
||||
void set_shape(const PartialShape& shape) {
|
||||
OPENVINO_ASSERT(
|
||||
!m_spatial_shape_set,
|
||||
"'set_spatial_static_shape', 'set_spatial_dynamic_shape', 'set_shape' shall not be used together");
|
||||
m_shape = shape;
|
||||
m_shape_set = true;
|
||||
}
|
||||
|
||||
bool is_shape_set() const {
|
||||
return m_shape_set;
|
||||
}
|
||||
|
||||
const PartialShape& get_shape() const {
|
||||
return m_shape;
|
||||
}
|
||||
|
||||
private:
|
||||
ColorFormat m_color_format = ColorFormat::UNDEFINED;
|
||||
std::vector<std::string> m_planes_sub_names;
|
||||
@ -138,6 +156,9 @@ private:
|
||||
|
||||
std::string m_memory_type = {};
|
||||
bool m_memory_type_set = false;
|
||||
|
||||
PartialShape m_shape = {};
|
||||
bool m_shape_set = false;
|
||||
};
|
||||
|
||||
class OutputTensorInfo::OutputTensorInfoImpl : public TensorInfoImplBase {};
|
||||
@ -371,6 +392,9 @@ std::shared_ptr<Function> PrePostProcessor::build() {
|
||||
|
||||
auto net_shape = param->get_partial_shape();
|
||||
auto new_param_shape = net_shape;
|
||||
if (input->get_tensor_data()->is_shape_set()) {
|
||||
new_param_shape = input->get_tensor_data()->get_shape();
|
||||
}
|
||||
if (input->get_tensor_data()->is_layout_set() && !param->get_layout().empty() &&
|
||||
param->get_layout() != input->get_tensor_data()->get_layout()) {
|
||||
// Find transpose between network and tensor layouts and update tensor shape
|
||||
@ -652,6 +676,11 @@ InputTensorInfo& InputTensorInfo::set_memory_type(const std::string& memory_type
|
||||
return *this;
|
||||
}
|
||||
|
||||
InputTensorInfo& InputTensorInfo::set_shape(const PartialShape& shape) {
|
||||
m_impl->set_shape(shape);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// --------------------- PreProcessSteps ------------------
|
||||
|
||||
PreProcessSteps::PreProcessSteps() : m_impl(std::unique_ptr<PreProcessStepsImpl>(new PreProcessStepsImpl())) {}
|
||||
|
@ -636,6 +636,42 @@ TEST(pre_post_process, tensor_spatial_shape_no_layout_dims) {
|
||||
p.build(), ov::AssertFailure);
|
||||
}
|
||||
|
||||
TEST(pre_post_process, tensor_set_shape_incompatible) {
|
||||
auto f = create_simple_function(element::f32, Shape{1, 3, 224, 224});
|
||||
auto p = PrePostProcessor(f);
|
||||
EXPECT_THROW(p.input().tensor().set_shape({1, 4, 224, 224}); p.build(), ov::AssertFailure);
|
||||
}
|
||||
|
||||
// Check that 'set_shape' shall not be used together with set_spatial_..._shape
|
||||
// This test can be removed if this requirement is relaxed in future releases
|
||||
TEST(pre_post_process, tensor_set_shape_with_spatial) {
|
||||
auto f = create_simple_function(element::f32, PartialShape{-1, -1, -1, -1});
|
||||
{
|
||||
auto p = PrePostProcessor(f);
|
||||
p.input().tensor().set_layout("NCHW");
|
||||
EXPECT_THROW(p.input().tensor().set_shape({1, 3, 224, 224}).set_spatial_static_shape(448, 448);
|
||||
p.build(), ov::AssertFailure);
|
||||
}
|
||||
{
|
||||
auto p = PrePostProcessor(f);
|
||||
p.input().tensor().set_layout("NCHW");
|
||||
EXPECT_THROW(p.input().tensor().set_spatial_static_shape(448, 448).set_shape({1, 3, 224, 224});
|
||||
p.build(), ov::AssertFailure);
|
||||
}
|
||||
{
|
||||
auto p = PrePostProcessor(f);
|
||||
p.input().tensor().set_layout("NCHW");
|
||||
EXPECT_THROW(p.input().tensor().set_shape({1, 3, 224, 224}).set_spatial_dynamic_shape();
|
||||
p.build(), ov::AssertFailure);
|
||||
}
|
||||
{
|
||||
auto p = PrePostProcessor(f);
|
||||
p.input().tensor().set_layout("NCHW");
|
||||
EXPECT_THROW(p.input().tensor().set_spatial_dynamic_shape().set_shape({1, 3, 224, 224});
|
||||
p.build(), ov::AssertFailure);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(pre_post_process, resize_no_tensor_height) {
|
||||
auto f = create_simple_function(element::f32, Shape{1, 3, 224, 224});
|
||||
auto p = PrePostProcessor(f);
|
||||
|
Loading…
Reference in New Issue
Block a user