使用 LabVIEW调用LeNet快速搭建手写数字识别系统(内含源码)

news2024/11/26 19:52:40

‍‍🏡博客主页: virobotics的CSDN博客:LabVIEW深度学习、人工智能博主
🎄所属专栏:『LabVIEW深度学习实战』
🍻上期文章: 【图像分类】基于OpenVINO实现PyTorch ResNet50图像分类
📰如觉得博主文章写的不错或对你有所帮助的话,还望大家多多支持呀! 欢迎大家✌关注、👍点赞、✌收藏、👍订阅专栏

文章目录

  • 前言
  • 一、LeNet简介
  • 二、环境搭建
    • 2.1 部署本项目时所用环境
    • 2.2 LabVIEW工具包下载及安装网址
  • 三、LabVIEW调用LeNet搭建手写数字识别系统
    • 3.1 LeNet的手写数字识别模型
    • 3.2 查看模型输出输出
    • 3.3 实现手写数字识别(mnist_pytorch_onnx.vi)
  • 四、项目源码
  • 总结

前言

之前给大家介绍过使用仪酷AI视觉工具包的DNN模块实现手写数字识别,今天给大家介绍一下在LabVIEW使用ONNX工具包部署LeNet实现手写数字识别


一、LeNet简介

LeNet-5是一种经典的卷积神经网络(Convolutional Neural Network,CNN),一般LeNet即指代LeNet-5,由Yann LeCun等人于1998年提出。LeNet主要用于手写数字识别,是深度学习领域的重要里程碑,也是现代CNN架构的基础。

LeNet的架构包括了两个卷积层,两个池化层和三个全连接层。其中,卷积层和池化层用于提取图像的特征,全连接层用于输出分类结果。LeNet的架构采用了加速学习的方法,即卷积和池化层的交替使用,可以减少参数数量,并提高特征提取的效率,LeNet网络模型框架如下图所示:

在这里插入图片描述

LeNet的输入为32x32的灰度图像,因为在当时的计算能力下,处理更大的图像会很困难。第一个卷积层包含了6个5x5的卷积核,每个卷积核对应了一个输出特征图。第一个池化层是2x2的最大池化,用于减小特征图的大小。第二个卷积层包含了16个5x5的卷积核,同样每个卷积核对应了一个输出特征图。第二个池化层是2x2的最大池化。最后是三个全连接层,用于对特征进行分类。

在这里插入图片描述

LeNet在MNIST手写数字识别数据集上表现出色,达到了当时最佳的分类准确率。虽然LeNet的架构相对简单,但它奠定了卷积神经网络在计算机视觉领域的地位,并为后来的深度学习研究提供了重要的基础。

二、环境搭建

2.1 部署本项目时所用环境

  • 操作系统:Windows10
  • python:3.6及以上
  • LabVIEW:2018及以上 64位版本
  • AI视觉工具包:techforce_lib_opencv_cpu-1.0.0.98.vip

2.2 LabVIEW工具包下载及安装网址

  • https://www.virobotics.net/
  • AI视觉工具包下载与安装参考:
    https://blog.csdn.net/virobotics/article/details/123656523
  • AI视觉工具包介绍:
    https://blog.csdn.net/virobotics/article/details/123522165
  • onnx工具包下载与安装参考:
    https://blog.csdn.net/virobotics/article/details/124998746

三、LabVIEW调用LeNet搭建手写数字识别系统

3.1 LeNet的手写数字识别模型

我们已经给大家准备了训练好的手写数字识别模型,可以直接使用~
在这里插入图片描述

如果大家想要重新训练手写数字模型并生成该模型的onnx格式,则可以参考以下代码:

import torch
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

from torchvision import datasets
from torchvision.transforms import ToTensor


#下载并导入训练和测试数据集,并进行预处理
#https://blog.csdn.net/qimo601/article/details/112526722
train_data = datasets.MNIST(
    root = 'data',
    train = True,                         
    transform = ToTensor(), 
    download = True,            
)
test_data = datasets.MNIST(
    root = 'data', 
    train = False, 
    transform = ToTensor()
)
print(train_data)
print(test_data)
print(train_data.data.size())


#import matplotlib.pyplot as plt
#plt.imshow(train_data.data[0], cmap='gray')
#plt.title('%i' % train_data.targets[0])
#plt.show()
#把数据集分为训练集和测试集
from torch.utils.data import DataLoader
loaders = {
    'train' : torch.utils.data.DataLoader(train_data, 
                                          batch_size=512, 
                                          shuffle=True, 
                                          num_workers=0),
    
    'test'  : torch.utils.data.DataLoader(test_data, 
                                          batch_size=512, 
                                          shuffle=True, 
                                          num_workers=0),
}
loaders

