OpenVINO运行Tensorflow模型

本文涉及的产品
模型训练 PAI-DLC,5000CU*H 3个月
模型在线服务 PAI-EAS,A10/V100等 500元 1个月
小语种识别,小语种识别 200次/月
简介: OpenVINO运行Tensorflow模型

OpenVINO运行Tensorflow模型


最近看到一个巨牛的人工智能教程,分享一下给大家。教程不仅是零基础,通俗易懂,而且非常风趣幽默,像看小说一样!觉得太牛了,所以分享给大家。平时碎片时间可以当小说看,【点这里可以去膜拜一下大神的“小说”】。

请先阅读我的上一篇文章《Visual Studio 2017 配置OpenVINO开发环境》,在VS2017中配置好OpenVINO环境。

1 模型转换

1.1安装模型转换工具

打开conda控制台,创建虚拟环境vino

conda create -n vino python=3.6

创建完成后,执行activate vino。然后安装OpenVINO模型转换工具,具体命令如下:

> activate vino
> cd E:\OpenVINO\openvino_2019.3.334\deployment_tools\model_optimizer
> pip install -r requirements_tf.txt

1.2 模型转换

以MobileNet为例,前往https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet_v1.md下载MobileNet_v1_1.0_224模型,解压到目录E:\model后,对mobilenet_v1_1.0_224_frozen.pb执行如下命令完成模型转换:

python E:\OpenVINO\openvino_2019.3.334\deployment_tools\model_optimizer\mo_tf.py --input_model mobilenet_v1_1.0_224_frozen.pb --input_shape [1,224,224,3] --output MobilenetV1/Logits/Conv2d_1c_1x1/Conv2D --mean_values [127.5,127.5,127.5] --scale_values [127.5,127.5,127.5]

参数介绍:

--input_model :指定输入模型路径
--input_shape :指定模型的输入Tensor的shape,如果不指定,则会自动从pb中读取
--output :指定输出节点名称,如果不指定,会自动从图中提取。注意,这里由于openVINO不支持squeeze层,所以我们主动指定squeeze的上一层即:MobilenetV1/Logits/Conv2d_1c_1x1/Conv2D,获取每一层名称的方法:可以先不指定output,会自动导出xml,从xml中即可看到每一层名称。
--scale_values :指定数据预处理的scale系数 
--mean_values: 指定数据预处理的mean系数

除了上面参数外,还有一些其他常用的参数:

--data_type: 指定计算类型,可以选择全浮点和半浮点,可选参数为:{FP16,FP32,half,float}

注意,scale_values参数和mean_values参数一般用于输入Tensor预处理,更常见的就是归一化。假设输入Tensor名称为in_tensor,经过预处理后,输出Tensor为out_tensor,其计算公式如下:

out_tensor = (in_tensor-mean_values)/scale_values 

例如,需要将输入归一化为[-1,1],则mean_values取值为[127.5,127.5,127.5]且scale_values取值为[127.5,127.5,127.5]

完成后,在E:\model目录中生成如下三个文件:

其中bin文件是模型参数,xml文件是网络结构,mapping文件是模型转换前后计算节点映射关系。我们主要用bin和xml文件。

注意,如果转换过程中出错了,可以尝试卸载Tenorflow,可能是因为Tensorflow版本问题,改为Tensorflow1.14-cpu版本,笔者这边使用1.14-cpu版本没有问题。

2 VS2017运行

2.1 环境配置

主要用到OpenVINO和OpenCV环境,OpenCV用于读取图片,OpenVINO用于运行模型。

参考我的上一篇文章【Visual Studio 2017 配置OpenVINO开发环境】配置好openVINO环境。

参考我的另一篇文章【OpenCV 3.2.0 opencv_contrib VS2017】配置好OpenCV环境。

注意:如果懒得配置,可以从附件中下载笔者已经搭建好的环境,可直接用VS2017打开运行

2.2 代码实现

将E:\model拷贝到项目根目录,输入以下代码。

