从零开始详细讲解OpenVINO推理程序

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

OpenVINO版本:2021.4
Visual Studio版本:2019
模型转换命令关键参数
: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;数据格式: 1, 1, N, 7, 这里 N 是检测框数量. 对于每个检测格式为: [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 
#include 
#include 
#include 

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;
    // 获得网络输入信息(键值对) 
    InferenceEngine::InputsDataMap inputs_info = network.getInputsInfo();
    // 获得网络输出信息(键值对)
    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, 保持默认的禁止自动放缩输入图像和禁止自动转换颜色通道
    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. 载入模型到执行硬件 ----------
    // -------------------------------------------
    std::cout << "Step 4.Loading model to the device." << std::endl;
    ExecutableNetwork executable_network = core.LoadNetwork(network, DEVICE);

    // ----- Step 5. 创建推理请求 ----------------
    // -------------------------------------------
    std::cout << "Step 5.Create infer request." << std::endl;
    InferRequest infer_request = executable_network.CreateInferRequest();

    // ----- Step 6. 准备输入数据 ----------------
    // -------------------------------------------
    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输入的数据缓冲 */
    Blob::Ptr input_tensor_blob = infer_request.GetBlob(input_tensor_name);
    /* 将OpenCV Mat 数据填入模型的input_tensor输入的数据缓冲 */
    matU8ToBlob(image, input_tensor_blob);

    /* 获得模型的image_info输入的数据缓冲 */
    Blob::Ptr image_info_blob = infer_request.GetBlob(image_info_name);
    /** 向模型的image_info输入的数据缓冲填入数据: height, width, scale=1.0 **/
    LockedMemory blobMapped = as(image_info_blob)->wmap();
    auto data = blobMapped.as();
    data[0] = static_cast(input_tensor_ptr->getTensorDesc().getDims()[2]);  //填入height
    data[1] = static_cast(input_tensor_ptr->getTensorDesc().getDims()[3]);  //填入width
    data[2] = 1.0f; //填入Scale = 1.0

    // ----- step 7. 执行推理计算 ----------------
    // -------------------------------------------
    std::cout << "step 7.do inference..." << std::endl;
    infer_request.Infer();

    // ----- Step 8. 处理推理计算结果 ------------
    // -------------------------------------------
    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);     //获取模型输出的缓冲区
    const float* detections = output_blob->buffer().as::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;

    /* 每个检测结果的格式为: [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(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;

}

你可能感兴趣的:(从零开始详细讲解OpenVINO推理程序)