OpenCV使用Tensorflow2-Keras模型

前言

最近工作上需要在C++上快速集成Tensorflow/Keras训练好的模型,做算法验证。首先想到的就是opencv里面的dnn模块了,但是它需要的格式文件比较郁闷,是pb格式的模型,但是keras通常保存的是h5文件,查阅了很多资料,最后找到了很方便的方法。

国际惯例,参考博客

Frozen_Graph_TensorFlow

这个地址的大佬用fashion mnist写的训练和测试,我这里用更简单的线性回归为例。

训练

老样子,引入相关的包,创建数据集

import numpy as np
import tensorflow as tf

# build data
input_x = np.random.rand(1000, 4)
output_y = np.dot(input_x,np.array([[3],[14],[6],[10]]))

然后创建简单的模型

# build model
inputs = tf.keras.layers.Input(shape=(4,));
outputs = tf.keras.layers.Dense(units=1)(inputs)
model = tf.keras.Model(inputs=inputs,outputs=outputs)

编译、训练

model.compile(optimizer=tf.keras.optimizers.SGD(learning_rate=0.01),loss='mse')
model.fit(x=input_x,y=output_y,epochs=100,validation_split=0.1)

看看训练完毕的权重是否接近我们创建的权重

model.get_weights()
'''
[array([[ 2.669988],
        [13.562156],
        [ 5.622848],
        [ 9.587276]], dtype=float32),
 array([0.80391794], dtype=float32)]
'''

保存

保存的时候就需要注意了,要保存成pb格式的,不要直接model.saveh5格式的,如果你已经保存完了,可以model.load_model载入进来,然后再执行如下函数

# Convert Keras model to ConcreteFunction
full_model = tf.function(lambda x: model(x))
full_model = full_model.get_concrete_function(
    tf.TensorSpec(model.inputs[0].shape, model.inputs[0].dtype))

# Get frozen ConcreteFunction
frozen_func = convert_variables_to_constants_v2(full_model)
frozen_func.graph.as_graph_def()

layers = [op.name for op in frozen_func.graph.get_operations()]
print("-" * 50)
print("Frozen model layers: ")
for layer in layers:
    print(layer)

print("-" * 50)
print("Frozen model inputs: ")
print(frozen_func.inputs)
print("Frozen model outputs: ")
print(frozen_func.outputs)

# Save frozen graph from frozen ConcreteFunction to hard drive
tf.io.write_graph(graph_or_graph_def=frozen_func.graph,
                  logdir="./frozen_models",
                  name="frozen_graph.pb",
                  as_text=False)
'''
--------------------------------------------------
Frozen model layers: 
x
model/dense/MatMul/ReadVariableOp/resource
model/dense/MatMul/ReadVariableOp
model/dense/MatMul
model/dense/BiasAdd/ReadVariableOp/resource
model/dense/BiasAdd/ReadVariableOp
model/dense/BiasAdd
Identity
--------------------------------------------------
Frozen model inputs: 
[<tf.Tensor 'x:0' shape=(None, 4) dtype=float32>]
Frozen model outputs: 
[<tf.Tensor 'Identity:0' shape=(None, 1) dtype=float32>]
'''

这样就会在./frozen_models/frozen_graph.pb目录下看到模型了。

使用TensorFlow调用

在参考博客中,作者也提供了对应的调用方法

def wrap_frozen_graph(graph_def, inputs, outputs, print_graph=False):
    def _imports_graph_def():
        tf.compat.v1.import_graph_def(graph_def, name="")

    wrapped_import = tf.compat.v1.wrap_function(_imports_graph_def, [])
    import_graph = wrapped_import.graph

    print("-" * 50)
    print("Frozen model layers: ")
    layers = [op.name for op in import_graph.get_operations()]
    if print_graph == True:
        for layer in layers:
            print(layer)
    print("-" * 50)

    return wrapped_import.prune(
        tf.nest.map_structure(import_graph.as_graph_element, inputs),
        tf.nest.map_structure(import_graph.as_graph_element, outputs))

通过tensorflow1.x载入模型

with tf.io.gfile.GFile("./frozen_models/frozen_graph.pb", "rb") as f:
        graph_def = tf.compat.v1.GraphDef()
        loaded = graph_def.ParseFromString(f.read())

随后生成预测函数

frozen_func = wrap_frozen_graph(graph_def=graph_def,
                                    inputs=["x:0"],
                                    outputs=["Identity:0"],
                                    print_graph=True)

调用这个预测函数试验一下:

test_x = np.array([[1,1,1,1]],np.float32)
pred_y = frozen_func(x=tf.constant(test_x))[0]
print(pred_y)#tf.Tensor([[32.246185]], shape=(1, 1), dtype=float32)
true_y = np.dot(test_x,np.array([[3],[14],[6],[10]]))
print(true_y) #[[33.]]

使用OpenCV-python调用模型

这个非常简单了,四句话完成创建测试数据、读取模型、载入数据、预测

test_x = np.array([[1,1,1,1]],np.float32)
net = cv2.dnn.readNetFromTensorflow("./frozen_models/frozen_graph.pb")
net.setInput(test_x)
pred = net.forward()
print(pred)#[[32.246185]]