#include <inference_engine.hpp> 
#include <iostream>
#include <string> 
#include <vector>
#include <opencv2/opencv.hpp>
using namespace InferenceEngine;
using namespace std;
string inputName;
string outputName;
InferRequest inferReq;
vector<wstring> labels;
//初试化模型相关参数
void initModel(string xml,string bin,string plugin="plugins.xml") { 
  try {
    Core ie(plugin);
    CNNNetReader network_reader;
    network_reader.ReadNetwork(xml);
    network_reader.ReadWeights(bin);
    network_reader.getNetwork().setBatchSize(1);
    CNNNetwork network = network_reader.getNetwork();
    InputInfo::Ptr input_info = network.getInputsInfo().begin()->second;
    inputName = network.getInputsInfo().begin()->first;
    input_info->getPreProcess().setResizeAlgorithm(RESIZE_BILINEAR);
    input_info->setLayout(Layout::NCHW);
    input_info->setPrecision(Precision::U8);
    DataPtr output_info = network.getOutputsInfo().begin()->second;
    outputName = network.getOutputsInfo().begin()->first;
    output_info->setPrecision(Precision::FP32);
    ExecutableNetwork executable_network = ie.LoadNetwork(network, "CPU");
    inferReq = executable_network.CreateInferRequest();
  }catch (const std::exception & ex) {
    std::cerr << ex.what() << std::endl; 
  }
}
//Mat 转Blob
void  matU8ToBlob(const cv::Mat& orig_image, InferenceEngine::Blob::Ptr& blob, int batchIndex=0) {
  InferenceEngine::SizeVector blobSize = blob->getTensorDesc().getDims();
  const size_t width = blobSize[3];
  const size_t height = blobSize[2];
  const size_t channels = blobSize[1];
  uint8_t* blob_data = blob->buffer().as<uint8_t*>();
  cv::Mat resized_image(orig_image);
  if (static_cast<int>(width) != orig_image.size().width ||
    static_cast<int>(height) != orig_image.size().height) {
    cv::resize(orig_image, resized_image, cv::Size(width, height));
  }
  int batchOffset = batchIndex * width * height * channels;
  for (size_t c = 0; c < channels; c  ) {
    for (size_t h = 0; h < height; h  ) {
      for (size_t w = 0; w < width; w  ) {
        blob_data[batchOffset   c * width * height   h * width   w] =
          resized_image.at<cv::Vec3b>(h, w)[c];
      }
    }
  }
}
//读取label
void readLabel(string labelPath)
{
  std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
  ifstream in(labelPath.c_str());
  string line;
  if (in) { // 有该文件 
    while (getline(in, line)) { // line中不包括每行的换行符 
      wstring wb = conv.from_bytes(line);
      labels.push_back(wb);
    } 
  } else { // 没有该文件 
    cout << "no such file:" << labelPath << endl;
  } 
}
//前向计算
wstring infer(cv::Mat rgb,float& rtP) {
  Blob::Ptr imgBlob = inferReq.GetBlob(inputName);
  matU8ToBlob(rgb, imgBlob);
  inferReq.Infer();
  Blob::Ptr output = inferReq.GetBlob(outputName);
  float* logits = output->buffer().as<InferenceEngine::PrecisionTrait<InferenceEngine::Precision::FP32>::value_type*>();
  int maxIdx = 0;
  float maxP = 0;
  int nclasses = labels.size();//1001类
  float sum = 1;
  //softmax
  for (int i = 0; i < nclasses; i  ) {
    logits[i] = exp(logits[i]);
    sum = sum   logits[i];
    if (logits[i] > maxP) {
      maxP = logits[i];
      maxIdx = i;
    }
  }
  rtP = maxP / sum; 
  return labels[maxIdx];
}
//测试
int main()
{
  string xml = "../model/mobilenet_v1_1.0_224_frozen.xml";
  string bin = "../model/mobilenet_v1_1.0_224_frozen.bin";
  string plugin = "../model/plugins.xml";
  string label = "../model/labels.txt";
  string testImg = "../model/test.png";
  initModel(xml, bin, plugin);
  readLabel(label);
  cv::Mat test = cv::imread(testImg);
  cv::Mat rgb;
  cv::cvtColor(test,rgb, cv::COLOR_BGR2RGB);
  float p;
  wstring cls = infer(rgb, p);
  std::wcout.imbue(std::locale("chs"));
  wcout << "类别:" << cls << ",概率:" << p << endl;
}

readLabel函数读取label信息,用于将模型识别出的最大概率类别对应的中文文字,测试图片如下:

运行后,结果如下:

军用飞机,0.927341

3 附件下载

可以从【附件】中下载所有相关文件,直接用VS2017打开即可,注意只能用x64模式运行,openVNO目前不支持x86。另外,如果CSDN下载没有积分,或者是下载链接出错,可直接加群:824420877,联系群主免费获取代码。

