【VisionFive 2 Lite 单板计算机】边缘AI视觉应用部署:网页手写数字识别

【VisionFive 2 Lite 单板计算机】边缘AI视觉应用部署:网页手写数字识别

本文介绍了昉·星光 VisionFive2 Lite 单板计算机结合 OpenCV 软件库和 MNIST 数据集实现网页手写数字识别的项目设计。

项目介绍

VisionFive 2 Lite 结合 OpenCV 实现手写数字识别的项目设计。

  • 准备工作:硬件连接、系统安装、软件更新、OpenCV 部署、MNIST 数据集等;
  • 网页手写数字识别:包括流程图、代码、网页设计、效果演示等;

准备工作

包括硬件连接、OpenCV 部署及软件更新等。

硬件连接

包括供电、联网、显示、鼠标键盘输入等。

系统安装

安装和烧录 VisionFive2 Lite 官方 Ubuntu 操作系统。

详见:VF2 Lite 系统安装

软件更新

更新软件包

wget https://github.com/starfive-tech/Debian/releases/download/v0.15.0-engineering-release-wayland/install_full.sh
sudo chmod +x install_full.sh
sudo ./install_full.sh

详见: StarFive-Tech | Debian .

OpenCV

包括 OpenCV 安装及版本检测流程。

  • 安装 OpenCV

    sudo apt install python3-opencv
    
  • 安装缺失的 libopencv 包

sudo apt install -y libopencv-dev
  • 验证安装结果
python3 -c "import cv2,sys;print(cv2.__version__,sys.version)"
  • 输出 OpenCV 版本号

Qt 平台

完整 Qt 环境部署,以便 SSH 正常弹窗显示结果

sudo apt-get install -y libxcb-xinerama0 libxcb-xinput0 libxcb-cursor0
sudo apt-get install -y libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0
sudo apt-get install -y libxcb-render-util0 libxcb-shape0 libxcb-sync1 libxcb-xfixes0
sudo apt-get install -y libxcb-xkb1 libxkbcommon-x11-0

# 安装 Qt 相关的库
sudo apt-get install -y libqt5gui5 libqt5widgets5 libqt5core5a

模型下载

下载预训练的 MNIST 数字识别 ./model/mnist-12.onnx 模型

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

详见:mnist | github .

工程代码

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

#!/usr/bin/env python3
"""
手写数字识别 Web 服务
- 模型:mnist-12.onnx
- 推理:OpenCV-DNN(CPU)
"""
import cv2, numpy as np, base64, time
from flask import Flask, render_template_string, request, jsonify

app = Flask(__name__)
MODEL = './model/mnist-12.onnx'
net = cv2.dnn.readNetFromONNX(MODEL)
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)

# 稳定版 softmax
def softmax(x):
    x = x - np.max(x)
    return np.exp(x) / np.sum(np.exp(x))

# 解码前端画布 base64
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 = cv2.dnn.blobFromImage(img, 1/255.0, (28, 28), swapRB=False)
    # 形状 (1,1,28,28),发送至 Web
    net.setInput(blob)
    logits = net.forward()[0, :]        # 长度为 10 的向量
    prob = softmax(logits)
    digit = int(np.argmax(prob))
    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 lang="zh-CN">
<head>
<meta charset="utf-8">
<title>VisionFive 2 Lite MNIST</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>VisionFive 2 手写数字识别</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>

保存代码。

效果

终端执行指令 python3 mnist_web.py 输出网页服务器地址等信息

浏览器中输入网址 http://192.168.31.111:8080 打开数字识别网页界面;

  • 使用鼠标或触摸屏在空白面板上手写数字;
  • 点击 识别 按钮,下方立即显示识别结果;
  • 点击 清空 按钮,即可再次手写数字;

更多效果演示

总结

本文介绍了昉·星光 VisionFive2 Lite 单板计算机结合 OpenCV 软件库和 MNIST 数据集实现网页手写数字识别的项目设计,包括准备工作、环境部署、模型获取、工程代码、效果演示等,为 VisionFive 2 Lite 单板计算机及其相关产品的快速开发和设计应用提供了参考。

1 Like