Files
Pre_Seg_Server/README.md
admin 8a9247075e feat: 完善 AI 分割与工作区标注闭环
功能增加:

- 将视频导入和生成帧拆成两个明确动作,项目库生成帧时选择 FPS,工作区不再自动触发拆帧。

- 为工作区新增调整多边形工具,支持选中 mask、拖动顶点、边中点插点、双击边界按位置插点,并保留多 polygon 子区域编辑。

- 打通 AI 页 SAM2/SAM3 结果到工作区的联动,生成 mask 后自动选中,可在右侧分类树换标签,并推送到工作区继续编辑。

- 增强 Dashboard WebSocket 连接状态与心跳,使用真实 onopen/onclose/onerror 状态驱动前端显示。

- 完善 SAM3 external worker 适配,支持 box prompt、semantic 请求级阈值和 video tracker 路径。

bugfix:

- 修复 SAM2 文本语义误走自动分割的问题,改为提示使用点提示或切换 SAM3。

- 修复 SAM2 多候选重叠显示的问题,点提示和 auto fallback 默认只采用最高分候选。

- 修复 SAM2 反向点看起来无效的问题,带负点时启用背景过滤,过滤为空时移除旧候选。

- 修复 SAM3 单个 2D mask 结果无法转 polygon、低阈值 semantic 返回被默认阈值吞掉的问题。

- 修复 AI 页 mask 未选中导致分类树无法修改 SAM2 结果标签的问题。

测试和文档:

- 补充 CanvasArea、AISegmentation、ProjectLibrary、VideoWorkspace、Dashboard、websocket 和 SAM engine/API 测试。

- 新增 backend/tests/test_sam2_engine.py,覆盖 SAM2 单候选请求和 auto fallback 行为。

- 更新 README、AGENTS 和 doc 需求/设计/接口/测试矩阵,按当前实现冻结功能状态。
2026-05-01 21:50:17 +08:00

