跳至主要内容

執行模型

使用與 您好,Neat! 相同的運作目錄,來執行一個用於物件偵測的實際模型。 這個應用程式會載入一個 YOLOv8 模型,讀取一張範例圖片,執行推論,解碼邊界框,並印出偵測到的物件數量。

本頁介紹兩個 Neat 概念:

  • Model 載入編譯後的模型套件,並提供 run(...) 進入點。
  • ModelOptions 告訴 Neat 如何準備圖片並解碼偵測器的輸出。

您目前不需要完全掌握整個 API;現在,請專注於 ModelModelOptions 如何協同工作,以執行一個編譯後的模型。

您好,這是 Neat YOLOv8 的流程。

取得模型和範例圖片

  1. 建立一個「assets」目錄,我們將在其中儲存模型和輸入圖片:

    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. 從檔案下載範例圖片,並將其儲存為 tutorial_sample_image.png,儲存在 assets 目錄中。

    開啟或下載範例圖片

  4. 傳回您的專案目錄:

    cd ..

逐步說明

我們將以 您好,Neat! 中的程式碼為基礎:保留相同的 CMakeLists.txt(它已經連結了 Neat 和 OpenCV),並將程式碼主體替換為以下四個步驟。每個步驟都是最終程式碼的一個小部分——請依序閱讀它們,然後取得 完整程式 並複製貼上後執行。在任何程式碼區塊中選擇一個語言標籤;您的選擇將遵循網站範圍內的選擇器。

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 是您的影像與模型之間的執行階段合約。它在此宣告兩件事: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++ 每次會傳遞一個 cv::Mat 作為模型輸入。Python 首先將 NumPy 影像包裝成帶有 BGR 標籤的 Tensor,以便 Neat 知道位元組設定,然後傳遞 [tensor],因為 Python 模型輸入是一個序列。

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 檢測數量開始,因此我們讀取其前四個位元組。完整的序列格式(每個框的座標、分數和類別)已在 從模型輸出的結果中讀取檢測框 中說明。

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 連結),並將程式碼主體替換為以下完整檔案。標記的行是核心的三個步驟:建立 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 學習資源: