{ "id": "conv_20250929_192001_757", "title": "给你一个人工智能专业的基础实验,自己写一个用于识别手写0-9数字的应用", "created_at": "2025-09-29T19:20:01.757618", "updated_at": "2025-09-29T20:12:00.133688", "messages": [ { "role": "user", "content": "给你一个人工智能专业的基础实验,自己写一个用于识别手写0-9数字的应用", "timestamp": "2025-09-29T19:20:58.688406" }, { "role": "assistant", "content": "我来为你创建一个手写数字识别的完整应用。这是一个经典的机器学习实验项目,我会使用Python和深度学习框架来实现。", "timestamp": "2025-09-29T19:21:01.248298" }, { "role": "assistant", "content": "", "timestamp": "2025-09-29T19:21:01.258750", "tool_calls": [ { "id": "create_folder:0", "index": 0, "type": "function", "function": { "name": "create_folder", "arguments": "{\"path\": \"handwriting_recognition\"}" } } ] }, { "role": "tool", "content": "{\"success\": true, \"path\": \"handwriting_recognition\"}", "timestamp": "2025-09-29T19:21:03.085410", "tool_call_id": "create_folder:0", "name": "create_folder" }, { "role": "assistant", "content": "", "timestamp": "2025-09-29T19:21:08.062781", "tool_calls": [ { "id": "create_file:1", "index": 0, "type": "function", "function": { "name": "create_file", "arguments": "{\"path\": \"handwriting_recognition/requirements.txt\", \"file_type\": \"txt\", \"content\": \"tensorflow==2.15.0\\nnumpy==1.24.3\\nmatplotlib==3.7.2\\nopencv-python==4.8.1.78\\npillow==10.0.1\\nscikit-learn==1.3.2\\nflask==3.0.0\", \"annotation\": \"项目依赖文件\"}" } } ] }, { "role": "tool", "content": "{\"success\": true, \"path\": \"handwriting_recognition/requirements.txt\", \"size\": 122}", "timestamp": "2025-09-29T19:21:09.881214", "tool_call_id": "create_file:1", "name": "create_file" }, { "role": "assistant", "content": "", "timestamp": "2025-09-29T19:22:12.314814", "tool_calls": [ { "id": "create_file:2", "index": 0, "type": "function", "function": { "name": "create_file", "arguments": "{\"path\": \"handwriting_recognition/digit_recognizer.py\", \"file_type\": \"py\", \"content\": \"import tensorflow as tf\\nimport numpy as np\\nimport matplotlib.pyplot as plt\\nfrom tensorflow.keras import layers, models\\nfrom tensorflow.keras.datasets import mnist\\nfrom tensorflow.keras.utils import to_categorical\\nimport cv2\\nimport os\\n\\nclass DigitRecognizer:\\n def __init__(self):\\n self.model = None\\n self.history = None\\n self.model_path = 'handwriting_recognition/models/digit_model.h5'\\n \\n def load_or_create_model(self):\\n \\\"\\\"\\\"加载已有模型或创建新模型\\\"\\\"\\\"\\n if os.path.exists(self.model_path):\\n print(\\\"正在加载已有模型...\\\")\\n self.model = tf.keras.models.load_model(self.model_path)\\n return True\\n else:\\n print(\\\"正在创建新模型...\\\")\\n self.create_model()\\n return False\\n \\n def create_model(self):\\n \\\"\\\"\\\"创建CNN模型\\\"\\\"\\\"\\n model = models.Sequential([\\n layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),\\n layers.MaxPooling2D((2, 2)),\\n layers.Conv2D(64, (3, 3), activation='relu'),\\n layers.MaxPooling2D((2, 2)),\\n layers.Conv2D(64, (3, 3), activation='relu'),\\n layers.Flatten(),\\n layers.Dense(64, activation='relu'),\\n layers.Dropout(0.5),\\n layers.Dense(10, activation='softmax')\\n ])\\n \\n model.compile(optimizer='adam',\\n loss='categorical_crossentropy',\\n metrics=['accuracy'])\\n \\n self.model = model\\n return model\\n \\n def prepare_data(self):\\n \\\"\\\"\\\"准备MNIST数据集\\\"\\\"\\\"\\n print(\\\"正在加载MNIST数据集...\\\")\\n (train_images, train_labels), (test_images, test_labels) = mnist.load_data()\\n \\n # 归一化图像数据\\n train_images = train_images.reshape((60000, 28, 28, 1)).astype('float32') / 255\\n test_images = test_images.reshape((10000, 28, 28, 1)).astype('float32') / 255\\n \\n # 将标签转换为分类编码\\n train_labels = to_categorical(train_labels)\\n test_labels = to_categorical(test_labels)\\n \\n return (train_images, train_labels), (test_images, test_labels)\\n \\n def train_model(self, epochs=5, batch_size=64):\\n \\\"\\\"\\\"训练模型\\\"\\\"\\\"\\n (train_images, train_labels), (test_images, test_labels) = self.prepare_data()\\n \\n print(\\\"开始训练模型...\\\")\\n self.history = self.model.fit(train_images, train_labels,\\n epochs=epochs, batch_size=batch_size,\\n validation_data=(test_images, test_labels))\\n \\n # 保存模型\\n os.makedirs('handwriting_recognition/models', exist_ok=True)\\n self.model.save(self.model_path)\\n print(f\\\"模型已保存到: {self.model_path}\\\")\\n \\n return self.history\\n \\n def evaluate_model(self):\\n \\\"\\\"\\\"评估模型性能\\\"\\\"\\\"\\n _, (test_images, test_labels) = self.prepare_data()\\n \\n print(\\\"正在评估模型性能...\\\")\\n test_loss, test_acc = self.model.evaluate(test_images, test_labels)\\n print(f\\\"测试准确率: {test_acc:.4f}\\\")\\n print(f\\\"测试损失: {test_loss:.4f}\\\")\\n \\n return test_acc, test_loss\\n \\n def predict_digit(self, image):\\n \\\"\\\"\\\"预测单个数字图像\\\"\\\"\\\"\\n # 确保图像是28x28的灰度图像\\n if len(image.shape) == 3:\\n image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\\n \\n if image.shape != (28, 28):\\n image = cv2.resize(image, (28, 28))\\n \\n # 归一化\\n image = image.astype('float32') / 255\\n image = image.reshape(1, 28, 28, 1)\\n \\n # 预测\\n prediction = self.model.predict(image)\\n digit = np.argmax(prediction)\\n confidence = np.max(prediction)\\n \\n return digit, confidence, prediction[0]\\n \\n def predict_from_file(self, image_path):\\n \\\"\\\"\\\"从文件预测数字\\\"\\\"\\\"\\n image = cv2.imread(image_path)\\n if image is None:\\n raise ValueError(f\\\"无法加载图像: {image_path}\\\")\\n \\n return self.predict_digit(image)\\n \\n def show_training_history(self):\\n \\\"\\\"\\\"显示训练历史\\\"\\\"\\\"\\n if self.history is None:\\n print(\\\"没有训练历史可显示\\\")\\n return\\n \\n plt.figure(figsize=(12, 4))\\n \\n # 准确率\\n plt.subplot(1, 2, 1)\\n plt.plot(self.history.history['accuracy'], label='训练准确率')\\n plt.plot(self.history.history['val_accuracy'], label='验证准确率')\\n plt.title('模型准确率')\\n plt.xlabel('轮次')\\n plt.ylabel('准确率')\\n plt.legend()\\n \\n # 损失\\n plt.subplot(1, 2, 2)\\n plt.plot(self.history.history['loss'], label='训练损失')\\n plt.plot(self.history.history['val_loss'], label='验证损失')\\n plt.title('模型损失')\\n plt.xlabel('轮次')\\n plt.ylabel('损失')\\n plt.legend()\\n \\n plt.tight_layout()\\n plt.savefig('handwriting_recognition/training_history.png')\\n plt.show()\\n \\n def test_sample_images(self, num_samples=10):\\n \\\"\\\"\\\"测试一些样本图像\\\"\\\"\\\"\\n _, (test_images, test_labels) = self.prepare_data()\\n \\n # 随机选择一些测试图像\\n indices = np.random.choice(len(test_images), num_samples, replace=False)\\n \\n plt.figure(figsize=(15, 6))\\n for i, idx in enumerate(indices):\\n image = test_images[idx]\\n true_label = np.argmax(test_labels[idx])\\n \\n # 预测\\n predicted_digit, confidence, _ = self.predict_digit(image.reshape(28, 28))\\n \\n plt.subplot(2, 5, i+1)\\n plt.imshow(image.reshape(28, 28), cmap='gray')\\n plt.title(f'真实: {true_label}, 预测: {predicted_digit}\\\\n置信度: {confidence:.3f}')\\n plt.axis('off')\\n \\n # 标记错误预测\\n if predicted_digit != true_label:\\n plt.text(0.5, -0.1, '错误!', color='red', \\n transform=plt.gca().transAxes, ha='center')\\n \\n plt.tight_layout()\\n plt.savefig('handwriting_recognition/sample_predictions.png')\\n plt.show()\\n\\nif __name__ == \\\"__main__\\\":\\n # 创建识别器\\n recognizer = DigitRecognizer()\\n \\n # 加载或创建模型\\n model_exists = recognizer.load_or_create_model()\\n \\n if not model_exists:\\n # 训练模型\\n recognizer.train_model(epochs=3)\\n \\n # 评估模型\\n recognizer.evaluate_model()\\n \\n # 显示训练历史(如果有)\\n recognizer.show_training_history()\\n \\n # 测试一些样本\\n recognizer.test_sample_images()\", \"annotation\": \"主要的手写数字识别类\"}" } } ] }, { "role": "tool", "content": "{\"success\": true, \"path\": \"handwriting_recognition/digit_recognizer.py\", \"size\": 6285}", "timestamp": "2025-09-29T19:22:14.131792", "tool_call_id": "create_file:2", "name": "create_file" }, { "role": "assistant", "content": "", "timestamp": "2025-09-29T19:22:44.369848", "tool_calls": [ { "id": "create_file:3", "index": 0, "type": "function", "function": { "name": "create_file", "arguments": "{\"path\": \"handwriting_recognition/web_interface.py\", \"file_type\": \"py\", \"content\": \"from flask import Flask, render_template, request, jsonify\\nimport base64\\nimport numpy as np\\nimport cv2\\nfrom PIL import Image\\nimport io\\nimport os\\nfrom digit_recognizer import DigitRecognizer\\n\\napp = Flask(__name__)\\n\\n# 全局识别器实例\\nrecognizer = DigitRecognizer()\\nmodel_loaded = False\\n\\ndef init_model():\\n \\\"\\\"\\\"初始化模型\\\"\\\"\\\"\\n global model_loaded\\n try:\\n model_exists = recognizer.load_or_create_model()\\n if not model_exists:\\n print(\\\"模型不存在,请先运行 digit_recognizer.py 训练模型\\\")\\n return False\\n model_loaded = True\\n print(\\\"模型加载成功!\\\")\\n return True\\n except Exception as e:\\n print(f\\\"模型加载失败: {e}\\\")\\n return False\\n\\n@app.route('/')\\ndef index():\\n \\\"\\\"\\\"主页\\\"\\\"\\\"\\n return render_template('index.html')\\n\\n@app.route('/predict', methods=['POST'])\\ndef predict():\\n \\\"\\\"\\\"预测手写数字\\\"\\\"\\\"\\n if not model_loaded:\\n return jsonify({'error': '模型未加载'})\\n \\n try:\\n # 获取图像数据\\n data = request.json\\n image_data = data['image'].split(',')[1] # 移除data:image/png;base64,前缀\\n \\n # 解码base64图像\\n image_bytes = base64.b64decode(image_data)\\n image = Image.open(io.BytesIO(image_bytes))\\n \\n # 转换为numpy数组\\n image_array = np.array(image)\\n \\n # 转换为灰度图(如果不是的话)\\n if len(image_array.shape) == 3:\\n image_array = cv2.cvtColor(image_array, cv2.COLOR_RGB2GRAY)\\n \\n # 反转颜色(白底黑字 -> 黑底白字)\\n image_array = 255 - image_array\\n \\n # 预测\\n digit, confidence, probabilities = recognizer.predict_digit(image_array)\\n \\n # 返回结果\\n return jsonify({\\n 'digit': int(digit),\\n 'confidence': float(confidence),\\n 'probabilities': probabilities.tolist()\\n })\\n \\n except Exception as e:\\n return jsonify({'error': str(e)})\\n\\n@app.route('/train', methods=['POST'])\\ndef train():\\n \\\"\\\"\\\"训练模型\\\"\\\"\\\"\\n try:\\n data = request.json\\n epochs = data.get('epochs', 3)\\n \\n # 训练模型\\n recognizer.train_model(epochs=epochs)\\n \\n global model_loaded\\n model_loaded = True\\n \\n return jsonify({'success': True, 'message': '模型训练完成'})\\n \\n except Exception as e:\\n return jsonify({'error': str(e)})\\n\\n@app.route('/evaluate')\\ndef evaluate():\\n \\\"\\\"\\\"评估模型\\\"\\\"\\\"\\n if not model_loaded:\\n return jsonify({'error': '模型未加载'})\\n \\n try:\\n accuracy, loss = recognizer.evaluate_model()\\n return jsonify({\\n 'accuracy': float(accuracy),\\n 'loss': float(loss)\\n })\\n except Exception as e:\\n return jsonify({'error': str(e)})\\n\\nif __name__ == '__main__':\\n # 初始化模型\\n if init_model():\\n print(\\\"启动Web服务...\\\")\\n app.run(debug=True, port=5000)\\n else:\\n print(\\\"请先在命令行运行: python digit_recognizer.py\\\")\", \"annotation\": \"Web界面应用\"}" } } ] }, { "role": "tool", "content": "{\"success\": true, \"path\": \"handwriting_recognition/web_interface.py\", \"size\": 2812}", "timestamp": "2025-09-29T19:22:46.199229", "tool_call_id": "create_file:3", "name": "create_file" }, { "role": "assistant", "content": "", "timestamp": "2025-09-29T19:22:47.714928", "tool_calls": [ { "id": "create_folder:4", "index": 0, "type": "function", "function": { "name": "create_folder", "arguments": "{\"path\": \"handwriting_recognition/templates\"}" } } ] }, { "role": "tool", "content": "{\"success\": true, \"path\": \"handwriting_recognition/templates\"}", "timestamp": "2025-09-29T19:22:49.544020", "tool_call_id": "create_folder:4", "name": "create_folder" }, { "role": "assistant", "content": "", "timestamp": "2025-09-29T19:24:17.328434", "tool_calls": [ { "id": "create_file:5", "index": 0, "type": "function", "function": { "name": "create_file", "arguments": "{\"path\": \"handwriting_recognition/templates/index.html\", \"file_type\": \"txt\", \"content\": \"\\n\\n
\\n \\n \\n请在画布上书写数字,然后点击\\\"识别\\\"按钮
\\n