Kaynağa Gözat

初始化项目

eric.w 2 hafta önce
ebeveyn
işleme
461618c899
2 değiştirilmiş dosya ile 78 ekleme ve 26 silme
  1. 59 22
      README.md
  2. 19 4
      docker/backend/bootstrap.py

+ 59 - 22
README.md

@@ -1,6 +1,6 @@
 # 检澜(DockScope)
 
-**检澜 DockScope** 是面向**桥梁安全隐患智能检测**的一体化工作台:围绕「媒体 / 模型 / 检测任务 / 结果与指标 / 台账与报告」闭环,提供 Web 端界面与 REST API。本仓库为检澜**前后端源码**——前端 **Vue 3 + Element Plus + ECharts**(`bridge-disease-frontend-main`);后端 **Flask + SQLAlchemy + MySQL**(`BridgeDiseaseBackend-main`),检测推理基于 **Ultralytics YOLO**,对影像中的结构隐患区域进行识别、标注与量化评估。
+**检澜 DockScope** 是面向**桥梁安全隐患智能检测**的一体化工作台:围绕「媒体 / 模型 / **模型训练** / 检测任务 / 结果与指标 / 台账与报告」闭环,提供 Web 端界面与 REST API。本仓库为检澜**前后端源码**——前端 **Vue 3 + Element Plus + ECharts**(`bridge-disease-frontend-main`);后端 **Flask + SQLAlchemy + MySQL**(`BridgeDiseaseBackend-main`),检测推理基于 **Ultralytics YOLO**,对影像中的结构隐患区域进行识别、标注与量化评估。
 
 ![检澜 界面](images/0数据看板.png)
 
@@ -18,6 +18,15 @@
 
 - 登录后的默认工作台:侧栏导航、面包屑、**数据洞察**与**社群快捷入口**等壳层组件,以及基于 ECharts 的**历史统计图表**(`StatisticsCharts`)。
 
+### 模型训练(`/model-training`)
+
+- **`ADMIN` / `DEVELOPER` 可见**(侧栏紧跟在「数据看板」之后):上传 Ultralytics **YOLO 格式**数据集(ZIP,内含 `data.yaml`),选择 YOLOv8n/s/m-seg 基线权重启动**分割**训练。
+- 训练在 Flask 进程内以后台线程执行(**无需单独起训练服务**);任务列表展示排队 / 训练中 / 已完成 / 失败,支持刷新与自动恢复排队任务。
+- 完成后可将 `best.pt` **自动注册到模型库**(含 mAP 等指标);任务元数据持久化于 `data/training_meta/jobs.json`。
+- 数据与产物目录:`BridgeDiseaseBackend-main/data/datasets`、`data/training_runs`、`app/static/models`。
+- 文档与模板:[`docs/TRAINING_DATASET.md`](BridgeDiseaseBackend-main/docs/TRAINING_DATASET.md)、[`training_templates/data.yaml.example`](BridgeDiseaseBackend-main/training_templates/data.yaml.example)。
+- 试跑演示 ZIP:`cd BridgeDiseaseBackend-main && python scripts/create_demo_dataset.py` → `training_templates/bridge_hazard_demo.zip`(CPU 建议 `yolov8n-seg`、`epochs=5`、`batch=2`)。
+
 ### 桥梁安全隐患检测(`/disease-detection`)
 
 - 三步向导:选择 **检测模型**(`.pt`)→ 选择 **媒体**(图像或视频)→ 发起 **安全隐患检测**。
