이미지 분류
Overview
이 튜토리얼에서는 RBLN SDK C/C++ Runtime API
를 사용하여 PyTorch ResNet50 모델로 추론을 실행하는 방법을 소개합니다.
모델은 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 torchvision cmake
pip install --extra-index-url https://pypi.rbln.ai/simple/ rebel-compiler>=0.7.4
|
Note
RBLN SDK는 .whl
패키지로 배포됩니다. RBLN 컴파일러와 런타임을 사용하려면 RBLN Portal 계정이 필요합니다.
RBLN Python API
를 사용한 컴파일
모델 준비
TorchVision에서 ResNet50
모델을 불러옵니다.
| from torchvision import models
import rebel
import torch
model_name = "resnet50"
weights = models.get_model_weights(model_name).DEFAULT
model = getattr(models, model_name)(weights=weights).eval()
|
모델 컴파일
Torch 모델(torch.nn.Module)이 준비되면 rebel.compile_from_torch()
를 사용해 컴파일합니다.
그리고 compiled_model.save()
로 컴파일된 모델을 저장합니다.
| # Compile the model
compiled_model = rebel.compile_from_torch(model, [("x", [1, 3, 224, 224], "float32")])
# Save the compiled model to local storage
compiled_model.save(f"{model_name}.rbln")
|
컴파일 실행
위 컴파일 코드 스니펫은 compile.py에 포함되어 있습니다.
모델을 컴파일하고 *.rbln
파일을 생성하려면 다음 명령을 실행하세요:
| $ python compile.py --model-name=resnet50
|
RBLN SDK C/C++ Runtime API
를 사용한 추론
CMake 빌드 스크립트 준비
이 튜토리얼은 이미지 전/후처리를 위해 OpenCV를, CLI 파라미터 파싱을 위해 argparse를 사용합니다.
아래 CMake 스크립트는 외부 패키지 종속성과 링크 설정을 설명합니다.
| # Define dependencies for external Package
include(FetchContent)
include(cmake/opencv.cmake)
include(cmake/argparse.cmake)
# Define the name of executable
add_executable(image_classification main.cc)
# Update link info for package dependencies: OpenCV
find_package(OpenCV CONFIG REQUIRED)
target_link_libraries(image_classification ${OpenCV_LIBS})
# Update link info for dependencies: RBLN
find_package(rbln CONFIG REQUIRED)
target_link_libraries(image_classification rbln::rbln_runtime)
# Update including dependencies: argparse
target_include_directories(image_classification PRIVATE ${argparse_INCLUDE_DIRS})
|
입력 데이터 준비
OpenCV API를 사용하여 입력 이미지를 전처리합니다.
다음 코드 스니펫은 이미지를 읽고 색상 변환, 종횡비 유지 리사이즈, 중앙 크롭, 픽셀 값 정규화를 수행합니다.
| std::string input_path = "${SAMPLE_PATH}/tabby.jpg";
// Read image
cv::Mat input_image;
try {
input_image = cv::imread(input_path);
} catch (const cv::Exception &err) {
std::cerr << err.what() << std::endl;
std::exit(1);
}
// Convert BGR to RGB
cv::Mat image;
cv::cvtColor(input_image, image, cv::COLOR_BGR2RGB);
// Resize while maintaining aspect ratio
float scale = image.rows < image.cols ? 256. / image.rows : 256. / image.cols;
cv::resize(image, image, cv::Size(), scale, scale, cv::INTER_LINEAR);
// Center crop to 224x224
image = image(cv::Rect((image.cols - 224) / 2, (image.rows - 224) / 2, 224, 224));
// Normalize the image
image.convertTo(image, CV_32F);
cv::Vec3f mean(123.68, 116.28, 103.53);
cv::Vec3f std(58.395, 57.120, 57.385);
for (unsigned i = 0; i < image.rows; i++) {
for (unsigned j = 0; j < image.cols; j++) {
cv::subtract(image.at<cv::Vec3f>(i, j), mean, image.at<cv::Vec3f>(i, j));
cv::divide(image.at<cv::Vec3f>(i, j), std, image.at<cv::Vec3f>(i, j));
}
}
// Convert image to blob
cv::Mat blob = cv::dnn::blobFromImage(image);
|
동기식 추론 실행
아래 코드 스니펫은 동기식 추론 예시를 보여줍니다.
| std::string model_path = "${SAMPLE_PATH}/resnet50.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
float *logits = static_cast<float *>(rbln_get_output(rt, 0));
|
비동기식 추론 실행
아래 코드 스니펫은 비동기식 추론 예시를 보여줍니다.
| std::string model_path = "${SAMPLE_PATH}/resnet50.rbln";
RBLNModel *mod = rbln_create_model(model_path.c_str());
RBLNRuntime *rt = rbln_create_async_runtime(mod, "default", 0, 0);
// Allocate 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 for inference completion
rbln_async_wait(rt, rid, 1000);
|
후처리(Post Processing)
출력 logits
는 ImageNet의 각 카테고리 점수를 나타내는 크기 (1,1000)의 float32 배열입니다.
top-1 인덱스를 구하고 해당 카테고리를 출력합니다.
| // Postprocessing
size_t max_idx = 0;
float max_val = std::numeric_limits<float>::min();
for (size_t i = 0; i < 1000; i++) {
if (logits[i] > max_val) {
max_val = logits[i];
max_idx = i;
}
}
// Print the predicted category
std::cout << "Predicted category: " << IMAGENET_CATEGORIES[max_idx] << std::endl;
|
리소스 해제
런타임과 모델을 해제합니다.
| // Release Runtime
rbln_destroy_runtime(rt);
// Release Model
rbln_destroy_model(mod);
|
CMake 빌드 방법
위 예제의 전체 코드는 RBLN Model Zoo C++ 예제에 포함되어 있습니다.
코드를 컴파일하고 실행 파일을 생성하려면 다음 명령을 실행하세요:
| $ mkdir ${SAMPLE_PATH}/build
$ cd ${SAMPLE_PATH}/build
$ cmake ..
$ make
|
실행 파일 사용 방법
모든 단계를 완료한 후 빌드 디렉토리에서 실행 파일을 확인할 수 있습니다.
| # Synchronous execution
$ ${SAMPLE_PATH}/build/image_classification -i ${SAMPLE_PATH}/tabby.jpg -m ${SAMPLE_PATH}/resnet50.rbln
# Asynchronous execution
$ ${SAMPLE_PATH}/build/image_classification_async -i ${SAMPLE_PATH}/tabby.jpg -m ${SAMPLE_PATH}/resnet50.rbln
|
결과는 다음과 같이 표시됩니다:
| Predicted category: tabby
|
Summary and References
이 튜토리얼에서는 RBLN SDK Python API
를 사용하여 PyTorch ResNet50 모델을 컴파일하고
RBLN SDK C/C++ Runtime API
로 추론을 실행하는 방법을 보여주었습니다.
생성된 실행 파일은 사람이 읽을 수 있는 카테고리 예측 결과를 제공합니다.
References: