OpenCV读取tensorflow 2.X模型的方法:将SavedModel转为frozen graph

简介: 【2月更文挑战第22天】本文介绍基于Python的tensorflow库,将tensorflow与keras训练好的SavedModel格式神经网络模型转换为frozen graph格式,从而可以用OpenCV库在C++等其他语言中将其打开的方法~

  本文介绍基于Pythontensorflow库,将tensorflowkeras训练好的SavedModel格式神经网络模型转换为frozen graph格式,从而可以用OpenCV库在C++等其他语言中将其打开的方法。

  如果我们需要训练使用一个神经网络模型,一般情况下都是首先借助Python语言中完善的神经网络模型API对其加以训练,训练完毕后在C++Java等语言环境下高效、快速地使用它。最近,就需要在C++中打开、使用几个前期已经在Pythontensorflow库中训练好的神经网络模型。但是,由于训练模型时使用的是2.X版本的tensorflow库(且用的是keras的框架),所以训练模型后保存的是SavedModel格式的神经网络模型文件——就是包含3.pb格式文件,以及assetsvariables2个文件夹那种形式的模型;如下图所示。

  而在C++中读取神经网络模型,首先是可以借助tensorflow库的C++ API来实现,但是这种方法非常复杂——完整的TensorFlow C++ API部署起来非常困难——需要系统盘至少40 G50 G的剩余空间、动辄0.5 h1 h的编译时长,经常需要花费一周的时间才可以配置成功;所以如果仅仅是需要在C++中读取已经训练好的神经网络模型的话,没必要花费这么大功夫去配置TensorFlow C++ API。而同时,基于OpenCV库,我们则可以在简单、快速地配置完其环境后,就基于1个函数对训练好的tensorflow库神经网络模型加以读取、使用。这里如果大家需要配置C++环境的OpenCV库,可以参考文章C++计算机视觉库OpenCV在Visual Studio 2022的配置方法

  但是,还有一个问题——OpenCV库自身目前仅支持读取tensorflowfrozen graph格式的神经网络模型,不支持读取SavedModel格式的模型。因此,如果希望基于OpenCV库读取tensorflowSavedModel格式的模型,就需要首先将其转换为frozen graph格式;那么,本文就介绍一下这个操作的具体方法,并给出2种实现这一转换功能的Python代码。

  首先,本文神经网络模型格式转换的代码是基于Python环境中tensorflow库实现的,因此需要配置好这一个库(大家都已经需要转换神经网络模型的格式了,那Python环境中tensorflow库肯定早已经配置好了);如果没有配置,可以参考文章Anaconda配置Python新版本tensorflow库(CPU、GPU通用)的方法

  第1种代码如下。

# -*- coding: utf-8 -*-
"""
Created on Sat Mar  9 14:31:18 2024

@author: fkxxgis
"""

import tensorflow as tf
from tensorflow.keras import models
from tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2

# model_save_model = tf.saved_model.load("F:/Data_Reflectance_Rec/model/model_blue/")
model_save_model = models.load_model("F:/Data_Reflectance_Rec/model/model_blue/")

signatures = model_save_model.signatures["serving_default"]
graph = tf.function(lambda x: model_save_model(x))
graph = graph.get_concrete_function(tf.TensorSpec(signatures.inputs[0].shape.as_list(), signatures.inputs[0].dtype.name))
frozen_variable = convert_variables_to_constants_v2(graph)
frozen_variable.graph.as_graph_def();

tf.io.write_graph(graph_or_graph_def = frozen_variable.graph, 
                  logdir = "F:/Data_Reflectance_Rec/model/model_blue_new", 
                  name = "frozen_graph.pb", 
                  as_text = False)
