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

[OV20 Preprocessing] Preprocessing API - basic preprocessing functionality #7391

Merged
merged 5 commits into from
Sep 8, 2021
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
72 changes: 72 additions & 0 deletions ngraph/core/include/openvino/core/preprocess/input_info.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#pragma once

#include "openvino/core/core_visibility.hpp"
#include "openvino/core/preprocess/input_tensor_info.hpp"
#include "openvino/core/preprocess/preprocess_steps.hpp"

namespace ov {
namespace preprocess {

/// \brief Class holding preprocessing information for one input
/// API has Builder-like style to allow chaining calls in client's code, like
/// \code{.cpp}
/// auto proc = PrePostProcessor().input(InputInfo().tensor(...).preprocess(...);
/// \endcode
class OPENVINO_API InputInfo final {
class InputInfoImpl;
std::unique_ptr<InputInfoImpl> m_impl;
friend class PrePostProcessor;

public:
/// \brief Empty constructor. Should be used only if network will have only one input
InputInfo();

/// \brief Information about info for particular input index of model
///
/// \param input_index Index to address specified input parameter of model
InputInfo(size_t input_index);
nosovmik marked this conversation as resolved.
Show resolved Hide resolved

/// \brief Default move constructor
InputInfo(InputInfo&&) noexcept;

/// \brief Default move assignment operator
InputInfo& operator=(InputInfo&&) noexcept;

/// \brief Default destructor
~InputInfo();

/// \brief Set input tensor information for input - Lvalue version
///
/// \param builder Input tensor information.
///
/// \return Reference to 'this' to allow chaining with other calls in a builder-like manner
InputInfo& tensor(InputTensorInfo&& builder) &;

/// \brief Set input tensor information for input - Rvalue version
///
/// \param builder Input tensor information.
///
/// \return Rvalue reference to 'this' to allow chaining with other calls in a builder-like manner
InputInfo&& tensor(InputTensorInfo&& builder) &&;

/// \brief Set preprocessing operations for input - Lvalue version
///
/// \param builder Preprocessing operations.
///
/// \return Reference to 'this' to allow chaining with other calls in a builder-like manner
InputInfo& preprocess(PreProcessSteps&& builder) &;

/// \brief Set preprocessing operations for input - Rvalue version
///
/// \param builder Preprocessing operations.
///
/// \return Rvalue reference to 'this' to allow chaining with other calls in a builder-like manner
InputInfo&& preprocess(PreProcessSteps&& builder) &&;
};

} // namespace preprocess
} // namespace ov
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#pragma once

#include "openvino/core/core_visibility.hpp"
#include "openvino/core/type/element_type.hpp"

namespace ov {
namespace preprocess {

/// \brief Information about user's input tensor. By default, it will be initialized to same data (type/shape/etc) as
/// network's input parameter User application can override particular parameters (like 'element_type') according to
/// application's data and specify appropriate conversions in pre-processing steps
///
/// \code{.cpp}
/// auto proc =
/// PrePostProcessor()
/// .input(InputInfo()
/// .tensor(InputTensorInfo()
/// .set_element_type(ov::element::u8))
/// .preprocess(<add steps + conversion to network's input element type>)
/// );
/// \endcode
class OPENVINO_API InputTensorInfo final {
class InputTensorInfoImpl;
std::unique_ptr<InputTensorInfoImpl> m_impl;
friend class InputInfo;

public:
/// \brief Default empty constructor
InputTensorInfo();

/// \brief Default move constructor
InputTensorInfo(InputTensorInfo&&) noexcept;

/// \brief Default move assignment
InputTensorInfo& operator=(InputTensorInfo&&) noexcept;

/// \brief Default destructor
~InputTensorInfo();

/// \brief Set element type for user's input tensor
/// This version allows chaining for Lvalue objects
///
/// \param type Element type for user's input tensor.
///
/// \return Reference to 'this' to allow chaining with other calls in a builder-like manner
InputTensorInfo& set_element_type(const ov::element::Type& type) &;

/// \brief Set element type for user's input tensor
/// This version allows chaining for Rvalue objects
///
/// \param builder Pre-processing data for input tensor of model.
///
/// \return Rvalue reference to 'this' to allow chaining with other calls in a builder-like manner
InputTensorInfo&& set_element_type(const ov::element::Type& type) &&;
};

} // namespace preprocess
} // namespace ov
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#pragma once

#include "openvino/core/core_visibility.hpp"
#include "openvino/core/preprocess/input_info.hpp"

