当前位置: 首页 > news >正文

构建手写数字识别Web应用:前后端完整解决方案

 

在深度学习项目中,将模型部署为Web应用是一个重要的环节。本文将详细介绍如何构建一个完整的手写数字识别Web应用,涵盖前端界面设计、后端API开发和模型部署。

 

技术栈概览

 

· 前端: HTML5 Canvas + JavaScript + Bootstrap

· 后端: Python Flask + TensorFlow/Keras

· 模型: 卷积神经网络(CNN)

· 部署: 本地服务器或云平台

 

1. 后端API开发 (Flask)

 

首先,我们创建一个Flask后端服务来处理图像和进行预测。

 

app.py - 主后端应用

 

```python

from flask import Flask, request, jsonify, render_template

from flask_cors import CORS

import numpy as np

import cv2

import base64

import io

from PIL import Image

import tensorflow as tf

import os

 

app = Flask(__name__)

CORS(app) # 允许跨域请求

 

# 全局变量存储模型

model = None

 

def load_model():

    """加载预训练模型"""

    global model

    try:

        model = tf.keras.models.load_model('models/handwritten_digit_model.h5')

        print("模型加载成功")

    except Exception as e:

        print(f"模型加载失败: {e}")

        model = None

 

def preprocess_image(image):

    """

    预处理图像以匹配模型输入要求

    """

    # 转换为灰度图

    if len(image.shape) == 3:

        image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

    

    # 调整大小为28x28

    image = cv2.resize(image, (28, 28))

    

    # 反转颜色(MNIST是白字黑底)

    image = cv2.bitwise_not(image)

    

    # 归一化

    image = image.astype('float32') / 255.0

    

    # 调整形状

    image = image.reshape(1, 28, 28, 1)

    

    return image

 

@app.route('/')

def index():

    """渲染主页面"""

    return render_template('index.html')

 

@app.route('/health', methods=['GET'])

def health_check():

    """健康检查端点"""

    return jsonify({

        'status': 'healthy',

        'model_loaded': model is not None

    })

 

@app.route('/predict', methods=['POST'])

def predict_digit():

    """

    预测手写数字的API端点

    接收Base64编码的图像数据

    """

    if model is None:

        return jsonify({

            'error': '模型未加载',

            'success': False

        }), 500

    

    try:

        # 获取JSON数据

        data = request.get_json()

        

        if not data or 'image' not in data:

            return jsonify({

                'error': '未提供图像数据',

                'success': False

            }), 400

        

        # 解码Base64图像

        image_data = data['image'].split(',')[1] # 移除data:image/png;base64,前缀

        image_bytes = base64.b64decode(image_data)

        

        # 转换为PIL图像

        image = Image.open(io.BytesIO(image_bytes))

        

        # 转换为numpy数组

        image_array = np.array(image)

        

        # 预处理图像

        processed_image = preprocess_image(image_array)

        

        # 进行预测

        predictions = model.predict(processed_image, verbose=0)

        

        # 获取预测结果

        predicted_digit = int(np.argmax(predictions[0]))

        confidence = float(np.max(predictions[0]))

        

        # 获取所有数字的概率

        probabilities = {

            str(i): float(predictions[0][i]) 

            for i in range(10)

        }

        

        return jsonify({

            'success': True,

            'prediction': predicted_digit,

            'confidence': confidence,

            'probabilities': probabilities,

            'message': f'识别结果: {predicted_digit} (置信度: {confidence:.2%})'

        })

        

    except Exception as e:

        return jsonify({

            'error': f'预测过程中发生错误: {str(e)}',

            'success': False

        }), 500

 

@app.route('/batch_predict', methods=['POST'])

def batch_predict():

    """

    批量预测多个数字

    """

    if model is None:

        return jsonify({

            'error': '模型未加载',

            'success': False

        }), 500

    

    try:

        data = request.get_json()

        images_data = data.get('images', [])

        

        results = []

        for img_data in images_data:

            # 解码Base64图像

            image_data = img_data.split(',')[1]

            image_bytes = base64.b64decode(image_data)

            image = Image.open(io.BytesIO(image_bytes))

            image_array = np.array(image)

            

            # 预处理和预测

            processed_image = preprocess_image(image_array)

            predictions = model.predict(processed_image, verbose=0)

            

            predicted_digit = int(np.argmax(predictions[0]))

            confidence = float(np.max(predictions[0]))

            

            results.append({

                'prediction': predicted_digit,

                'confidence': confidence

            })

        

        return jsonify({

            'success': True,

            'results': results

        })

        

    except Exception as e:

        return jsonify({

            'error': f'批量预测失败: {str(e)}',

            'success': False

        }), 500

 

@app.route('/model_info', methods=['GET'])

def get_model_info():

    """获取模型信息"""

    if model is None:

        return jsonify({'error': '模型未加载'}), 404

    

    try:

        # 获取模型摘要信息

        model_summary = []

        model.summary(print_fn=lambda x: model_summary.append(x))

        

        return jsonify({

            'success': True,

            'model_layers': len(model.layers),

            'input_shape': model.input_shape,

            'output_shape': model.output_shape,

            'summary': '\n'.join(model_summary)

        })

    except Exception as e:

        return jsonify({

            'error': f'获取模型信息失败: {str(e)}',

            'success': False

        }), 500

 

if __name__ == '__main__':

    # 加载模型

    load_model()

    

    # 启动Flask应用

    app.run(

        host='0.0.0.0',

        port=5000,

        debug=True,

        threaded=True

    )

```

 

