從零開始詳細講解OpenVINO推理程序

本文選取的模型:Faster R-CNN ResNet50 V1 640x640

OpenVINO版本:2021.4
Visual Studio版本:2019
模型轉(zhuǎn)換命令關(guān)鍵參數(shù)
:python mo_tf.py --saved_model_dir
--tensorflow_object_detection_api_pipeline_config
--transformations_config faster_rcnn_support_api_v2.0.json

獲得了IR模型,用Netron 查看, 其模型輸入包含兩個部分:

  • image_info, 形狀: 1, 3, 格式: B, C,:
    B - batch size
    C - vector of 3 values in format H, W, S, where H is an image height, W is an image width, S is an image scale factor (usually 1).


    image_info
  • input_tensor 形狀: 1, 3, 600, 1024, 格式: N, C, H, W:
    N - batch size
    C - number of channels
    H - image height
    W - image width


    input_tensor

模型輸出為:形狀: 1, 1, 100, 7;數(shù)據(jù)格式: 1, 1, N, 7, 這里 N 是檢測框數(shù)量. 對于每個檢測格式為: [image_id, label, conf, x_min, y_min, x_max, y_max], 這里:
image_id - 每批次中的image_id
label - 標簽值
conf - 預測類別的信心閾值
(x_min, y_min) - 歸一化的左上角坐標,取值范圍[0, 1])
(x_max, y_max) - 歸一化的右下角坐標,取值范圍 [0, 1])

DetectionOutput

#include <iostream>
#include <inference_engine.hpp>
#include <opencv2/opencv.hpp>
#include <utils/ocv_common.hpp>

using namespace InferenceEngine;
std::string DEVICE = "CPU";
std::string MODEL_FILE = "C:/Users/jzhang6/models/faster_rcnn_resnet50/saved_model.xml";
std::string IMAGE_FILE = "C:/Users/jzhang6/models/faster_rcnn_resnet50/image1.jpg";