490 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<div align="center">
<img width="1200" height="475" alt="GHBanner" src="https://github.com/user-attachments/assets/0aa67016-6eaf-458a-adb2-6e31a0763ed6" />
</div>
# 语义分割系统SegServer
> 基于 React + FastAPI + 可选 SAM 2 / SAM 3 的全栈交互式图像/视频语义分割与标注平台。
>
> 支持本地多媒体资产上传、服务器端按帧解析、交互式 Canvas 标注、视频片段传播、GT mask 导入、模板分类管理和标注数据结构化导出;工作区点/框 AI 推理默认走 SAM 2SAM 3 支持语义文本、框选提示和 video tracker前端会显示真实 GPU/模型状态。
---
## 核心功能
- **多媒体资产管理** — 支持视频MP4/AVI/MOV和 DICOM 医学影像上传;视频导入与生成帧分离,生成帧时选择目标 FPS
- **AI 智能分割引擎** — 后端提供 SAM 2 / SAM 3 模型选择SAM 2 支持点分割point、框分割box、自动分割auto和 video predictor 传播前端默认只采用最高分候选避免重叠备选同时显示SAM 3 入口支持文本语义提示、框选提示和 external video tracker并按真实运行环境显示可用性
- **交互式画布标注** — 基于 Konva 的高性能 Canvas支持缩放/平移/手工多边形/矩形/圆/点/线、polygon 顶点拖动/删除、边中点插点、双击边界插点、区域合并/去除、选点/框选、撤销/重做,实时渲染 Mask 遮罩
- **GT Mask 导入** — 工作区可导入 GT mask 图片,后端按非零像素值和连通域生成 polygon 标注并用 distance transform 写入 seed point前端可回显和拖动 seed point
- **本体字典管理** — 可配置的分类体系、颜色映射、图层优先级z-index
- **项目工作区** — 项目创建、帧浏览、多图层标注、进度追踪
- **数据导出** — 支持 COCO JSON 格式和 PNG Mask 批量导出PNG ZIP 包含单标注 mask、按 z-index 融合的语义 mask 和类别映射
---
## 系统架构
```
┌─────────────────────────────────────────────────────────────┐
│ 前端展示层 (React 19 + Vite + TailwindCSS) │
│ localhost:3000 │
│ Zustand(状态) + Axios(API) + WebSocket(实时进度) │
│ Konva(Canvas渲染) + lucide-react(图标) │
└──────────────────────────┬──────────────────────────────────┘
│ HTTP / WebSocket
┌──────────────────────────▼──────────────────────────────────┐
│ 业务逻辑层 (FastAPI + Python 3.11) │
│ localhost:8000 │
│ ├── /api/auth 登录认证 │
│ ├── /api/projects 项目 & 视频帧 CRUD │
│ ├── /api/templates 本体字典(分类/颜色/z-index
│ ├── /api/media 文件上传 & 异步拆帧任务创建 │
│ ├── /api/tasks Celery 后台任务状态/取消/重试/详情 │
│ ├── /api/ai SAM 2 / SAM 3 推理与模型状态 │
│ └── /api/export COCO JSON / PNG Masks 导出 │
└──────────────────────────┬──────────────────────────────────┘
│ SQLAlchemy 2.0
┌──────────────────────────▼──────────────────────────────────┐
│ 数据持久化层 │
│ PostgreSQL 14 — 项目/帧/标注/Mask/Task 元数据 │
│ Redis 6 — Celery broker/result backend + 进度 pub/sub │
│ MinIO — 对象存储(原始视频/解析帧/Mask图像
└─────────────────────────────────────────────────────────────┘
```
---
## 技术栈
| 层级 | 技术选型 | 版本 |
|------|----------|------|
| 前端框架 | React + TypeScript | React 19, TS 5.8 |
| 构建工具 | Vite | v6 |
| 样式方案 | TailwindCSS + 自定义深色主题 | v4 |
| 状态管理 | Zustand | - |
| Canvas 渲染 | Konva + react-konva | - |
| 几何布尔运算 | polygon-clipping | 0.15+ |
| HTTP 客户端 | Axios | - |
| 后端框架 | FastAPI | v0.136+ |
| 数据库 ORM | SQLAlchemy依赖中包含 Alembic | 2.0+ |
| 数据库 | PostgreSQL | 14 |
| 队列 Broker | Redis | 6 |
| 后台任务 | Celery worker | 5.6+ |
| 对象存储 | MinIO | 2025+ |
| AI 推理 | SAM 2 / SAM 3 (Meta) + PyTorch | - |
| 视频处理 | FFmpeg + OpenCV | 4.4+ |
| DICOM 处理 | pydicom | 3.0+ |
---
## 目录结构
```
Seg_Server/
├── backend/ # FastAPI 后端
│ ├── main.py # 应用入口CORS/生命周期/路由注册/WebSocket
│ ├── config.py # 环境变量配置Pydantic Settings
│ ├── database.py # SQLAlchemy 引擎 + Session
│ ├── models.py # ORM 模型Project/Frame/Template/Annotation/Mask/ProcessingTask
│ ├── schemas.py # Pydantic 请求/响应校验模型
│ ├── minio_client.py # MinIO 上传/下载/预签名URL封装
│ ├── redis_client.py # Redis 连接封装
│ ├── progress_events.py # 任务进度事件 payload 与 Redis 发布
│ ├── statuses.py # 项目/任务状态常量
│ ├── celery_app.py # Celery app 配置
│ ├── worker_tasks.py # Celery 任务入口
│ ├── download_sam2.py # SAM 2 模型权重自动下载脚本
│ ├── setup_sam3_env.sh # SAM 3 独立 Python 3.12 环境安装脚本
│ ├── requirements.txt # Python 依赖
│ ├── routers/ # API 路由
│ │ ├── auth.py # 登录认证
│ │ ├── projects.py # 项目 & 帧 CRUD
│ │ ├── templates.py # 本体字典管理
│ │ ├── media.py # 上传 & 解析
│ │ ├── ai.py # SAM 推理与模型状态接口
│ │ └── export.py # 数据导出
│ └── services/ # 业务服务
│ ├── sam2_engine.py # SAM 2 推理引擎(单帧推理 + video predictor 传播)
│ ├── sam3_engine.py # SAM 3 状态检测、外部环境桥接、文本语义推理、框选与 video tracker 适配器
│ ├── sam3_external_worker.py # 独立 sam3 conda 环境中执行的状态/推理 helper
│ ├── sam_registry.py # SAM 模型选择、GPU 状态与推理分发
│ └── frame_parser.py # FFmpeg 拆帧 / pydicom 读片
├── src/ # React 前端
│ ├── main.tsx # 应用挂载点
│ ├── App.tsx # 根组件(模块路由 + 鉴权)
│ ├── store/
│ │ └── useStore.ts # Zustand 全局状态
│ ├── lib/
│ │ ├── api.ts # Axios 实例 + API 方法封装
│ │ ├── websocket.ts # WebSocket 客户端(解析进度)
│ │ └── utils.ts # cn() 工具函数
│ └── components/ # 组件(扁平化目录)
│ ├── Login.tsx # 登录页
│ ├── Sidebar.tsx # 左侧导航栏
│ ├── Dashboard.tsx # 总体概况仪表盘(解析队列/任务控制)
│ ├── ProjectLibrary.tsx # 项目库列表
│ ├── VideoWorkspace.tsx # 核心分割工作区布局
│ ├── CanvasArea.tsx # Konva 画布(缩放/平移/手工绘制/选点/Mask渲染
│ ├── ToolsPalette.tsx # 左侧工具栏
│ ├── OntologyInspector.tsx # 右侧本体/属性检查面板
│ ├── FrameTimeline.tsx # 底部时间轴
│ ├── AISegmentation.tsx # AI 智能分割引擎界面
│ └── TemplateRegistry.tsx # 模板库管理
├── models/ # SAM 2 模型权重(.pt 文件)
├── uploads/ # 临时上传目录
├── frames/ # 临时帧目录
├── doc/ # 当前实现审计、接口契约与后续实施文档
├── public/
│ └── logo.png # 侧边栏 Logo 静态资源
├── start_services.sh # 一键启动所有服务脚本
├── server.ts # Express + Vite 前端入口(也保留少量旧版 mock API
├── index.html # SPA HTML 入口
├── vite.config.ts # Vite 构建配置
├── package.json # npm 依赖与脚本
└── tsconfig.json # TypeScript 配置
```
---
## 项目文档
当前实现审计与接口契约文档在 `doc/` 目录:
- `doc/01-purpose-and-word-summary.md` — 项目目的、Word 方案摘要与当前落地程度
- `doc/03-frontend-element-audit.md` — 前端逐元素功能审计标注真实可用、部分可用、Mock/UI-only、接口不通
- `doc/04-api-contracts.md` — 前后端接口契约和已知不一致
- `doc/06-fastapi-docs-explained.md``http://192.168.3.11:8000/docs` 的作用说明
---
## 环境准备
### 系统要求
- **OS**: Ubuntu 22.04 LTS
- **GPU**: NVIDIA GPU推荐 RTX 4090 或同等算力),用于 SAM 推理SAM 3 官方要求 Python 3.12+、PyTorch 2.7+ 和 CUDA 12.6+ 环境
- **CUDA**: 12.x / 13.x
- **Node.js**: 22.x+
- **Python**: 主后端使用 3.11(通过 Miniconda/Anaconda 管理SAM 3 使用独立 `sam3` Python 3.12 conda 环境
### 安装系统级依赖
```bash
# 更新包索引
sudo apt update
# 安装 PostgreSQL、Redis、FFmpeg、构建工具
sudo apt install -y postgresql postgresql-contrib redis-server ffmpeg \
libpq-dev build-essential curl ca-certificates gnupg
# 安装 MinIO二进制方式
mkdir -p ~/minio_data
cd /tmp
wget https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x minio
sudo mv minio /usr/local/bin/
```
---
## 部署流程
### 步骤 1: 配置 PostgreSQL 数据库
```bash
# 启动服务
sudo systemctl start postgresql redis-server
# 创建数据库和用户
sudo -u postgres psql -c "CREATE DATABASE segserver;"
sudo -u postgres psql -c "CREATE USER seguser WITH PASSWORD 'segpass123';"
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE segserver TO seguser;"
sudo -u postgres psql -d segserver -c "GRANT ALL ON SCHEMA public TO seguser;"
sudo -u postgres psql -c "ALTER DATABASE segserver OWNER TO seguser;"
```
### 步骤 2: 启动 MinIO
```bash
nohup minio server ~/minio_data --console-address :9001 > /tmp/minio.log 2>&1 &
# 验证
# API: http://localhost:9000
# 控制台: http://localhost:9001 minioadmin / minioadmin
```
### 步骤 3: 创建 Conda 环境并安装 Python 依赖
```bash
# 创建环境
conda create -n seg_server python=3.11 -y
conda activate seg_server
# 安装 PyTorch根据 CUDA 版本选择)
# CUDA 12.x 用户:
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124
# CPU 用户(无 GPU:
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
# 安装后端依赖
cd ~/Desktop/Seg_Server/backend
pip install -r requirements.txt
```
### 步骤 4: 下载 SAM 2 模型权重
```bash
cd ~/Desktop/Seg_Server/backend
python download_sam2.py
# 模型将下载到 ~/Desktop/Seg_Server/models/
# sam2_hiera_tiny.pt (149 MB)
# sam2_hiera_small.pt (176 MB)
# sam2_hiera_base_plus.pt (309 MB)
# sam2_hiera_large.pt (856 MB)
```
> **注意**:当前系统磁盘紧张时,建议仅保留 `sam2_hiera_tiny.pt`,删除其他模型以释放空间。
### 步骤 5: 可选安装 SAM 3 环境
当前后端不会把 SAM 3 直接装进 `seg_server`,而是通过独立 `sam3` conda 环境执行 `backend/services/sam3_external_worker.py`。这样可以保留现有 Python 3.11 / SAM 2 环境。
```bash
cd ~/Desktop/Seg_Server
./backend/setup_sam3_env.sh
# 如果已把权重放在 sam3权重/sam3.pt可直接走本地 checkpoint
# 未配置本地 checkpoint 时,才需要 Hugging Face gated repo 授权和登录。
```
官方 `facebook/sam3` 权重约 3.45 GB当前没有类似 SAM 2 `tiny/small/base/large` 的官方小权重梯度。当前仓库默认使用本机 `sam3权重/sam3.pt`,不会提交权重文件;未配置本地 checkpoint 且未获得 gated model 授权时,`GET /api/ai/models/status` 会把 SAM 3 标为不可用并说明 checkpoint access 不满足。
### 步骤 6: 配置环境变量
后端通过 `backend/config.py` 中的 Pydantic Settings 读取 `backend/.env`。如需覆盖默认值,请编辑以下文件:
**backend/.env**(数据库/Redis/MinIO/SAM 路径):
```ini
db_url=postgresql://seguser:segpass123@localhost:5432/segserver
redis_url=redis://localhost:6379/0
minio_endpoint=192.168.3.11:9000
minio_access_key=minioadmin
minio_secret_key=minioadmin
minio_secure=false
sam_model_path=/home/wkmgc/Desktop/Seg_Server/models/sam2_hiera_tiny.pt
sam_model_config=configs/sam2/sam2_hiera_t.yaml
sam_default_model=sam2
sam3_model_version=sam3
sam3_checkpoint_path=/home/wkmgc/Desktop/Seg_Server/sam3权重/sam3.pt
sam3_external_enabled=true
sam3_external_python=/home/wkmgc/miniconda3/envs/sam3/bin/python
sam3_timeout_seconds=300
cors_origins=["http://localhost:3000","http://192.168.3.11:3000"]
```
前端根目录的 `.env.example` 包含 AI Studio 注入变量和前端 API 配置:
```ini
VITE_API_BASE_URL=http://192.168.3.11:8000
VITE_WS_PROGRESS_URL=ws://192.168.3.11:8000/ws/progress
```
如果未配置 `VITE_API_BASE_URL`,前端会按当前浏览器 hostname 推导 `http://<host>:8000`
### 步骤 7: 启动后端服务
```bash
cd ~/Desktop/Seg_Server/backend
source ~/miniconda3/etc/profile.d/conda.sh
conda activate seg_server
uvicorn main:app --host 0.0.0.0 --port 8000
# 或使用后台模式
nohup uvicorn main:app --host 0.0.0.0 --port 8000 > /tmp/fastapi.log 2>&1 &
```
后端启动后将自动:
- 创建数据库表(如果不存在)
- 检查 MinIO bucket 是否存在
- 测试 Redis 连接
- 懒加载 SAM 模型;`GET /api/ai/models/status` 会返回 SAM 2、SAM 3、GPU 和 SAM 3 checkpoint access 的真实可用状态
- `/api/ai/predict` 支持 AI 参数 `crop_to_prompt``auto_filter_background``min_score`,用于点/框 prompt 的局部裁剪推理、回映射和背景过滤
- `/api/ai/propagate` 支持从当前帧 seed 区域向视频片段传播SAM 2 使用 `SAM2VideoPredictor.add_new_mask()` + `propagate_in_video()`SAM 3 通过独立 Python 3.12 helper 调用官方 `build_sam3_video_predictor()` video tracker
### 步骤 6.1: 启动 Celery Worker
```bash
cd ~/Desktop/Seg_Server/backend
source ~/miniconda3/etc/profile.d/conda.sh
conda activate seg_server
celery -A celery_app:celery_app worker --loglevel=info --concurrency=1
# 或使用后台模式
nohup celery -A celery_app:celery_app worker --loglevel=info --concurrency=1 > /tmp/celery.log 2>&1 &
```
视频导入只创建项目并把源视频保存到 MinIO不会自动拆帧用户在项目库点击“生成帧”后再选择目标 FPS 并调用 `POST /api/media/parse`。该接口只创建 `processing_tasks` 记录并把任务投递给 Celery真正的 FFmpeg/OpenCV/pydicom 拆帧由 worker 执行。接口支持 `parse_fps``max_frames``target_width`,用于生成后续 SAM 2 / SAM 3 视频处理可复用的标准帧序列;视频帧按 `frame_%06d.jpg` 连续命名,帧表会记录 `timestamp_ms``source_frame_number`,任务完成结果会返回 `frame_sequence` 元数据。worker 每次更新任务状态后会发布到 Redis `seg:progress` 频道FastAPI 订阅后转发到 `/ws/progress`,前端 Dashboard 可实时更新。Dashboard 的 WebSocket 状态由浏览器 `onopen/onclose/onerror` 驱动,客户端会定时发送 `ping` 心跳,服务端返回 `status` 确认连接。Dashboard 也可调用 `/api/tasks/{id}/cancel``/api/tasks/{id}/retry``/api/tasks/{id}` 完成任务取消、重试与失败详情查看。
### 步骤 7: 安装前端依赖并构建
```bash
cd ~/Desktop/Seg_Server
# 安装依赖
npm install
# 类型检查
npm run lint
# 生产构建
npm run build
# 启动前端服务
npm start
# 或使用后台模式
nohup npm start > /tmp/frontend.log 2>&1 &
```
---
## 一键启动(推荐)
项目根目录提供了 `start_services.sh` 脚本,可一键启动所有服务:
```bash
cd ~/Desktop/Seg_Server
./start_services.sh
```
脚本将依次检查并启动PostgreSQL → Redis → MinIO → FastAPI 后端 → Celery Worker → 前端。
---
## 访问地址与默认凭证
| 服务 | 地址 | 说明 |
|------|------|------|
| 前端界面 | http://localhost:3000 | admin / 123456 |
| 后端 API 文档 | http://localhost:8000/docs | Swagger UI |
| MinIO 控制台 | http://localhost:9001 | minioadmin / minioadmin |
| PostgreSQL | localhost:5432 | seguser / segpass123 |
---
## 可用命令
### 前端
```bash
npm install # 安装依赖
npm run dev # 运行 tsx server.tsExpress + Vite 中间件(端口 3000
npm run build # 生产构建(输出到 dist/
npm run lint # TypeScript 类型检查
npm run test # Vitest watch 模式
npm run test:run # Vitest 单次运行
npm start # Node.js 运行 server.ts生产静态服务 / 旧版 mock API
```
### 后端
```bash
# 在 conda seg_server 环境中
cd backend
pip install -r requirements-dev.txt # 安装后端测试依赖
pytest tests # 后端接口测试
uvicorn main:app --host 0.0.0.0 --port 8000 --reload # 开发模式(热重载)
uvicorn main:app --host 0.0.0.0 --port 8000 # 生产模式
celery -A celery_app:celery_app worker --loglevel=info --concurrency=1 # 后台任务 worker
```
---
## 常见问题
### Q1: 磁盘空间不足导致 PyTorch / sam2 安装失败
**现象**: `OSError: [Errno 28] No space left on device`
**解决**:
```bash
# 1. 清理系统包缓存
sudo apt autoremove -y && sudo apt clean
# 2. 清理 conda 缓存
conda clean --all -y
# 3. 仅保留最小模型
rm ~/Desktop/Seg_Server/models/sam2_hiera_large.pt
rm ~/Desktop/Seg_Server/models/sam2_hiera_base_plus.pt
rm ~/Desktop/Seg_Server/models/sam2_hiera_small.pt
# 4. 如需安装 sam2 包,确保有 >5GB 可用空间后再执行
```
### Q2: SAM 2 推理返回 dummy polygons矩形框
**原因**: `sam2` Python 包未安装,或模型权重路径不正确。
**解决**:
```bash
# 1. 确认模型文件存在
ls ~/Desktop/Seg_Server/models/sam2_hiera_tiny.pt
# 2. 安装 sam2需 >5GB 磁盘空间)
cd /tmp
git clone --depth 1 https://github.com/facebookresearch/segment-anything-2.git
cd segment-anything-2
pip install -e . --no-build-isolation
# 3. 重启后端服务
```
### Q3: MinIO 报 `XMinioStorageFull`
**原因**: 系统磁盘可用空间低于 MinIO 默认阈值。
**解决**: 清理解析产生的临时帧文件或扩展磁盘空间。
### Q4: 前端无法连接后端 API
**检查清单**:
1. 后端是否已启动(`curl http://localhost:8000/health`
2. `backend/.env` 中的 `cors_origins` 是否包含 `http://localhost:3000`
3. 前端是否配置了正确的 `VITE_API_BASE_URL`;未配置时会按当前浏览器 hostname 推导 `http://<host>:8000`
### Q5: 如何验证 AI 推理或 COCO 导出接口
**当前状态**:
- 前端 `predictMask()` 已发送后端需要的 `image_id``prompt_type``prompt_data`,并把后端 `polygons` 转成 Konva `pathData`
- 工作区点选/框选会使用当前帧的数据库 `frame.id` 调用 `/api/ai/predict`
- 工作区 SAM 2 交互式细化包含反向点时会启用后端背景过滤;若反向点排除了当前候选区域并返回空结果,前端会移除旧候选 mask。
- AI 页面生成的 SAM 2/SAM 3 mask 会写入全局 `masks` 并自动选中;右侧分类树可直接给生成结果换标签,“推送至工作区编辑”会切回工作区的多边形调整工具并保留选择。
- 工作区“传播片段”会使用当前选中区域或当前帧第一个区域作为 seed调用 `/api/ai/propagate`,并在完成后刷新已保存标注。
- 前端 `exportCoco()` 已对齐到 `/api/export/{projectId}/coco`
- 工作区“导出 JSON 标注集”和“导出 PNG Mask ZIP”按钮已绑定下载流程导出前会先保存当前待归档的前端 mask。
- 工作区“导入 GT Mask”按钮已绑定 `/api/ai/import-gt-mask`,导入后会刷新并回显已保存标注和 seed point。
- 工作区“结构化归档保存”按钮会把当前项目未保存 mask 写入 `POST /api/ai/annotate`,并把 dirty mask 写入 `PATCH /api/ai/annotations/{id}`
- 工作区“清空遮罩”会通过 `DELETE /api/ai/annotations/{id}` 删除当前帧已保存标注,并清空当前帧本地 mask。
**验证**:
```bash
curl http://localhost:8000/health
curl http://localhost:8000/api/export/1/coco
curl http://localhost:8000/api/export/1/masks
```
---
## 开发团队
本项目基于 Google AI Studio 模板构建,经全栈化改造后用于工业级语义分割场景。
---
> 如需添加新功能或修复问题,请遵循项目根目录 `工程分析/代码编纂工作流.md` 中定义的代码编纂流程。