@@ -58,14 +67,6 @@
 - 上传与管理 **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`),用于展示监测业务界面,**未接后端**:
@@ -93,11 +94,27 @@
 
 ## 角色与界面
 
+### 侧栏菜单顺序(`SidebarMenu.vue`)
+
+1. 数据看板  
+2. **模型训练**(仅 `ADMIN` / `DEVELOPER`)  
+3. 桥梁安全隐患检测  
+4. 安全隐患检测记录  
+5. 批量安全隐患检测  
+6. 安全隐患台账  
+7. 报告中心  
+8. 媒体库  
+9. 传感器管理 → 数据采集 → 数据处理 → 预警管理(物联网演示)  
+10. 模型库(仅 `DEVELOPER`)  
+11. 用户管理、系统操作日志(`ADMIN` / `DEVELOPER`)
+
+### 角色可见入口
+
 | 角色 | 典型可见菜单 |
 |------|----------------|
 | `USER` | 数据看板、桥梁安全隐患检测、安全隐患检测记录、批量检测、安全隐患台账、报告中心、媒体库、物联网监测四模块 |
-| `DEVELOPER` | 上述 + **模型库** + **模型训练** + 用户管理 + 系统操作日志 |
-| `ADMIN` | 与 `USER` 相同业务菜单 + **模型训练** + 用户管理 + 系统操作日志(**无模型库**) |
+| `DEVELOPER` | 上述 + **模型训练**(第 2 项)+ **模型库** + 用户管理 + 系统操作日志 |
+| `ADMIN` | 与 `USER` 相同业务菜单 + **模型训练**(第 2 项)+ 用户管理 + 系统操作日志(**无模型库**) |
 
 路由见 `bridge-disease-frontend-main/src/router/index.js`;菜单见 `src/components/SidebarMenu.vue`。产品对外文案常量见 `src/shellConstants.js`(副标题:**桥梁安全隐患智能检测工作台**)。
 
@@ -144,7 +161,7 @@ flowchart LR
 | `/media` | 媒体上传与分页列表 |
 | `/model` | 模型上传与分页列表 |
 | `/detection` | 发起安全隐患检测、检测记录分页查询等 |
-| `/training` | 数据集上传、YOLOv8 训练任务启停与进度查询(开发人员) |
+| `/training` | 数据集上传、YOLOv8 训练任务、进度/日志、恢复排队任务(`ADMIN` / `DEVELOPER`) |
 | `/operation` | 操作日志分页(高权限) |
 | `/file` | 静态文件访问(头像、媒体、结果图等) |
 
@@ -177,9 +194,13 @@ sequenceDiagram
 |------|------|
 | `bridge-disease-frontend-main/` | 检澜 Web 前端(Vite + Vue 3) |
 | `BridgeDiseaseBackend-main/` | 检澜 API 与推理服务 |
-| `BridgeDiseaseBackend-main/scripts/` | 媒体/检测种子、编码修复等运维脚本 |
+| `BridgeDiseaseBackend-main/scripts/` | 媒体/检测/训练数据集种子、编码修复等运维脚本 |
+| `BridgeDiseaseBackend-main/docs/TRAINING_DATASET.md` | 模型训练数据集格式说明 |
+| `BridgeDiseaseBackend-main/training_templates/` | `data.yaml` 模板与演示 ZIP |
+| `scripts/start-backend.ps1` | 释放 5000 端口并启动检澜后端(Windows) |
 | `BridgeDiseaseBackend-main/seed_assets/` | 真实照片源文件(媒体种子) |
-| `BridgeDiseaseBackend-main/sql/` | `init_db.sql`、Docker 补丁 SQL |
+| `BridgeDiseaseBackend-main/sql/` | `init_db.sql`(最小种子)、`seed_snapshot.sql`(完整演示库) |
+| `BridgeDiseaseBackend-main/seed_assets/snapshot/` | 可提交的演示静态资源与训练元数据快照 |
 | `docker/` | 镜像构建、Nginx、后端 bootstrap |
 | `docker-compose.yml` | MySQL、后端、前端编排 |
 | `images/` | README 界面截图 |
@@ -279,22 +300,32 @@ npm run serve
 
 - Web:<http://localhost:5173>
 
-**4. 初始化种子数据(首次或空库)**
+**4. 初始化演示数据(首次或空库)**
+
+**方式 A — 一键快照(推荐,与维护者演示效果一致)**
+
+仓库已包含导出的 `sql/seed_snapshot.sql` 与 `seed_assets/snapshot/`(媒体、模型、检测结果、训练任务元数据):
 
 ```powershell
 cd BridgeDiseaseBackend-main
 $env:SQLALCHEMY_DATABASE_URI="mysql+pymysql://root:bridgedisease_root@127.0.0.1:3307/bridge_disease?charset=utf8mb4"
+python scripts/import_db_snapshot.py
+python run.py
+```
 
-# 建表后导入用户/模型(若 user 表为空,也可手动导入 sql/init_db.sql)
-python run.py   # 首次会 db.create_all()
+维护者更新快照:`python scripts/export_db_snapshot.py` 后提交 `sql/seed_snapshot.sql` 与 `seed_assets/snapshot/`。说明见 [`seed_assets/snapshot/README.md`](BridgeDiseaseBackend-main/seed_assets/snapshot/README.md)。
 
-# 可选:下载真实桥梁照片到 seed_assets(需联网)
-python scripts/download_real_medias.py
+**方式 B — 分步种子(体积极小,需联网下载照片)**
 
-# 媒体库种子(真实照片 → static/medias + media 表)
-python scripts/seed_medias.py
+```powershell
+cd BridgeDiseaseBackend-main
+$env:SQLALCHEMY_DATABASE_URI="mysql+pymysql://root:bridgedisease_root@127.0.0.1:3307/bridge_disease?charset=utf8mb4"
 
