Files
Pre_Seg_Server/doc/07-current-requirements-freeze.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

13 KiB
Raw Blame History

当前需求冻结文档

冻结日期2026-05-01

本文档描述当前仓库已经实现或明确保留为占位的需求。测试用例以本文档为准,不把早期设想或 Word 文档中的远期能力当作当前版本必须实现的功能。

R1 登录与会话

  • 系统提供登录页。
  • 默认开发凭证为 admin / 123456
  • 登录成功后前端保存 token并进入主应用。
  • 登录失败时显示错误信息。
  • 当前 token 是开发用固定 token不做真实 JWT 校验。

R2 项目管理

  • 前端展示项目库,并从 GET /api/projects 获取项目列表。
  • 用户可以新建项目,前端调用 POST /api/projects
  • 用户可以选择项目,进入工作区。
  • 用户可以导入视频文件,前端创建项目、上传文件并刷新项目列表;导入视频不自动拆帧。
  • 用户可以对已导入且尚未生成帧的视频项目点击“生成帧”,在弹窗中选择目标 FPS 后创建拆帧任务。
  • 用户可以导入 DICOM 序列,前端上传 DICOM、触发拆帧、刷新项目列表。
  • 后端支持项目创建、列表、详情、局部更新和删除。
  • 后端支持项目帧创建、列表和单帧查询。

R3 媒体上传与拆帧

  • 后端允许上传视频、图片、DICOM 文件,其他扩展名返回 400。
  • 未提供项目 ID 上传时,后端自动创建项目。
  • 提供项目 ID 上传时,后端把上传对象关联到该项目。
  • 拆帧接口根据项目 source_type 处理视频或 DICOM。
  • 拆帧接口支持 parse_fpsmax_framestarget_width 参数,用于生成可被 SAM 2 / SAM 3 视频处理复用的标准帧序列。
  • 视频帧使用连续 frame_%06d.jpg 命名,默认从 frame_000000.jpg 开始,并按 target_width 缩放。
  • 拆帧完成后写入 frames 记录,并把项目状态设为 ready
  • 每条帧记录包含 frame_indeximage_urlwidthheighttimestamp_mssource_frame_number
  • 任务完成结果包含 frame_sequence 元数据:original_fpsparse_fpsframe_countduration_mstarget_width、帧宽高和对象存储前缀。
  • 拆帧接口会创建 processing_tasks 记录并投递 Celery worker。
  • 前端可通过 GET /api/tasks/{task_id} 查询任务状态。
  • 后端支持 POST /api/tasks/{task_id}/cancel 取消 queued/running 任务,写入 cancelled 状态并尝试 revoke Celery。
  • 后端支持 POST /api/tasks/{task_id}/retry 对 failed/cancelled 任务创建新的 queued 任务。
  • worker 会在关键阶段检查任务是否已取消,取消后停止继续写帧。

R4 工作区与帧浏览

  • 工作区根据当前项目加载帧列表。
  • 若项目有媒体但无帧,工作区只提示需要先在项目库生成帧,不再自动触发拆帧。
  • Canvas 显示当前帧图片。
  • Canvas 支持滚轮缩放、移动工具拖拽、鼠标坐标显示。
  • 时间轴支持缩略图点击切帧、range 拖动切帧、键盘左右方向键切帧、播放/暂停顺序推进帧。
  • 播放帧率使用项目 parse_fpsoriginal_fps,限制在 1 到 30 FPS。
  • 时间轴显示当前帧时间和总时长,时间基准使用项目 parse_fpsoriginal_fps,格式为 mm:ss.cc

R5 工具栏

  • 工具栏可以切换当前 active tool。
  • 正向点、反向点、框选工具会影响 Canvas 交互。
  • 魔法棒按钮切换到 AI 页面。
  • 多边形、矩形、圆、点、线工具会在 Canvas 上生成可保存的 polygon mask。
  • 多边形通过点击取点并按 Enter 完成,也支持三点后点击首节点闭合;矩形、圆、线通过拖拽生成;点工具生成小点区域。
  • 绘制工具点击已有 mask 时应继续执行当前绘制动作,不应被 mask 选择逻辑吞掉。
  • 工具栏提供“调整多边形”工具,用户可以点击 mask 进入 polygon 顶点编辑态;拖动顶点会更新 mask 几何并把已保存 mask 标记为 dirty。
  • 顶点编辑态显示边中点插入手柄;点击边中点会在该边中间新增顶点。
  • “调整多边形”工具下双击 polygon 边界时,会在最接近的线段上按双击位置新增顶点。
  • 顶点编辑态下选中顶点后可用 Delete/Backspace 删除顶点,但不会让 polygon 少于三点。
  • 选中整个 mask 且未选中具体顶点时Delete/Backspace 删除该 mask已保存 mask 同步调用后端删除接口。
  • 撤销、重做绑定全局 maskHistory/maskFuture支持工具栏按钮、AI 页按钮和 Canvas 快捷键。
  • 区域合并工具支持多选当前帧 mask并使用 polygon union 生成合并后的主 mask。
  • 区域去除工具支持多选当前帧 mask并从第一个选中的主 mask 中扣除后续选中 mask。
  • 区域合并/去除模式显示已选数量,并隐藏 polygon 编辑手柄以避免手柄抢占多选点击。
  • 区域去除结果包含内洞时,前端保留 hole ring 并用 even-odd 规则渲染。

