Browse Source

Automatic Commit By liuyuqi

fish 2 weeks ago
commit
99ca14c8f9
12 changed files with 336 additions and 0 deletions
  1. 2 0
      .gitignore
  2. 13 0
      README.md
  3. 23 0
      app.py
  4. 28 0
      models.py
  5. 40 0
      nlp_utils.py
  6. 22 0
      ocr_utils.py
  7. 10 0
      requirements.txt
  8. 84 0
      routes.py
  9. 58 0
      static/css/styles.css
  10. 21 0
      static/js/main.js
  11. 35 0
      static/register.html
  12. 0 0
      utils/__init__.py

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+*.pyc
+instance/database.db

+ 13 - 0
README.md

@@ -0,0 +1,13 @@
+# campus_activity_system
+
+缓存目录
+
+```
+~/.cache/huggingface/hub/models--dslim--bert-base-NER
+
+
+apt-get update
+apt-get install tesseract-ocr
+apt-get install tesseract-ocr-chi-sim
+
+```

+ 23 - 0
app.py

@@ -0,0 +1,23 @@
+from flask import Flask, jsonify, request
+from models import db, User, Club, Activity
+from routes import activity_bp, user_bp
+from nlp_utils import classify_activity_type
+
+app = Flask(__name__, static_url_path='/static', static_folder='static')
+# app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://username:password@localhost/campus_activity'
+app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db'
+
+app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
+
+
+db.init_app(app)
+
+# 注册蓝图
+app.register_blueprint(activity_bp)
+app.register_blueprint(user_bp)
+# app.register_blueprint(club_bp)
+
+if __name__ == '__main__':
+    with app.app_context():
+        db.create_all()  # 创建所有表
+    app.run(debug=True)

+ 28 - 0
models.py

