AI嵌入式K210项目(25)-手写数字识别

本文详细描述了如何在K210开发板上使用KPU进行手写和打印数字识别,包括实验准备、过程中的图像预处理和模型运行,以及如何通过IDE连接和调整阈值优化识别准确率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

本节课主要学习K210识别数字的功能,能识别手写的数字和打印的数字。


一、实验准备

请先将模型文件导入内存卡上,再将内存卡插入到K210开发板的内存卡插槽上,具体操作步骤请参考:

AI嵌入式K210项目(21)-AI模型文件导入至TF卡

本实验使用/sd/KPU/mnist/uint8_mnist_cnn_model.kmodel模型;

数字识别需要用的内存卡加载模型文件,所以需要提前将模型文件导入内存卡,再将内存卡插入K210开发板的内存卡卡槽里,如果无法读取到内存卡里的模型文件,则会报错。

二、实验过程

导入相关库,并初始化摄像头和LCD显示屏;

import sensor, image, time, lcd
from maix import KPU
import gc

lcd.init(freq=15000000)
sensor.reset()                      # Reset and initialize the sensor. It will
                                    # run automatically, call sensor.run(0) to stop
sensor.set_pixformat(sensor.RGB565) # Set pixel format to RGB565 (or GRAYSCALE)
sensor.set_framesize(sensor.QVGA)   # Set frame size to QVGA (320x240)
sensor.set_windowing((224, 224))
sensor.skip_frames(time = 1000)     # Wait for settings take effect.
clock = time.clock()                # Create a clock object to track the FPS.

初始化KPU相关的参数,kpu需要加载kmodel文件,本次实验需要的模型文件路径为:/sd/KPU/mnist/uint8_mnist_cnn_model.kmodel

kpu = KPU()
kpu.load_kmodel("/sd/KPU/mnist/uint8_mnist_cnn_model.kmodel")

新建while循环读取摄像头画面,然后复制一个112*112大小的画面,对像素进行取反等处理,再将图像传入KPU里进行计算,与模型文件做运算,最终得到最优识别结果和识别分数。

while True:
    gc.collect()
    img = sensor.snapshot()
    img_mnist1=img.to_grayscale(1)        #convert to gray
    img_mnist2=img_mnist1.resize(112,112)
    a=img_mnist2.invert()                 #invert picture as mnist need
    a=img_mnist2.strech_char(1)           #preprocessing pictures, eliminate dark corner
    a=img_mnist2.pix_to_ai()

    out = kpu.run_with_output(img_mnist2, getlist=True)
    max_mnist = max(out)
    index_mnist = out.index(max_mnist)
    #score = KPU.sigmoid(max_mnist)
    display_str = "num: %d" % index_mnist
    print(display_str)
    a=img.draw_string(4,3,display_str,color=(0,0,0),scale=2)
    lcd.display(img)

kpu.deinit()

更多API接口可以参考https://developer.canaan-creative.com/canmv/main/canmv/library/index.html
在这里插入图片描述

三、实验结果

将K210开发板通过TYPE-C数据线连接到电脑上,CanMV IDE点击连接按钮,连接完成后点击运行按钮,运行例程代码。也可以将代码作为main.py下载到K210开发板上运行。

等待系统初始化完成后,LCD显示摄像头画面,将摄像头拍摄自己手写的数字或打印的数字,屏幕左上角会显示当前识别到的数字。

在这里插入图片描述


总结

本实验使用K210的KPU和yolov2模型实现数字识别功能,使用IDE示例中代码,对实现的功能模块加以分析;可以通过调节阈值调整识别的准确率;

