本文选取的模型: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])
#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;
}
网友评论