int main()
{
    // ----- Step 1. 初始化Core對象 --------
    // -------------------------------------
    std::cout << "Step 1. Initialize inference engine Core." << std::endl;
    Core core;
    // 輸出IE版本信息
    auto v = core.GetVersions(DEVICE)[DEVICE];
    std::cout << "Build Number: " << v.buildNumber << std::endl;
    std::cout << "Description: " << v.description << "; IE_Version:" << IE_VERSION_MAJOR << "." << IE_VERSION_MINOR << "." << IE_VERSION_PATCH << std::endl;

    // ----- Step 2. 讀取IR模型 或 ONNX模型 ------
    // -------------------------------------------
    std::cout << "Step 2. Read a IR or ONNX model." << std::endl;
    CNNNetwork network = core.ReadNetwork(MODEL_FILE);

    // ----- Step 3. 配置模型輸入&輸出 ----------------
    // ------------------------------------------------
    // 參考資料:https://docs.openvinotoolkit.org/latest/openvino_docs_IE_DG_Integrate_with_customer_application_new_API.html
    std::cout << "Step 3. Configure input & output." << std::endl;
    // 獲得網(wǎng)絡(luò)輸入信息(鍵值對) 
    InferenceEngine::InputsDataMap inputs_info = network.getInputsInfo();
    // 獲得網(wǎng)絡(luò)輸出信息(鍵值對)
    InferenceEngine::OutputsDataMap output_info = network.getOutputsInfo();
    
    
    std::string image_info_name = "";      //存儲image_info的名字
    std::string input_tensor_name = "";    //存儲input_tensor的名字
    auto item = inputs_info.begin();
    image_info_name = item->first;         //獲取image_info輸入的名字
    auto image_info_ptr = item->second;    //獲取image_info輸入的指針
    item++;
    input_tensor_name = item->first;       //獲取input_tensor輸入的名字
    auto input_tensor_ptr = item->second;  //獲取input_tensor輸入的指針
    std::cout << "image_info_name:" << image_info_name << "; input_tensor_name:" << input_tensor_name << std::endl;

    //配置input_tensor輸入:U8,NCHW, 保持默認的禁止自動放縮輸入圖像和禁止自動轉(zhuǎn)換顏色通道
    input_tensor_ptr->setPrecision(InferenceEngine::Precision::U8); // U8最通用,參考資料:https://docs.openvinotoolkit.org/latest/openvino_docs_IE_DG_supported_plugins_Supported_Devices.html
    input_tensor_ptr->setLayout(InferenceEngine::Layout::NCHW);
    //輸出精度不用配置,保持默認的Precision::FP32

    // ----- Step 4. 載入模型到執(zhí)行硬件 ----------
    // -------------------------------------------
    std::cout << "Step 4.Loading model to the device." << std::endl;
    ExecutableNetwork executable_network = core.LoadNetwork(network, DEVICE);

    // ----- Step 5. 創(chuàng)建推理請求 ----------------
    // -------------------------------------------
    std::cout << "Step 5.Create infer request." << std::endl;
    InferRequest infer_request = executable_network.CreateInferRequest();

    // ----- Step 6. 準備輸入數(shù)據(jù) ----------------
    // -------------------------------------------
    std::cout << "Step 6.Prepare input data." << std::endl;
    /* 讀取圖片 */
    cv::Mat image = cv::imread(IMAGE_FILE);
    
    /* 記錄圖片原始H,W */
    auto original_height = image.rows;
    auto original_width = image.cols;
    /* 獲得模型的input_tensor輸入的數(shù)據(jù)緩沖 */
    Blob::Ptr input_tensor_blob = infer_request.GetBlob(input_tensor_name);
    /* 將OpenCV Mat 數(shù)據(jù)填入模型的input_tensor輸入的數(shù)據(jù)緩沖 */
    matU8ToBlob<uint8_t>(image, input_tensor_blob);

    /* 獲得模型的image_info輸入的數(shù)據(jù)緩沖 */
    Blob::Ptr image_info_blob = infer_request.GetBlob(image_info_name);
    /** 向模型的image_info輸入的數(shù)據(jù)緩沖填入數(shù)據(jù): height, width, scale=1.0 **/
    LockedMemory<void> blobMapped = as<MemoryBlob>(image_info_blob)->wmap();
    auto data = blobMapped.as<float*>();
    data[0] = static_cast<float>(input_tensor_ptr->getTensorDesc().getDims()[2]);  //填入height
    data[1] = static_cast<float>(input_tensor_ptr->getTensorDesc().getDims()[3]);  //填入width
    data[2] = 1.0f; //填入Scale = 1.0

    // ----- step 7. 執(zhí)行推理計算 ----------------
    // -------------------------------------------
    std::cout << "step 7.do inference..." << std::endl;
    infer_request.Infer();

    // ----- Step 8. 處理推理計算結(jié)果 ------------
    // -------------------------------------------
    std::cout << "Step 8.Process the results of inference..." << std::endl;
    auto output_item = output_info.begin();
    std::string output_name = output_item->first;              //獲取模型輸出的名字
    std::cout << "output_name:" << output_name << std::endl;
    auto output_blob = infer_request.GetBlob(output_name);     //獲取模型輸出的緩沖區(qū)
    const float* detections = output_blob->buffer().as<PrecisionTrait<Precision::FP32>::value_type*>();
    size_t max_proposal_count = output_blob->getTensorDesc().getDims()[2];
    size_t proposal_size = output_blob->getTensorDesc().getDims()[3];
    std::cout << "max_proposal_count:" << max_proposal_count << "; proposal_size:" << proposal_size << std::endl;

    /* 每個檢測結(jié)果的格式為: [image_id, label, conf, x_min, y_min, x_max, y_max] */
    for (size_t i = 0; i < max_proposal_count; i++) {
        int label = static_cast<int>(detections[i * proposal_size + 1]);
        float conf = detections[i * proposal_size + 2];
        float x_min = detections[i * proposal_size + 3] * original_width; //將比例值還原為圖片像素坐標
        float y_min = detections[i * proposal_size + 4] * original_height;
        float x_max = detections[i * proposal_size + 5] * original_width;
        float y_max = detections[i * proposal_size + 6] * original_height;

        if (conf > 0.85) {          
            std::ostringstream confidence;
            confidence << "conf:" << std::fixed << std::setprecision(3) << conf;
            cv::putText(image, confidence.str(), cv::Point2f(x_min, y_min - 5), cv::FONT_HERSHEY_COMPLEX_SMALL, 1, cv::Scalar(0, 0, 255));
            cv::rectangle(image, cv::Point2f(x_min, y_min), cv::Point2f(x_max, y_max), cv::Scalar(0, 0, 255));
        }
    }
    std:: cout<< "Infer done!" << std::endl;
    cv::imshow("Detection results", image);
    cv::waitKey();
    cv::destroyAllWindows();

    return 0;

}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容