@@ -0,0 +1,28 @@
+from flask_sqlalchemy import SQLAlchemy
+from datetime import datetime
+
+db = SQLAlchemy()
+
+class User(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    username = db.Column(db.String(80), unique=True, nullable=False)
+    email = db.Column(db.String(120), unique=True, nullable=False)
+    created_at = db.Column(db.DateTime, default=datetime.utcnow)
+    name = db.Column(db.String(120)) # 身份证姓名
+    id_number=db.Column(db.String(20))
+
+
+class Club(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String(120), unique=True, nullable=False)
+    description = db.Column(db.Text, nullable=False)
+    created_at = db.Column(db.DateTime, default=datetime.utcnow)
+
+class Activity(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    title = db.Column(db.String(200), nullable=False)
+    description = db.Column(db.Text, nullable=False)
+    type = db.Column(db.String(50))  # 活动类型
+    date = db.Column(db.DateTime, nullable=False)
+    location = db.Column(db.String(200))
+    created_at = db.Column(db.DateTime, default=datetime.utcnow)

+ 40 - 0
nlp_utils.py

@@ -0,0 +1,40 @@
+from transformers import pipeline
+import re
+# 加载预训练的BERT分类器
+classifier = pipeline("text-classification", model="distilbert-base-uncased-finetuned-sst-2-english")
+
+def classify_activity_type(description):
+    """根据描述文本对活动进行类型分类"""
+    result = classifier(description)[0]
+    label = result['label']
+    
+    # 简化标签映射到具体活动类型
+    if 'positive' in label.lower():
+        return "学术讲座"
+    elif 'negative' in label.lower():
+        return "文体比赛"
+    else:
+        return "其他"
+
+ner_model = pipeline("ner", model="dslim/bert-base-NER")
+
+def extract_information(text):
+    """从文本中抽取姓名和身份证号"""
+    result = ner_model(text)
+
+    name = None
+    id_number = None
+
+    for entity in result:
+        if entity['entity'] == 'B-PER':  # 姓名
+            if name is None:
+                name = entity['word'].replace('#', '')
+        elif entity['entity'] == 'I-PER':
+            name += entity['word'].replace('#', '')
+
+        # 使用正则表达式匹配身份证号
+        match = re.search(r'\d{17}[\dxX]|\d{15}', text)
+        if match:
+            id_number = match.group(0)
+
+    return {'name': name, 'id_number': id_number}

+ 22 - 0
ocr_utils.py

@@ -0,0 +1,22 @@
+import pytesseract
+from PIL import Image
+import cv2
+import numpy as np
+
+def extract_text_from_image(image_path):
+    """从图片中提取文本"""
+    # 使用OpenCV读取图像
+    img = cv2.imread(image_path)
+    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
+
+    # 使用PIL将灰度图像转换为二值图像(黑白)
+    _, thresh = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY_INV)
+
+    # 使用pytesseract进行OCR
+    text = pytesseract.image_to_string(thresh, lang='chi_sim')  # 支持中文
+    return text.strip()
+
+# 示例调用
+if __name__ == "__main__":
+    text = extract_text_from_image('path_to_image.png')
+    print("Extracted Text:", text)

+ 10 - 0
requirements.txt

@@ -0,0 +1,10 @@
+
+Flask 
+SQLAlchemy 
+PyMySQL 
+#transformers 
+#torch
+pytesseract
+opencv-python
+pillow
+flask_sqlalchemy

+ 84 - 0
routes.py

@@ -0,0 +1,84 @@
+from flask import Blueprint, request, jsonify,render_template_string
+from models import db, Activity
+from nlp_utils import classify_activity_type
+from flask import Blueprint, request, jsonify
+from models import db, User
+from ocr_utils import extract_text_from_image
+from nlp_utils import extract_information
+import os
+activity_bp = Blueprint('activity', __name__)
+user_bp = Blueprint('user', __name__)
+
+@activity_bp.route('/activities', methods=['POST'])
+def create_activity():
+    data = request.json
+    title = data.get('title')
+    description = data.get('description')
+    date = data.get('date')
+    location = data.get('location')
+
+    # 使用NLP工具进行活动类型分类
+    activity_type = classify_activity_type(description)
+
+    new_activity = Activity(title=title, description=description, type=activity_type, date=date, location=location)
+    db.session.add(new_activity)
+    db.session.commit()
+
+    return jsonify({'message': 'Activity created successfully', 'type': activity_type}), 201
+
+@activity_bp.route('/activities', methods=['GET'])
+def get_activities():
+    activities = Activity.query.all()
+    result = []
+    for activity in activities:
+        result.append({
+            'id': activity.id,
+            'title': activity.title,
+            'description': activity.description,
+            'type': activity.type,
+            'date': activity.date.strftime('%Y-%m-%d %H:%M:%S'),
+            'location': activity.location
+        })
+    return jsonify(result), 200
+
+@user_bp.route('/register', methods = ['GET'])
+def index():
+    return render_template_string(open('static/register.html').read())
+
+@user_bp.route('/register', methods=['POST'])
+def register_user():
+    data = request.form
+    image_file = request.files.get('id_card_image')
+
+    if not image_file:
+        return jsonify({'error': '请上传身份证图片'}), 400
+
+    # 保存上传的图片到临时目录
+    image_path = os.path.join('/tmp', image_file.filename)
+    image_file.save(image_path)
+
+    try:
+        # 提取文本
+        extracted_text = extract_text_from_image(image_path)
+
+        # 抽取姓名和身份证号
+        user_info = extract_information(extracted_text)
+
+        # 创建新用户
+        new_user = User(
+            username=data.get('username'),
+            email=data.get('email'),
+            name=user_info.get('name'),
+            id_number=user_info.get('id_number')
+        )
+        db.session.add(new_user)
+        db.session.commit()
+
+        return jsonify({'message': '注册成功', 'name': user_info.get('name'), 'id_number': user_info.get('id_number')}), 201
+
+    except Exception as e:
+        return jsonify({'error': str(e)}), 500
+    finally:
+        # 清理临时文件
+        if os.path.exists(image_path):
+            os.remove(image_path)

+ 58 - 0
static/css/styles.css

@@ -0,0 +1,58 @@
+body {
+    font-family: Arial, sans-serif;
+    background-color: #f4f4f4;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    height: 100vh;
+    margin: 0;
+}
+
+.container {
+    background: white;
+    padding: 20px;
+    border-radius: 8px;
+    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+    width: 300px;
+}
+
+h1 {
+    text-align: center;
+    margin-bottom: 20px;
+}
+
+.form-group {
+    margin-bottom: 15px;
+}
+
+label {
+    display: block;
+    margin-bottom: 5px;
+}
+
+input[type="text"],
+input[type="email"],
+input[type="file"] {
+    width: 100%;
+    padding: 8px;
+    box-sizing: border-box;
+}
+
+button {
+    width: 100%;
+    padding: 10px;
+    background-color: #28a745;
+    color: white;
+    border: none;
+    cursor: pointer;
+    font-size: 16px;
+}
+
+button:hover {
+    background-color: #218838;
+}
+
+#message {
+    margin-top: 15px;
+    color: red;
+}

+ 21 - 0
static/js/main.js

@@ -0,0 +1,21 @@
+document.getElementById('registerForm').addEventListener('submit', async function (event) {
+    event.preventDefault();
+
+    const form = document.getElementById('registerForm');
+    const formData = new FormData(form);
+
+    const response = await fetch('/register', {
+        method: 'POST',
+        body: formData,
+    });
+
+    const result = await response.json();
+
+    if (response.ok) {
+        document.getElementById('message').innerText = '注册成功!';
+        document.getElementById('message').style.color = 'green';
+    } else {
+        document.getElementById('message').innerText = `注册失败: ${result.error}`;
+        document.getElementById('message').style.color = 'red';
+    }
+});

+ 35 - 0
static/register.html

@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>校园活动管理系统 - 注册</title>
+    <link rel="stylesheet" href="/static/css/styles.css">
+</head>
+
+<body>
+    <div class="container">
+        <h1>用户注册</h1>
+        <form id="registerForm" enctype="multipart/form-data">
+            <div class="form-group">
+                <label for="username">用户名:</label>
+                <input type="text" id="username" name="username" required>
+            </div>
+            <div class="form-group">
+                <label for="email">邮箱地址:</label>
+                <input type="email" id="email" name="email" required>
+            </div>
+            <div class="form-group">
+                <label for="id_card_image">上传身份证图片:</label>
+                <input type="file" id="id_card_image" name="id_card_image" accept="image/*" required>
+            </div>
+            <button type="submit">注册</button>
+        </form>
+        <p id="message"></p>
+    </div>
+
+    <script src="/static/js/main.js"></script>
+</body>
+
+</html>

+ 0 - 0
utils/__init__.py