feat: 建立 SAM2 标注闭环基线
- 打通工作区真实标注闭环:支持手工多边形、矩形、圆形、点区域和线段生成 mask,并可保存、回显、更新和删除后端 annotation。 - 增强 polygon 编辑器:支持顶点拖动、顶点删除、边中点插入、多 polygon 子区域选择编辑,以及区域合并和区域去除。 - 接入 GT mask 导入:后端支持二值/多类别 mask 拆分、contour 转 polygon、distance transform seed point,前端支持导入、回显和 seed point 拖动编辑。 - 完善导出能力:COCO JSON 导出对齐前端,PNG mask ZIP 同时包含单标注 mask、按 zIndex 融合的 semantic_frame 和 semantic_classes.json。 - 打通异步任务管理:新增任务取消、重试、失败详情接口与 Dashboard 控件,worker 支持取消状态检查并通过 Redis/WebSocket 推送 cancelled 事件。 - 对接 Dashboard 后端数据:概览统计、解析队列和实时流转记录从 FastAPI 聚合接口与 WebSocket 更新。 - 增强 AI 推理参数:前端发送 crop_to_prompt、auto_filter_background 和 min_score,后端支持点/框 prompt 局部裁剪推理、结果回映射和负向点/低分过滤。 - 接入 SAM3 基础设施:新增独立 Python 3.12 sam3 环境安装脚本、外部 worker helper、后端桥接和真实 Python/CUDA/包/HF checkpoint access 状态检测。 - 保留 SAM3 授权边界:当前官方 facebook/sam3 gated 权重未授权时状态接口会返回不可用,不伪装成可推理。 - 增强前端状态管理:新增 mask undo/redo 历史栈、AI 模型选择状态、保存状态 dirty/draft/saved 流转和项目状态归一化。 - 更新前端 API 封装:补充 annotation CRUD、GT mask import、mask ZIP export、task cancel/retry/detail、AI runtime status 和 prediction options。 - 更新 UI 控件:ToolsPalette、AISegmentation、VideoWorkspace 和 CanvasArea 接入真实操作、导入导出、撤销重做、任务控制和模型状态。 - 新增 polygon-clipping 依赖,用于前端区域 union/difference 几何运算。 - 完善后端 schemas/status/progress:补充 AI 模型外部状态字段、任务 cancelled 状态和进度事件 payload。 - 补充测试覆盖:新增后端任务控制、SAM3 桥接、GT mask、导出融合、AI options 测试;补充前端 Canvas、Dashboard、VideoWorkspace、ToolsPalette、API 和 store 测试。 - 更新 README、AGENTS 和 doc 文档:冻结当前需求/设计/测试计划,标注真实功能、剩余 Mock、SAM3 授权边界和后续实施顺序。
This commit is contained in:
@@ -34,6 +34,8 @@ Authorization: Bearer <token>
|
||||
| `uploadDicomBatch(files, projectId)` | `POST /api/media/upload/dicom` | 对齐 | multipart form-data |
|
||||
| `parseMedia(projectId)` | `POST /api/media/parse?project_id=...` | 对齐 | 创建异步拆帧任务并返回 task |
|
||||
| `getTask(taskId)` | `GET /api/tasks/{task_id}` | 对齐 | 查询异步任务状态 |
|
||||
| `cancelTask(taskId)` | `POST /api/tasks/{task_id}/cancel` | 对齐 | 取消 queued/running 任务,后端写 cancelled 并尝试 revoke Celery |
|
||||
| `retryTask(taskId)` | `POST /api/tasks/{task_id}/retry` | 对齐 | 对 failed/cancelled 任务创建新的 queued 重试任务 |
|
||||
| `getProjectFrames(projectId)` | `GET /api/projects/{id}/frames` | 对齐 | 后端返回预签名 image_url |
|
||||
| `predictMask(payload)` | `POST /api/ai/predict` | 对齐 | 前端发送 `image_id/prompt_type/prompt_data/model`,并把后端 `polygons` 转为 `masks[].pathData` |
|
||||
| `getAiModelStatus(selectedModel?)` | `GET /api/ai/models/status` | 对齐 | 返回 GPU、SAM 2、SAM 3 的真实运行状态 |
|
||||
@@ -41,8 +43,10 @@ Authorization: Bearer <token>
|
||||
| `saveAnnotation(payload)` | `POST /api/ai/annotate` | 对齐 | 工作区归档保存当前项目未保存 mask |
|
||||
| `updateAnnotation(annotationId, payload)` | `PATCH /api/ai/annotations/{annotation_id}` | 对齐 | 工作区归档保存 dirty mask |
|
||||
| `deleteAnnotation(annotationId)` | `DELETE /api/ai/annotations/{annotation_id}` | 对齐 | 工作区清空当前帧已保存标注 |
|
||||
| `importGtMask(file, projectId, frameId, templateId?)` | `POST /api/ai/import-gt-mask` | 对齐 | multipart 上传 GT mask,后端按非零像素值/连通域生成 polygon 标注和 seed point |
|
||||
| `getDashboardOverview()` | `GET /api/dashboard/overview` | 对齐 | Dashboard 初始统计、队列和活动日志 |
|
||||
| `exportCoco(projectId)` | `GET /api/export/{projectId}/coco` | 对齐 | 后端实际是 `GET /api/export/{project_id}/coco` |
|
||||
| `exportMasks(projectId)` | `GET /api/export/{projectId}/masks` | 对齐 | 下载单标注 mask、语义融合 mask 和类别映射 ZIP |
|
||||
|
||||
## 后端 FastAPI 接口
|
||||
|
||||
@@ -69,10 +73,13 @@ Authorization: Bearer <token>
|
||||
| POST | `/api/media/parse` | 创建 Celery 拆帧任务 |
|
||||
| GET | `/api/tasks` | 查询后台任务列表 |
|
||||
| GET | `/api/tasks/{task_id}` | 查询单个后台任务 |
|
||||
| POST | `/api/tasks/{task_id}/cancel` | 取消后台任务 |
|
||||
| POST | `/api/tasks/{task_id}/retry` | 重试失败或取消的后台任务 |
|
||||
| POST | `/api/ai/predict` | SAM 2 / SAM 3 可选推理 |
|
||||
| GET | `/api/ai/models/status` | GPU 和 SAM 模型状态 |
|
||||
| POST | `/api/ai/auto` | 自动分割 |
|
||||
| POST | `/api/ai/annotate` | 保存 AI 标注 |
|
||||
| POST | `/api/ai/import-gt-mask` | 导入 GT mask 并生成标注/seed point |
|
||||
| GET | `/api/ai/annotations` | 查询项目标注,可选按帧过滤 |
|
||||
| PATCH | `/api/ai/annotations/{annotation_id}` | 更新已保存标注 |
|
||||
| DELETE | `/api/ai/annotations/{annotation_id}` | 删除已保存标注 |
|
||||
@@ -143,7 +150,13 @@ Authorization: Bearer <token>
|
||||
|
||||
- `point`
|
||||
- `box`
|
||||
- `semantic`,选择 `sam3` 时进入 SAM 3 文本语义推理;选择 `sam2` 时仍回退到 auto segmentation
|
||||
- `semantic`,选择 `sam3` 时进入 SAM 3 文本语义推理;选择 `sam2` 时仍回退到 auto segmentation。SAM 3 真实可用性由 `/api/ai/models/status` 中的外部环境和 checkpoint access 状态决定。
|
||||
|
||||
可选 `options` 字段:
|
||||
|
||||
- `crop_to_prompt`:对 point/box prompt 按锚点或框附近区域裁剪后推理,再把 polygon 回映射到原图坐标。
|
||||
- `auto_filter_background`:过滤低分结果,并移除包含负向点的 polygon。
|
||||
- `min_score`:配合 `auto_filter_background` 使用的最低置信度阈值。
|
||||
|
||||
后端响应:
|
||||
|
||||
@@ -181,13 +194,19 @@ Authorization: Bearer <token>
|
||||
- `getProjectAnnotations()` 已接入 `GET /api/ai/annotations`。
|
||||
- `updateAnnotation()` 已接入 `PATCH /api/ai/annotations/{annotationId}`。
|
||||
- `deleteAnnotation()` 已接入 `DELETE /api/ai/annotations/{annotationId}`。
|
||||
- `importGtMask()` 已接入 `POST /api/ai/import-gt-mask`,导入后端生成的 polygon 标注、原始 `gt_label_value` 和 seed point。
|
||||
- `exportMasks()` 已接入 `GET /api/export/{projectId}/masks`。
|
||||
- `parseMedia()` 已改为创建 Celery 后台任务,并返回 `ProcessingTask`。
|
||||
- `getTask()` 已接入 `GET /api/tasks/{taskId}`。
|
||||
- `cancelTask()` 已接入 `POST /api/tasks/{taskId}/cancel`。
|
||||
- `retryTask()` 已接入 `POST /api/tasks/{taskId}/retry`。
|
||||
- `getDashboardOverview()` 已从 `processing_tasks` 聚合解析队列。
|
||||
- 工作区导出按钮已调用 `exportCoco()`,并会先保存未归档 mask。
|
||||
- Dashboard 任务列表已展示 queued/running/failed/cancelled 任务,并可通过 `getTask()` 查看失败详情。
|
||||
- 工作区导出按钮已调用 `exportCoco()` / `exportMasks()`,并会先保存未归档 mask。
|
||||
- PNG mask ZIP 已包含每帧 `semantic_frame_*.png` 和 `semantic_classes.json`,重叠区域按 zIndex 裁决。
|
||||
|
||||
## 仍需处理的接口问题
|
||||
|
||||
- WebSocket 地址已从 `VITE_WS_PROGRESS_URL` 读取,未配置时从 `API_BASE_URL` 推导;部署时仍要确认浏览器能访问该地址。
|
||||
- Celery worker 进度会写 PostgreSQL 任务表,同时发布到 Redis `seg:progress`;FastAPI 订阅后广播到 `/ws/progress`。
|
||||
- 已保存标注目前支持分类级更新和整帧清空删除;逐点几何编辑器尚未实现。
|
||||
- 已保存标注目前支持分类级更新、polygon 顶点拖动、顶点删除、边中点插入、多 polygon 子区域选择编辑后的 PATCH 更新和整帧清空删除;复杂洞结构的专业编辑仍未实现。
|
||||
|
||||
Reference in New Issue
Block a user