メインコンテンツまでスキップ

モデルを実行する

こんにちは、Neat!で使用したのと同じワーキングディレクトリを使用して、オブジェクト検出のための実際のモデルを実行します。 このアプリケーションは、YOLOv8モデルをロードし、サンプル画像を読み込み、推論を実行し、バウンディングボックスをデコードし、検出されたオブジェクトの数を表示します。

このページでは、次の2つのNeatの概念を紹介します。

  • Modelは、コンパイルされたモデルパッケージをロードし、run(...)のエントリポイントを提供します。
  • ModelOptionsは、Neatに、画像をどのように準備し、検出器の出力をどのようにデコードするかを指示します。

まだ完全なAPIを習得する必要はありません。現時点では、ModelModelOptionsがどのように連携して、コンパイルされたモデルを実行するかという点に焦点を当ててください。

こんにちは、Neat YOLOv8フロー。

モデルとサンプル画像を取得する

  1. モデルと入力画像を保存するアセットディレクトリを作成します。

    mkdir -p assets
    cd assets
  2. モデルをダウンロードします:

    sima-cli modelzoo -v 2.0.0 get yolo_v8s
    sima-cli モデルのダウンロード

    sima-cli がモデルを assets ディレクトリ以外の場所に書き込む場合は、そのファイルを assets/yolo_v8s_mpk.tar.gz にコピーしてください。

  3. サンプル画像をダウンロードし、assets ディレクトリに tutorial_sample_image.png として保存します。

    サンプル画像を閲覧またはダウンロードしてください。

  4. プロジェクトディレクトリに戻ります:

    cd ..

概要

このプログラムをさらに発展させます。 こんにちは、Neat!:変更しない CMakeLists.txt (すでにリンクされています) Neat および OpenCV を使用し、プログラムの本体を以下の 4 つの手順に置き換えます。各手順は、最終的なプログラムの一部です。手順を順番に読み、次に次の手順に進んでください。 完全版プログラム 貼り付けて実行します。任意のブロックにある言語タブを選択してください。選択内容はサイト全体の設定に反映されます。

1. 画像を読み込み、サイズを変更します。

YOLOv8s は固定サイズの 640×640 BGR 画像を想定しているため、OpenCV でサンプル画像を読み込み、サイズを変更します。これは通常の画像入出力処理であり、この時点ではまだ Neat API を使用しません。

cv::Mat load_sample_image() {
cv::Mat bgr = cv::imread("assets/tutorial_sample_image.png", cv::IMREAD_COLOR);
if (bgr.empty())
throw std::runtime_error("failed to load sample image");
cv::resize(bgr, bgr, cv::Size(640, 640)); // YOLOv8s input size
return bgr;
}

2. 入力とデコードについて説明します。 ModelOptions

ModelOptions これは、お客様のイメージとモデル間のランタイム契約です。ここでは、以下の2つのことを規定します。 Neat 推論の前に、デコードされたピクセルをどのように前処理すべきか、また、検出器の生の出力データをどのようにボックスに変換すべきか。 decode_type YOLOv8デコーダーを選択し、閾値を使用して、検出精度の低い、または重複するバウンディングボックスを排除します。 top_k 上限を設定します。

simaai::neat::Model::Options opt;
opt.preprocess.kind = simaai::neat::InputKind::Image;
opt.preprocess.preset = simaai::neat::NormalizePreset::COCO_YOLO;
opt.decode_type = simaai::neat::BoxDecodeType::YoloV8;
opt.score_threshold = 0.55f;
opt.nms_iou_threshold = 0.5f;
opt.top_k = 100;

3. モデルをロードし、推論を実行する

コンパイルされた .tar.gz パッケージとオプションから Model を構築し、次にタイムアウトを指定して run(...) を呼び出します。これは同期的に実行され、出力テンソルを返します。timeout_ms を設定することで、処理が停止した場合に、ハングアップするのではなく、エラーを明確に表示するようにします。

C++ では、モデル入力ごとに 1 つの cv::Mat を渡します。Python では、まず NumPy イメージを BGR タグが付いた Tensor としてラップし、Neat にバイトレイアウトを認識させた後、Python モデル入力はシーケンスであるため、[tensor] を渡します。

simaai::neat::Model yolo("assets/yolo_v8s_mpk.tar.gz", opt);
simaai::neat::TensorList outputs = yolo.run(std::vector<cv::Mat>{bgr}, /*timeout_ms=*/2000);

4. 検出数の読み込み

