객체 감지
Overview
이 튜토리얼에서는 RBLN SDK C/C++ Runtime API를 사용하여 PyTorch YOLOv8 모델로 추론을 실행하는 방법을 배웁니다.
모델은 RBLN SDK Python API를 사용해 컴파일하며, 생성된 *.rbln 파일은 RBLN SDK C/C++ Runtime API로 추론에 사용됩니다.
이 접근 방식은 Python에서 모델 준비의 편의성과 C/C++의 성능 이점을 결합합니다.
튜토리얼에 사용된 전체 코드는 RBLN Model Zoo에서 확인할 수 있습니다.
Setup & Installation
시작하기 전에 시스템 환경이 올바르게 구성되어 있으며, 필요한 모든 필수 패키지가 설치되어 있는지 확인하십시오. 다음 항목이 포함됩니다:
- System Requirements:
- Packages Requirements:
- Installation Command:
| pip install torch ultralytics cmake
pip install --extra-index-url https://pypi.rbln.ai/simple/ rebel-compiler>=0.8.0
|
Note
RBLN SDK는 .whl 패키지로 배포됩니다. RBLN 컴파일러와 런타임을 사용하려면 RBLN Portal 계정이 필요합니다.
RBLN Python API를 사용한 컴파일
모델 준비
ultralytics 라이브러리에서 YOLOv8m 모델을 임포트하고 포워드 패스를 실행하여 모델을 초기화합니다.
| from ultralytics import YOLO
import rebel
import torch
model_name = "yolov8m"
yolo = YOLO(f"{model_name}.pt")
model = yolo.model.eval()
model(torch.zeros(1, 3, 640, 640))
|
모델 컴파일
Torch 모델(torch.nn.Module)이 준비되면 rebel.compile_from_torch()로 컴파일합니다.
compiled_model.save()로 컴파일된 모델을 저장합니다.
| # Compile the model
compiled_model = rebel.compile_from_torch(model, [ ("x", [1, 3, 640, 640], "float32") ])
# Save the compiled model to local storage
compiled_model.save(f"{model_name}.rbln")
|
컴파일 실행
컴파일 코드는 compile.py에 포함되어 있습니다.
다음 명령으로 스크립트를 실행하여 .rbln 파일을 생성하세요:
| $ python compile.py --model-name=yolov8m
|
RBLN SDK C/C++ Runtime API를 사용한 추론
CMake 빌드 스크립트 준비
예제 애플리케이션은 OpenCV로 이미지 전/후처리를 수행하고, argparse로 CLI 파라미터를 파싱합니다.
아래 CMake 스크립트는 외부 패키지 종속성과 링크 설정을 설명합니다.
| # Define dependencies for external Package
include(FetchContent)
include(cmake/opencv.cmake)
include(cmake/argparse.cmake)
# Define the name of executable
add_executable(object_detection main.cc)
# Update link info for package dependencies: OpenCV
find_package(OpenCV CONFIG REQUIRED)
target_link_libraries(object_detection ${OpenCV_LIBS})
# Update link info for dependencies: RBLN
find_package(rbln CONFIG REQUIRED)
target_link_libraries(object_detection rbln::rbln_runtime)
# Update including dependencies: argparse
target_include_directories(object_detection PRIVATE ${argparse_INCLUDE_DIRS})
|
입력 데이터 준비
OpenCV API를 사용하여 입력 이미지를 전처리합니다. 아래 코드에서는 이미지를 읽고 전처리하는 과정을 보여줍니다.
| std::string input_path = "${SAMPLE_PATH}/people4.jpg";
cv::Mat image;
try {
image = cv::imread(input_path);
} catch (const cv::Exception &err) {
std::cerr << err.what() << std::endl;
std::exit(1);
}
cv::Mat blob = cv::dnn::blobFromImage(GetSquareImage(image, 640), 1./255., cv::Size(), cv::Scalar(), true, false, CV_32F);
|
동기식 추론 실행
아래 코드는 동기식 추론 예시를 보여줍니다.
| std::string model_path = "${SAMPLE_PATH}/yolov8m.rbln";
RBLNModel *mod = rbln_create_model(model_path.c_str());
RBLNRuntime *rt = rbln_create_runtime(mod, "default", 0, 0);
// Set input data
rbln_set_input(rt, 0, blob.data);
// Run sync inference
rbln_run(rt);
// Get output results
void *data = rbln_get_output(rt, 0);
|
비동기식 추론 실행
아래 코드는 비동기식 추론 예시를 보여줍니다.
| std::string model_path = "${SAMPLE_PATH}/yolov8m.rbln";
RBLNModel *mod = rbln_create_model(model_path.c_str());
RBLNRuntime *rt = rbln_create_async_runtime(mod, "default", 0, 0);
// Alloc output buffer
auto buf_size = rbln_get_layout_nbytes(rbln_get_output_layout(rt, 0));
std::vector<float> logits(buf_size/sizeof(float));
// Run async inference
int rid = rbln_async_run(rt, blob.data, logits.data());
// Wait inference done
rbln_async_wait(rt, rid, 1000);
|
후처리(Post Processing)
출력 데이터(float32 배열, shape=(1,84,8400))에 대해 NMS를 수행하고 바운딩 박스를 그립니다.
아래 코드는 처리 과정을 개략적으로 보여줍니다:
| // Postprocessing for NMS
const RBLNTensorLayout *layout = rbln_get_output_layout(rt, 0);
cv::Mat logits{layout->ndim, layout->shape, CV_32F};
memcpy(logits.data, data, rbln_get_layout_nbytes(layout));
std::vector<cv::Rect> nms_boxes;
std::vector<float> nms_confidences;
std::vector<size_t> nms_class_ids;
for (size_t i = 0; i < layout->shape[2]; i++) {
auto cx = logits.at<float>(0, 0, i);
auto cy = logits.at<float>(0, 1, i);
auto w = logits.at<float>(0, 2, i);
auto h = logits.at<float>(0, 3, i);
auto x = cx - w / 2;
auto y = cy - h / 2;
cv::Rect rect{static_cast<int>(x), static_cast<int>(y), static_cast<int>(w), static_cast<int>(h)};
float confidence = std::numeric_limits<float>::min();
int cls_id;
for (size_t j = 4; j < layout->shape[1]; j++) {
if (confidence < logits.at<float>(0, j, i)) {
confidence = logits.at<float>(0, j, i);
cls_id = j - 4;
}
}
nms_boxes.push_back(rect);
nms_confidences.push_back(confidence);
nms_class_ids.push_back(cls_id);
}
std::vector<int> nms_indices;
cv::dnn::NMSBoxes(nms_boxes, nms_confidences, 0.25f, 0.45f, nms_indices);
cv::Mat output_img = image.clone();
for (size_t i = 0; i < nms_indices.size(); i++) {
auto idx = nms_indices[i];
auto class_id = nms_class_ids[idx];
auto scaled_box = ScaleBox(nms_boxes[idx], output_img.size(), 640);
cv::rectangle(output_img, scaled_box, cv::Scalar(255, 0, 0));
std::stringstream ss;
ss << COCO_CATEGORIES[class_id] << ": " << nms_confidences[idx];
cv::putText(output_img, ss.str(), scaled_box.tl() - cv::Point(0, 1), cv::FONT_HERSHEY_DUPLEX, 1, cv::Scalar(255, 0, 0));
}
cv::imwrite("result.jpg", output_img);
|
리소스 해제
런타임과 모델을 해제합니다.
| rbln_destroy_runtime(rt);
rbln_destroy_model(mod);
|
CMake 빌드 방법
예제 코드는 RBLN Model Zoo C++ 예제에 포함되어 있습니다.
아래 명령으로 컴파일하고 실행 파일을 생성하세요:
| $ mkdir ${SAMPLE_PATH}/build
$ cd ${SAMPLE_PATH}/build
$ cmake ..
$ make
|
실행 파일 사용 방법
모든 단계가 완료된 후, 빌드 디렉토리에서 실행 파일을 확인할 수 있습니다.
| # Synchronous execution
$ ${SAMPLE_PATH}/build/object_detection -i ${SAMPLE_PATH}/people4.jpg -m ${SAMPLE_PATH}/yolov8m.rbln
# Asynchronous execution
$ ${SAMPLE_PATH}/build/object_detection_async -i ${SAMPLE_PATH}/people4.jpg -m ${SAMPLE_PATH}/yolov8m.rbln
|
결과는 다음과 같이 표시됩니다:

Summary and References
이 튜토리얼에서는 RBLN SDK Python API를 사용하여 PyTorch YOLOv8 모델을 컴파일하고,
RBLN SDK C/C++ Runtime API로 추론을 실행하는 방법을 보여주었습니다.
References: