Hello NV12 入力分類サンプル#

このサンプルでは、同期推論要求 API を使用して、NV12 カラー形式の画像の画像分類モデルの推論を実行する方法を示します。サンプルを使用する前に、次の要件を参照してください:

  • このサンプルは、ov::Core::read_model でサポートされるすべてのファイル形式を受け入れます。

  • サンプルをビルドするには、 “サンプルの導入” ガイドのサンプル・アプリケーションのビルドセクションにある手順を参照してください。

どのように動作するか#

起動時に、サンプル・アプリケーションはコマンドライン・パラメーターを受け取り、指定されたモデルと NV12 カラー形式の画像を OpenVINO™ ランタイムプラグインに読み込みます。次に、サンプルは同期推論リクエスト・オブジェクトを作成します。推論が完了すると、アプリケーションはデータを標準出力ストリームに出力します。ラベルをモデルの .labels ファイルに配置すると、きれいな出力が得られます。

// Copyright (C) 2018-2024 Intel Corporation 
// SPDX-License-Identifier: Apache-2.0 
// 

#include <sys/stat.h> 

#include <cassert> 
#include <fstream> 
#include <iostream> 
#include <memory> 
#include <sstream> 
#include <string> 
#include <utility> 
#include <vector> 
#ifdef _WIN32 
# include "samples/os/windows/w_dirent.h" 
#else 
# include <dirent.h> 
#endif 

// clang-format off 
#include "openvino/openvino.hpp" 

#include "samples/args_helper.hpp" 
#include "samples/common.hpp" 
#include "samples/slog.hpp" 
#include "samples/classification_results.h" 
#include "format_reader_ptr.h" 
// clang-format on 

constexpr auto N_TOP_RESULTS = 10; 

using namespace ov::preprocess; 

/**
 * @brief Parse image size provided as string in format WIDTHxHEIGHT
 * @param string of image size in WIDTHxHEIGHT format
 * @return parsed width and height
 */ 
std::pair<size_t, size_t> parse_image_size(const std::string& size_string) { 
    auto delimiter_pos = size_string.find("x"); 
    if (delimiter_pos == std::string::npos || delimiter_pos >= size_string.size() - 1 || delimiter_pos == 0) { 
        std::stringstream err; 
        err << "Incorrect format of image size parameter, expected WIDTHxHEIGHT, " "actual: " << size_string; 
        throw std::runtime_error(err.str()); 
    } 

    size_t width = static_cast<size_t>(std::stoull(size_string.substr(0, delimiter_pos))); 
    size_t height = static_cast<size_t>(std::stoull(size_string.substr(delimiter_pos + 1, size_string.size()))); 

    if (width == 0 || height == 0) { 
        throw std::runtime_error(
                                    "Incorrect format of image size parameter, width 「 
                                    "and height must not be equal to 0"); 
    } 

    if (width % 2 != 0 || height % 2 != 0) { 
        throw std::runtime_error("Unsupported image size, width and height must be even numbers"); 
    } 

    return {width, height}; 
} 

/**
 * @brief The entry point of the OpenVINO Runtime sample application
 */ 
int main(int argc, char* argv[]) { 
    try { 
        // -------- OpenVINO ランタイムのバージョンを取得 -------- 
        slog::info << ov::get_openvino_version() << slog::endl; 

        // -------- 入力引数の解析と検証 -------- 

        if (argc != 5) { 
            std::cout << "Usage : " << argv[0] << " <path_to_model> <path_to_image> <image_size> <device_name>" << std::endl; 
            return EXIT_FAILURE; 
        } 

        const std::string model_path{argv[1]}; 
        const std::string image_path{argv[2]}; 
        size_t input_width = 0; 
        size_t input_height = 0; 
        std::tie(input_width, input_height) = parse_image_size(argv[3]); 
        const std::string device_name{argv[4]}; 
        // ----------------------------------------------------------------------------------------------------- 
        // -------- Read image names -------- 
        FormatReader::ReaderPtr reader(image_path.c_str()); 
        if (reader.get() == nullptr) { 
            std::string msg = "Image " + image_path + " cannot be read!"; 
            throw std::logic_error(msg); 
        } 

        size_t batch = 1; 

        // ----------------------------------------------------------------------------------------------------- 
        // -------- ステップ 1. OpenVINO ランタイムコアの初期化 --------- 
    ov::Core core; 

    // -------- ステップ 2. モデルの読み取り -------- 
        slog::info << "Loading model files: " << model_path << 
    slog::endl; 
    std::shared_ptr<ov::Model> model = core.read_model(model_path); 
    printInputAndOutputsInfo(*model); 

    OPENVINO_ASSERT(model->inputs().size() == 1, "Sample supports models with 1 input only"); 
    OPENVINO_ASSERT(model->outputs().size() == 1, "Sample supports models with 1 output only"); 

    std::string input_tensor_name = model->input().get_any_name(); 
    std::string output_tensor_name = model->output().get_any_name(); 

    // -------- ステップ 3. 前処理の構成 -------- 
    PrePostProcessor ppp = PrePostProcessor(model); 

    // 1) 'input_tensor_name' テンソル名を持つ入力を選択し 
    InputInfo& input_info = ppp.input(input_tensor_name); 
    // 2) 入力タイプを設定 
    // - 精度 'u8'  
    // - カラー形式 NV12 (シングル平面) 
    // - サイズ変更前の処理操作で使用する静的空間次元 
    input_info.tensor() 
        .set_element_type(ov::element::u8) 
        .set_color_format(ColorFormat::NV12_SINGLE_PLANE) 
        .set_spatial_static_shape(input_height, input_width); 
    // 3) 前処理ステップ: 
    // a) 'float' に変換これは色変換をより正確にします 
    // b) BGR へ変換: モデルが BGR 形式の画像を受け入れることを前提としています。RGB の場合は手動で変更してください。 
    // c) 画像のサイズをテンソルの次元からモデルの次元に変更 
    input_info.preprocess() 
        .convert_element_type(ov::element::f32) 
        .convert_color(ColorFormat::BGR) 
        .resize(ResizeAlgorithm::RESIZE_LINEAR); 
    // 4) モデルのデータレイアウトを設定 (モデルが NCHW レイアウトの画像を受け入れると仮定) 
    input_info.model().set_layout("NCHW"); 

    // 5) ロードされたモデルの 'input_tensor_name' 名の入力に前処理を適用 
    model = ppp.build(); 

    // -------- ステップ 4. モデルをデバイスにロード -------- 
    ov::CompiledModel compiled_model = core.compile_model(model, device_name); 

    // -------- ステップ 5. 推論要求を作成 -------- 
    ov::InferRequest infer_request = compiled_model.create_infer_request(); 

    // -------- ステップ 6. 入力データの準備 -------- 
    std::shared_ptr<unsigned char> image_data = reader->getData(input_width, input_height); 

    ov::Tensor input_tensor{ov::element::u8, {batch, input_height * 3 / 2, input_width, 1}, image_data.get()}; 

    // ファイルからラベルを読み取る (例. AlexNet.labels) 
    std::string labelFileName = fileNameNoExt(model_path) + ".labels"; 
    std::vector<std::string> labels; 

    std::ifstream inputFile; 
    inputFile.open(labelFileName, std::ios::in); 
    if (inputFile.is_open()) { 
        std::string strLine; 
        while (std::getline(inputFile, strLine)) { 
            trim(strLine); 
            labels.push_back(strLine); 
        } 
    } 

        // -------- ステップ 7. 入力テンソルの設定 -------- 
        // テンソル名による入力テンソルを InferRequest に設定 
        infer_request.set_tensor(input_tensor_name, input_tensor); 

        // -------- ステップ 8. 推論を実行 -------- 
        // リクエストを同期的に実行 
        infer_request.infer(); 

        // -------- ステップ 9. 出力処理 -------- 
        ov::Tensor output = infer_request.get_tensor(output_tensor_name); 

        // 分類結果を出力 
        ClassificationResult classification_result(output, {image_path}, batch, N_TOP_RESULTS, labels); 
        classification_result.show(); 
        } catch (const std::exception& ex) { 
        std::cerr << ex.what() << std::endl; 

        return EXIT_FAILURE; 
    } 

    return EXIT_SUCCESS; 
}
// Copyright (C) 2018-2024 Intel Corporation 
// SPDX-License-Identifier: Apache-2.0 
// 

#include <stdbool.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#include "openvino/c/openvino.h" 

/**
 * @brief Struct to store infer results
 */ 
struct infer_result { 
    size_t class_id; 
    float probability; 
}; 

/**
 * @brief Sort result by probability
 * @param struct with infer results to sort
 * @param result_size of the struct
 * @return none
 */ 
int compare(const void* a, const void* b) { 
    const struct infer_result* sa = (const struct infer_result*)a; 
    const struct infer_result* sb = (const struct infer_result*)b; 
    if (sa->probability < sb->probability) { 
        return 1; 
    } else if ((sa->probability == sb->probability) && (sa->class_id > sb->class_id)) { 
        return 1; 
    } else if (sa->probability > sb->probability) { 
        return -1; 
    } 
    return 0; 
} 

void infer_result_sort(struct infer_result* results, size_t result_size) { 
    qsort(results, result_size, sizeof(struct infer_result), compare); 
} 

/**
 * @brief Convert output tensor to infer result struct for processing results * @param tensor of output tensor
 * @param result_size of the infer result
 * @return struct infer_result
 */ 
struct infer_result* tensor_to_infer_result(ov_tensor_t* tensor, size_t* result_size) { 
    ov_status_e status = ov_tensor_get_size(tensor, result_size); 
    if (status != OK) 
        return NULL; 

    struct infer_result* results = (struct infer_result*)malloc(sizeof(struct infer_result) * (*result_size)); 
    if (!results) 
        return NULL; 

    void* data = NULL; 
    status = ov_tensor_data(tensor, &data); 
    if (status != OK) { 
        free(results); 
        return NULL; 
    } 

    float* float_data = (float*)(data); 
    for (size_t i = 0; i < *result_size; ++i) { 
        results[i].class_id = i; 
        results[i].probability = float_data[i]; 
    } 
    return results; 
} 

/**
 * @brief Print results of infer
 * @param results of the infer results
 * @param result_size of the struct of classification results
 * @param img_path image path
 * @return none
 */ 
void print_infer_result(struct infer_result* results, size_t result_size, const char* img_path) { 
    printf("\nImage %s\n", img_path); 
    printf("\nclassid probability\n"); 
    printf("------- -----------\n"); 
    for (size_t i = 0; i < result_size; ++i) { 
        printf("%zu %f\n", results[i].class_id, results[i].probability); 
    } 
} 

void print_model_input_output_info(ov_model_t* model) { 
    char* friendly_name = NULL; 
    ov_model_get_friendly_name(model, &friendly_name); 
    printf("[INFO] model name: %s \n", friendly_name); 
    ov_free(friendly_name); 
} 

/**
 * @brief Check image has supported width and height
 * @param string image size in WIDTHxHEIGHT format
 * @param pointer to image width
 * @param pointer to image height
 * @return bool status True(success) or False(fail)
 */ 

bool is_supported_image_size(const char* size_str, size_t* width, size_t* height) { 
    const char* _size = size_str; 
    size_t _width = 0, _height = 0; 
    while (_size && *_size != 'x' && *_size != '\0') { 
        if ((*_size <= '9') && (*_size >= '0')) { 
            _width = (_width * 10) + (*_size - '0'); 
            _size++; 
        } else { 
            goto err; 
        } 
    } 

    if (_size) 
        _size++; 

    while (_size && *_size != '\0') { 
        if ((*_size <= '9') && (*_size >= '0')) { 
            _height = (_height * 10) + (*_size - '0'); 
            _size++; 
        } else { 
            goto err; 
        } 
    } 

    if (_width > 0 && _height > 0) { 
        if (_width % 2 == 0 && _height % 2 == 0) { 
            *width = _width; 
            *height = _height; 
            return true; 
        } else { 
            printf("Unsupported image size, width and height must be even numbers \n"); 
            return false; 
        } 
    } else { 
        goto err; 
    } 
err: 
    printf("Incorrect format of image size parameter, expected WIDTHxHEIGHT, " "actual: %s\n", size_str); 
    return false; 
} 

size_t read_image_from_file(const char* img_path, unsigned char* img_data, size_t size) { 
    FILE* fp = fopen(img_path, "rb"); 
    size_t read_size = 0; 

    if (fp) { 
        fseek(fp, 0, SEEK_END); 
        if ((size_t)ftell(fp) >= size) { 
            fseek(fp, 0, SEEK_SET); 
            read_size = fread(img_data, 1, size, fp); 
        } 
        fclose(fp); 
    } 

    return read_size; 
} 

#define CHECK_STATUS(return_status) \ 
    if (return_status != OK) { \ 
        fprintf(stderr, "[ERROR] return status %d, line %d\n", return_status, __LINE__); \ 
        goto err; \ 
    } 

int main(int argc, char** argv) { 
    // -------- 入力パラメーターを確認 -------- 
    if (argc != 5) { 
        printf("Usage : ./hello_nv12_input_classification_c <path_to_model> <path_to_image> " "<WIDTHxHEIGHT> <device_name>\n"); 
        return EXIT_FAILURE; 
    } 

    size_t input_width = 0, input_height = 0, img_size = 0; 
    if (!is_supported_image_size(argv[3], &input_width, &input_height)) { 
        fprintf(stderr, "ERROR is_supported_image_size, line %d\n", __LINE__); 
        return EXIT_FAILURE; 
    } 
    unsigned char* img_data = NULL; 
    ov_core_t* core = NULL; 
    ov_model_t* model = NULL; 
    ov_tensor_t* tensor = NULL; 
    ov_preprocess_prepostprocessor_t* preprocess = NULL; 
    ov_preprocess_input_info_t* input_info = NULL; 
    ov_model_t* new_model = NULL; 
    ov_preprocess_input_tensor_info_t* input_tensor_info = NULL; 
    ov_preprocess_preprocess_steps_t* input_process = NULL; 
    ov_preprocess_input_model_info_t* p_input_model = NULL; 
    ov_compiled_model_t* compiled_model = NULL; 
    ov_infer_request_t* infer_request = NULL; 
    ov_tensor_t* output_tensor = NULL; 
    struct infer_result* results = NULL; 
    char* input_tensor_name = NULL; 
    char* output_tensor_name = NULL; 
    ov_output_const_port_t* input_port = NULL; 
    ov_output_const_port_t* output_port = NULL; 
    ov_layout_t* model_layout = NULL; 
    ov_shape_t input_shape; 

    // -------- OpenVINO ランタイムのバージョンを取得 -------- 
    ov_version_t version = {.description = NULL, .buildNumber = NULL}; 
    CHECK_STATUS(ov_get_openvino_version(&version)); 
    printf("---- OpenVINO INFO----\n"); 
    printf("description : %s \n", version.description); 
    printf("build number: %s \n", version.buildNumber); 
    ov_version_free(&version); 

    // -------- 入力引数の解析と検証 -------- 
    const char* input_model = argv[1]; 
    const char* input_image_path = argv[2]; 
    const char* device_name = argv[4]; 

    // -------- ステップ 1. OpenVINO ランタイムコアを初期化 -------- 
    CHECK_STATUS(ov_core_create(&core)); 

    // -------- ステップ 2. モデルを読み取り -------- 
    printf("[INFO] Loading model files: %s\n", input_model); 
    CHECK_STATUS(ov_core_read_model(core, input_model, NULL, &model)); 
    print_model_input_output_info(model); 
    
    CHECK_STATUS(ov_model_const_output(model, &output_port)); 

    CHECK_STATUS(ov_model_const_input(model, &input_port)); 

    CHECK_STATUS(ov_port_get_any_name(input_port, &input_tensor_name)); 
    CHECK_STATUS(ov_port_get_any_name(output_port, &output_tensor_name)); 

    // -------- ステップ 3. 前処理の構成 -------- 
    CHECK_STATUS(ov_preprocess_prepostprocessor_create(model, &preprocess)); 

    // 1) 'input_tensor_name' テンソル名を持つ入力を選択 
    CHECK_STATUS(ov_preprocess_prepostprocessor_get_input_info_by_name(preprocess, input_tensor_name, &input_info)); 

    // 2) 入力タイプの設定 
    // - 精度 'u8'  
    // - カラー形式 NV12 (シングル平面
    ) 
    // - サイズ変更前の処理操作で使用する静的空間次元 
    CHECK_STATUS(ov_preprocess_input_info_get_tensor_info(input_info, &input_tensor_info)); 

    CHECK_STATUS(ov_preprocess_input_tensor_info_set_element_type(input_tensor_info, U8)); 
    CHECK_STATUS(ov_preprocess_input_tensor_info_set_color_format(input_tensor_info, NV12_SINGLE_PLANE)); 
    CHECK_STATUS( ov_preprocess_input_tensor_info_set_spatial_static_shape(input_tensor_info, input_height, input_width)); 

    // 3) 前処理のステップ: 
    // a)  'float' に変換これは色変換をより正確にします 
    // b) BGR へ変換: モデルが BGR 形式の画像を受け入れることを前提としています。RGB の場合は手動で変更 
    // c) 画像のサイズをテンソルの次元からモデルの次元に変更 
    CHECK_STATUS(ov_preprocess_input_info_get_preprocess_steps(input_info, &input_process)); 

    CHECK_STATUS(ov_preprocess_preprocess_steps_convert_element_type(input_process, F32)); 
    CHECK_STATUS(ov_preprocess_preprocess_steps_convert_color(input_process, BGR)); 
    CHECK_STATUS(ov_preprocess_preprocess_steps_resize(input_process, RESIZE_LINEAR)); 

    // 4) モデルのデータレイアウトの設定 (モデルが NCHW レイアウトの画像を受け入れると仮定) 
    CHECK_STATUS(ov_preprocess_input_info_get_model_info(input_info, &p_input_model)); 

    const char* model_layout_desc = "NCHW"; 
    CHECK_STATUS(ov_layout_create(model_layout_desc, &model_layout)); 
    CHECK_STATUS(ov_preprocess_input_model_info_set_layout(p_input_model, model_layout)); 

    // 5) ロードされたモデルの 'input_tensor_name' 名の入力に前処理を適用 
    CHECK_STATUS(ov_preprocess_prepostprocessor_build(preprocess, &new_model)); 

    // -------- ステップ 4. モデルをデバイスにロード -------- 
