Python全栈项目--基于深度学习的手写识别系统

一、项目简介

手写数字识别是深度学习入门项目中的经典场景,但如果只停留在模型训练脚本层面,就很难体现真实业务系统的完整链路。本文实现一个 Python 全栈项目--基于深度学习的手写识别系统:用户可以注册登录,在浏览器中绘制 28×28 手写数字,提交给后端 PyTorch 推理模型识别,并把自己的样本沉淀到数据库中,形成可持续优化的个人识别原型。

项目采用前后端分离架构:后端提供认证、样本、识别、历史接口;前端提供登录注册、画板绘制、训练样本提交、识别结果展示。为了适合离线学习和部署,推理部分使用轻量 PyTorch 原型分类网络 PrototypeDigitNet,不依赖外部大模型权重,但完整保留了 Tensor 预处理、特征池化、模型前向推理、Softmax 评分和结果记录等核心步骤。

二、技术栈

  • 后端:FastAPI、SQLAlchemy、SQLite、Pydantic、PyTorch
  • 前端:Vue 3、Vite、Fetch API
  • 认证:PBKDF2 密码哈希、Bearer Token
  • 数据存储:SQLite 本地数据库
  • 项目打包:zip 压缩包

三、系统架构

text 复制代码
浏览器(Vue 3 + Vite)
  ├── 注册/登录页面
  ├── 28×28 手写画板
  ├── 样本采集模块
  └── 识别历史页面
          │ HTTP + Bearer Token
          ▼
FastAPI 后端服务
  ├── Auth API:注册、登录、退出、当前用户
  ├── Sample API:保存与查询训练样本
  ├── Recognition API:PyTorch 预处理、模型推理、记录结果
  └── Stats API:统计用户样本和识别次数
          │ SQLAlchemy ORM
          ▼
SQLite 数据库
  ├── users
  ├── access_tokens
  ├── handwriting_samples
  └── recognition_records

该架构既能满足课程设计、毕业设计、项目实训展示,也方便后续把当前 PyTorch 原型分类器替换成训练好的 CNN、CRNN 或 ONNX 推理模型。

四、功能模块

  1. 用户模块
    • 用户注册
    • 用户登录
    • Token 鉴权
    • 退出登录
  2. 手写识别模块
    • 浏览器绘制 28×28 灰度图
    • 后端使用 PyTorch Tensor 归一化输入数据
    • 通过自适应平均池化下采样为 8×8 特征向量
    • PrototypeDigitNet 计算输入与数字原型的距离并输出 Softmax 概率
  3. 样本管理模块
    • 保存当前画板为训练样本
    • 按用户隔离样本数据
    • 动态生成用户个性化数字原型
  4. 历史记录模块
    • 保存每次识别结果
    • 查询最近识别历史
  5. 统计模块
    • 样本数量
    • 识别次数
    • 各数字样本分布

五、数据库/数据模型设计

1. 用户表 users

字段 类型 说明
id Integer 用户 ID
username String 用户名,唯一
password_hash String PBKDF2 哈希密码
created_at DateTime 创建时间

2. 访问令牌表 access_tokens

字段 类型 说明
id Integer Token ID
token String Bearer Token
user_id Integer 所属用户
created_at DateTime 创建时间

3. 手写样本表 handwriting_samples

字段 类型 说明
id Integer 样本 ID
digit Integer 真实数字标签
grid Text 28×28 灰度数组 JSON
source String 样本来源
user_id Integer 所属用户
created_at DateTime 创建时间

4. 识别记录表 recognition_records

字段 类型 说明
id Integer 记录 ID
predicted_digit Integer 预测数字
confidence Float 置信度
grid Text 输入图像数组
user_id Integer 所属用户
created_at DateTime 创建时间

六、后端接口设计

方法 路径 说明 鉴权
GET /api/health 健康检查
POST /api/auth/register 注册
POST /api/auth/login 登录
POST /api/auth/logout 退出登录 可选
GET /api/users/me 当前用户
POST /api/samples 新增样本
GET /api/samples 样本列表
POST /api/recognize 手写识别
GET /api/records 识别历史
GET /api/stats 数据统计

其中核心业务接口均要求携带:

http 复制代码
Authorization: Bearer <access_token>

七、前端页面设计

前端使用 Vue 3 + Vite,主要页面区域如下:

  • 登录/注册卡片:未登录时展示,登录成功后保存 Token 到 localStorage
  • 顶部信息区:展示项目名称、技术栈和退出按钮。
  • 手写画板:使用 28×28 网格模拟灰度像素画布。
  • 样本训练区:选择数字标签,把当前画板提交为训练样本。
  • 最近样本列表:展示用户提交过的训练样本。
  • 识别历史列表:展示最近识别结果和置信度。

这种设计可以清晰体现全栈项目中的"用户操作 -> API 请求 -> 数据库存储 -> 页面反馈"闭环。

八、核心代码讲解

1. FastAPI 应用入口

backend/app/main.py 中创建数据库表、配置跨域,并声明认证依赖:

python 复制代码
def current_user(authorization: str = Header(default=""), db: Session = Depends(get_db)):
    if not authorization.lower().startswith("bearer "):
        raise HTTPException(status_code=401, detail="Missing bearer token")
    token = authorization.split(" ", 1)[1].strip()
    user = crud.get_user_by_token(db, token)
    if not user:
        raise HTTPException(status_code=401, detail="Invalid or expired token")
    return user