import torch.nn as nn
#定义网络
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        #定义第一层卷积的Sequential函数(包含卷积、激活函数、池化)
        self.conv1 = nn.Sequential(         
            nn.Conv2d(
                in_channels=1,              
                out_channels=16,            
                kernel_size=5,              
                stride=1,                   
                padding=2,                  
            ),                              
            nn.ReLU(),                      
            nn.MaxPool2d(kernel_size=2),    
        )
        #定义第二层卷积的Sequential函数
        self.conv2 = nn.Sequential(         
            nn.Conv2d(16, 32, 5, 1, 2),     
            nn.ReLU(),                      
            nn.MaxPool2d(2),                
        )
        # fully connected layer, output 10 classes(全连接层)
        self.out = nn.Linear(32 * 7 * 7, 10)
    def forward(self, x):
        #调用第一层卷积函数
        x = self.conv1(x)
        #调用第二层卷积函数
        x = self.conv2(x)
        # flatten the output of conv2 to (batch_size, 32 * 7 * 7)
        x = x.view(x.size(0), -1)
        #调用全连接层
        output = self.out(x)
        return output, x    # return x for visualization
cnn = CNN().to(device)
#定义网络训练时用的损失函数
loss_func = nn.CrossEntropyLoss()
from torch import optim
optimizer = optim.Adam(cnn.parameters(), lr = 0.01)

from torch.autograd import Variable
num_epochs = 10
def train(num_epochs, cnn, loaders):
    
    cnn.train()
        
    # Train the model
    total_step = len(loaders['train'])
        
    for epoch in range(num_epochs):
        for i, (images, labels) in enumerate(loaders['train']):
            images, labels = images.to(device),labels.to(device)
            # gives batch data, normalize x when iterate train_loader
            b_x = Variable(images)   # batch x
            b_y = Variable(labels)   # batch y
            output = cnn(b_x)[0]               
            loss = loss_func(output, b_y)
            
            # clear gradients for this training step   
            optimizer.zero_grad()           
            
            # backpropagation, compute gradients 
            loss.backward()    
            # apply gradients             
            optimizer.step()                
            
            if (i+1) % 100 == 0:
                print ('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}' 
                       .format(epoch + 1, num_epochs, i + 1, total_step, loss.item()))
            else:
                pass
        
        pass
    pass
train(num_epochs, cnn, loaders)

def test():
    # Test the model
    cnn.eval()
    with torch.no_grad():
        correct = 0
        total = 0
        for images, labels in loaders['test']:
            images, labels = images.to(device),labels.to(device)
            test_output, last_layer = cnn(images)
            pred_y = torch.max(test_output, 1)[1].data.squeeze()
            accuracy = (pred_y == labels).sum().item() / float(labels.size(0))
        print('Test Accuracy of the model on the 10000 test images: %.2f' % accuracy)
test()

sample = next(iter(loaders['test']))
imgs, lbls = sample
actual_number = lbls[:10].numpy()
x=imgs[:10].to(device)
test_output, last_layer = cnn(x)
pred_y = torch.max(test_output, 1)[1].data.cpu().numpy().squeeze()
print(f'Prediction number: {pred_y}')
print(f'Actual number: {actual_number}')

# 转onnx代码
#第一步:先要定义一个或多个随机的tensor,作为onnx文件的输入口
#该tensor的大小要和pytorch模型的输入大小一致(mnist为1*1*28*28)
#第一个1:batchsize,代表输入的图片为1张,也可以为多张
#第二个1:图片的通道数为1,即为灰度图
#28*28:图片的高度和宽度
a=torch.rand(1, 1, 28, 28)
#第二步:需要讲模型回落到cpu上
cnn2=cnn.to("cpu")
#第三步:生成onnx模型
torch.onnx.export(
        cnn2,
        a,
        "model.onnx",
        input_names=["input"],verbose=False,opset_version=11
    )

3.2 查看模型输出输出

打开http://netron.app,载入本地onnx模型,我们可以看到模型的输入输出

在这里插入图片描述
我们查看模型的输入shape,是因为推理过程我们需要输入shape,不过我么也可以使用GetInputInfo.vi来直接获取模型输入的shape
在这里插入图片描述

3.3 实现手写数字识别(mnist_pytorch_onnx.vi)

  1. 读取onnx模型并选择推理加速引擎,使用属性节点获取输入输出名字