在当今数字化教育蓬勃发展的背景下,校园网络作为教学与科研的关键基础设施,其重要性日益凸显。本文旨在探讨小型校园网络的规划与设计,以满足网络实验教学的需求,为相关专业师生提供一个高效、稳定且功能完备的网络实验环境,助力教学活动顺利开展,提升学生的实践能力创新思维。 网络实验教学要求校园网络具备高度的灵活性与可扩展性。学生需在实验过程中模拟各种网络拓扑结构、配置不同网络设备参数,这就要求网络能够快速调整资源分配,适应多样化的实验场景。同时,为保证实验数据的准确性实验过程的稳定性,网络的高可靠性与低延迟特性不可或缺。此外,考虑到校园内多用户同时接入的场景,网络还需具备良好的并发处理能力,确保每位用户都能流畅地进行实验操作。 采用层次化结构构建小型校园网络,分为核心层、汇聚层与接入层。核心层选用高性能交换机,负责高速数据转发与关键路由决策,保障网络主干的稳定运行;汇聚层连接不同教学区域,实现数据的汇聚与初步处理,通过划分虚拟局域网(VLAN)对不同专业或班级的实验流量进行隔离,避免相互干扰;接入层则直接连接学生终端设备,提供充足的接入端口,满足大量用户同时接入的需求,并通过端口安全策略限制非法设备接入,保障网络安全。 在设备选型上,核心层交换机需具备高吞吐量、低延迟以及丰富的路由协议支持能力,以满足复杂网络流量的转发需求;汇聚层交换机则注重VLAN划分与管理功能,以及对链路聚合的支持,提升网络的可靠性带宽利用率;接入层交换机则需具备高密度端口、灵活的端口配置以及完善的用户认证功能。配置方面,通过静态路由与动态路由协议相结合的方式,确保网络路径的最优选择;在汇聚层与接入层设备上启用VLAN Trunk技术,实现不同VLAN间的数据交换;同时,利用网络管理软件对设备进行集中监控与管理,实时掌握网络运行状态,及时发现并解决潜在问题。 网络安全是校园网络规划的关键环节。在接入层设置严
管理后台HTML页面是Web开发中一种常见的实践,主要用于构建企业或组织内部的管理界面,具备数据监控、用户管理、内容编辑等功能。本文将探讨一套美观易用的二级菜单目录设计,帮助开发者创建高效且直观的后台管理系统。 HTML5:作为超文本标记语言的最新版本,HTML5增强了网页的互动性可访问性,提供了更多语义元素,如<header>、<nav>、<section>、<article>等,有助于清晰地定义网页结构。在管理后台中,HTML5可用于构建页面布局,划分功能区域,并集成多媒体内容,如图像、音频视频。 界面设计:良好的管理后台界面应具备清晰的导航、一致的布局易于理解的图标。二级菜单目录设计能够有效组织信息,主菜单涵盖大类功能,次级菜单则提供更具体的操作选项,通过展开折叠实现层次感,降低用户认知负担。 CSS:CSS是用于控制网页外观布局的语言,可对HTML元素进行样式设置,包括颜色、字体、布局等。在管理后台中,CSS能够实现响应式设计,使页面在不同设备上具有良好的显示效果。借助CSS预处理器(如Sass或Less),可以编写更高效、模块化的样式代码,便于维护。 文件结构: guanli.html:可能是管理页面的主入口,包含后台的主要功能布局。 xitong.html:可能是系统设置或配置页面,用于管理员调整系统参数。 denglu.html:登录页面,通常包含用户名密码输入框、登录按钮,以及注册或忘记密码的链接。 image文件夹:存放页面使用的图片资源,如图标、背景图等。 css文件夹:包含后台系统的样式文件,如全局样式表style.css或按模块划分的样式文件。 响应式设计:在移动设备普及的背景下,管理后台需要支持多种屏幕尺寸。通过媒体查询(Media Queries)流式布局(Fluid Grids),可以确保后台在桌面、平板手机上都能良好展示。
### 动态规划求解最短路径问题 动态规划是一种通过分解子问题来解决问题的方法,通常用于优化问题。对于最短路径问题,可以利用动态规划的思想构建状态转移方程并逐步计算最优解[^4]。 以下是基于网格图的一个简单例子,展示如何使用动态规划算法找到起点到终点的最短路径: #### 代码实现 ```python import numpy as np def dynamic_programming_shortest_path(grid, start, goal): rows, cols = grid.shape # 初始化价值函数矩阵 value_matrix = np.full((rows, cols), float('inf')) value_matrix[start] = 0 # 定义动作集合(上下左右) actions = [(-1, 0), (1, 0), (0, -1), (0, 1)] updated = True while updated: updated = False for r in range(rows): for c in range(cols): if grid[r][c] == 1: # 障碍物跳过 continue current_value = value_matrix[r][c] for dr, dc in actions: nr, nc = r + dr, c + dc if 0 <= nr < rows and 0 <= nc < cols and grid[nr][nc] != 1: neighbor_value = value_matrix[nr][nc] + 1 if neighbor_value < current_value: value_matrix[r][c] = neighbor_value updated = True return value_matrix[goal] # 示例输入 grid = np.array([ [0, 0, 0, 0], [0, 1, 1, 0], [0, 0, 0, 0], [0, 0, 1, 0] ]) start = (0, 0) goal = (3, 3) shortest_distance = dynamic_programming_shortest_path(grid, start, goal) print(f"The shortest distance from {start} to {goal} is {shortest_distance}.") ``` #### 解释 上述代码定义了一个 `dynamic_programming_shortest_path` 函数,该函数接受一个二维数组作为地图表示,其中 `0` 表示可通过区域,而 `1` 则代表障碍物。它还接收起始位置目标位置作为参数。 - **初始化**:创建一个与地图大小相同的值矩阵 (`value_matrix`) 并将其初始设为无穷大,除了起始点外。 - **迭代更新**:遍历整个地图中的每一个单元格,并尝试从其邻居节点获取更优的距离值。如果发现新的距离小于当前记录,则更新此单元格的价值。 - **终止条件**:当不再有任何单元格被更新时停止循环。 最终返回的目标点处存储的就是从起点到达它的最小步数。 --- ### 关键概念补充 动态规划的核心在于建立合适的状态转移关系 \(Q\) 折扣因子 \(\gamma\)。在这个特定场景下,我们简化了模型假设——即每一步移动成本固定为单位长度,因此无需显式引入奖励机制或未来收益折现的概念。 此外,在实际应用中可能还需要考虑更多复杂因素,比如不同地形的成本差异、多维空间下的路径搜索等问题。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

叶与花语

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值