关注:OpenCV干货与教程第一时间送达! 欢迎星标或者置顶【OpenCV学堂】
概述
OpenVINO除了可以集成OpenCV DNN一起使用之外,其本身也提供了一套开发接口(SDK),可以不依赖于其他任何第三方库实现对模型的加速推断运行。
其基于IE SDK实现模型加载与运行步骤分为如下七步:
01
读取IR中间层模型(xml与bin文件)
02
声明模型输入与输出格式
03
创建IE插件,实现引擎加载
04
使用插件加载与编译网络
05
设置网络的输入参数/数据
06
执行网络推断预测
07
解析网络输出结果
上述各个步骤依赖的相关API与函数列表如下:
各步相关函数
1 | InferenceEngine::CNNNetReader |
---|---|
2 | CNNNetwork::getInputInfo()、 CNNNetwork::getOutputInfo() |
3 | InferenceEngine::PluginDispatcher |
4 | LoadNetwork() |
5 | infer_request.GetBlob(input_name); |
6 | ExecutableNetwork::CreateInferRequest()、Infer() |
7 | GetBlob() |
CPU扩展配置
在代码执行层面,首先会加载IE加速引擎,主要依靠两个CPU级别的加速引擎为MKLDNN与clDNN库文件。标准的不支持扩展层,导致MKLDNN无法加载一些扩展深度学习层,比如SSD网络或者Faster-RCNN网络的特定输出层,所以需要CPU扩展支持,这部分需要编译OpenVINO样例代码中的common部分,双击打开VS2015 Sample Code的工程文件:
C:%local_user_dir% \Documents\Intel\OpenVINO\inference_engine_samples_2015\Samples.sln
在VS2015中选择object_detection_sample_ssd 工程,右键【生成】即可。然后把生成之后的cpu_extension.lib路径添加库目录,cpu_extension.dll路径添加到环境变量中,重启VS2015。最终的VS2015中库目录与附加依赖项配置显示如下:
代码实现与运行
创建IE插件与加载CPU扩展
// 创建IE插件
InferenceEnginePluginPtr engine_ptr = PluginDispatcher(dirs).getSuitablePlugin(TargetDevice::eCPU);
InferencePlugin plugin(engine_ptr);
// 加载CPU扩展库支持
plugin.AddExtension(std::make_shared<Extensions::Cpu::CpuExtensions>());
加载网络模型
// SSD 车辆检测模型
CNNNetReader network_reader;
network_reader.ReadNetwork("D:/projects/models/vehicle-license-plate-detection-barrier-0106/FP32/vehicle-license-plate-detection-barrier-0106.xml");
network_reader.ReadWeights("D:/projects/models/vehicle-license-plate-detection-barrier-0106/FP32/vehicle-license-plate-detection-barrier-0106.bin");
请求网络输入与输出信息
// 请求网络输入与输出信息
auto network = network_reader.getNetwork();
InferenceEngine::InputsDataMap input_info(network.getInputsInfo());
InferenceEngine::OutputsDataMap output_info(network.getOutputsInfo());
设置输入与输出数据精度
/**设置输入精度与维度**/
for (auto &item : input_info) {
auto input_data = item.second;
input_data->setPrecision(Precision::U8);
input_data->setLayout(Layout::NCHW);
}
/** 设置输出精度与内容**/
for (auto &item : output_info) {
auto output_data = item.second;
output_data->setPrecision(Precision::FP32);
}
创建可执行网络与获取推断图
// 创建可执行网络对象
auto executable_network = plugin.LoadNetwork(network, {});
// 请求推断图
auto infer_request = executable_network.CreateInferRequest();
输入图像数据
// NCHW
unsigned char* data = static_cast<unsigned char*>(input->buffer());
for (size_t row = 0; row < h; row++) {
for (size_t col = 0; col < w; col++) {
for (size_t ch = 0; ch < num_channels; ch++) {
data[image_size*ch + row*w+col] = blob_image.at<Vec3b>(row, col)[ch];
}
}
}
执行预测
// 执行预测
infer_request.Infer();
解析输出结果
// 获取输出数据
auto output = infer_request.GetBlob(output_name);
const float* detection = static_cast<PrecisionTrait<Precision::FP32>::value_type*>(output->buffer());
const SizeVector outputDims = output->getTensorDesc().getDims();
const int maxProposalCount = outputDims[2];
const int objectSize = outputDims[3];
// 解析输出结果
for (int curProposal = 0; curProposal < maxProposalCount; curProposal++) {
float label = detection[curProposal * objectSize + 1];
float confidence = detection[curProposal * objectSize + 2];
float xmin = detection[curProposal * objectSize + 3] * image_width;
float ymin = detection[curProposal * objectSize + 4] * image_height;
float xmax = detection[curProposal * objectSize + 5] * image_width;
float ymax = detection[curProposal * objectSize + 6] * image_height;
if (confidence > 0.5) {
printf("label id : %d\n", static_cast<int>(label));
Rect rect;
rect.x = static_cast<int>(xmin);
rect.y = static_cast<int>(ymin);
rect.width = static_cast<int>(xmax - xmin);
rect.height = static_cast<int>(ymax - ymin);
putText(src, "OpenVINO-Vehicle-Detection@JiaZhiGang", Point(20, 50), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(0, 0, 255), 2, 8);
rectangle(src, rect, Scalar(0, 255, 255), 2, 8, 0);
}
}
运行结果如下:
觉得不错,请点【在看】