namespace ov {

class Function;

namespace preprocess {

/// \brief Main class for adding pre- and post- processing steps to existing ov::Function
/// API has Builder-like style to allow chaining calls in client's code, like
/// \code{.cpp}
/// auto proc = PrePostProcessor().input(<for input1>).input(<input2>);
/// \endcode
///
/// This is a helper class for writing easy pre- and post- processing operations on ov::Function object assuming that
/// any preprocess operation takes one input and produces one output.
///
/// For advanced preprocessing scenarios, like combining several functions with multiple inputs/outputs into one,
/// client's code can use transformation passes over ov::Function
///
class OPENVINO_API PrePostProcessor final {
class PrePostProcessorImpl;
std::unique_ptr<PrePostProcessorImpl> m_impl;

public:
/// \brief Default constructor
PrePostProcessor();

/// \brief Default move constructor
PrePostProcessor(PrePostProcessor&&) noexcept;

/// \brief Default move assignment operator
PrePostProcessor& operator=(PrePostProcessor&&) noexcept;

/// \brief Default destructor
~PrePostProcessor();

/// \brief Adds pre-processing information and steps to input of model. This method can be used only if ov::Function
/// passed on `build` has only one input
///
/// \param builder Pre-processing data for input tensor of model.
///
/// \return Reference to 'this' to allow chaining with other calls in a builder-like manner
PrePostProcessor& input(InputInfo&& builder) &;

/// \brief Adds pre-processing information and steps to input of model - Rvalue version. This method can be used
/// only if ov::Function passed on `build` has only one input.
///
/// \param builder Pre-processing data for input tensor of model.
///
/// \return Rvalue reference to 'this' to allow chaining with other calls in a builder-like manner
PrePostProcessor&& input(InputInfo&& builder) &&;

/// \brief Adds pre/post-processing operations to existing function
///
/// \param function Existing function representing loaded model
///
/// \return Function with added pre/post-processing operations
std::shared_ptr<Function> build(const std::shared_ptr<Function>& function);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we create a copy of function or we are changing the original funciton?
I mean that if we return the pointer to function the user can be surprised if original function also was changed.

};

} // namespace preprocess
} // namespace ov
117 changes: 117 additions & 0 deletions ngraph/core/include/openvino/core/preprocess/preprocess_steps.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#pragma once

#include "openvino/core/core_visibility.hpp"
#include "openvino/core/type/element_type.hpp"

namespace ov {

class Node;

namespace preprocess {

/// \brief Preprocessing steps. Each step typically intends adding of some operation to input parameter
/// User application can specify sequence of preprocessing steps in a builder-like manner
/// \code{.cpp}
/// auto proc = PrePostProcessor()
/// .input(InputInfo()
/// .preprocess(PreProcessSteps()
/// .mean(0.2f) // Subtract 0.2 from each element
/// .scale(2.3f)) // then divide each element to 2.3
/// );
/// \endcode
class OPENVINO_API PreProcessSteps final {
class PreProcessStepsImpl;
std::unique_ptr<PreProcessStepsImpl> m_impl;
friend class InputInfo;

public:
/// \brief Default empty constructor
PreProcessSteps();

/// \brief Default move constructor
PreProcessSteps(PreProcessSteps&&) noexcept;

/// \brief Default move assignment operator
PreProcessSteps& operator=(PreProcessSteps&&) noexcept;

/// \brief Default destructor
~PreProcessSteps();

/// \brief Add convert element type preprocess operation - Lvalue version
///
/// \param type Desired type of input.
///
/// \return Reference to 'this' to allow chaining with other calls in a builder-like manner
PreProcessSteps& convert_element_type(const ov::element::Type& type) &;

/// \brief Add convert element type preprocess operation - Rvalue version
///
/// \param type Desired type of input.
///
/// \return Rvalue reference to 'this' to allow chaining with other calls in a builder-like manner
PreProcessSteps&& convert_element_type(const ov::element::Type& type) &&;

/// \brief Add scale preprocess operation - Lvalue version
/// Divide each element of input by specified value
///
/// \param value Scaling value.
///
/// \return Reference to 'this' to allow chaining with other calls in a builder-like manner
PreProcessSteps& scale(float value) &;

/// \brief Add scale preprocess operation - Rvalue version
/// Divide each element of input by specified value
///
/// \param value Scaling value.
///
/// \return Rvalue reference to 'this' to allow chaining with other calls in a builder-like manner
PreProcessSteps&& scale(float value) &&;

/// \brief Add mean preprocess operation - Lvalue version
/// Subtract specified value from each element of input
///
/// \param value Value to subtract from each element.
///
/// \return Reference to 'this' to allow chaining with other calls in a builder-like manner
PreProcessSteps& mean(float value) &;

/// \brief Add mean preprocess operation - Rvalue version
/// Subtract specified value from each element of input
///
/// \param value Value to subtract from each element.
///
/// \return Rvalue reference to 'this' to allow chaining with other calls in a builder-like manner
PreProcessSteps&& mean(float value) &&;

/// \brief Signature for custom preprocessing operation. Custom preprocessing operation takes one input node and
/// produces one output node. For more advanced cases, client's code can use transformation passes over ov::Function
/// directly
///
/// \param node Input node for custom preprocessing operation
///
/// \return New node after applying custom preprocessing operation
using CustomPreprocessOp = std::function<std::shared_ptr<ov::Node>(const std::shared_ptr<ov::Node>& node)>;

/// \brief Add custom preprocess operation - Lvalue version
/// Client application can specify callback function for custom action
///
/// \param preprocess_cb Client's custom preprocess operation.
///
/// \return Reference to 'this' to allow chaining with other calls in a builder-like manner
PreProcessSteps& custom(const CustomPreprocessOp& preprocess_cb) &;

/// \brief Add custom preprocess operation - Rvalue version
/// Client application can specify callback function for custom action
///
/// \param preprocess_cb Client's custom preprocess operation.
///
/// \return Rvalue reference to 'this' to allow chaining with other calls in a builder-like manner
PreProcessSteps&& custom(const CustomPreprocessOp& preprocess_cb) &&;
};

} // namespace preprocess
} // namespace ov
Loading