OpenMV(六)--STM32实现物体识别与手写数字识别

)

OpenMV(一)–基础介绍与硬件架构
OpenMV(二)–IDE安装与固件下载
OpenMV(三)–实时获取摄像头图片
OpenMV(四)–STM32实现特征检测
OpenMV(五)–STM32实现人脸识别

前言

本专栏基于以STM32H743为MCU的OpenMV-H7基板,结合OV7725卷帘快门摄像头进行相关机器视觉应用的开发。本篇博文主要介绍了怎么根据官方训练好的神经网络实现物体识别与手写数字识别的功能。

1. 物体识别

1.1 构造函数

OpenMV内置了很多已经训练好的CNN神经网络,本小节根据官方基于CIFAR10数据集训练的CNN网络,进行十种物体的分类。CIFAR10是一个拥有十种物体的数据集,这十类分别是“飞机”, “汽车”, “鸟”, “猫”, “鹿”, “狗”, “青蛙”, “马”, “船”, “卡车”。
相关的构造函数非常简单,就是加载模型与返回预测结果:

  • net = nn.load(path)
    从指定路径中加载.network的神经网络模型文件

    • path: 文件路径
  • net.forward(image, roi, softmax=False, dry_run=False)
    在图像上运行神经网络并返回结果的浮点值表,每个值得范围是0~1,数值越大匹配度越高。

    • image: 指定要分析的图像
    • roi: 指定图像区域(x, y, w, h)
    • softmax: 设置为True时,列表中所有的输出总和为1。否则列表中的任何输出都可以在0和1之间。
    • dry_run: 设置为True时,可以打印处正在执行的网络层而不是实际执行,这是为了debug用的
1.2 源码分析
"""
物体识别例程
分类模型:训练好的CNN
数据集:CIFAR10
"""
# 导入相应的库
import sensor, image, time, os, nn

# 初始化摄像头
sensor.reset()

# 设置相机图像的对比度
sensor.set_contrast(3)

# 设置采集到照片的大小:320*240
sensor.set_framesize(sensor.QVGA)

# 设置采集到照片的格式:彩色图像
sensor.set_pixformat(sensor.RGB565)

# 设置128*128窗口
sensor.set_windowing((128, 128))

# 设置延时等待摄像头配置完成
sensor.skip_frames(time = 2000)

# 关闭自动摄像头增益
sensor.set_auto_gain(False)
sensor.set_auto_exposure(False)

# 加载训练好的网络
# 加载之前我们需要将官方的网络“cifar10.network”拷贝到OpenMV-H7的内存中
net = nn.load('/cifar10.network')

# 十种标签
labels = ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']

while(True):
	# 拍摄图片并返回img
	img = sensor.snapshot()

	# 对于拍摄到的图片进行分类,返回浮点值列表,共有十个值,范围在0~1之间
	out = net.forward(img)

	# 挑选列表中的最大值
	max_id = out.index(max(out))

	# 将0-1之间的值扩大到百分制
	score = int(out[max_id]*100)

	# 60分以上算识别成功
	if(score < 60):
		score_str = "Nothing"
	else:
		score_str = "%s:%d%% "%(labels[max_idx], score)
		
	# 显示分类结果
	img.draw_string(0, 0, score_str, color = (255, 0, 0))

我们来看一下分类结果:
在这里插入图片描述
我在网页上找的一张青蛙的图片,可以看到预测为青蛙的概率为69%

2. 手写数字识别

OpenMV官方提供的一个手写数字识别例程是基于MINST手写数字数据集训练的,神经网络模型为Lenet模型,具体的实现可以参考我之前些的博客:动手学深度学习(PyTorch实现)(七)–LeNet模型

2.1 构造函数

构造函数与上一节物体识别的一样,也是加载模型与返回预测结果:

  • net = nn.load(path)
    从指定路径中加载.network的神经网络模型文件

    • path: 文件路径
  • net.forward(image, roi, softmax=False, dry_run=False)
    在图像上运行神经网络并返回结果的浮点值表,每个值得范围是0~1,数值越大匹配度越高。

    • image: 指定要分析的图像
    • roi: 指定图像区域(x, y, w, h)
    • softmax: 设置为True时,列表中所有的输出总和为1。否则列表中的任何输出都可以在0和1之间。
    • dry_run: 设置为True时,可以打印处正在执行的网络层而不是实际执行,这是为了debug用的
2.2 源码分析
"""
手写数字识别例程
分类模型:训练好的Lenet
数据集:MNIST
"""
# 导入相应的库
import sensor, image, time, os, nn

# 初始化摄像头
sensor.reset()

# 设置相机图像的对比度
sensor.set_contrast(3)

# 设置采集到照片的大小:320*240
sensor.set_framesize(sensor.QVGA)

# 设置采集到照片的格式:灰色图像
sensor.set_pixformat(sensor.GRAYSCALE)

# 设置128*128窗口
sensor.set_windowing((128, 128))

# 设置延时等待摄像头配置完成
sensor.skip_frames(time = 2000)

# 关闭自动摄像头增益
sensor.set_auto_gain(False)
sensor.set_auto_exposure(False)

# 加载Lenet网络模型
# 加载之前我们需要将官方的网络“lenet.network”拷贝到OpenMV-H7的内存中
net = nn.load('/lenet.network')

# 十个标签
labels = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

while(True):
	# 拍摄图片并返回img
	img = sensor.snapshot()

	# copy()表示创建一个图像副本储存在MicroPython堆中而不是帧缓冲区
	# 二值化是为了方便处理,阈值可以自己设定
	out = net.forward(img.copy().binary([(150, 255)], invert=True))

	# 挑选列表中的最大值
	max_id = out.index(max(out))

	# 将0-1之间的值扩大到百分制
	score = int(out[max_id]*100)

	# 70分以上算识别成功
	if(score < 70):
		score_str = "Nothing"
	else:
		score_str = "%s:%d%% "%(labels[max_idx], score)
		
	# 显示分类结果
	img.draw_string(0, 0, score_str, color = (255, 0, 0))

我们来看一下分类结果:
在这里插入图片描述
可以看到,网络成功识别了数字7。

评论好多朋友反馈需要lenet.network的文件,我现在上传到百度云供大家免费下载。

注:我已经将资源上传到百度云,提取密码为1234。

版权声明:本文为CSDN博主「爱吃骨头的猫、」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42580947/article/details/105923064

生成海报
点赞 0

爱吃骨头的猫、

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

STM32F4最小系统硬件设计

对于硬件工程师来讲,想要入门STM32相关的开发,我想除了深入阅读一下STM32的数据手册外,最实用且有效的方法就是自己实际做一个STM32的最小系统板了。本文将以一个小的STM32F427VG的电路最

STM32F2————配置时钟延迟不准的问题

STM32F2配置时钟问题 笔者在本科毕业设计使用STM32F207芯片,但是在配置时钟时出现了问题。 问题 我按照F1写代码的延时函数放在F2竟然不准了 换个办法 使用Systick时钟也是不准,原因是笔者代

为什么重写printf函数没有用?

以前在网上找了无数方法去重写printf函数,但发现都没效果,今天偶然发现重写printf函数可以了,原因是以前没有勾选微库(Use MicroLlB)! 这里