Запустіть програму.

Результати, отримані програмою, відображені на вихідному зображенні.
Це такий самий висновок YOLOv8, як і в невеликій програмі: замість безпосереднього виклику Model.run(...) (як у Запустіть модель.), ви створюєте модель у вигляді Graph — іменованого графа, що містить вхідні дані, модель і вихідні дані, — а потім збираєте його та передаєте/отримуєте дані. Та сама програма, написана мовами Python і C++; виберіть потрібну мову у відповідному блоці коду.
Для цієї першої програми структура навмисно проста:
- Іменований параметр вхідних даних (
nodes.input("image")) позначає місце, звідки дані надходять у застосунок. - Модель (
graph.add(model)) виконує модель як один крок у графі. - Іменований параметр output (
nodes.output("detections")) вказує, звідки ваша програма отримує результат.
Цей самий API можна використовувати для розробки набагато складніших застосунків у майбутньому; тут основна мета полягає в реалізації базової моделі компонування.
Використовуйте вкладки Python / C++ у будь-якому блоці коду — ваш вибір відповідатиме загальному мовному селектору сайту, тому всі фрагменти коду та повна програма перемикатимуться одночасно.
Налаштуйте проєкт.
Ви можете пропустити цей розділ, оскільки в ньому використовуються ті самі assets/, пакунок моделі та зразок зображення. Перейдіть одразу до Перегляньте код..
-
Створіть теку для ресурсів для моделі та вхідного зображення:
sdk or devkit$mkdir -p assets -
Завантажте модель:
sdk or devkit$sima-cli modelzoo -v 2.0.0 get yolo_v8ssima-cli завантажити модельЯкщо
sima-cliзберігає модель в іншому місці, ніж директоріяassets, скопіюйте цей файл доassets/yolo_v8s_mpk.tar.gz. -
Завантажте зразок зображення з документації та збер ежіть його під назвою
assets/tutorial_sample_image.png.
Перегляньте код.
Програма складається з восьми коротких фрагментів. Перемикайте вкладку мови для кожного блоку.
1. Зчитайте зображення.
#include <opencv2/opencv.hpp>
cv::Mat bgr = cv::imread("assets/tutorial_sample_image.png");
cv::Mat rgb;
cv::cvtColor(bgr, rgb, cv::COLOR_BGR2RGB);
OpenCV зчитує BGR; YOLOv8 очікує RGB. Цей крок не є Neat — ваша програма отримує пікселі з файлу, камери або декодера; Neat переходить до наступного кроку.
2. Опишіть доступні варіанти моделі.
#include <neat.h>
namespace neat = simaai::neat;
neat::Model::Options opt;
opt.preprocess.kind = neat::InputKind::Image;
opt.preprocess.preset = neat::NormalizePreset::COCO_YOLO;
opt.decode_type = neat::BoxDecodeType::YoloV8;
opt.score_threshold = 0.25f;
opt.nms_iou_threshold = 0.45f;
opt.top_k = 100;
ModelOptions визначає маршрут моделі в одному об’єкті: як Neat попередньо обробляє вхідні пікселі та як він декодує вихідні дані детектора.
| Поле | Що в ньому міститься. |
|---|---|
preprocess.kind = Image | На вхід подаються необроблені пікселі, а не попередньо сформований тензор. |
preprocess.preset = COCO_YOLO | Змініть розмір і додайте рамки, щоб відповідало вхідним даним моделі, RGB, масштабуйте на 1/255, не виконуйте віднімання середнього значення. |
decode_type = YoloV8 | Сімейство декодерів, що використовують метод виявлення об’єктів. |
score_threshold / nms_iou_threshold / top_k | Мінімальний поріг впевненості, ступінь перекриття NMS і максимальна кількість збережених обмежувальних рамок. |
3. Завантажте модель.
neat::Model model("assets/yolo_v8s_mpk.tar.gz", opt);
Model зчитує .tar.gz, перевіряє його MPK-контракт на відповідність ModelOptions, які ви надали, і створює фрагмент моделі. Наразі жоден процес не було запущено.
4. Перетворіть ваше зображення на Tensor.
neat::Tensor input = neat::Tensor::from_cv_mat(
rgb,
neat::ImageSpec::PixelFormat::RGB);
Tensor — це контейнер для даних із зазначенням типу, який використовується в Neat: він містить інформацію про розмір, тип даних, структуру та формат пікселів, необхідний для інтерпретації байтів. Передача PixelFormat є обов’язковою, щоб Neat знав структуру даних, а не лише самі байти.
5. Створіть граф.
neat::Graph graph("hello_neat_app");
graph.add(neat::nodes::Input("image"));
graph.add(model);
graph.add(neat::nodes::Output("detections"));
Graph – це схема взаємодії між компонентами застосунку. Кожен add(...) додає наступний крок, таким чином формуючи лінійний потік image → model → detections. Фрагмент моделі з кроку 3 стає одним із кроків у цьому потоці.
6. Створіть і запустіть граф.
neat::Run run = graph.build();
run.push("image", neat::TensorList{input});
run.close_input();
neat::TensorList outputs = run.pull_tensors("detections", /*timeout_ms=*/2000);
run.close();
build() перетворює загальнодоступний граф в один виконуваний граф для середовища виконання, зберігаючи назви ваших вузлів. Потім ви push вхідні дані в іменовані вхідні дані, викликаєте close_input(), коли більше не надходить вхідних даних, і pull результати з іменованих вихідних даних із заданим часом очікування. pull_tensors повертає TensorList — тензор зі структурою, яку б створив Model.run — тут це об’єднаний вихід YOLOv8 BBOX.
7. Розшифруйте вміст коробок.
neat::TensorList decoded = neat::decode_bbox(outputs);
decode_bbox — це TensorList → TensorList трансформація, що застосовується в співвідношенні 1:1. Кожен декодований вихід є float32 тензором розмірності [num_detections, 6], що містить стовпці (x1, y1, x2, y2, score, class_id).
8. Зчитайте обмежувальні рамки
const neat::Tensor& boxes = decoded.front(); // [num_detections, 6] float32
auto m = boxes.map_read();
const float* d = static_cast<const float*>(m.data);
for (int64_t i = 0; i < boxes.shape[0]; ++i) {
const float* r = d + i * 6; // x1 y1 x2 y2 score class_id
const int cls = static_cast<int>(r[5]);
const char* name = (cls == 0) ? "person" : (cls == 27) ? "tie" : "?";
std::printf("%-8s %.2f [%4.0f %4.0f %4.0f %4.0f]\n", name, r[4], r[0], r[1], r[2], r[3]);
}
У Python декодований тензор зчитується як масив NumPy за допомогою [N, 6] та функції to_numpy(). У C++ ви відображаєте тензор і зчитуєте значення з плаваючою комою. Модель генерує ідентифікатори класів COCO; відображення їх на відображувані назви здійснюється в застосунку.
Повна програма
Створіть файли у каталозі вашого проєкту, а потім скомпілюйте та запустіть їх.
Створіть файли CMakeLists.txt та main.cpp:
cmake_minimum_required(VERSION 3.16)
project(sima_neat_app LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Supports both DevKit/native installs (system paths) and
# cross builds with SYSROOT exported (SDK sysroot paths).
if(DEFINED ENV{SYSROOT} AND NOT "$ENV{SYSROOT}" STREQUAL "")
list(APPEND CMAKE_PREFIX_PATH
"$ENV{SYSROOT}/usr"
"$ENV{SYSROOT}/usr/lib"
"$ENV{SYSROOT}/usr/lib/aarch64-linux-gnu"
)
endif()
find_package(SimaNeat REQUIRED CONFIG)
find_package(PkgConfig REQUIRED)
pkg_check_modules(OPENCV REQUIRED IMPORTED_TARGET opencv4)
add_executable(sima_neat_app main.cpp)
target_link_libraries(sima_neat_app
PRIVATE
SimaNeat::sima_neat
PkgConfig::OPENCV
)
Дві виділені рядки показують, як ваш застосунок пов’язаний із Neat: find_package(SimaNeat REQUIRED CONFIG) знаходить встановлений пакет Neat (через SimaNeatConfig.cmake), а target_link_libraries(sima_neat_app PRIVATE SimaNeat::sima_neat ...) встановлює зв’язок із ним — імпортована ціль SimaNeat::sima_neat автоматично передає каталоги заголовків і транзитивні залежності Neat, тому не потрібно вказувати шляхи до заголовків/бібліотек вручну. (PkgConfig::OPENCV потрібен лише тому, що цей застосунок використовує OpenCV для завантаження зображень).
#include "neat.h"
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <cstdint>
#include <cstdio>
#include <stdexcept>
namespace neat = simaai::neat;
neat::Model::Options yolo_model_options() {
neat::Model::Options opt;
opt.preprocess.kind = neat::InputKind::Image;
opt.preprocess.preset = neat::NormalizePreset::COCO_YOLO;
opt.decode_type = neat::BoxDecodeType::YoloV8;
opt.score_threshold = 0.25f;
opt.nms_iou_threshold = 0.45f;
opt.top_k = 100;
return opt;
}
int main() {
cv::Mat bgr = cv::imread("assets/tutorial_sample_image.png");
if (bgr.empty())
throw std::runtime_error("failed to read assets/tutorial_sample_image.png");
cv::Mat rgb;
cv::cvtColor(bgr, rgb, cv::COLOR_BGR2RGB);
neat::Model model("assets/yolo_v8s_mpk.tar.gz", yolo_model_options());
neat::Tensor input = neat::Tensor::from_cv_mat(
rgb,
neat::ImageSpec::PixelFormat::RGB);
// Compose the model into a Graph application: image -> model -> detections.
neat::Graph graph("hello_neat_app");
graph.add(neat::nodes::Input("image"));
graph.add(model);
graph.add(neat::nodes::Output("detections"));
// Build the app, push the image into the named input, pull the named output.
neat::Run run = graph.build();
run.push("image", neat::TensorList{input});
run.close_input();
neat::TensorList outputs = run.pull_tensors("detections", /*timeout_ms=*/2000);
run.close();
neat::TensorList decoded = neat::decode_bbox(outputs);
const neat::Tensor& boxes = decoded.front(); // [num_detections, 6] float32
auto m = boxes.map_read();
const float* d = static_cast<const float*>(m.data);
for (int64_t i = 0; i < boxes.shape[0]; ++i) {
const float* r = d + i * 6; // x1 y1 x2 y2 score class_id
const int cls = static_cast<int>(r[5]);
const char* name = (cls == 0) ? "person" : (cls == 27) ? "tie" : "?";
std::printf("%-8s %.2f [%4.0f %4.0f %4.0f %4.0f]\n", name, r[4], r[0], r[1], r[2], r[3]);
}
std::printf("[OK] Graph app completed\n");
return 0;
}
Збірка:
sdk or devkit$cmake -S . -B build -DCMAKE_BUILD_TYPE=Releasecmake --build build -jЗапустити:
devkit$./build/sima_neat_appsdk$dk build/sima_neat_appВи повинні бачити один рядок для кожного виявленого об’єкта, а потім:
[OK] Graph app completed
Що зібрав Neat?
Інтерфейси прикладного програмування (API) безпосередньо відображаються на цю структуру:
Graphмістить схему взаємодії застосунку;graph.add(...)додає кожен крок у відповідному порядку.- Вказані вхідні та вихідні дані стають кінцевими точками середовища виконання:
run.push("image", ...)іrun.pull_tensors("detections"). Model— це той самий фрагмент, який ви б викликали безпосередньо за допомогоюModel.run; тут він виконується як один вузол усередині програми.
Наступні кроки
Для більш глибокої композиції графа продовжуйте використовувати Модель графового програмування..
Звідти перейдіть до ширшого кола навчальних матеріалів SiMa.ai Neat:
- Вивчіть основна модель програмування, яка пояснює основні концепції Neat, такі як моделі, графи та виконання програми.
- Дотр имуйтесь інструкцій із серії навчальні матеріали, де покроково пояснюються конкретні концепції та робочі процеси.
- Перегляньте підбірку застосунків на портал застосунків, а також ознайомтеся з їх вихідним кодом у репозиторій застосунків на GitHub.