decode_type が設定されているため、最初の出力テンソルにはデコードされたバウンディングボックスが含まれます。BBOXテンソルは、uint32 形式の検出数で始まり、最初の4バイトを読み取ります。完全なワイヤー形式(ボックスごとの座標、スコア、クラス)については、モデルの出力から検出ボックスを読み取る を参照してください。

std::uint32_t detections = 0;
if (!outputs.empty()) {
simaai::neat::Mapping view = outputs.front().map_read();
if (view.size_bytes >= sizeof(detections))
std::memcpy(&detections, view.data, sizeof(detections));
}
std::cout << "detections=" << detections << "\n";

プログラム全体

こんにちは、Neat!CMakeLists.txt をそのまま使用します(すでにアプリケーションと Neat および OpenCV をリンクしています)。プログラムの本体を、以下に示す完全なファイルに置き換えます。強調表示されている行が、プログラムの主要な3つの部分です。Model を作成し、入力を構築し、run() を呼び出します。

プログラム全体を表示する
main.cpp
#include "neat.h"

#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>

#include <cstdint>
#include <cstring>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>

cv::Mat load_sample_image() {
cv::Mat bgr = cv::imread("assets/tutorial_sample_image.png", cv::IMREAD_COLOR);
if (bgr.empty())
throw std::runtime_error("failed to load sample image");

// YOLOv8s expects a 640 x 640 input in this tutorial.
cv::resize(bgr, bgr, cv::Size(640, 640));
return bgr;
}

int main() {
// 1. Load the sample image and resize it for the model.
cv::Mat bgr = load_sample_image();

// 2. Tell Neat how to preprocess pixels and decode YOLO boxes.
simaai::neat::Model::Options opt;
opt.preprocess.kind = simaai::neat::InputKind::Image;
opt.preprocess.preset = simaai::neat::NormalizePreset::COCO_YOLO;
opt.decode_type = simaai::neat::BoxDecodeType::YoloV8;
opt.score_threshold = 0.55f;
opt.nms_iou_threshold = 0.5f;
opt.top_k = 100;

// 3. Load the compiled model package and run inference.
simaai::neat::Model yolo("assets/yolo_v8s_mpk.tar.gz", opt);
simaai::neat::TensorList outputs = yolo.run(std::vector<cv::Mat>{bgr}, /*timeout_ms=*/2000);

// 4. The BBOX output starts with a uint32 detection count.
std::uint32_t detections = 0;
if (!outputs.empty()) {
simaai::neat::Mapping view = outputs.front().map_read();
if (view.size_bytes >= sizeof(detections))
std::memcpy(&detections, view.data, sizeof(detections));
}
std::cout << "detections=" << detections << "\n";
std::cout << "[OK] YOLOv8 completed\n";
return 0;
}

ビルドと実行

これらをプロジェクトディレクトリ(assets/ が含まれるディレクトリ)から実行してください。

「Hello Neat!」と同じコマンドで再構築し、その後、バイナリを実行します。

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
./build/sima_neat_hello # on the DevKit
dk build/sima_neat_hello # from the Palette SDK host

以下のような検出結果の概要が表示されるはずです。

detections=3
[OK] YOLOv8 completed

正確な数は、モデルパックとランタイムのバージョンによって異なります。重要なのは、アプリがビルドされ、実行され、[OK] YOLOv8 completed に到達することです。

作成した内容

この例では、より大規模な Neat アプリケーションで使用されるのと同じ基本的な手順に従います。

  • コンパイルされたモデルパッケージ(.tar.gz)をModel としてロードします。
  • 入力画像を、モデルが期待する形式に変換します。
  • Neat ランタイムステージを通じて推論を実行します。
  • 生の検出器出力を、バウンディングボックスにデコードします。

バウンディングボックスのデコード、閾値、NMS、および検出器出力構造の詳細な説明については、モデルの出力から検出ボックスを読み取る を参照してください。

次のステップ

YOLOv8の実行後、より広範な SiMa.ai Neat の学習リソースに進みます。

  • アプリを実行する を使用して、この同じモデルをGraph アプリケーションに組み込みます。これは、名前付きの入力 → モデル → 出力パイプラインであり、一度構築して、Model.run(...) を直接呼び出す代わりに、プッシュ/プルで実行します。
  • 基本的なプログラミングモデル を学習します。これには、モデル、グラフ、およびランタイム実行など、主要な Neat の概念が説明されています。
  • チュートリアル を参照して、特定の概念とワークフローを段階的に確認します。
  • アプリポータル で厳選されたアプリケーションを探索し、GitHub上のアプリケーションリポジトリ でソースコードを確認します。