美文网首页
从零开始详细讲解OpenVINO推理程序

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

作者: LabVIEW_Python | 来源:发表于2021-07-22 15:37 被阅读0次

    本文选取的模型: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 <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;
        // 获得网络输入信息(键值对) 
        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<uint8_t>(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<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. 执行推理计算 ----------------
        // -------------------------------------------
        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<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;
    
        /* 每个检测结果的格式为: [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;
    
    }
    

    相关文章

      网友评论

          本文标题:从零开始详细讲解OpenVINO推理程序

          本文链接:https://www.haomeiwen.com/subject/hqagultx.html