相关文章
|
30天前
|
机器学习/深度学习 TensorFlow 算法框架/工具
深度学习之格式转换笔记(三):keras(.hdf5)模型转TensorFlow(.pb) 转TensorRT(.uff)格式
将Keras训练好的.hdf5模型转换为TensorFlow的.pb模型,然后再转换为TensorRT支持的.uff格式,并提供了转换代码和测试步骤。
68 3
深度学习之格式转换笔记(三):keras(.hdf5)模型转TensorFlow(.pb) 转TensorRT(.uff)格式
|
14天前
|
机器学习/深度学习 人工智能 算法
【车辆车型识别】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+算法模型
车辆车型识别,使用Python作为主要编程语言,通过收集多种车辆车型图像数据集,然后基于TensorFlow搭建卷积网络算法模型,并对数据集进行训练,最后得到一个识别精度较高的模型文件。再基于Django搭建web网页端操作界面,实现用户上传一张车辆图片识别其类型。
54 0
【车辆车型识别】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+算法模型
|
2月前
|
机器学习/深度学习 人工智能 算法
鸟类识别系统Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+ResNet50算法模型+图像识别
鸟类识别系统。本系统采用Python作为主要开发语言,通过使用加利福利亚大学开源的200种鸟类图像作为数据集。使用TensorFlow搭建ResNet50卷积神经网络算法模型,然后进行模型的迭代训练,得到一个识别精度较高的模型,然后在保存为本地的H5格式文件。在使用Django开发Web网页端操作界面,实现用户上传一张鸟类图像,识别其名称。
104 12
鸟类识别系统Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+ResNet50算法模型+图像识别
|
30天前
|
机器学习/深度学习 移动开发 TensorFlow
深度学习之格式转换笔记(四):Keras(.h5)模型转化为TensorFlow(.pb)模型
本文介绍了如何使用Python脚本将Keras模型转换为TensorFlow的.pb格式模型,包括加载模型、重命名输出节点和量化等步骤,以便在TensorFlow中进行部署和推理。
69 0
|
3月前
|
API UED 开发者
如何在Uno Platform中轻松实现流畅动画效果——从基础到优化,全方位打造用户友好的动态交互体验!
【8月更文挑战第31天】在开发跨平台应用时,确保用户界面流畅且具吸引力至关重要。Uno Platform 作为多端统一的开发框架,不仅支持跨系统应用开发,还能通过优化实现流畅动画,增强用户体验。本文探讨了Uno Platform中实现流畅动画的多个方面,包括动画基础、性能优化、实践技巧及问题排查,帮助开发者掌握具体优化策略,提升应用质量与用户满意度。通过合理利用故事板、减少布局复杂性、使用硬件加速等技术,结合异步方法与预设缓存技巧,开发者能够创建美观且流畅的动画效果。
77 0
|
3月前
|
C# 开发者 前端开发
揭秘混合开发新趋势:Uno Platform携手Blazor,教你一步到位实现跨平台应用,代码复用不再是梦!
【8月更文挑战第31天】随着前端技术的发展,混合开发日益受到开发者青睐。本文详述了如何结合.NET生态下的两大框架——Uno Platform与Blazor,进行高效混合开发。Uno Platform基于WebAssembly和WebGL技术,支持跨平台应用构建;Blazor则让C#成为可能的前端开发语言,实现了客户端与服务器端逻辑共享。二者结合不仅提升了代码复用率与跨平台能力,还简化了项目维护并增强了Web应用性能。文中提供了从环境搭建到示例代码的具体步骤,并展示了如何创建一个简单的计数器应用,帮助读者快速上手混合开发。
75 0
|
3月前
|
开发者 算法 虚拟化
惊爆!Uno Platform 调试与性能分析终极攻略,从工具运用到代码优化,带你攻克开发难题成就完美应用
【8月更文挑战第31天】在 Uno Platform 中,调试可通过 Visual Studio 设置断点和逐步执行代码实现,同时浏览器开发者工具有助于 Web 版本调试。性能分析则利用 Visual Studio 的性能分析器检查 CPU 和内存使用情况,还可通过记录时间戳进行简单分析。优化性能涉及代码逻辑优化、资源管理和用户界面简化,综合利用平台提供的工具和技术,确保应用高效稳定运行。
78 0
|
3月前
|
前端开发 开发者 设计模式
揭秘Uno Platform状态管理之道:INotifyPropertyChanged、依赖注入、MVVM大对决,帮你找到最佳策略!
【8月更文挑战第31天】本文对比分析了 Uno Platform 中的关键状态管理策略,包括内置的 INotifyPropertyChanged、依赖注入及 MVVM 框架。INotifyPropertyChanged 方案简单易用,适合小型项目;依赖注入则更灵活,支持状态共享与持久化,适用于复杂场景;MVVM 框架通过分离视图、视图模型和模型,使状态管理更清晰,适合大型项目。开发者可根据项目需求和技术栈选择合适的状态管理方案,以实现高效管理。
42 0
|
3月前
|
Apache 开发者 Java
Apache Wicket揭秘:如何巧妙利用模型与表单机制,实现Web应用高效开发?
【8月更文挑战第31天】本文深入探讨了Apache Wicket的模型与表单处理机制。Wicket作为一个组件化的Java Web框架,提供了多种模型实现,如CompoundPropertyModel等,充当组件与数据间的桥梁。文章通过示例介绍了模型创建及使用方法,并详细讲解了表单组件、提交处理及验证机制,帮助开发者更好地理解如何利用Wicket构建高效、易维护的Web应用程序。
44 0
|
3月前
|
机器学习/深度学习 API TensorFlow
深入解析TensorFlow 2.x中的Keras API:快速搭建深度学习模型的实战指南
【8月更文挑战第31天】本文通过搭建手写数字识别模型的实例,详细介绍了如何利用TensorFlow 2.x中的Keras API简化深度学习模型构建流程。从环境搭建到数据准备,再到模型训练与评估,展示了Keras API的强大功能与易用性,适合初学者快速上手。通过简单的代码,即可完成卷积神经网络的构建与训练,显著降低了深度学习的技术门槛。无论是新手还是专业人士,都能从中受益,高效实现模型开发。
26 0
下一篇
无影云桌面