feat: 完善 SAM2.1 模型选择与标注工作流
- 后端 SAM2 引擎新增 sam2.1_hiera_tiny、sam2.1_hiera_small、sam2.1_hiera_base_plus、sam2.1_hiera_large 四个变体定义,并按变体维护 checkpoint/config、image predictor、video predictor、加载状态、错误信息和真实状态回报。 - 后端 SAM registry 仅暴露当前产品启用的 SAM2.1 变体,保留 sam2 作为 tiny 兼容别名,拒绝 sam3 产品入口,并把 point、box、interactive、auto、propagate 都分发到所选 SAM2.1 变体。 - 后端默认配置和下载脚本切换到 SAM2.1 checkpoint 命名,支持 legacy SAM2 checkpoint fallback,并在状态消息中标出 fallback 使用情况。 - 前端全局 AI 模型状态新增 SAM2.1 tiny/small/base+/large 类型和默认 tiny,API 请求默认携带 sam2.1_hiera_tiny,AI 页面提供模型变体选择和所选模型状态展示。 - AI 智能分割页移除当前产品不使用的 SAM3/文本提示入口,保留正向点、反向点、框选和参数开关;AI 页只展示本页生成的候选 mask,并支持遮罩清晰度调节、候选 mask 上继续加正/反点、清空本页候选、推送到工作区编辑。 - 工作区和 Canvas 补强 SAM2 交互式细化链路:框选后正/反点继续细化同一个候选 mask,反向点请求启用背景过滤,空结果会移除被否定候选;AI 推送到工作区后保留选中态和未保存 draft mask。 - 工作区标注保存闭环补强:未保存 mask 可归档保存,dirty saved mask 可更新,保存后用后端 saved annotation 替换已提交 draft,清空/删除已保存 mask 时同步后端删除。 - Dashboard 任务进度区改为展示 queued、running、success、failed、cancelled 最近任务,处理中统计只计算 queued/running,并保留近期完成记录。 - 时间轴在顶部时间进度条和底部缩略图导航轴之间新增已编辑帧标记带,基于当前项目帧内 masks 标出已有编辑/标注的帧,并支持点击标记跳转。 - 前端测试覆盖 SAM2.1 变体选择、模型状态徽标、AI 页候选隔离、遮罩透明度、候选上追加正/反点、推送工作区保留选择、Canvas 交互式细化、VideoWorkspace 传播/保存、Dashboard 进度和时间轴已编辑帧标记。 - 后端测试覆盖 SAM2.1 变体状态、sam2 alias 兼容、sam3 禁用、semantic 禁用、传播标注保存、Dashboard 最近任务状态和 SAM3 历史测试跳过说明。 - README、AGENTS 和 doc 文档同步当前真实进度,更新 SAM2.1 变体、SAM3 禁用、接口契约、设计冻结、需求冻结、前端元素审计、实施计划、FastAPI docs 说明和测试矩阵。
This commit is contained in:
26
AGENTS.md
26
AGENTS.md
@@ -6,7 +6,7 @@
|
||||
|
||||
## 项目概述
|
||||
|
||||
本项目是一个**语义分割系统**(Semantic Segmentation System),当前形态是 React 前端 + FastAPI 后端的全栈 Web 应用,用于视频/DICOM 医学影像上传、显式视频生成帧、交互式 Canvas 标注、视频片段传播、GT mask 导入、SAM 2/SAM 3 可选辅助分割、模板分类管理和标注导出。
|
||||
本项目是一个**语义分割系统**(Semantic Segmentation System),当前形态是 React 前端 + FastAPI 后端的全栈 Web 应用,用于视频/DICOM 医学影像上传、显式视频生成帧、交互式 Canvas 标注、视频片段传播、GT mask 导入、可选 SAM 2.1 tiny/small/base+/large 辅助分割、模板分类管理和标注导出。SAM 3 相关源码和安装脚本保留在仓库中,但由于当前产品不提供文本提示,前端入口已隐藏,后端 registry 也不暴露 `sam3` 模型。
|
||||
|
||||
- **项目名称**: `react-example`(`package.json` 中的 `name`)
|
||||
- **前端入口**: `src/main.tsx` → `src/App.tsx`
|
||||
@@ -39,9 +39,9 @@
|
||||
| 缓存 / 队列 Broker | Redis |
|
||||
| 后台任务 | Celery worker |
|
||||
| 对象存储 | MinIO |
|
||||
| AI 推理 | SAM 2 / SAM 3 可选模型 + PyTorch;SAM 3 通过独立 Python 3.12 conda 环境桥接;`GET /api/ai/models/status` 返回真实 GPU/模型/本地 checkpoint 状态 |
|
||||
| AI 推理 | 当前启用 SAM 2.1 + PyTorch,可选 tiny/small/base+/large;`GET /api/ai/models/status` 返回真实 GPU 和各 SAM 2.1 变体状态;SAM 3 源码保留但产品入口禁用 |
|
||||
| 视频 / 影像处理 | FFmpeg / OpenCV / pydicom |
|
||||
| 运行时 | Node.js ES Modules;Python 3.11 后端环境;可选 `sam3` Python 3.12 conda 环境 |
|
||||
| 运行时 | Node.js ES Modules;Python 3.11 后端环境;历史保留的 `sam3` Python 3.12 conda 环境不是当前必需运行条件 |
|
||||
|
||||
---
|
||||
|
||||
@@ -71,7 +71,7 @@ Seg_Server/
|
||||
│ ├── celery_app.py # Celery app 配置
|
||||
│ ├── worker_tasks.py # Celery 任务入口
|
||||
│ ├── download_sam2.py # SAM 2 权重下载脚本
|
||||
│ ├── setup_sam3_env.sh # SAM 3 独立 Python 3.12 环境安装脚本
|
||||
│ ├── setup_sam3_env.sh # 历史保留的 SAM 3 独立 Python 3.12 环境安装脚本;当前产品入口禁用
|
||||
│ ├── requirements.txt # Python 依赖
|
||||
│ ├── routers/
|
||||
│ │ ├── auth.py # /api/auth/login
|
||||
@@ -82,10 +82,10 @@ Seg_Server/
|
||||
│ │ └── export.py # /api/export/{project_id}/coco、/masks
|
||||
│ └── services/
|
||||
│ ├── frame_parser.py # FFmpeg/OpenCV 拆帧、pydicom 读片、帧上传
|
||||
│ ├── 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 状态与推理分发
|
||||
│ ├── sam2_engine.py # SAM 2.1 变体选择、单帧推理和 video predictor 传播封装
|
||||
│ ├── sam3_engine.py # 历史保留的 SAM 3 桥接实现;当前未接入 registry
|
||||
│ ├── sam3_external_worker.py # 历史保留的独立 sam3 helper;当前未被产品入口调用
|
||||
│ └── sam_registry.py # 当前暴露 SAM 2.1 变体、GPU 状态与推理分发
|
||||
└── src/ # React 前端
|
||||
├── main.tsx # React StrictMode 挂载
|
||||
├── App.tsx # 登录拦截 + 模块切换
|
||||
@@ -222,10 +222,10 @@ uvicorn main:app --host 0.0.0.0 --port 8000 --reload
|
||||
3. 上传资源:视频走 `/api/media/upload`,只上传源文件并关联项目,不自动拆帧;DICOM 批量走 `/api/media/upload/dicom`。
|
||||
4. 生成帧入队:用户在项目库点击“生成帧”,选择目标 FPS 后前端调用 `/api/media/parse`;后端创建 `ProcessingTask` 并投递 Celery,接口支持 `parse_fps`、`max_frames` 和 `target_width` 标准帧序列参数。
|
||||
5. worker 执行:Celery worker 用 FFmpeg 优先拆视频帧,失败后用 OpenCV fallback,DICOM 使用 pydicom;视频帧按 `frame_%06d.jpg` 连续命名并记录 `timestamp_ms`、`source_frame_number` 和任务 `frame_sequence` 元数据。
|
||||
6. 帧展示:`VideoWorkspace.tsx` 调用 `/api/projects/{id}/frames`,`CanvasArea.tsx` 和 `FrameTimeline.tsx` 显示当前帧与时间轴缩略图;前端 `Frame` 会保留后端返回的帧序列时间戳和源帧号。
|
||||
6. 帧展示:`VideoWorkspace.tsx` 调用 `/api/projects/{id}/frames`,`CanvasArea.tsx` 和 `FrameTimeline.tsx` 显示当前帧与时间轴缩略图;`FrameTimeline` 会根据当前项目帧内的 `masks` 在进度条和缩略图导航轴之间标出已有编辑/标注的帧;前端 `Frame` 会保留后端返回的帧序列时间戳和源帧号。
|
||||
7. 手工标注:`CanvasArea.tsx` 支持多边形、矩形、圆、点区域和线段生成 polygon mask;多边形可按 Enter 或点击首节点闭合;绘制工具可在已有 mask 上继续落点;工具栏有“调整多边形”入口,点击 mask 可拖动/删除 polygon 顶点、通过边中点或双击边界插入新顶点,并能选择编辑多 polygon mask 的单个子区域;选中整块 mask 可用 Delete/Backspace 删除,已保存 mask 会同步后端删除;区域合并/去除会隐藏编辑手柄并显示已选数量,使用 `polygon-clipping` 做 union/difference,内含去除结果用 even-odd 规则渲染 hole;Zustand 维护 `maskHistory/maskFuture` 支持撤销/重做。
|
||||
8. AI 分割:前端工具包括正向点、反向点和框选;SAM 2 框选会建立候选 mask,后续正/反点通过 `interactive` prompt 携带原始框和累计点细化同一个候选 mask;包含反向点时工作区会传 `options.auto_filter_background=true` 和 `min_score=0.05`,如果后端过滤为空则移除旧候选 mask。后端 `ai.py` 期望按 `image_id`、`prompt_type`、`prompt_data`、`model` 和可选 `options` 调用 SAM registry。SAM 2 支持点/框/interactive/自动分割和 video predictor 传播,但不支持文本语义提示;AI 页面在 SAM 2 纯文本时提示改用点提示或切换 SAM 3,SAM 2 多候选默认只采用最高分区域,避免重叠候选同时显示;AI 页面生成的 mask 会写入全局 `masks` 并自动选中,右侧分类树可直接改标签,推送到工作区会切到“调整多边形”并保留选择。`options.crop_to_prompt` 可对点/框/interactive prompt 做局部裁剪推理并回映射,`options.auto_filter_background` 可按分数和负向点过滤结果;SAM 3 入口支持文本语义推理、框选提示和 external video tracker,semantic 请求会把正数 `options.min_score` 传给 external worker 作为置信度阈值,主后端会通过 `sam3_external_worker.py` 调用独立 Python 3.12 环境,并优先使用 `sam3_checkpoint_path` 指向的本地 `sam3权重/sam3.pt`;如果 Python/CUDA/包/本地 checkpoint 均满足,会在状态接口中标为可用。
|
||||
9. 视频片段传播:工作区“传播片段”把当前选中 mask 或当前帧第一个 mask 作为 seed,调用 `POST /api/ai/propagate`;后端按项目帧序列下载片段帧,SAM 2 用 `SAM2VideoPredictor.add_new_mask()` + `propagate_in_video()`,SAM 3 用独立 helper 的官方 `build_sam3_video_predictor()`,并把后续帧结果保存为 `Annotation`。
|
||||
8. AI 分割:前端工具包括 SAM 2.1 变体选择、正向点、反向点和框选;SAM 2.1 框选会建立候选 mask,后续正/反点通过 `interactive` prompt 携带原始框和累计点细化同一个候选 mask;包含反向点时工作区会传 `options.auto_filter_background=true` 和 `min_score=0.05`,如果后端过滤为空则移除旧候选 mask。后端 `ai.py` 期望按 `image_id`、`prompt_type`、`prompt_data`、`model` 和可选 `options` 调用 SAM registry。当前 registry 暴露 `sam2.1_hiera_tiny`、`sam2.1_hiera_small`、`sam2.1_hiera_base_plus`、`sam2.1_hiera_large`,并兼容 `sam2` 作为 tiny 别名;`model=sam3` 会被拒绝,`semantic` 文本提示也被禁用。SAM 2.1 支持点/框/interactive/自动分割和 video predictor 传播;多候选默认只采用最高分区域,避免重叠候选同时显示;AI 页面只渲染本页新生成的候选 mask,不会把工作区已有 mask 带入 AI 画布;AI 页面生成的 mask 会写入全局 `masks` 并自动选中,右侧分类树可直接改标签,推送到工作区会切到“调整多边形”并保留选择。`options.crop_to_prompt` 可对点/框/interactive prompt 做局部裁剪推理并回映射,`options.auto_filter_background` 可按分数和负向点过滤结果。
|
||||
9. 视频片段传播:工作区“传播片段”把当前选中 mask 或当前帧第一个 mask 作为 seed,调用 `POST /api/ai/propagate`;后端按项目帧序列下载片段帧,当前使用所选 SAM 2.1 变体的 `SAM2VideoPredictor.add_new_mask()` + `propagate_in_video()`,并把后续帧结果保存为 `Annotation`。
|
||||
10. GT 导入:工作区“导入 GT Mask”调用 `/api/ai/import-gt-mask`;后端按非零像素值和连通域生成 polygon 标注,并用 distance transform 生成 seed point;前端回显 seed point,拖动后可归档更新。
|
||||
11. 模板管理:`TemplateRegistry.tsx` 管理分类、颜色和 z-index;`OntologyInspector.tsx` 在工作区显示当前模板分类树。
|
||||
12. 导出:后端支持 COCO JSON 和 PNG mask ZIP 导出;PNG ZIP 包含单标注 mask、按 zIndex 融合的语义 mask 和 `semantic_classes.json`。
|
||||
@@ -242,12 +242,12 @@ uvicorn main:app --host 0.0.0.0 --port 8000 --reload
|
||||
- 前端 `importGtMask()` 已对齐后端 `/api/ai/import-gt-mask`;工作区“导入 GT Mask”会导入后端生成的多类别标注和 seed point 并回显。
|
||||
- 前端 `exportCoco()` 已对齐后端 `/api/export/{project_id}/coco`;前端 `exportMasks()` 已对齐后端 `/api/export/{project_id}/masks`;工作区导出按钮会先保存当前待归档 mask。
|
||||
- 工作区“结构化归档保存”按钮已接入 `POST /api/ai/annotate` 和 `PATCH /api/ai/annotations/{id}`;加载工作区时会通过 `GET /api/ai/annotations` 回显已保存标注。
|
||||
- 工作区“传播片段”按钮已接入 `POST /api/ai/propagate`;SAM 2 路径使用视频 predictor,SAM 3 路径使用独立 Python helper 的官方 video tracker,完成后刷新后端已保存标注。
|
||||
- 工作区“传播片段”按钮已接入 `POST /api/ai/propagate`;当前启用所选 SAM 2.1 变体的视频 predictor,完成后刷新后端已保存标注。
|
||||
- 工作区“清空遮罩”会调用 `DELETE /api/ai/annotations/{id}` 删除当前帧已保存标注,并清空当前帧本地 mask。
|
||||
- 项目状态已统一为 `pending`、`parsing`、`ready`、`error`;前端 `src/lib/api.ts` 会兼容归一化旧库中可能存在的 `Ready`、`Parsing`、`Error`。
|
||||
- 项目库的视频导入与生成帧是两个独立动作:导入视频只上传源文件,生成帧按钮才会带 `parse_fps` 调用 `/api/media/parse`;工作区不会再因“有视频但无帧”自动创建拆帧任务。
|
||||
- `server.ts` 仍有旧版 `/api/login`、`/api/projects`、`/api/templates` mock;当前前端真实 API 调用主要走 FastAPI 的 `/api/auth/*`、`/api/projects`、`/api/templates` 等接口。
|
||||
- `Dashboard.tsx` 初始统计、队列和活动日志来自 `GET /api/dashboard/overview`;解析队列来自 `processing_tasks`,支持取消 queued/running 任务、重试 failed/cancelled 任务和查看失败详情。Celery worker 通过 Redis pub/sub 的 `seg:progress` 频道推送细粒度进度,再由 FastAPI 广播到 `/ws/progress`;前端 WebSocket 客户端通过 `onopen/onclose/onerror` 更新连接状态,并定时发送 `ping` 心跳。
|
||||
- `Dashboard.tsx` 初始统计、任务进度和活动日志来自 `GET /api/dashboard/overview`;任务进度来自 `processing_tasks` queued/running/success/failed/cancelled,处理中统计只计算 queued/running,支持取消 queued/running 任务、重试 failed/cancelled 任务和查看失败详情。Celery worker 通过 Redis pub/sub 的 `seg:progress` 频道推送细粒度进度,再由 FastAPI 广播到 `/ws/progress`;前端 WebSocket 客户端通过 `onopen/onclose/onerror` 更新连接状态,并定时发送 `ping` 心跳。
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user