從零開始詳細(xì)講解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 - 標(biāo)簽值
conf - 預(yù)測類別的信心閾值
(x_min, y_min) - 歸一化的左上角坐標(biāo),取值范圍[0, 1])
(x_max, y_max) - 歸一化的右下角坐標(biāo)品姓,取值范圍 [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, 保持默認(rèn)的禁止自動放縮輸入圖像和禁止自動轉(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);
    //輸出精度不用配置缕允,保持默認(rèn)的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. 準(zhǔn)備輸入數(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; //將比例值還原為圖片像素坐標(biāo)
        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)系作者
  • 序言:七十年代末润讥,一起剝皮案震驚了整個濱河市魄咕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌撕捍,老刑警劉巖衔憨,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異席舍,居然都是意外死亡,警方通過查閱死者的電腦和手機哮笆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進(jìn)店門来颤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來汰扭,“玉大人,你說我怎么就攤上這事福铅÷苊” “怎么了?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵滑黔,是天一觀的道長笆包。 經(jīng)常有香客問我,道長略荡,這世上最難降的妖魔是什么庵佣? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮汛兜,結(jié)果婚禮上巴粪,老公的妹妹穿的比我還像新娘。我一直安慰自己粥谬,他們只是感情好肛根,可當(dāng)我...
    茶點故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著漏策,像睡著了一般派哲。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上掺喻,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天狮辽,我揣著相機與錄音,去河邊找鬼巢寡。 笑死喉脖,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的抑月。 我是一名探鬼主播树叽,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼谦絮!你這毒婦竟也來了题诵?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤层皱,失蹤者是張志新(化名)和其女友劉穎性锭,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體叫胖,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡草冈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怎棱。...
    茶點故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡哩俭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拳恋,到底是詐尸還是另有隱情凡资,我是刑警寧澤,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布谬运,位于F島的核電站隙赁,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏梆暖。R本人自食惡果不足惜伞访,卻給世界環(huán)境...
    茶點故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望式廷。 院中可真熱鬧,春花似錦芭挽、人聲如沸滑废。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蠕趁。三九已至,卻和暖如春辛馆,著一層夾襖步出監(jiān)牢的瞬間俺陋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工昙篙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留腊状,地道東北人。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓苔可,卻偏偏與公主長得像缴挖,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子焚辅,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,562評論 2 349

推薦閱讀更多精彩內(nèi)容