与上面用tensorflow调用的结果一模一样。

使用opencv-C++调用模型

核心就在于opencv的readNetFromTensorflow接受的输入固定是InputArray类型的,这个类型等价于Mat、vector等,具体可以上网查。这里我们需要创建一个大小为(1,4)Mat数据;

下面这个函数就是使用数组去初始化Mat数据

void InitMat(Mat& m,float* num)
{
 for(int i=0;i<m.rows;i++)
  for(int j=0;j<m.cols;j++)
   m.at<float>(i,j)=*(num+i*m.rows+j);
}

创建一个Mat数据

float sz[] = {1,1,1,1};
Mat input(1,4,CV_32F);
InitMat(input, sz);

接下来就是读取模型、载入数据、预测

dnn::Net net = dnn::readNetFromTensorflow("./frozen_models/frozen_graph.pb");
net.setInput(input);
Mat pred = net.forward();
cout<<pred<<endl; //[32.246185]

后记

上面基本贴出了所有的代码,如果运行不了,可以进入公众号,在公众号简介的github中找到源码。
在这里插入图片描述

  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 手写数字识别是深度学习在计算机视觉领域的一项经典任务,可以使用PyQt5和TensorFlow Keras框架来实现。这种任务可以通过卷积神经网络(CNN)来完成。 首先,需要下载一个手写数字图像数据集,例如MNIST数据集。然后,可以使用TensorFlow Keras框架来搭建一个简单的CNN模型,来对图像进行分类。这个CNN模型可以包含一些卷积层、池化层、扁平层和全连接层来实现对手写数字图像的分类。 接下来,使用PyQt5编写一个简单的GUI界面,提供用户手动输入数字图像的功能。GUI界面可以提供一个画布来让用户手动在上面绘制数字,然后对这个数字图像进行预测和分类。 具体实现时,可以结合PyQt5的信号和槽机制,将用户手动绘制的数字图像与CNN模型进行关联。当用户完成数字图像的绘制后,程序可以自动进行图像分类,并输出数字的识别结果。 总之,PyQt5和TensorFlow Keras框架提供了一个完整的工具链,用于实现手写数字识别的任务。开发者可以使用这些工具和技术来实现更加复杂的图像识别和分析任务。 ### 回答2: 手写数字识别是深度学习中的一个常见问题,而PyQt5则是一个流行的Python图形界面开发框架,可以将模型的结果以可视化的方式展示给用户。因此,使用PyQt5和TensorFlow-Keras搭建一个手写数字识别的应用程序是很有实际应用价值的。下面简单介绍一下实现步骤。 首先,我们需要一个手写数字数据集,可以使用MNIST数据集。通过使用TensorFlow-Keras的API,我们可以快速地构建一个CNN模型,并在训练数据上进行训练。 接下来,我们需要使用PyQt5构建GUI界面,这里可以使用QWidget框架。我们需要构建一个画布,允许用户手写数字,然后将用户手写的图像输入到CNN模型进行预测。 在这里,我们可以使用QPainter来绘图,它可以使用户绘制完整的数字。在预测数字时,我们需要对图像进行一些预处理,例如将其大小调整为网络需要的输入尺寸,并将其转换为灰度图像。 在模型训练完毕之后,我们可以将模型保存下来,然后在PyQt5应用程序中加载模型,并使用进行手写数字的识别。当用户在画布上完成手写数字绘制后,我们可以将其送入已经训练好的CNN模型,然后让程序显示识别结果。 通过这样的方式,我们可以使用PyQt5和TensorFlow-Keras开发手写数字识别应用程序,为用户提供更加便捷的数字识别方式。 ### 回答3: 手写数字识别是深度学习中的一个经典问题,利用人工神经网络或深度卷积神经网络可以达到很高的准确率。PyQt5是一个Python编写的GUI库,可以将深度学习算法应用到用户友好的界面中,同时TensorFlow-Keras是一个强大的深度学习框架,利用它可以快速搭建一个卷积神经网络。 首先,我们需要准备手写数字数据集,比如MNIST数据集。我们可以使用Keras自带的数据集接口进行加载。然后,通过PyQt5绘制一个界面,使得用户可以在界面上进行手写数字输入。手写数字数据可以通过鼠标或触控板进行输入,我们可以将手写数字截图并进行处理,可以使用 PIL 库或 OpenCV 进行图片处理,将图片大小调整为合适的大小。接着,我们需要将图片输入到卷积神经网络中进行预测。我们可以使用TensorFlow-Keras搭建一个卷积神经网络模型,并把刚刚处理好的图片输入到模型中,进行预测。最后,我们可以在界面上输出预测结果,告诉用户识别的数字是什么。 总之,借助PyQt5和TensorFlow-Keras的强大功能,我们可以轻松地设计一个手写数字识别的应用程序。但是需要注意的是,要精度高的数字识别需要使用比较深的卷积神经网络模型,并花费更多的时间来训练和调优模型
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风翼冰舟

额~~~CSDN还能打赏了

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值