关于机器学习:手把手教你使用LabVIEW-OpenCV-DNN实现手写数字识别含源码

51次阅读

共计 5294 个字符,预计需要花费 14 分钟才能阅读完成。

前言

明天和大家一起来看一下在 LabVIEW 中如何应用 OpenCV DNN 模块实现手写数字辨认

一、OpenCV DNN 模块

1.OpenCV DNN 简介

OpenCV 中的 DNN(Deep Neural Network module)模块是专门用来实现深度神经网络相干性能的模块。OpenCV 本人并不能训练神经网络模型,然而它能够载入别的深度学习框架(例如 TensorFlow、pytorch、Caffe 等等)训练好的模型,而后应用该模型做 inference(预测)。而且 OpenCV 在载入模型时会应用本人的 DNN 模块对模型重写,使得模型的运行效率更高。所以如果你想在 OpenCV 我的项目中融入深度学习模型,能够先用本人相熟的深度学习框架训练好,而后应用 OpenCV 的 DNN 模块载入。

2.LabVIEW 中 DNN 模块函数

DNN 模块位于程序框图 - 函数选板 -Addons-VIRobotics-opencv_yiku 中,如下图所示:

Net 选版中的函数与 python 中的函数比照如下:

二、TensorFlow pb 文件的生成和调用

1.TensorFlow2 Keras 模型(mnist)

注:本范例必须应用 tensorflow 2.x 版本

如下图所示所示为数据集以及 LabVIEW 与 Python 推理和训练代码,相干源码可在链接中下载。

2. 应用 Keras 搭建 cnn 训练 mnist(train.py),训练局部源码如下:

train_images = train_images.reshape(train_images.shape[0], 28, 28, 1)
test_images = test_images.reshape(test_images.shape[0], 28, 28, 1)
train_images = train_images / 255.0
test_images = test_images / 255.0

train_labels = to_categorical(train_labels, 10)
test_labels = to_categorical(test_labels, 10)

model = Sequential()  #创立一个 Sequential 模型
# 第一层卷积:6 个卷积核, 大小:5*5, 激活函数:relu
model.add(Conv2D(6, kernel_size=(5, 5), activation='relu', input_shape=(28, 28, 1)))
# 第二层池化:最大池化
model.add(MaxPooling2D(pool_size=(2, 2)))
# 第三层卷积:16 个卷积核, 大小: 5*5, 激活函数:relu
model.add(Conv2D(16, kernel_size=(5, 5), activation='relu'))
# 第四层池化:最大池化
model.add(MaxPooling2D(pool_size=(2, 2)))
# 进行扁平化
model.add(Flatten())
# 全连贯层一:输入节点为 120 个
model.add(Dense(120, activation='relu'))
# 全连贯层二:输入节点为 84 个
model.add(Dense(84, activation='relu'))
# 输入层:用 softmax 激活函数计算分类的概率
model.add(Dense(10, activation='softmax'))  # 最初是 10 个数字,10 个分类
model.compile(optimizer=keras.optimizers.Adam(), loss=keras.metrics.categorical_crossentropy, metrics=['accuracy'])
model.fit(train_images, train_labels, batch_size=32, epochs=2, verbose=1)
loss, accuracy = model.evaluate(test_images, test_labels,verbose=0)
#model.save("A:\\code\\tensorflow\\course\\1_fashion_mnist\\mymodel")
print('损失:', loss)
print('准确率:', accuracy)

3. 训练后果保留成解冻模型(pb 文件)(train.py),训练后果保留为解冻模型的源码如下:

注:无需装置 tensorflow 也能够运行

# 以下是生成 pb 的代码。留神:用 model.save 生成的 pb 文件不能被 opencv 调用
# 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=datapath+r"\frozen_models",
                  name="frozen_graph.pb",
                  as_text=False)

运行之后可生成如下图所示的 pb 模型:

4.python opencv 调用解冻模型(cvcallpb.py)

import time
model_path = 'frozen_models\\frozen_graph.pb'
config_path = ''
#net = cv.dnn.readNetFromTensorflow(model_path, config_path)
import gzip
import os
import numpy as np
datapath=os.path.split(os.path.realpath(__file__))[0]
import cv2

