Files
openvino/docs/snippets/ov_preprocessing.py
Jan Iwaszkiewicz 8fae2ddfe3 update docs (#12974)
2022-09-12 11:04:54 +02:00

233 lines
7.9 KiB
Python

# Copyright (C) 2018-2022 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
#
from openvino.preprocess import ResizeAlgorithm, ColorFormat
from openvino.runtime import Layout, Type, serialize
xml_path = ''
input_name = ''
# ! [ov:preprocess:create]
from openvino.preprocess import PrePostProcessor
from openvino.runtime import Core
core = Core()
model = core.read_model(model=xml_path)
ppp = PrePostProcessor(model)
# ! [ov:preprocess:create]
# ! [ov:preprocess:tensor]
from openvino.preprocess import ColorFormat
from openvino.runtime import Layout, Type
ppp.input(input_name).tensor() \
.set_element_type(Type.u8) \
.set_shape([1, 480, 640, 3]) \
.set_layout(Layout('NHWC')) \
.set_color_format(ColorFormat.BGR)
# ! [ov:preprocess:tensor]
# ! [ov:preprocess:model]
# `model's input` already `knows` it's shape and data type, no need to specify them here
ppp.input(input_name).model().set_layout(Layout('NCHW'))
# ! [ov:preprocess:model]
# ! [ov:preprocess:steps]
from openvino.preprocess import ResizeAlgorithm
ppp.input(input_name).preprocess() \
.convert_element_type(Type.f32) \
.convert_color(ColorFormat.RGB) \
.resize(ResizeAlgorithm.RESIZE_LINEAR) \
.mean([100.5, 101, 101.5]) \
.scale([50., 51., 52.])
# .convert_layout(Layout('NCHW')); # Not needed, such conversion will be added implicitly
# ! [ov:preprocess:steps]
# ! [ov:preprocess:build]
print(f'Dump preprocessor: {ppp}')
model = ppp.build()
# ! [ov:preprocess:build]
# ! [ov:preprocess:input_index]
ppp.input(1) # Gets 2nd input in a model
ppp.output(2) # Gets output with index=2 (3rd one) in a model
# ! [ov:preprocess:input_index]
# ! [ov:preprocess:input_name]
ppp.input('image')
ppp.output('result')
# ! [ov:preprocess:input_name]
# ! [ov:preprocess:input_1]
# no index/name is needed if model has one input
ppp.input().preprocess().scale(50.)
# same for output
ppp.output() \
.postprocess().convert_element_type(Type.u8)
# ! [ov:preprocess:input_1]
# ! [ov:preprocess:mean_scale]
ppp.input('input').preprocess().mean(128).scale(127)
# ! [ov:preprocess:mean_scale]
# ! [ov:preprocess:mean_scale_array]
# Suppose model's shape is {1, 3, 224, 224}
# N=1, C=3, H=224, W=224
ppp.input('input').model().set_layout(Layout('NCHW'))
# Mean/Scale has 3 values which matches with C=3
ppp.input('input').preprocess() \
.mean([103.94, 116.78, 123.68]).scale([57.21, 57.45, 57.73])
# ! [ov:preprocess:mean_scale_array]
# ! [ov:preprocess:convert_element_type]
# First define data type for your tensor
ppp.input('input').tensor().set_element_type(Type.u8)
# Then define preprocessing step
ppp.input('input').preprocess().convert_element_type(Type.f32)
# If conversion is needed to `model's` element type, 'f32' can be omitted
ppp.input('input').preprocess().convert_element_type()
# ! [ov:preprocess:convert_element_type]
# ! [ov:preprocess:convert_layout]
# First define layout for your tensor
ppp.input('input').tensor().set_layout(Layout('NHWC'))
# Then define layout of model
ppp.input('input').model().set_layout(Layout('NCHW'))
print(ppp) # Will print 'implicit layout conversion step'
# ! [ov:preprocess:convert_layout]
# ! [ov:preprocess:convert_layout_2]
ppp.input('input').tensor().set_shape([1, 480, 640, 3])
# Model expects shape {1, 3, 480, 640}
ppp.input('input').preprocess()\
.convert_layout([0, 3, 1, 2])
# 0 -> 0; 3 -> 1; 1 -> 2; 2 -> 3
# ! [ov:preprocess:convert_layout_2]
# ! [ov:preprocess:resize_1]
ppp.input('input').tensor().set_shape([1, 3, 960, 1280])
ppp.input('input').model().set_layout(Layout('??HW'))
ppp.input('input').preprocess()\
.resize(ResizeAlgorithm.RESIZE_LINEAR, 480, 640)
# ! [ov:preprocess:resize_1]
# ! [ov:preprocess:resize_2]
ppp.input('input').tensor().set_shape([1, 3, 960, 1280])
# Model accepts {1, 3, 480, 640} shape, thus last dimensions are 'H' and 'W'
ppp.input('input').model().set_layout(Layout('??HW'))
# Resize to model's dimension
ppp.input('input').preprocess().resize(ResizeAlgorithm.RESIZE_LINEAR)
# ! [ov:preprocess:resize_2]
# ! [ov:preprocess:convert_color_1]
ppp.input('input').tensor().set_color_format(ColorFormat.BGR)
ppp.input('input').preprocess().convert_color(ColorFormat.RGB)
# ! [ov:preprocess:convert_color_1]
# ! [ov:preprocess:convert_color_2]
# This will split original `input` to 2 separate inputs: `input/y' and 'input/uv'
ppp.input('input').tensor()\
.set_color_format(ColorFormat.NV12_TWO_PLANES)
ppp.input('input').preprocess()\
.convert_color(ColorFormat.RGB)
print(ppp) # Dump preprocessing steps to see what will happen
# ! [ov:preprocess:convert_color_2]
# ! [ov:preprocess:custom]
# It is possible to insert some custom operations
import openvino.runtime.opset8 as ops
from openvino.runtime import Output
from openvino.runtime.utils.decorators import custom_preprocess_function
@custom_preprocess_function
def custom_abs(output: Output):
# Custom nodes can be inserted as Preprocessing steps
return ops.abs(output)
ppp.input("input_image").preprocess() \
.custom(custom_abs)
# ! [ov:preprocess:custom]
# ! [ov:preprocess:postprocess]
# Model's output has 'NCHW' layout
ppp.output('result_image').model().set_layout(Layout('NCHW'))
# Set target user's tensor to U8 type + 'NHWC' layout
# Precision & layout conversions will be done implicitly
ppp.output('result_image').tensor()\
.set_layout(Layout("NHWC"))\
.set_element_type(Type.u8)
# Also it is possible to insert some custom operations
import openvino.runtime.opset8 as ops
from openvino.runtime import Output
from openvino.runtime.utils.decorators import custom_preprocess_function
@custom_preprocess_function
def custom_abs(output: Output):
# Custom nodes can be inserted as Post-processing steps
return ops.abs(output)
ppp.output("result_image").postprocess()\
.custom(custom_abs)
# ! [ov:preprocess:postprocess]
# ! [ov:preprocess:save_headers]
from openvino.preprocess import PrePostProcessor, ColorFormat, ResizeAlgorithm
from openvino.runtime import Core, Layout, Type, set_batch
# First method - imports
from openvino.runtime import serialize
# Second method - imports
from openvino.runtime.passes import Manager, Serialize
# ! [ov:preprocess:save_headers]
# ! [ov:preprocess:save]
# ======== Step 0: read original model =========
core = Core()
model = core.read_model(model='/path/to/some_model.onnx')
# ======== Step 1: Preprocessing ================
ppp = PrePostProcessor(model)
# Declare section of desired application's input format
ppp.input().tensor() \
.set_element_type(Type.u8) \
.set_spatial_dynamic_shape() \
.set_layout(Layout('NHWC')) \
.set_color_format(ColorFormat.BGR)
# Specify actual model layout
ppp.input().model().set_layout(Layout('NCHW'))
# Explicit preprocessing steps. Layout conversion will be done automatically as last step
ppp.input().preprocess() \
.convert_element_type() \
.convert_color(ColorFormat.RGB) \
.resize(ResizeAlgorithm.RESIZE_LINEAR) \
.mean([123.675, 116.28, 103.53]) \
.scale([58.624, 57.12, 57.375])
# Dump preprocessor
print(f'Dump preprocessor: {ppp}')
model = ppp.build()
# ======== Step 2: Change batch size ================
# In this example we also want to change batch size to increase throughput
set_batch(model, 2)
# ======== Step 3: Save the model ================
# First method - using serialize runtime wrapper
serialize(model, '/path/to/some_model_saved.xml', '/path/to/some_model_saved.bin')
# Second method - using Manager and Serialize pass
manager = Manager()
manager.register_pass(Serialize('/path/to/some_model_saved.xml', '/path/to/some_model_saved.bin'))
manager.run_passes(model)
# ! [ov:preprocess:save]
# ! [ov:preprocess:save_load]
core = Core()
core.set_property({'CACHE_DIR': '/path/to/cache/dir'})
# In case that no preprocessing is needed anymore, we can load model on target device directly
# With cached model available, it will also save some time on reading original model
compiled_model = core.compile_model('/path/to/some_model_saved.xml', 'CPU')
# ! [ov:preprocess:save_load]