后续样本、识别、历史接口都通过 Depends(current_user) 保护,确保不同用户的数据不会互相访问。

2. 密码哈希与 Token 登录

backend/app/crud.py 使用标准库 hashlib.pbkdf2_hmac 进行密码哈希:

python 复制代码
def hash_password(password: str) -> str:
    salt = secrets.token_hex(16)
    digest = hashlib.pbkdf2_hmac("sha256", password.encode(), salt.encode(), 120_000)
    return f"pbkdf2_sha256$120000${salt}${digest.hex()}"

登录成功后生成随机 Token,并写入 access_tokens 表。前端后续请求统一携带 Bearer Token。

3. PyTorch 手写数字识别流程

系统接收长度为 784 的数组,代表 28×28 灰度图。后端先使用 PyTorch Tensor 完成归一化和自适应池化:

python 复制代码
def downsample_to_8x8(grid):
    values = torch.tensor(list(grid), dtype=torch.float32).view(1, 1, 28, 28)
    pooled = F.adaptive_avg_pool2d(values, output_size=(8, 8)).view(-1)
    max_value = torch.clamp(pooled.max(), min=1.0)
    normalized = torch.clamp(pooled / max_value, 0.0, 1.0)
    return [round(float(v), 4) for v in normalized.tolist()]

随后进入轻量级 PyTorch 模型 PrototypeDigitNet

python 复制代码
class PrototypeDigitNet(nn.Module):
    def __init__(self, temperature: float = 4.0):
        super().__init__()
        self.temperature = temperature

    def forward(self, features, prototypes):
        distances = torch.cdist(features, prototypes, p=2)
        logits = -distances * self.temperature
        return torch.softmax(logits, dim=1)

模型把输入特征与 0-9 数字原型计算距离,将负距离转换为 logits,再通过 Softmax 输出每个数字的概率。若用户提交了自己的训练样本,系统会按用户维度重新计算对应数字的原型均值,因此同一套 PyTorch 推理代码可以逐步适配个人书写习惯。

4. Vue API 封装

frontend/src/api.js 封装所有 HTTP 请求,并自动添加 Token:

javascript 复制代码
async function request(path, options = {}) {
  const headers = { 'Content-Type': 'application/json', ...(options.headers || {}) }
  if (token) headers.Authorization = `Bearer ${token}`
  const response = await fetch(`${API_BASE}${path}`, { ...options, headers })
  const data = await response.json().catch(() => ({}))
  if (!response.ok) throw new Error(data.detail || '请求失败')
  return data
}

这样 Vue 组件只需要调用 api.recognize()api.addSample() 等方法即可。

5. 画板绘制逻辑

Vue 组件使用 784 个 div 表示像素点,鼠标划过时提高灰度值:

javascript 复制代码
function paint(index) {
  drawing.value = true
  const next = [...grid.value]
  const neighbors = [index, index - 1, index + 1, index - 28, index + 28]
  neighbors.forEach(i => { if (i >= 0 && i < next.length) next[i] = Math.min(1, next[i] + 0.6) })
  grid.value = next
}

虽然实现轻量,但已经具备真实手写识别系统的输入交互形式。

九、部署与运行步骤

1. 启动后端

bash 复制代码
cd project/backend
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

后端默认地址:http://127.0.0.1:8000,接口文档:http://127.0.0.1:8000/docs

2. 启动前端

bash 复制代码
cd project/frontend
npm install
npm run dev

前端默认访问地址:http://127.0.0.1:5173

3. 体验流程

  1. 注册账号,例如 demo / 123456
  2. 登录后绘制一个数字。
  3. 点击"开始识别"。
  4. 选择真实标签并保存训练样本。
  5. 查看识别历史与统计信息。

十、可扩展方向

  • 将当前 PyTorch 原型分类器替换为训练好的 CNN .pt/.pth 权重。
  • 增加图片上传识别功能。
  • 增加管理员样本审核模块。
  • 增加模型版本管理与在线评估。
  • 使用 Redis 管理 Token 或会话。
  • 使用 Docker Compose 部署前后端。

十一、项目总结

本文完成了一个完整的手写识别全栈项目。它不仅包含 PyTorch 模型推理逻辑,还包含用户系统、认证鉴权、数据模型、后端 API、Vue 前端页面和运行部署说明。相比单独的算法 Demo,这类项目更接近真实业务系统,适合用于课程设计、项目实训和毕业设计原型。

项目代码

下载链接

相关推荐
油丶酸萝卜别吃1 小时前
Java 集合类全景介绍
java·开发语言
Iruoyaoxh2 小时前
类和对象~
开发语言·c++
程序喵大人2 小时前
【C++进阶】STL算法与函数对象 - 04 find、count和any_of把查询写成意图
开发语言·c++·算法
Livia要学习2 小时前
Python装饰器
开发语言·python
一直都在5722 小时前
LangChain4j精讲
开发语言·人工智能
吹什么轩2 小时前
c++复习:c++11:lambda表达式
开发语言·c++
不会代码的小猴2 小时前
标准模板库(STL)
开发语言·c++·笔记·算法
大模型码小白3 小时前
【AI】一文讲清 RAG:从大模型局限到企业级知识库落地流程
人工智能·深度学习·学习
circuitsosk3 小时前
向量数据库选型与性能压测:Milvus、Pinecone、Chroma在真实业务下的对比
数据库·python·pinecone·milvus·向量数据库·chroma