在这里插入图片描述

  1. 获取取神经网络模型输入输出shape备用
    在这里插入图片描述
  2. 从二进制文件里读取某一幅图并显示出来
    在这里插入图片描述
    在这里插入图片描述

get_one_image.vi主要是用来获取一张图片
在这里插入图片描述
4. 对进入神经网络的图像进行预处理
在这里插入图片描述
5. 将处理后的结果送入神经网络进行推理,并获取结果
在这里插入图片描述

  1. 最终实现完整程序如下:
    在这里插入图片描述

  2. 运行结果如下,可以修改index,来识别其他数字。
    在这里插入图片描述

四、项目源码

码字不易,如需LabVIEW源码,请一键三连并订阅本专栏后评论区留下邮箱


总结

以上就是今天要给大家分享的内容,希望对大家有用。我们下篇文章见~

创作不易,如果文章对你有帮助,欢迎✌关注、👍点赞、✌收藏、👍订阅专栏

推荐阅读

LabVIEW图形化的AI视觉开发平台(非NI Vision),大幅降低人工智能开发门槛
LabVIEW图形化的AI视觉开发平台(非NI Vision)VI简介
LabVIEW AI视觉工具包OpenCV Mat基本用法和属性
手把手教你使用LabVIEW人工智能视觉工具包快速实现图像读取与采集

👇技术交流 · 一起学习 · 咨询分享,请联系👇

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/627350.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PyCaret解决二分类任务教程示例

PyCaret是一个Python中的开源、低代码机器学习库,可以自动化机器学习工作流。它是一个端到端的机器学习和模型管理工具,可以成倍地加快实验周期,提高工作效率。 与其他开源机器学习库相比,PyCaret是一个替代的低代码库&#xff0c…

多分类问题与卷积模型的优化

文章目录 1. 创建自定义Dataset类2. 基础卷积模型3. Dropout抑制过拟合4. 批标准化5. 学习速率衰减6. 最终优化整合代码 首先导入用到的库: import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim import numpy as np import matp…

文章写作的诀窍:10个技巧让你的文章升华

首先要找到自己的写作声音和确定文章的中心思想,其次要使用简单明了和描述性的语言,增加细节并结构化文章: 找到你的写作声音:找到适合自己的写作风格和声音,这有助于让读者更容易地理解和记住你的文章。确定文章的中心…

QxRibbon 知:搭建 CMake 构建环境

文章目录 前言安装 cmake问题处理qtcreator 检测 CMake 异常 参考资料 前言 高版本的 QtCreator 已经集成了 cmake 工具,并支持以 CMakelists.txt 文件作为工程开发项目。 https://www.qt.io/blog/2019/07/30/update-on-cmake-project-support-in-qt-creator 安装…

NodeLocal DNS介绍及部署应用

目录 一、NodeLocal DNS是什么? 二、为什么使用NodeLocal DNS? 三、工作原理 四、安装NodeLocal DNS 五、在应用中使用NodeLocal DNSCache 六、验证 一、NodeLocal DNS是什么? NodeLocal DNSCache 通过在集群节点上运行一个 DaemonSet …

qrcodejs2生成二维码,通过canvas绘制带边框+中间logo的二维码图片,下载二维码

文章目录 一、通过qrcodejs2生成一个二维码二、点击【下载配置服务器二维码】来下载二维码1、通过canvas去绘制 边框二维码logo(1)为canvas增加绘制圆角矩形的方法(canvas本身不提供)(2)通过canvas绘制 圆角…

饮酒过多和腌制食品是导致中风的最大导火索

中风是一种常见的疾病,它的发生和饮食习惯有很大关系。近年来,我国中风病患人数和病发率都呈现出了不同程度的上升趋势,这给我们的健康带来了很大的威胁。下面我们可以通过数据可视化大屏来了解一下饮食健康与预防中风有哪些影响,…

ESP32-S3 边缘人工智能|使用加速度计数据和 ESP-DL 识别人体活动

边缘计算是一种分布式计算范例,指在更靠近设备的地方进行数据存储和计算。边缘人工智能(边缘 AI)是边缘计算中一项振奋人心的成果,可以令传统技术更高效地运行,在降低功耗的同时又有更好的性能。训练好的神经网络可以在…

通信算法之167: (低空无人机)机载视频通信传输系统基带算法设计

一.物理层基带仿真 通信系统的链路级仿真主要可以分成5个部分。 1.系统参数 2.发送机算法 3.信道模型 4.接收机算法 5.统计性能 其中主要组成部分很明显是中间三部分,即发送,信道,接收。但系统参数和统计性能这两部分的适当设计会大大…