CHECK_STATUS(ov_core_compile_model(core, new_model, device_name, 0, &compiled_model)); 

    // -------- ステップ 5. 推論要求を作成 -------- 
    CHECK_STATUS(ov_compiled_model_create_infer_request(compiled_model, &infer_request)); 

    // -------- ステップ 6. 入力データの準備 -------- 
    img_size = input_width * (input_height * 3 / 2); 
    if (!img_size) { 
        fprintf(stderr, "[ERROR] Invalid Image size, line %d\n", __LINE__); 
        goto err; 
    } 
    img_data = (unsigned char*)calloc(img_size, sizeof(unsigned char)); 
    if (!img_data) { 
        fprintf(stderr, "[ERROR] calloc returned NULL, line %d\n", __LINE__); 
        goto err; 
    } 
    if (img_size != read_image_from_file(input_image_path, img_data, img_size)) { 
        fprintf(stderr, "[ERROR] Image dimensions not match with NV12 file size, line %d\n", __LINE__); 
        goto err; 
    } 
    ov_element_type_e input_type = U8; 
    size_t batch = 1; 
    int64_t dims[4] = {batch, input_height * 3 / 2, input_width, 1}; 
    ov_shape_create(4, dims, &input_shape); 
    CHECK_STATUS(ov_tensor_create_from_host_ptr(input_type, input_shape, img_data, &tensor)); 

    // -------- ステップ 6. 入力テンソルの設定 -------- 
    // テンソル名による入力テンソルを InferRequest に設定 
    CHECK_STATUS(ov_infer_request_set_tensor(infer_request, input_tensor_name, tensor)); 

    // -------- ステップ 7. 推論を実行 -------- 
    // リクエストを同期的に実行 
    CHECK_STATUS(ov_infer_request_infer(infer_request)); 

    // -------- ステップ 8. 出力を処理 -------- 

CHECK_STATUS(ov_infer_request_get_output_tensor_by_index(infer_request, 0, &output_tensor)); 
    // 分類結果をプリント 
    size_t results_num = 0; 
    results = tensor_to_infer_result(output_tensor, &results_num); 
    if (!results) { 
        goto err; 
    } 
    infer_result_sort(results, results_num); 
    size_t top = 10; 
    if (top > results_num) { 
        top = results_num; 
    } 
    printf("\nTop %zu results:\n", top); 
    print_infer_result(results, top, input_image_path); 

    // -------- 割り当てられたリソースを解放 -------- 
err: 
    free(results); 
    free(img_data); 
    ov_shape_free(&input_shape); 
    ov_free(input_tensor_name); 
    ov_free(output_tensor_name); 
    ov_output_const_port_free(output_port); 
    ov_output_const_port_free(input_port); 
    if (output_tensor) 
        ov_tensor_free(output_tensor); 
    if (infer_request) 
        ov_infer_request_free(infer_request); 
    if (compiled_model) 
        ov_compiled_model_free(compiled_model); 
    if (p_input_model) 
        ov_preprocess_input_model_info_free(p_input_model); 
    if (input_process) 
        ov_preprocess_preprocess_steps_free(input_process); 
    if (model_layout) 
        ov_layout_free(model_layout); 
    if (input_tensor_info) 
        ov_preprocess_input_tensor_info_free(input_tensor_info); 
    if (input_info) 
        ov_preprocess_input_info_free(input_info); 
    if (preprocess) 
        ov_preprocess_prepostprocessor_free(preprocess); 
    if (new_model) 
        ov_model_free(new_model); 
    if (tensor) 
        ov_tensor_free(tensor); 
    if (model) 
        ov_model_free(model); 
    if (core) 
        ov_core_free(core); 
    return EXIT_SUCCESS; 
}

