본문으로 건너뛰기

모델 실행

안녕하세요 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. 샘플 이미지를 다운로드하여 assets 디렉터리에 tutorial_sample_image.png로 저장합니다.

    샘플 이미지를 열거나 다운로드하세요..

  4. 프로젝트 디렉터리로 돌아갑니다:

    cd ..

단계별 설명

안녕하세요 Neat!의 프로그램을 기반으로 구축합니다. 동일한 CMakeLists.txt 파일을 유지합니다(이미 Neat 및 OpenCV와 연결되어 있음). 그런 다음 프로그램 본문을 아래의 네 단계로 대체합니다. 각 단계는 최종 프로그램의 작은 부분입니다. 순서대로 읽은 다음 전체 프로그램을 가져와 붙여넣고 실행합니다. 모든 블록에서 언어 탭을 선택합니다. 선택은 사이트 전체 선택기를 따릅니다.

1. 이미지 {#step-load-image} 로드 및 크기 조정

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이 바이트 레이아웃을 알 수 있도록 한 다음, 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와 연결합니다). 그리고 프로그램 본문을 아래의 전체 파일로 대체합니다. 강조 표시된 세 줄이 핵심입니다. 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 학습 자료를 계속 진행하십시오.

  • Model.run(...)을 직접 호출하는 대신, 동일한 모델을 Graph 애플리케이션(한 번 빌드하고 푸시/풀 방식으로 구동하는 명명된 입력 → 모델 → 출력 파이프라인)으로 구성하기 위해 **앱 실행**을 계속 진행합니다.
  • 모델, 그래프 및 런타임 실행과 같은 주요 Neat 개념을 설명하는 핵심 프로그래밍 모델을 학습합니다.
  • 특정 개념과 워크플로를 단계별로 안내하는 튜토리얼를 따릅니다.
  • 깃허브의 앱 저장소에 있는 소스 코드와 함께 앱 포털에서 선별된 애플리케이션을 탐색합니다.