R6 AI 推理

  • 前端可以在 AI 页面选择 sam2sam3,选择结果存放在全局 store。
  • 前端和工作区通过 GET /api/ai/models/status 展示 GPU、SAM 2 和 SAM 3 的真实运行状态。
  • 前端 predictMask() 调用 POST /api/ai/predict
  • 前端发送后端契约:image_idprompt_typeprompt_datamodel
  • 点提示传 { points, labels },正向点 label 为 1反向点 label 为 0。
  • 框选提示传归一化 [x1, y1, x2, y2]
  • 工作区 SAM 2 框选会建立一个候选 mask后续正向点/反向点会携带原始框和累计点,以 interactive prompt 细化并替换同一个候选 mask。
  • 工作区 SAM 2 一旦包含反向点,会随请求启用 auto_filter_backgroundmin_score=0.05;若后端判定反向点排除了当前候选区域并返回空结果,前端会移除旧候选 mask避免继续显示已被否定的区域。
  • SAM 2 不支持文本语义提示AI 页面在 SAM 2 下输入纯文本时会提示用户改用点提示或切换 SAM 3不再回退到自动分割。
  • SAM 2 点提示和 auto fallback 默认只采用一个最高分候选 mask避免多个候选 mask 作为同一结果重叠显示。
  • AI 页面生成的 SAM 2/SAM 3 mask 会写入全局 masks,自动同步到当前项目帧,并写入全局 selectedMaskIds;右侧语义分类树可以直接给新生成 mask 换标签。
  • AI 页面“推送至工作区编辑”会切回工作区并把工具切到“调整多边形”,保留当前选中的 AI mask 以便继续编辑轮廓和归档保存。
  • 语义文本提示传 semantic;选择 sam3 且独立 Python 3.12 环境、CUDA、官方包和本地 checkpoint 均满足时走 SAM 3 文本语义推理。
  • SAM 3 支持工作区框选提示;后端把 normalized [x1, y1, x2, y2] 转成官方 add_geometric_prompt() 需要的 [center_x, center_y, width, height] 正框。
  • 当前 SAM 3 前端路径不支持正/反点修正;在工作区用 SAM 3 进行点交互时,前端会提示切回 SAM 2。
  • 工作区“传播片段”会把当前选中区域或当前帧第一个区域作为 seed调用 POST /api/ai/propagate,默认从当前帧向后传播 30 帧并保存结果标注。
  • POST /api/ai/propagate 支持 model=sam2model=sam3SAM 2 使用官方 SAM2VideoPredictor.add_new_mask()propagate_in_video()SAM 3 通过独立 Python 3.12 helper 调用官方 build_sam3_video_predictor() video tracker。
  • 传播结果会写入后续帧 annotationsmask_data.source 分别标记为 sam2_propagationsam3_propagation,并保留 label、color 和 class 元数据。
  • AI 页面会对 SAM 3 空文本、推理失败和返回 0 个 mask 的情况显示明确反馈。
  • AI 参数支持 crop_to_promptauto_filter_backgroundmin_score;点/框 prompt 可以裁剪局部区域推理并回映射结果,背景过滤会移除低分结果和包含负向点的 polygonSAM 3 semantic 会用 min_score 控制 external worker 的置信度阈值。
  • 后端返回 polygonsscores
  • 前端把后端 polygons 转成 Konva pathDatasegmentationbboxarea
  • AI 推理结果先存放在前端 store 的 masks 中,点击“结构化归档保存”后持久化到后端标注表。