-# 安全隐患检测记录种子(20 条演示记录 + 结果预览图)
+python run.py   # 首次会 db.create_all(),空库可再导入 sql/init_db.sql
+
+python scripts/download_real_medias.py   # 可选
+python scripts/seed_medias.py
+python scripts/seed_models.py
 python scripts/seed_detections.py
 ```
 
@@ -356,6 +387,9 @@ npm run down
 | `scripts/fix_user_names.py` | 修复用户姓名 `??` 乱码 |
 | `scripts/fix_model_texts.py` | 修复模型隐患类别、检测描述乱码 |
 | `scripts/seed_models.py` | 下载 YOLOv8n-seg 并复制为演示用 `.pt` 权重 |
+| `scripts/create_demo_dataset.py` | 生成试跑用 `bridge_hazard_demo.zip` 与 YOLO 分割演示数据集 |
+| `scripts/export_db_snapshot.py` | 将当前 MySQL + 静态资源导出到 `sql/seed_snapshot.sql` 与 `seed_assets/snapshot/` |
+| `scripts/import_db_snapshot.py` | 导入上述快照(新同事一键还原演示环境) |
 
 照片版权说明见 `BridgeDiseaseBackend-main/seed_assets/medias/ATTRIBUTION.md`。
 
@@ -385,6 +419,7 @@ npm run down
 | 前端开发 | `cd bridge-disease-frontend-main && npm run serve` |
 | 前端构建 | `cd bridge-disease-frontend-main && npm run build` |
 | 后端开发 | `cd BridgeDiseaseBackend-main && python run.py` |
+| 后端开发(Windows) | 项目根目录 `.\scripts\start-backend.ps1` |
 
 ---
 
@@ -400,6 +435,8 @@ npm run down
 | 推理慢或内存不足 | PyTorch/YOLO 需足够 RAM;可选 GPU 环境 |
 | 批量检测 / 台账 / 报告 / IoT 数据丢失 | 上述模块数据在浏览器 `localStorage`,清缓存会重置 |
 | Mermaid 图不渲染 | 使用支持 Mermaid 的 Markdown 预览(GitHub、VS Code 插件等) |
+| 模型训练一直「排队」、列表变空 | 确认 5000 为本项目后端;刷新训练页或重启后端(会恢复 pending);`jobs.json` 损坏时可从 `jobs.json.bak` 恢复 |
+| 训练完成但任务列表无数据 | 多为 `jobs.json` 写入异常,已修复 datetime 序列化;修复后刷新页面 |
 
 ---
 

+ 19 - 4
docker/backend/bootstrap.py

@@ -1,7 +1,9 @@
-"""Create tables and seed MySQL from sql/init_db.sql when the user table is empty."""
+"""Create tables and seed MySQL when the user table is empty."""
 import os
+import shutil
 import subprocess
 import sys
+from pathlib import Path
 
 from app import create_app
 from app.models import User, db
@@ -15,9 +17,11 @@ def main() -> None:
             print("Database already initialized, skipping seed.")
             return
 
-        sql_path = os.path.join(os.getcwd(), "sql", "init_db.sql")
+        sql_path = os.path.join(os.getcwd(), "sql", "seed_snapshot.sql")
         if not os.path.isfile(sql_path):
-            print(f"Seed file not found: {sql_path}", file=sys.stderr)
+            sql_path = os.path.join(os.getcwd(), "sql", "init_db.sql")
+        if not os.path.isfile(sql_path):
+            print("Seed file not found: sql/seed_snapshot.sql or sql/init_db.sql", file=sys.stderr)
             sys.exit(1)
 
         host = os.environ["MYSQL_HOST"]
@@ -35,11 +39,22 @@ def main() -> None:
             f"-p{password}",
             database,
         ]
-        print("Seeding database from sql/init_db.sql ...")
+        print(f"Seeding database from {os.path.basename(sql_path)} ...")
         with open(sql_path, "rb") as f:
             subprocess.run(cmd, stdin=f, check=True)
         print("Seed completed.")
 
+        snapshot_static = Path("seed_assets/snapshot/static")
+        if snapshot_static.is_dir():
+            static_root = Path("app/static")
+            static_root.mkdir(parents=True, exist_ok=True)
+            for child in snapshot_static.iterdir():
+                dst = static_root / child.name
+                if dst.exists():
+                    shutil.rmtree(dst)
+                shutil.copytree(child, dst)
+            print(f"Restored static assets from {snapshot_static}")
+
 
 if __name__ == "__main__":
     main()