各サンプルの明示的な説明は、“OpenVINO™ ランタイムとアプリケーションの統合” ガイドの統合ステップセクションで確認できます。

実行する#

hello_nv12_input_classification <path_to_model> <path_to_image> <image_size> <device_name>
hello_nv12_input_classification_c <path_to_model> <path_to_image> <device_name>

サンプルを実行するには、モデルとイメージを指定する必要があります:

  • TensorFlow Zoo、HuggingFace、TensorFlow Hub などのモデル・リポジトリーから推論タスクに固有のモデルを取得できます。

  • ストレージで利用可能なメディア・ファイル・コレクションの画像を使用できます。

このサンプルは、NV12 カラー形式の非圧縮画像を受け入れます。サンプルを実行するには、BGR/RGB 画像を NV12 に変換する必要があります。これを行うには、FFmpeg や GStreamer などのツールを使用できます。次の FFmpeg コマンドを使用すると、通常の画像を非圧縮 NV12 画像に変換できます:

ffmpeg -i cat.jpg -pix_fmt nv12 cat.yuv

  • サンプルでは生の画像ファイルを読み取るため、画像パスとともに正しい画像サイズを指定する必要があります。このサンプルでは、バッファーサイズではなく、画像の論理サイズを想定しています。例えば、640x480 BGR/RGB 画像の場合、対応する NV12 論理画像サイズも 640x480 ですが、バッファーサイズは 640x720 です。

  • デフォルトでは、このサンプルはモデル入力に BGR チャンネル順序があることを想定しています。RGB 順序で動作するようにモデルをトレーニングした場合は、reverse_input_channels 引数を指定したモデル・トランスフォーメーション API を使用してモデルを再変換する必要があります。引数の詳細については、前処理計算の埋め込み入力チャンネルを反転するときセクションを参照してください。

  • トレーニングされたモデルでサンプルを実行する前に、モデル・トランスフォーメーション API を使用してモデルが中間表現 (IR) 形式 (*.xml + *.bin) に変換されていることを確認してください。

  • このサンプルは、前処理を必要としない ONNX 形式 (.onnx) のモデルを受け入れます。

#

  1. 事前トレーニングされたモデルをダウンロードします。

  2. 以下を使用して変換できます:

    ovc ./models/alexnet
  3. CPU 上のモデルを使用して、NV12 画像の推論を実行します。例:

    hello_nv12_input_classification ./models/alexnet.xml ./images/cat.yuv 300x300 CPU
    hello_nv12_input_classification_c ./models/alexnet.xml ./images/cat.yuv 300x300 CPU

サンプルの出力#

アプリケーションは上位 10 の推論結果を出力します。

[ INFO ] OpenVINO Runtime version .........<version> 
[ INFO ] Build ...........<build> 
[ INFO ] 
[ INFO ] Loading model files: \models\alexnet.xml 
[ INFO ] model name: AlexNet 
[ INFO ]     inputs 
[ INFO ]         input name: data 
[ INFO ]         input type: f32 
[ INFO ]         input shape: {1, 3, 227, 227} 
[ INFO ]     outputs 
[ INFO ]         output name: prob 
[ INFO ]         output type: f32 
[ INFO ]         output shape: {1, 1000} 

Top 10 results: 

Image \images\car.yuv

classid probability 
------- ----------- 
656 0.6668988 
654 0.1125269 
581 0.0679280 
874 0.0340229 
436 0.0257744 
817 0.0169367 
675 0.0110199 
511 0.0106134 
569 0.0083373 
717 0.0061734

アプリケーションは上位 10 の推論結果を出力します。


Top 10 results: 

Image ./cat.yuv

classid probability 
------- ----------- 
435 0.091733 
876 0.081725 
999 0.069305 
587 0.043726 
666 0.038957 
419 0.032892 
285 0.030309 
700 0.029941 
696 0.021628 
855 0.020339 

This sample is an API example, for any performance measurements please use the dedicated benchmark_app tool

関連情報#