Changing Input Shapes — OpenVINO™ documentation (original) (raw)
OpenVINO™ enables you to change model input shape during the application runtime. It may be useful when you want to feed the model an input that has different size than the model input shape. The following instructions are for cases where you need to change the model input shape repeatedly.
The reshape method#
The reshape method is used as ov::Model::reshape
in C++ andModel.reshapein Python. The method updates input shapes and propagates them down to the outputs of the model through all intermediate layers. The code below is an example of how to set a new batch size with the reshape
method:
Python
model.reshape([8, 3, 448, 448])
C++
model->reshape({8, 3, 448, 448});
The diagram below presents the results of using the method, where the size of model input is changed with an image input:
When using the reshape
method, you may take one of the approaches:
- You can pass a new shape to the method in order to change the input shape of the model with a single input. See the example of adjusting spatial dimensions to the input image:
Python
image = get_image()
model.reshape([1, 3, image.shape[0], image.shape[1]])
C++
// Read an image and adjust models single input for image to fit
cv::Mat image = cv::imread("path/to/image");
model->reshape({1, 3, image.rows, image.cols});
To do the opposite - to resize input image to match the input shapes of the model, use the pre-processing API. - You can express a reshape plan, specifying the input by the port, the index, and the tensor name:
Port
Pythonopenvino.runtime.Output
dictionary key specifies input by passing actual input object. Dictionary values representing new shapes could bePartialShape
:
port_to_shape = dict()
for input_obj in model.inputs:
shape = input_obj.get_partial_shape()modify shape to fit your needs
port_to_shape[input_obj] = shape ...
model.reshape(port_to_shape)
C++map<ov::Output<ov::Node>, ov::PartialShape
specifies input by passing actual input port:
std::map<ov::Outputov::Node, ov::PartialShape> port_to_shape;
for (const ov::Outputov::Node& input : model->inputs()) {
ov::PartialShape shape = input.get_partial_shape();
// Modify shape to fit your needs
// ...
port_to_shape[input] = shape;
}
model->reshape(port_to_shape);
Index
Pythonint
dictionary key specifies input by its index. Dictionary values representing new shapes could betuple
:
idx_to_shape = dict()
i = 0
for input_obj in model.inputs:
shape = input_obj.get_partial_shape()modify shape to fit your needs
idx_to_shape[i] = shape ...
i += 1
model.reshape(idx_to_shape)
C++map<size_t, ov::PartialShape>
specifies input by its index:
size_t i = 0;
std::map<size_t, ov::PartialShape> idx_to_shape;
for (const ov::Outputov::Node& input : model->inputs()) {
ov::PartialShape shape = input.get_partial_shape();
// Modify shape to fit your needs
// ...
idx_to_shape[i++] = shape;
}
model->reshape(idx_to_shape);
Tensor Name
Pythonstr
dictionary key specifies input by its name. Dictionary values representing new shapes could bestr
:
name_to_shape = dict()
for input_obj in model.inputs:
shape = input_obj.get_partial_shape()if len(input_obj.get_names()) != 0: input may have no name, in such case use map based on input index or port instead
# modify shape to fit your needs
# ...
name_to_shape[input_obj.get_any_name()] = shape
model.reshape(name_to_shape)
C++map<string, ov::PartialShape>
specifies input by its name:
std::map<std::string, ov::PartialShape> name_to_shape;
for (const ov::Outputov::Node& input : model->inputs()) {
ov::PartialShape shape = input.get_partial_shape();
// input may have no name, in such case use map based on input index or port instead
if (!input.get_names().empty()) {
// Modify shape to fit your needs
// ...
name_to_shape[input.get_any_name()] = shape;
}
}
model->reshape(name_to_shape);
You can find the usage scenarios of the reshape
method inHello Reshape SSD Samples.
Note
In some cases, models may not be ready to be reshaped. Therefore, a new input shape cannot be set neither with Model Conversion APInor the reshape
method.
The set_batch method#
The meaning of the model batch may vary depending on the model design. To change the batch dimension of the model, set the layout and call the set_batch
method.
Python
model.get_parameters()[0].set_layout(ov.Layout("N..."))
C++
// Mark up batch in the layout of the input(s) and reset batch to the new value
model->get_parameters()[0]->set_layout("N...");
The set_batch
method is a high-level API of the reshape functionality, so all information about the reshape
method implications are applicable for set_batch
too.
Once you set the input shape of the model, call the compile_model
method to get a CompiledModel
object for inference with updated shapes.
There are other approaches to change model input shapes during the stage ofIR generation or model representation in OpenVINO Runtime.
Important
Shape-changing functionality could be used to turn dynamic model input into a static one and vice versa. Always set static shapes when the shape of data is NOT going to change from one inference to another. Setting static shapes can avoid memory and runtime overheads for dynamic shapes which may vary depending on hardware plugin and model used. For more information, refer to theDynamic Shapes.
Additional Resources#
- Extensibility documentation - describes a special mechanism in OpenVINO that allows adding support of shape inference for custom operations.
- ov::Model::reshape - in OpenVINO Runtime C++ API
- Model.reshape - in OpenVINO Runtime Python API.
- Dynamic Shapes
- OpenVINO samples
- Preprocessing API