ソースを参照

初始化项目

eric.w 2 週間 前
コミット
1bacc4c990

+ 3 - 0
BridgeDiseaseBackend-main/.gitignore

@@ -39,3 +39,6 @@ var/
 
 # 功能结果文件
 static/
+
+# 训练数据与任务元数据
+data/

+ 3 - 0
BridgeDiseaseBackend-main/app/__init__.py

@@ -38,6 +38,9 @@ def create_app():
     # 初始化数据库
     init_db(app)
 
+    from app.services.training_manager import init_training_manager
+    init_training_manager(app)
+
     # 注册蓝图
     register_routes(app)
 

+ 4 - 0
BridgeDiseaseBackend-main/app/config.py

@@ -32,7 +32,11 @@ class Config:
     MODELS_FOLDER = os.path.join(os.getcwd(), 'app', 'static', 'models')  # 模型存储的文件夹路径
     MEDIAS_FOLDER = os.path.join(os.getcwd(), 'app', 'static', 'medias')  # 媒体存储的文件夹路径
     RESULTS_FOLDER = os.path.join(os.getcwd(), 'app', 'static', 'results')  # 结果存储的文件夹路径
+    DATASETS_FOLDER = os.path.join(os.getcwd(), 'data', 'datasets')  # YOLO 训练数据集
+    TRAINING_RUNS_FOLDER = os.path.join(os.getcwd(), 'data', 'training_runs')  # Ultralytics 训练输出
+    TRAINING_META_FOLDER = os.path.join(os.getcwd(), 'data', 'training_meta')  # 任务/数据集元数据 JSON
     MAX_AVATAR_SIZE = 5 * 1024 * 1024  # 最大头像文件大小:5MB