# tf.io.write_graph(graph_or_graph_def = frozen_variable.graph, 
#                   logdir = "F:/Data_Reflectance_Rec/model/model_blue_new", 
#                   name = "frozen_graph.pbtxt", 
#                   as_text = True)

  其中,我们首先需要导入对应的Python模块和convert_variables_to_constants_v2()函数。

  随后,加载我们待转换的、SavedModel格式的tensorflow神经网络模型。这里需要注意,我写了2句不同的代码来加载初始的模型——其中,如果用第1句代码加载模型,倒也可以不报错地运行完成上述代码,但是等到用C++环境的OpenCV库读取这个转换后的模型时,会出现Microsoft C++ 异常: cv::Exception字样的报错,如下图所示;而如果用第2句代码加载模型,就没有问题。之所以会这样,应该是因为我当初训练这个神经网络模型时,用的是tensorflowkeras模块的Model,所以导致加载模型时,就不能用传统的加载SavedModel格式模型的方法了(可能是这样)。

  接下来,我们从初始模型中获取其签名tensorflow库中的签名(Signature),是用于定义模型输入、输出的一种机制——其定义了模型接受的输入参数和返回的输出结果的名称、数据类型和形状等信息;这个默认签名为serving_default,我们这里获取这个默认的签名即可。

  接下来,这个graph = tf.function(lambda x: model_save_model(x))表示将模型封装在tensorflow的图函数中;随后,get_concrete_function()获取具体函数并指定输入张量的形状和数据类型。说实话,这里的2行代码我也搞不太清楚具体详细含义是什么——但大体上,这些内容应该是tensorflow1.X版本中的一些操作与名词(因为frozen graph格式的模型本来就是tensorflow1.X版本中用的,而SavedModel格式则是2.X版本中常用的)。

  再次,通过convert_variables_to_constants_v2()函数,将图中的变量转换为常量,并基于as_graph_def()定义1个冻结图。

  最后,就可以通过tf.io.write_graph()函数,将冻结图写入指定的目录中,输出文件名为frozen_graph.pbas_text = False表示以二进制格式保存这个模型(如果不加这个参数,就相当于成了.pbtxt文件了,导致后续用C++环境的OpenCV库还是读取不了这个模型)。代码末尾,还有一段注释的部分——如果取消注释,将以文本格式保存冻结图,也就是.pbtxt文件。因为我们只要.pb文件就够了,所以就不需要这段代码了。

  执行上述代码,在结果文件夹中,我们将看到1.pb格式的神经网络模型结果文件,如下图所示。

  接下来,在C++Python等语言的OpenCV库中,我们都可以基于cv::dnn::readNetFromTensorflow()这个函数,来读取我们的神经网络模型了。

  除此之外,再给出另一个版本的转换代码;这个代码其实和前述代码的含义差不多,如果前述代码不能执行,大家可以再尝试尝试下面这个。

import tensorflow as tf
from tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2

loaded = tf.saved_model.load('F:/Data_Reflectance_Rec/model/model_nir/')
infer = loaded.signatures['serving_default']

f = tf.function(infer).get_concrete_function(tf.TensorSpec(infer.inputs[0].shape.as_list(), dtype=tf.float32))
f2 = convert_variables_to_constants_v2(f)
graph_def = f2.graph.as_graph_def()

with tf.io.gfile.GFile('frozen_graph.pb', 'wb') as f:
    f.write(graph_def.SerializeToString())

  至此,大功告成。

