使用例 - 前処理ステップを IR に統合して保存

前のセクションでは、前処理ステップのトピックとレイアウト API の概要について説明しました。

多くのアプリケーションでは、モデルの読み取り/読み込み時間を最小限に抑えることも重要です。したがって、ov::runtime::Core::read_model の後、アプリケーションの起動時に毎回前処理ステップの統合を実行するのは不便に思えるかもしれません。この場合、前処理ステップと後処理ステップを追加した後、新しい実行モデルを OpenVINO 中間表現 (OpenVINO IR、.xml 形式) に保存すると便利です。

利用可能な前処理ステップのほとんどは、モデル・オプティマイザーを使用してコマンドライン・オプションからも実行できます。コマンドライン・オプションの詳細については、前処理計算の最適化を参照してください。

サンプルコード - 前処理を含むモデルを OpenVINO IR に保存

一部の前処理ステップをモデル・オプティマイザーのコマンドライン・オプション (YUV ->``RGB`` 色空間変換、サイズ変更など) を使用して実行グラフに統合できない場合は、次のような単純なコードを記述することができます。

  • 元のモデル (OpenVINO IR、TensorFlow、TensorFlow Lite、ONNX、PaddlePaddle) を読み取ります。

  • 前処理/後処理ステップを追加します。

  • 結果のモデルを IR (.xml および .bin) として保存します。

元の ONNX モデルが、{1, 3, 224, 224} 形状、RGB チャネル順序、および平均/スケール値が適用された 1 つの float32 入力を受け取る例を考えてみます。対照的に、アプリケーションは、非固定サイズの BGR 画像バッファーと入力画像を 2 つのバッチとして提供します。以下は、このような場合にモデル準備スクリプトに適用できるモデル変換コードです。

  • インクルード/インポート

from openvino.preprocess import PrePostProcessor, ColorFormat, ResizeAlgorithm
from openvino import Core, Layout, Type, set_batch
from openvino import serialize
 #include <openvino/runtime/core.hpp>
 #include <openvino/core/preprocess/pre_post_process.hpp>
 #include <openvino/pass/serialize.hpp>
  • 前処理と OpenVINO IR コードへの保存。

# ========  Step 0: read original model =========
core = Core()
model = core.read_model(model=model_path)

# ======== 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 ================
serialize(model, serialized_model_path)
 // ========  Step 0: read original model =========
 ov::Core core;
 std::shared_ptr<ov::Model> model = core.read_model("/path/to/some_model.onnx");

 // ======== Step 1: Preprocessing ================
 ov::preprocess::PrePostProcessor prep(model);
 // Declare section of desired application's input format
 prep.input().tensor()
        .set_element_type(ov::element::u8)
        .set_layout("NHWC")
        .set_color_format(ov::preprocess::ColorFormat::BGR)
        .set_spatial_dynamic_shape();
 // Specify actual model layout
 prep.input().model()
        .set_layout("NCHW");
 // Explicit preprocessing steps. Layout conversion will be done automatically as last step
 prep.input().preprocess()
        .convert_element_type()
        .convert_color(ov::preprocess::ColorFormat::RGB)
        .resize(ov::preprocess::ResizeAlgorithm::RESIZE_LINEAR)
        .mean({123.675f, 116.28f, 103.53f}) // Subtract mean after color conversion
        .scale({58.624f, 57.12f, 57.375f});
 // Dump preprocessor
 std::cout << "Preprocessor: " << prep << std::endl;
 model = prep.build();

 // ======== Step 2: Change batch size ================
 // In this example we also want to change batch size to increase throughput
 ov::set_batch(model, 2);

 // ======== Step 3: Save the model ================
 std::string xml = "/path/to/some_model_saved.xml";
 std::string bin = "/path/to/some_model_saved.bin";
 ov::serialize(model, xml, bin);

アプリケーション・コード - モデルをターゲットデバイスにロード

この後、アプリケーション・コードは保存されたファイルをロードし、前処理を停止できます。この場合、モデルのキャッシュを有効にして、キャッシュされたモデルが使用可能なときにロード時間を最小限に抑えます。

core = Core()
core.set_property({props.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(serialized_model_path, 'CPU')
 ov::Core core;
 core.set_property(ov::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
 ov::CompiledModel compiled_model = core.compile_model("/path/to/some_model_saved.xml", "CPU");

関連情報