linux基础命令系列之10 分钟掌握 ln 命令:创建链接,软链接,硬链接,递归链接,打印详细输出

文章目录 前言一. ln命令介绍二. 语法格式及常用选项三. 参考案例3.1 ln命令创建硬链接3.1.1 创建硬链接3.1.2 源文件被删除,不影响链接文件的正常使用3.1.3 硬链接不能跨分区创建 3.2 为什么目录刚刚创建的时候,链接数为23.3 ln -s 软链接的创建3.3.1 l…

【漏洞修复】node-exporter被检测出来pprof调试信息泄露漏洞

node-exporter被检测出来pprof调试信息泄露漏洞 说在前面解决方法结语 说在前面 惯例开篇吐槽,有些二五仔习惯搞点自研的安全扫描工具,然后加点DIY元素,他也不管扫的准不准,就要给你报个高中危的漏洞,然后就要去修复&…

C++元模板技术与traits解析:根据类型的特性来调整代码的行为,解决没有重载运算符的情况

C元模板技术与traits解析 第一章、C元模板技术简介 (C Meta-template Introduction)1.1 元模板的定义与概念 (Definition and Concepts)1.2 元模板技术的发展历程 (Evolution of Meta-templates)1.3 元模板应用场景举例 (Examples of Meta-template Applications) 第二章、 tra…

[数据结构初阶]顺序表

目录 静态顺序表 动态顺序表 初始化 销毁 尾插 ​编辑 尾删 头插 头删 Insert erase find查找 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。 静态顺序表 定义结构体&#xff1…

Talk | 北卡罗来纳州立大学唐圣坤浙江大学张磊: 数据为中心的高效视觉语言学习—动态退出与数据蒸馏

本期为TechBeat人工智能社区第504期线上Talk! 北京时间6月8日(周四)20:00,北卡罗来纳州立大学在读博士生—唐圣坤与浙江大学硕士生—张磊的Talk将准时在TechBeat人工智能社区开播! 他们与大家分享的主题是: “数据为中心的高效视觉语言学习…

基于jsp+mysql+mybatis的SpringBoot美容院后台管理系统

运行环境: 最好是java jdk 1.8,我在这个平台上运行的。其他版本理论上也可以。 IDE环境: Eclipse,Myeclipse,IDEA或者Spring Tool Suite都可以,如果编译器的版本太低,需要升级下编译器,不要弄太低的版本 tomcat服务器环…

【嵌入式环境下linux内核及驱动学习笔记-(15)linux总线、设备、驱动模型之I2C总线】

目录 1、 I2C总线机制1.1 导入1.2 时序1.3 地址格式 2、华清fs4412上I2C的实现2.1 寄存器2.2 寄存器位具体含义2.3 fs4412上针对具本设备的I2C工作逻辑2.3.1 主机读写工作流程**2.3.1.1 主机发送时序及操作流程2.3.1.2 主机接收的时序及流程 2.3.2 从机读写工作流程 3、LINUX内…

Redis-认识NoSQl和Redis常见的通用命令

1. 认识NoSQL 非关系型数据库 NoSQL是指一类非关系型数据库,它们采用的数据模型不同于传统的关系模型,它通常使用键值对、文档、图形等非传统的数据结构进行数据存储,不遵循预定义的模式和模型。NoSQL数据库通常分布式、高可扩展性&#xff0…

【项目一】GCC(gcc,g++)、静态库、动态库、MakeFile、GDB调试

GCC、静态库 1.2 GCC(1)gcc(1)常用命令(2) C程序编译过程(3)GCC工作流程 1.3 GCC(2)g1.3静态库的制作1.5静态库的使用1.6动态库的制作1.7动态库加载失败的原因1.8解决动态库加载失败…

秋招必看,Java后端高频面试题1000题、拒绝简单背诵,深入浅出近30个技术栈

Java 面试随着时间的改变而改变。在过去的日子里,当你知道 String 和 StringBuilder 的区别就能让你直接进入第二轮面试,但是现在问题变得越来越高级,面试官问的问题也更深入。 在我初入职场的时候,类似于 Vector 与 Array 的区别…

面试专题:计算机网络常见面试点总结

socket、tcp、udp、http 的认识及区别 socket、tcp、udp、http 的认识及区别​ 一、先来一个讲TCP、UDP和HTTP关系的 1、TCP/IP是个协议组,可分为三个层次:网络层、传输层和应用层。 在网络层有IP协议、ICMP协议、ARP协议、RARP协议和BOOTP协议。 在传…