手把手教你使用LabVIEW OpenCV DNN实现手写数字识别(含源码)
@
前言
今天和大家一起来看一下在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_OcHgS0-5zNXQVkEt5uw
提取码: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 机器学习
手把手教你使用LabVIEW OpenCV DNN实现手写数字识别(含源码)的更多相关文章
- OpenCV+TensorFlow图片手写数字识别(附源码)
初次接触TensorFlow,而手写数字训练识别是其最基本的入门教程,网上关于训练的教程很多,但是模型的测试大多都是官方提供的一些素材,能不能自己随便写一串数字让机器识别出来呢?纸上得来终觉浅,带着这 ...
- 手把手教你使用LabVIEW OpenCV dnn实现图像分类(含源码)
@ 目录 前言 一.什么是图像分类? 1.图像分类的概念 2.MobileNet简介 二.使用python实现图像分类(py_to_py_ssd_mobilenet.py) 1.获取预训练模型 2.使 ...
- 手把手教你使用LabVIEW OpenCV dnn实现物体识别(Object Detection)含源码
前言 今天和大家一起分享如何使用LabVIEW调用pb模型实现物体识别,本博客中使用的智能工具包可到主页置顶博客LabVIEW AI视觉工具包(非NI Vision)下载与安装教程中下载 一.物体识别 ...
- keras和tensorflow搭建DNN、CNN、RNN手写数字识别
MNIST手写数字集 MNIST是一个由美国由美国邮政系统开发的手写数字识别数据集.手写内容是0~9,一共有60000个图片样本,我们可以到MNIST官网免费下载,总共4个.gz后缀的压缩文件,该文件 ...
- 基于OpenCV的KNN算法实现手写数字识别
基于OpenCV的KNN算法实现手写数字识别 一.数据预处理 # 导入所需模块 import cv2 import numpy as np import matplotlib.pyplot as pl ...
- 基于opencv的手写数字识别(MFC,HOG,SVM)
参考了秋风细雨的文章:http://blog.csdn.net/candyforever/article/details/8564746 花了点时间编写出了程序,先看看效果吧. 识别效果大概都能正确. ...
- opencv实现KNN手写数字的识别
人工智能是当下很热门的话题,手写识别是一个典型的应用.为了进一步了解这个领域,我阅读了大量的论文,并借助opencv完成了对28x28的数字图片(预处理后的二值图像)的识别任务. 预处理一张图片: 首 ...
- Pytorch入门——手把手教你MNIST手写数字识别
MNIST手写数字识别教程 要开始带组内的小朋友了,特意出一个Pytorch教程来指导一下 [!] 这里是实战教程,默认读者已经学会了部分深度学习原理,若有不懂的地方可以先停下来查查资料 目录 MNI ...
- 【YOLOv5】手把手教你使用LabVIEW ONNX Runtime部署 TensorRT加速,实现YOLOv5实时物体识别(含源码)
前言 上一篇博客给大家介绍了LabVIEW开放神经网络交互工具包[ONNX],今天我们就一起来看一下如何使用LabVIEW开放神经网络交互工具包实现TensorRT加速YOLOv5. 以下是YOLOv ...
随机推荐
- 平衡树——splay 三
前文链接: 平衡树--splay 一 - yi_fan0305 - 博客园 (cnblogs.com) 平衡树--splay 二 - yi_fan0305 - 博客园 (cnblogs.com) 再补 ...
- Netty源码解读(二)-服务端源码讲解
简单Echo案例 注释版代码地址:netty 代码是netty的源码,我添加了自己理解的中文注释. 了解了Netty的线程模型和组件之后,我们先看看如何写一个简单的Echo案例,后续的源码讲解都基于此 ...
- 第十九天python3 json和messagepack
json的数据类型官网:https://www.json.org/ 值: 双引号内的字符串,数值,true和false,null,对象,数组:字符串: 双引号内的任意字符的组合,可以有专一字符:数值: ...
- cordova 发送ajax请求的相关配置
<access origin="*" /> <preference name="scheme" value="http" ...
- 绝对路径和相对路径和File类的构造方法
路径: 绝对路径:是一个完整的路径 以盼复(C:,D:)开始的路径 c:\a.txt C:\User\itcast\IdeaProjects\shungyuan\123.txt D:\demo\b.t ...
- TFRecord的Shuffle、划分和读取
对数据集的shuffle处理需要设置相应的buffer_size参数,相当于需要将相应数目的样本读入内存,且这部分内存会在训练过程中一直保持占用.完全的shuffle需要将整个数据集读入内存,这在大规 ...
- 为美多商城(Django2.0.4)添加基于websocket的实时通信,主动推送,聊天室及客服系统
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_67 websocket是个啥? webSocket是一种在单个TCP连接上进行全双工通信的协议 webSocket使得客户端和服务 ...
- JavaScript 里三个点 ...,可不是省略号啊···
摘要:Three dots ( - ) in JavaScript. 本文分享自华为云社区<JavaScript 里三个点 ... 的用法>,作者: Jerry Wang . Rest P ...
- BZOJ1977/LuoguP4180【模板】严格次小生成树[BJWC2010] (次小生成树)
这道题本身思维难度不大,但综合性强,细节多 在其上浪一个早上,你的 最小生成树 树链剖分 线段树 DEBUG能力... 都大幅提升 细节与思路都在代码里面了. 欢迎hack. #include< ...
- Python 工匠:一个关于模块的小故事
前言 模块(Module)是我们用来组织 Python 代码的基本单位.很多功能强大的复杂站点,都由成百上千个独立模块共同组成. 虽然模块有着不可替代的用处,但它有时也会给我们带来麻烦.比如,当你接手 ...