相关文章
|
24天前
|
机器学习/深度学习 TensorFlow 算法框架/工具
深度学习之格式转换笔记(三):keras(.hdf5)模型转TensorFlow(.pb) 转TensorRT(.uff)格式
将Keras训练好的.hdf5模型转换为TensorFlow的.pb模型,然后再转换为TensorRT支持的.uff格式,并提供了转换代码和测试步骤。
60 3
深度学习之格式转换笔记(三):keras(.hdf5)模型转TensorFlow(.pb) 转TensorRT(.uff)格式
|
23天前
|
并行计算 PyTorch TensorFlow
Ubuntu安装笔记(一):安装显卡驱动、cuda/cudnn、Anaconda、Pytorch、Tensorflow、Opencv、Visdom、FFMPEG、卸载一些不必要的预装软件
这篇文章是关于如何在Ubuntu操作系统上安装显卡驱动、CUDA、CUDNN、Anaconda、PyTorch、TensorFlow、OpenCV、FFMPEG以及卸载不必要的预装软件的详细指南。
2052 3
|
24天前
|
PyTorch TensorFlow 算法框架/工具
Jetson环境安装(一):Ubuntu18.04安装pytorch、opencv、onnx、tensorflow、setuptools、pycuda....
本文提供了在Ubuntu 18.04操作系统的NVIDIA Jetson平台上安装深度学习和计算机视觉相关库的详细步骤,包括PyTorch、OpenCV、ONNX、TensorFlow等。
29 1
Jetson环境安装(一):Ubuntu18.04安装pytorch、opencv、onnx、tensorflow、setuptools、pycuda....
|
8天前
|
机器学习/深度学习 人工智能 算法
【车辆车型识别】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+算法模型
车辆车型识别,使用Python作为主要编程语言,通过收集多种车辆车型图像数据集,然后基于TensorFlow搭建卷积网络算法模型,并对数据集进行训练,最后得到一个识别精度较高的模型文件。再基于Django搭建web网页端操作界面,实现用户上传一张车辆图片识别其类型。
23 0
【车辆车型识别】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+算法模型
|
2月前
|
机器学习/深度学习 人工智能 算法
鸟类识别系统Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+ResNet50算法模型+图像识别
鸟类识别系统。本系统采用Python作为主要开发语言,通过使用加利福利亚大学开源的200种鸟类图像作为数据集。使用TensorFlow搭建ResNet50卷积神经网络算法模型,然后进行模型的迭代训练,得到一个识别精度较高的模型,然后在保存为本地的H5格式文件。在使用Django开发Web网页端操作界面,实现用户上传一张鸟类图像,识别其名称。
100 12
鸟类识别系统Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+ResNet50算法模型+图像识别
|
24天前
|
机器学习/深度学习 移动开发 TensorFlow
深度学习之格式转换笔记(四):Keras(.h5)模型转化为TensorFlow(.pb)模型
本文介绍了如何使用Python脚本将Keras模型转换为TensorFlow的.pb格式模型,包括加载模型、重命名输出节点和量化等步骤,以便在TensorFlow中进行部署和推理。
60 0
|
3月前
|
CDN 缓存 前端开发
JSF 性能优化:提升应用响应速度
【8月更文挑战第31天】JavaServer Faces (JSF) 是构建企业级 Web 应用的强大框架。但随着应用复杂度增加,性能问题可能显现。本文通过具体案例介绍如何优化 JSF 应用,提升响应速度。首先创建一个名为 “MyJSFOptimizationApp” 的新 JSF 项目,并在 `pom.xml` 中添加必要的依赖。接着,在 `WEB-INF` 目录下配置 `web.xml` 文件,设置 JSF servlet。然后创建一个 Managed Bean 包含简单属性和方法,并使用 Facelets 页面 `index.xhtml` 展示信息。
33 0
|
3月前
|
API UED 开发者
如何在Uno Platform中轻松实现流畅动画效果——从基础到优化,全方位打造用户友好的动态交互体验!
【8月更文挑战第31天】在开发跨平台应用时,确保用户界面流畅且具吸引力至关重要。Uno Platform 作为多端统一的开发框架,不仅支持跨系统应用开发,还能通过优化实现流畅动画,增强用户体验。本文探讨了Uno Platform中实现流畅动画的多个方面,包括动画基础、性能优化、实践技巧及问题排查,帮助开发者掌握具体优化策略,提升应用质量与用户满意度。通过合理利用故事板、减少布局复杂性、使用硬件加速等技术,结合异步方法与预设缓存技巧,开发者能够创建美观且流畅的动画效果。
76 0
|
3月前
|
C# 开发者 前端开发
揭秘混合开发新趋势:Uno Platform携手Blazor,教你一步到位实现跨平台应用,代码复用不再是梦!
【8月更文挑战第31天】随着前端技术的发展,混合开发日益受到开发者青睐。本文详述了如何结合.NET生态下的两大框架——Uno Platform与Blazor,进行高效混合开发。Uno Platform基于WebAssembly和WebGL技术,支持跨平台应用构建;Blazor则让C#成为可能的前端开发语言,实现了客户端与服务器端逻辑共享。二者结合不仅提升了代码复用率与跨平台能力,还简化了项目维护并增强了Web应用性能。文中提供了从环境搭建到示例代码的具体步骤,并展示了如何创建一个简单的计数器应用,帮助读者快速上手混合开发。
72 0
|
3月前
|
UED 开发工具 iOS开发
Uno Platform大揭秘:如何在你的跨平台应用中,巧妙融入第三方库与服务,一键解锁无限可能,让应用功能飙升,用户体验爆棚!
【8月更文挑战第31天】Uno Platform 让开发者能用同一代码库打造 Windows、iOS、Android、macOS 甚至 Web 的多彩应用。本文介绍如何在 Uno Platform 中集成第三方库和服务,如 Mapbox 或 Google Maps 的 .NET SDK,以增强应用功能并提升用户体验。通过 NuGet 安装所需库,并在 XAML 页面中添加相应控件,即可实现地图等功能。尽管 Uno 平台减少了平台差异,但仍需关注版本兼容性和性能问题,确保应用在多平台上表现一致。掌握正确方法,让跨平台应用更出色。
47 0