requirements.txt - 后端依赖

 

```txt

flask==2.3.3

flask-cors==4.0.0

tensorflow==2.13.0

numpy==1.24.3

opencv-python==4.8.1.78

Pillow==10.0.1

gunicorn==21.2.0

```

 

2. 前端界面开发

 

接下来,我们创建一个响应式的前端界面,使用HTML5 Canvas进行手写输入。

 

templates/index.html - 主页面

 

```html

<!DOCTYPE html>

<html lang="zh-CN">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>手写数字识别系统</title>

    <!-- Bootstrap CSS -->

    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">

    <!-- 自定义样式 -->

    <style>

        .drawing-canvas {

            border: 2px solid #007bff;

            border-radius: 8px;

            cursor: crosshair;

            background-color: white;

            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);

        }

        .probability-bar {

            height: 20px;

            background: linear-gradient(90deg, #4CAF50, #8BC34A);

            border-radius: 10px;

            transition: width 0.3s ease;

            margin-bottom: 5px;

        }

        .result-card {

            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);

            color: white;

            border-radius: 15px;

        }

        .drawing-area {

            background: #f8f9fa;

            border-radius: 15px;

            padding: 20px;

        }

        .loading-spinner {

            display: none;

            width: 3rem;

            height: 3rem;

        }

        .btn-custom {

            background: linear-gradient(45deg, #667eea, #764ba2);

            border: none;

            color: white;

            transition: all 0.3s ease;

        }

        .btn-custom:hover {

   

http://www.dtcms.com/a/610654.html

相关文章:

  • 网站制作过程简介网络规划设计师如何复习
  • 从 Chat Completions 到 Responses:不仅仅是更改了接口这么简单
  • (ICLR 2019)APPNP传播用 PageRank,不用神经网络!
  • 解决 Mac 迁移数据后用户目录无权限问题
  • 长春网站制作价格网站空间要备案吗
  • C#1114 枚举
  • 语义分割中上采样Up-sampling的原理
  • 如何建设局域网网站江苏强荣建设有限公司 网站
  • Android Neon支持
  • 合肥专业手机网站制作价格vs中的网站导航怎么做
  • 上海市建设工程质监站网站网站里怎么做301指向
  • 带数据库的网站模板下载wordpress章节分页
  • adb之系统工具—dumpsys 命令
  • Android Studio贪吃蛇游戏完整开发教程 - 5关卡可调节速度
  • k8s节点故障修复:v1.Secret观察失败解决方案
  • 中兴B862AV3.2M/B862AV3.1-M2-晨星MSO9385芯片-中兴STB3.0工具-开启ADB教程
  • 资源站 wordpress自建站怎么做
  • 外贸 静态网站 怎么做开通网站软件的会计科目怎么做
  • 企业部署求解器要考虑哪些因素?
  • 《电子政务电子认证服务业务规则规范》核心考点总览
  • 2025数维杯C题第一弹【透彻建模+无盲点解析】
  • css实现边框圆角的渐变色效果
  • 网站建设 思路长沙网站制
  • LeetCode hot100:002 两数相加(链表):逆序存储数字的加法运算
  • Transformer与MoE架构:原理、差异与应用全景
  • 使用 C# 实现 Excel 与 DataTable 相互转换
  • Meta DreamGym:用合成经验,重构智能体训练的“低成本革命”
  • 淮安建设网站制作权威发布的意思是什么
  • 数据库“Driver not loaded“错误,单例模式重构方案
  • 中山企业网站制作vi设计公司网站