def get_data():
    train_image = datapath+r"\train-images-idx3-ubyte.gz"
    test_image = datapath+r"\t10k-images-idx3-ubyte.gz"
    train_label = datapath+r"\train-labels-idx1-ubyte.gz"
    test_label = datapath+r"\t10k-labels-idx1-ubyte.gz" 
    paths = [train_label, train_image, test_label,test_image]

    with gzip.open(paths[0], 'rb') as lbpath:
        y_train = np.frombuffer(lbpath.read(), np.uint8, offset=8)

    with gzip.open(paths[1], 'rb') as imgpath:
        x_train = np.frombuffer(imgpath.read(), np.uint8, offset=16).reshape(len(y_train), 28, 28)

    with gzip.open(paths[2], 'rb') as lbpath:
        y_test = np.frombuffer(lbpath.read(), np.uint8, offset=8)

    with gzip.open(paths[3], 'rb') as imgpath:
        x_test = np.frombuffer(imgpath.read(), np.uint8, offset=16).reshape(len(y_test), 28, 28)

    return (x_train, y_train), (x_test, y_test)

(train_images, train_labels), (test_images, test_labels)=get_data()

def to_categorical(labels,number):
    a=np.zeros((labels.shape[0],number),dtype=labels.dtype)
    count=0
    for i in labels:
        a[count][i]=1
        count+=1
    return a
        
    
print(train_images.shape)
train_images = train_images.reshape(train_images.shape[0], 28, 28, 1)
test_images = test_images.reshape(test_images.shape[0], 28, 28, 1)
train_images = train_images / 255.0
test_images = test_images / 255.0

train_labels = to_categorical(train_labels, 10)
test_labels = to_categorical(test_labels, 10)

# Load a model imported from Tensorflow
net = cv2.dnn.readNetFromTensorflow(model_path, config_path)
 

a=test_images[0].reshape(1,1,28,28)

net.setInput(a)
 
# Runs a forward pass to compute the net output
networkOutput = net.forward()
print(networkOutput)

三、LabVIEW OpenCV DNN 实现手写数字辨认

1、实现手写数字辨认并实现 MNIST 数据简略的可视化(mnist_loadpb_simple.vi)

(1)读取 mnist 测试数据集二进制文件

(2)载入 pb 神经网络模型

(3)从二进制文件里读取某一幅图并显示进去

(4)blobImage,并把 blob 的后果用强度图显示进去

(5)把 blob 的后果送入神经网络推理,获取后果

(6)总体源码及成果如下:

2、实现手写数字辨认并实现 MNIST 数据高级的可视化(mnist_loadpb.vi)

与简略的可视化区别仅仅有以下几项:

(1)多了 getLayerName 读出所有的网络层名字

(2)应用了多通道的 forward(输出为名称数组)
(3)将前六层(两次卷积——relu——池化用强度图显示进去)

总体源码如下:

运行成果如下:

四、源码下载

链接:https://pan.baidu.com/s/1NU_O…
提取码:8888

总结

Q:我该应用 tensorflow 1 还是 tensorflow 2?
A:目前看 tensorflow 1 与 opencv dnn 模块、树莓派等开源硬件兼容性更好,且视觉对象检测的模型临时更丰盛。Tesnroflow 2 的 Keras 函数训练神经网络十分不便,但对第三方软硬件兼容性还未做到最佳。预计随着后续版本的推出,TF2 会逐步成为支流。有些新的神经网络算子,缓缓地就不反对 TF1 了。同时 opencv、开源硬件也会不断更新适应最新版本的 TF。
另外,训练图像神经网络不必局限于 TF,pytorch 也是很好的抉择。目前咱们公司已逐步从 TF 转向 pytorch 了。

Q:LabVIEW 的 opencv 及其 dnn 模块反对哪些硬件和神经网络模型?
A: 提供多种框架模型导入模块 :包含 tensorflow、pytorch、darknet、openvino 等多个平台的深度学习模型,官网的物体分类、物体检测、语义宰割、实例宰割都反对(后续会讲到),第三方的人脸识别、文字辨认也曾经通过验证。大量的高精度实例宰割模型临时不反对,后续咱们会给大家介绍 ONNX 工具包,反对市面上简直所有的模型。反对的硬件方面,反对 Nvidia GPU、Intel、TPU、NPU 多种硬件加速。

更多对于 LabVIEW 与人工智能技术,可增加技术交换群进一步探讨。qq 群号:705637299,请备注暗号:LabVIEW 机器学习

正文完
 0