콘텐츠로 이동

객체 감지

개요

이 튜토리얼에서는 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에서 확인할 수 있습니다.

환경 설정 및 설치 확인

시작하기 전에 시스템 환경이 올바르게 구성되어 있으며, 필요한 모든 필수 패키지가 설치되어 있는지 확인하십시오. 다음 항목이 포함됩니다:

Note

rebel-compiler를 사용하려면 RBLN Portal 계정이 필요합니다.

RBLN Python API를 사용한 컴파일

모델 준비

ultralytics 라이브러리에서 YOLOv8m 모델을 임포트하고 포워드 패스를 실행하여 모델을 초기화합니다.

1
2
3
4
5
6
7
8
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()로 컴파일된 모델을 저장합니다.

1
2
3
4
5
# 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를 사용하여 입력 이미지를 전처리합니다. 아래 코드에서는 이미지를 읽고 전처리하는 과정을 보여줍니다.

1
2
3
4
5
6
7
8
9
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);  

// Input Buffer Memory Mapping for Async execution
std::vector<void*> inputs = {blob.data};

// Output Buffer Memory Mapping for Async execution
auto n_out = rbln_get_num_outputs(rt);
std::vector<cv::Mat> outputs(n_out);
std::vector<char *> output_ptrs(n_out);
for (auto idx = 0; idx < n_out; idx++) {
    const RBLNTensorLayout *layout = rbln_get_output_layout(rt, idx);
    outputs[idx] = cv::Mat{layout->ndim, layout->shape, CV_32F};
    output_ptrs[idx] = reinterpret_cast<char *>(outputs[idx].data);
}

// Run async inference  
int rid = rbln_async_run(rt, inputs.data(), output_ptrs.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++ 예제에 포함되어 있습니다.
아래 명령으로 컴파일하고 실행 파일을 생성하세요:

1
2
3
4
$ mkdir ${SAMPLE_PATH}/build  
$ cd ${SAMPLE_PATH}/build  
$ cmake ..  
$ make  

실행 파일 사용 방법

모든 단계가 완료된 후, 빌드 디렉토리에서 실행 파일을 확인할 수 있습니다.

1
2
3
4
5
# 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  

예시 출력: Image

참고