R7 标注保存

  • 后端提供 POST /api/ai/annotate 保存标注。
  • 保存时必须存在项目;如果传入 frame_id,帧也必须存在。
  • 后端提供 GET /api/ai/annotations 查询项目标注,可选按 frame_id 过滤。
  • 后端提供 PATCH /api/ai/annotations/{annotation_id} 更新已保存标注的 mask_datapointsbboxtemplate_id
  • 后端提供 DELETE /api/ai/annotations/{annotation_id} 删除已保存标注。
  • 当前前端“结构化归档保存”会保存当前项目未保存 mask并会更新已标记为 dirty 的已保存 mask。
  • 工作区“清空遮罩”会删除当前帧已保存标注,并清空当前帧未保存 mask。
  • 工作区加载项目帧后会查询已保存标注并回显。
  • 工作区支持导入 GT mask 图片,前端调用 POST /api/ai/import-gt-mask
  • 后端导入 GT mask 时按非零像素值拆分多类别区域,再按连通域生成 polygon 标注,并通过距离变换写入 seed point。
  • 前端会回显导入标注的 seed point拖动 seed point 后,已保存标注会变为 dirty归档保存时会更新后端 points

R8 模板库

  • 前端展示模板列表,调用 GET /api/templates
  • 用户可以新建、编辑、删除模板。
  • 模板分类存放在 mapping_rules.classes,规则存放在 mapping_rules.rules
  • 前端支持添加/删除分类、拖拽排序后重算 zIndex、JSON 批量导入、加载腹腔镜默认分类。
  • 后端支持模板创建、列表、详情、局部更新和删除。

R9 本体检查面板

  • 工作区右侧可以选择模板。
  • 面板显示模板分类和组件本地自定义分类。
  • 用户可以选择具体分类;新 AI mask 会记录 classIdclassNameclassZIndex,并在保存时写入 mask_data.class
  • 如果 Canvas 当前已经选中一个或多个 mask点击语义分类树会把这些 mask 的 labelcolor 和 class 元数据改为该分类;已保存 mask 会进入 dirty 状态,归档保存时更新后端。
  • 添加自定义分类只存在组件本地状态,不保存到后端。
  • 置信度、拓扑锚点和重新提取骨架按钮当前为展示/占位。

R10 Dashboard 与 WebSocket

  • Dashboard 显示基础统计、解析队列和活动日志。
  • Dashboard 初始数据来自 GET /api/dashboard/overview
  • 后端聚合项目数、处理中任务数、标注数、帧数、模板数和主机 load average。
  • 解析队列由 processing_tasks 中的 queued/running/failed/cancelled 任务生成;活动日志由最近任务、项目、标注和模板记录生成。
  • Dashboard 对 queued/running 任务提供取消按钮,对 failed/cancelled 任务提供重试按钮。
  • Dashboard 任务详情会读取 GET /api/tasks/{task_id} 并展示失败 error、payload、result、Celery ID 和时间信息。
  • Dashboard 会连接 /ws/progress
  • 收到 progress、complete、error、status 消息时,前端会更新队列或日志。
  • 收到 cancelled 消息时,前端会把对应任务标记为已取消。
  • Celery worker 每次更新 processing_tasks 后会发布 Redis seg:progress 事件FastAPI 订阅并广播给 /ws/progress 客户端。
  • 后端 WebSocket 接收到客户端消息后返回 status heartbeat。

R11 导出

  • 后端支持 GET /api/export/{project_id}/coco 导出 COCO JSON。
  • 后端支持 GET /api/export/{project_id}/masks 导出 PNG mask ZIP。
  • 当前前端 exportCoco() API 封装已对齐后端路径。
  • 当前前端 exportMasks() API 封装已对齐后端路径。
  • 工作区“导出 JSON 标注集”按钮已绑定下载事件;导出前会先保存当前未归档 mask。
  • 工作区“导出 PNG Mask ZIP”按钮已绑定下载事件导出前会先保存当前未归档 mask。
  • PNG mask ZIP 包含单标注二值 mask、按 zIndex 融合后的每帧语义 mask 和 semantic_classes.json

R12 配置

  • 前端 API 地址由 src/lib/config.ts 统一推导。
  • VITE_API_BASE_URL 优先级高于自动推导。
  • VITE_WS_PROGRESS_URL 优先级高于从 API 地址推导 WebSocket 地址。
  • 未设置环境变量时,前端按当前浏览器 hostname 推导 http://<host>:8000

R13 文档与测试

  • doc/ 目录保存当前实现审计、接口契约、需求冻结、设计冻结和测试计划。
  • 测试应覆盖当前冻结需求中的真实功能、半可用行为和明确占位行为。
  • 对外部服务依赖 PostgreSQL、MinIO、Redis、SAM 模型的测试应使用 mock 或测试替身,不依赖真实服务可用性。