这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【树莓派Zero2W】网页数字识别

共1条 1/1 1 跳转至

【树莓派Zero2W】网页数字识别

工程师
2025-12-15 17:40:47     打赏

【树莓派Zero 2W】网页数字识别

本文介绍了树莓派 Zero 2W 实现 Web 手写数字识别的项目设计,包括环境搭建、MNIST 数据集、 ONNX 模型、流程图、工程代码、网页设计及效果演示等。

项目介绍

  • 准备工作:包括硬件连接、OpenCV 库、mnist 数据集、模型下载、软件包的安装部署等;

  • 网页手写数字识别:设计 Flask Web 网页端和手写面板,开发板接收网页传输的手写数据,调用预训练 onnx 模型完成板端推理,回传识别结果至 Web 端。

MNIST

Modified National Institute of Standards and Technology (MNIST) 由美国国家标准与技术研究所(NIST)收集并标准化,包含0到9的手写数字图片。训练集包含60,000张图片,测试集包含10,000张图片,每张图片为28x28像素的灰度图像,像素值范围为0到255,表示从黑到白的灰度。

mnist.jpg

图片经过中心化和规格化处理,数字位于图像的中心位置。数据以特殊的二进制格式存储,训练集和测试集分别包含图像文件和标签文件,标签以one-hot编码形式表示。

详见:yann.lecun.com .

硬件连接

这里采用 SSH 远程登录操作,则仅需连接电源供电即可;

hardware_connect.jpg

环境搭建

  • 终端执行指令 sudo apt install python3-opencv 安装 OpenCV 库;

  • 安装解析 ONNX 模型所需的 onnxruntime 库

 sudo apt install python3-pip
 sudo pip3 install onnxruntime --break-system-packages

模型下载

下载模型文件 ./model/mnist-12.onnx ;

wget https://github.com/onnx/models/blob/main/validated/vision/classification/mnist/model/mnist-12.onnx

该模型体积仅 26KB ,非常适合部署于轻量化设备。

流程图

flowchart_mnist_web.png

工程代码

终端执行 touch mnist_web.py 新建程序文件,并添加如下代码

 #!/usr/bin/env python3
 import cv2, numpy as np, onnxruntime as ort, base64, io, time
 from flask import Flask, render_template_string, request, jsonify
 
 app = Flask(__name__)
 MODEL = './model/mnist-12.onnx'
 sess = ort.InferenceSession(MODEL, providers=['CPUExecutionProvider'])
 in_name  = sess.get_inputs()[0].name   # Input3
 out_name = sess.get_outputs()[0].name  # Plus214_Output_0
 
 def softmax(x):
     """返回概率数组"""
     x = x - np.max(x)          # 防溢出
     exp_x = np.exp(x)
     return exp_x / np.sum(exp_x)
 
 def decode_canvas(data_url):
     header, encoded = data_url.split(',', 1)
     img = cv2.imdecode(np.frombuffer(base64.b64decode(encoded), np.uint8),
                        cv2.IMREAD_GRAYSCALE)
     return img
 
 @app.route('/')
 def index():
     with open('./web/index.html') as f:
         return render_template_string(f.read())
 
 @app.route('/predict', methods=['POST'])
 def predict():
     t0 = time.time()
     img = decode_canvas(request.json['image'])
     img = cv2.bitwise_not(img)          # 白底黑字-转换为-黑底白字
     img = cv2.resize(img, (28, 28))
     blob = img.astype(np.float32) / 255.0
     blob = blob.reshape(1, 1, 28, 28)   # NCHW
     pred = sess.run([out_name], {in_name: blob})[0][0] # logits
     prob = softmax(pred)                               # 归一化
     digit = int(np.argmax(prob))
     conf  = float(prob[digit])          # 置信度
     cost  = (time.time() - t0) * 1000
     return jsonify({'digit': digit, 'conf': round(conf, 3), 'time': round(cost, 1)})
 
 if __name__ == '__main__':
     app.run(host='0.0.0.0', port=8080, debug=False)


网页设计

新建文件 ./web/index.html 添加如下代码

 <!doctype html>
 <html>
 <head>
 <meta charset="utf-8">
 <title>树莓派 Zero 2W 手写识别</title>
 <style>
   body{font-family:Arial,Helvetica,sans-serif;text-align:center;background:#f2f2f2}
   canvas{border:1px solid #999;display:block;margin:10px auto;background:#fff}
   button{font-size:18px;margin:6px;padding:6px 14px}
   #res{color:#d44;font-size:20px;font-weight:bold}
 </style>
 </head>
 <body>
 <h2>树莓派 Zero 2W 手写数字识别</h2>
 <canvas id="c" width="280" height="280"></canvas>
 <div>
   <button id="clear">清空</button>
   <button id="go">识别</button>
 </div>
 <p id="res">等待识别…</p>
 
 <script>
 const canvas = document.getElementById('c');
 const ctx = canvas.getContext('2d');
 ctx.fillStyle='#fff'; ctx.fillRect(0,0,280,280);
 ctx.lineWidth=20; ctx.lineCap='round'; ctx.strokeStyle='#000';
 
 let drawing=false;
 function pos(e){const r=canvas.getBoundingClientRect();return [e.clientX-r.left,e.clientY-r.top];}
 canvas.onmousedown=e=>{drawing=true;ctx.beginPath();ctx.moveTo(...pos(e));};
 canvas.onmousemove=e=>{if(drawing){ctx.lineTo(...pos(e));ctx.stroke();}};
 canvas.onmouseup=()=>drawing=false;
 document.getElementById('clear').onclick=()=>{
   ctx.fillStyle='#fff';ctx.fillRect(0,0,280,280);document.getElementById('res').textContent='等待识别…';
 };
 
 document.getElementById('go').onclick=async()=>{
   const tmp=document.createElement('canvas');
   tmp.width=tmp.height=28;
   const tctx=tmp.getContext('2d');
   tctx.drawImage(canvas,0,0,28,28);
   const dataURL=tmp.toDataURL('image/png');
   const r=await fetch('/predict',{
     method:'POST',
     headers:{'Content-Type':'application/json'},
     body:JSON.stringify({image:dataURL})
   }).then(r=>r.json());
   document.getElementById('res').textContent=
     `识别结果:${r.digit}  (置信度 ${(r.conf*100).toFixed(1)}%)  耗时:${r.time} ms`;
 };
 </script>
 </body>
 </html>

保存代码。

效果演示

  • 终端执行指令 python mnist_web.py 运行程序;

  • 获取网页访问地址,在浏览器中输入该地址 http://192.168.31.105:8080;

mnist_web_print.jpg

  • 用鼠标或触摸板在面板区域手写数字,点击 识别 按钮,下方显示识别结果、置信度、耗时等信息;

mnist_num9.jpg

  • 更多识别效果如下

mnist_web_nums.jpg

总结

本文介绍了树莓派 Zero 2W 实现 Web 手写数字识别的项目设计,包括环境搭建、MNIST 数据集、 ONNX 模型、流程图、工程代码、网页设计及效果演示等,为相关产品在 AI 视觉领域的开发设计和快速应用提供了参考。






关键词: 树莓派     OpenCV     ONNX     MNIST     数字识    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]