+    MAX_DATASET_ZIP_SIZE = 500 * 1024 * 1024  # 数据集 ZIP 上限 500MB
     # HS256 需足夠長的密鑰;過短會觸發 PyJWT InsecureKeyLengthWarning,且驗證可能失敗(客戶端 422)
     JWT_SECRET_KEY = os.environ.get(
         'JWT_SECRET_KEY',

+ 3 - 0
BridgeDiseaseBackend-main/app/routes/__init__.py

@@ -7,6 +7,7 @@ media_routes = Blueprint('media', __name__, url_prefix='/media')
 detection_routes = Blueprint('detection', __name__, url_prefix='/detection')
 operation_routes = Blueprint('operation', __name__, url_prefix='/operation')
 file_routes = Blueprint('file', __name__, url_prefix='/file')
+training_routes = Blueprint('training', __name__, url_prefix='/training')
 
 
 def register_routes(app):
@@ -27,6 +28,7 @@ def register_routes(app):
     app.register_blueprint(detection_routes)
     app.register_blueprint(operation_routes)
     app.register_blueprint(file_routes)
+    app.register_blueprint(training_routes)
 
 
 from .user_route import *
@@ -35,3 +37,4 @@ from .media_route import *
 from .detection_route import *
 from .operation_route import *
 from .file_route import *
+from .training_route import *

+ 7 - 2
BridgeDiseaseBackend-main/app/routes/detection_route.py

@@ -9,13 +9,14 @@ from pathlib import Path
 from zoneinfo import ZoneInfo
 
 import numpy as np
+import torch
 from PIL import Image
 from flask import jsonify, request, current_app, Response, stream_with_context
 from flask_jwt_extended import jwt_required, get_jwt_identity
 from ultralytics import YOLO
 
 from app import Config
-from app.constants import TaskStatus, OperationType, UserRole
+from app.constants import TaskStatus, OperationType, UserRole, DiseaseGrade
 from app.decorators import login_required
 from app.models import Detection, Media, Model, Operation, User, db
 from app.routes import detection_routes
@@ -129,10 +130,12 @@ def detection_segmentation():
             current_app.logger.warning(failure_message)
             return jsonify({'operation': new_operation.to_dict()}), 400
         yolo_model = YOLO(model_path)
+        use_cuda = torch.cuda.is_available()
         results = yolo_model.predict(
             source=source_path,
             imgsz=1024,
-            half=True,
+            half=use_cuda,
+            device='cuda' if use_cuda else 'cpu',
             retina_masks=True,
             save=True,
             project=RESULTS_FOLDER,
@@ -237,6 +240,8 @@ def detection_segmentation():
                 average_crack_width,
                 average_avg_hue, media,
             )
+            if isinstance(disease_grade, str):
+                disease_grade = DiseaseGrade(disease_grade.lower())
 
             # 检测分割结果路径
             result_path = unify_result_media_format(media, current_user)

+ 1 - 0
BridgeDiseaseBackend-main/requirements.txt

@@ -14,4 +14,5 @@ torch
 torchvision
 torchaudio
 ultralytics
+PyYAML
 Werkzeug

+ 13 - 2
README.md

@@ -58,6 +58,14 @@
 - 上传与管理 **YOLO 权重**(`.pt`),供检测页选用。
 - 侧栏**仅对 `DEVELOPER` 可见**;`ADMIN` 与普通用户不展示该入口。
 
+### 模型训练(`/model-training`)
+
+- **`ADMIN` / `DEVELOPER` 可见**:上传 Ultralytics **YOLO 格式**数据集(ZIP,内含 `data.yaml`),选择 YOLOv8n/s/m-seg 基线权重启动分割训练。
+- 训练在后台线程执行,任务列表可查看进度与日志;完成后可将 `best.pt` **自动注册到模型库**(含 mAP 等指标)。
+- 数据与产物目录:`BridgeDiseaseBackend-main/data/datasets`、`data/training_runs`。
+- 数据集指南与 `data.yaml` 模板:[`docs/TRAINING_DATASET.md`](BridgeDiseaseBackend-main/docs/TRAINING_DATASET.md)、[`training_templates/data.yaml.example`](BridgeDiseaseBackend-main/training_templates/data.yaml.example)。
+- 试跑用演示 ZIP:`python scripts/create_demo_dataset.py` → `training_templates/bridge_hazard_demo.zip`。
+
 ### 物联网监测(前端演示)
 
 以下四个模块共用 `localStorage`(`dockscope_iot_monitoring_v1`),用于展示监测业务界面,**未接后端**:
@@ -88,8 +96,8 @@
 | 角色 | 典型可见菜单 |
 |------|----------------|
 | `USER` | 数据看板、桥梁安全隐患检测、安全隐患检测记录、批量检测、安全隐患台账、报告中心、媒体库、物联网监测四模块 |
-| `DEVELOPER` | 上述 + **模型库** + 用户管理 + 系统操作日志 |
-| `ADMIN` | 与 `USER` 相同业务菜单 + 用户管理 + 系统操作日志(**无模型库**) |
+| `DEVELOPER` | 上述 + **模型库** + **模型训练** + 用户管理 + 系统操作日志 |
+| `ADMIN` | 与 `USER` 相同业务菜单 + **模型训练** + 用户管理 + 系统操作日志(**无模型库**) |
 
 路由见 `bridge-disease-frontend-main/src/router/index.js`;菜单见 `src/components/SidebarMenu.vue`。产品对外文案常量见 `src/shellConstants.js`(副标题:**桥梁安全隐患智能检测工作台**)。
 
@@ -136,6 +144,7 @@ flowchart LR
 | `/media` | 媒体上传与分页列表 |
 | `/model` | 模型上传与分页列表 |
 | `/detection` | 发起安全隐患检测、检测记录分页查询等 |
+| `/training` | 数据集上传、YOLOv8 训练任务启停与进度查询(开发人员) |
 | `/operation` | 操作日志分页(高权限) |
 | `/file` | 静态文件访问(头像、媒体、结果图等) |
 
@@ -189,6 +198,7 @@ sequenceDiagram
 
 ## 检澜界面截图
 
+![检澜 界面 1](images/1.0桥梁安全隐患训练.png)
 
 ![检澜 界面 1](images/1桥梁安全隐患检测.png)
 
@@ -345,6 +355,7 @@ npm run down
 | `scripts/seed_detections.py` | 插入 20 条安全隐患检测演示记录(需已有 user/model/media) |
 | `scripts/fix_user_names.py` | 修复用户姓名 `??` 乱码 |
 | `scripts/fix_model_texts.py` | 修复模型隐患类别、检测描述乱码 |
+| `scripts/seed_models.py` | 下载 YOLOv8n-seg 并复制为演示用 `.pt` 权重 |
 
 照片版权说明见 `BridgeDiseaseBackend-main/seed_assets/medias/ATTRIBUTION.md`。
 

+ 1 - 0
bridge-disease-frontend-main/src/components/BreadcrumbNav.vue

@@ -31,6 +31,7 @@ const breadcrumbs = computed(() => {
       'data-processing': '数据处理',
       'alert-management': '预警管理',
       'model-library': '模型库',
+      'model-training': '模型训练',
       'user-management': '用户管理',
       'operation-logs': '系统操作日志',
       'user-center': '个人中心'

+ 7 - 0
bridge-disease-frontend-main/src/components/SidebarMenu.vue

@@ -18,6 +18,7 @@ import {
   Files,
   Notebook,
   FolderOpened,
+  MagicStick,
 } from '@element-plus/icons-vue'
 import { isCollapsed, toggleCollapse } from '../stores/sidebarStore'
 
@@ -46,6 +47,12 @@ const menuItems = computed(() => [
     icon: DataAnalysis,
     visible: true
   },
+  {
+    name: '模型训练',
+    path: '/model-training',
+    icon: MagicStick,
+    visible: isAdminOrDeveloper.value
+  },
   {
     name: '桥梁安全隐患检测',
     path: '/disease-detection',

+ 6 - 0
bridge-disease-frontend-main/src/router/index.js

@@ -17,6 +17,7 @@ import AlertManagementView from '../views/AlertManagementView.vue'
 import BatchDetectionView from '../views/BatchDetectionView.vue'
 import DefectLedgerView from '../views/DefectLedgerView.vue'
 import ReportCenterView from '../views/ReportCenterView.vue'
+import ModelTrainingView from '../views/ModelTrainingView.vue'
 
 const router = createRouter({
   history: createWebHistory(import.meta.env.BASE_URL),
@@ -105,6 +106,11 @@ const router = createRouter({
       name: 'model-library',
       component: ModelLibraryView,
     },
+    {
+      path: '/model-training',
+      name: 'model-training',
+      component: ModelTrainingView,
+    },
     {
       path: '/user-management',
       name: 'user-management',

BIN
images/1.0桥梁安全隐患训练.png