Files
my-vault/自动语义分割系统/系统设计.md

497 lines
15 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.
---
title: ComfyUI 视频语义分割系统设计
date: 2026-04-22
tags:
- comfyUI
- SAM2
- 视频分割
- 语义分割
- 系统设计
---
# ComfyUI 视频语义分割系统设计
## 1. 设计目标
通过对视频单帧进行交互式语义分割(点/框/文本提示),利用视频追踪能力将分割结果传播到整个视频序列,并支持人工修正与迭代优化,最终实现对完整视频的自动化语义分割。
## 2. 核心功能
| 功能模块 | 说明 |
|---------|------|
| 单帧交互分割 | 支持点标注(正/负)、框标注、语义文本提示 |
| 双向视频追踪 | 以关键帧为锚点,向前/向后追踪目标对象 |
| 人工修正回环 | 对追踪过程中的错误帧进行人工修正,重新触发追踪 |
| 批量输出 | 输出每帧分割掩码Mask Sequence及合成视频 |
## 3. 技术架构
```mermaid
flowchart TB
subgraph Input["输入层"]
V[视频文件]
FP[第一帧 / 关键帧]
SP[语义提示词]
end
subgraph Interaction["交互分割层"]
P[点标注: 正选/反选]
B[框标注]
T[语义提示: Grounding DINO / CLIP]
SAM2_IMG[SAM2 Image Encoder + Decoder]
end
subgraph Tracking["视频追踪层"]
SAM2_VID[SAM2 Video Predictor]
FWD[前向追踪]
BWD[后向追踪]
MEM[记忆库: 多帧特征缓存]
end
subgraph Correction["修正回环层"]
CHECK[人工质检]
FIX[修正帧标注]
RE_TRACK[重新追踪]
end
subgraph Output["输出层"]
MASK[掩码序列]
COMP[合成视频]
MAT[抠像结果]
end
V --> FP
FP --> P & B & T
P & B & T --> SAM2_IMG
SAM2_IMG --> SAM2_VID
SAM2_VID --> FWD & BWD
FWD & BWD --> MEM
MEM --> CHECK
CHECK -->|发现问题| FIX
FIX --> RE_TRACK
RE_TRACK --> SAM2_VID
CHECK -->|确认无误| MASK
MASK --> COMP & MAT
```
## 3.1 模型选型
| 组件 | 推荐模型 | 作用 |
|------|---------|------|
| 图像分割基座 | **SAM2** (Segment Anything Model 2) | 提供单帧分割与视频追踪能力 |
| 语义 grounding | Grounding DINO / YOLO-World | 将文本提示转为检测框 |
| 特征缓存 | SAM2 Memory Attention | 跨帧特征传播与目标记忆 |
| 后处理 | 形态学滤波 / 时序一致性约束 | 消除帧间抖动与空洞 |
## 4. ComfyUI 节点设计
### 4.1 节点拓扑图
```mermaid
flowchart LR
subgraph 输入
LoadVideo["🎬 Load Video (Path + FPS)"]
FramePicker["🔍 Frame Picker (选帧)"]
end
subgraph 提示生成
PointPrompt["📍 Point Prompt (points + labels)"]
BoxPrompt["📦 Box Prompt (xyxy)"]
TextPrompt["💬 Text Prompt (语义)"]
Grounding["🎯 Grounding DINO / YOLO-World"]
end
subgraph SAM2核心
SAM2Loader["⚙️ SAM2 Model Loader"]
SAM2Image["🖼️ SAM2 Image Predictor"]
SAM2Video["🎞️ SAM2 Video Predictor"]
SAM2AddMask[" SAM2 Add Mask Hint"]
end
subgraph 追踪控制
TrackForward["⏩ Track Forward"]
TrackBackward["⏪ Track Backward"]
TrackRange["🔀 Track Range (双向)"]
end
subgraph 修正与输出
MaskViewer["👁️ Mask Viewer / 人工检查"]
MaskFix["✏️ Manual Mask Correction"]
MaskToVideo["🎬 Mask Sequence to Video"]
Composite["🎨 Composite (原图 + Mask)"]
SaveMasks["💾 Save Mask Sequence"]
end
LoadVideo --> FramePicker
FramePicker --> SAM2Image
PointPrompt & BoxPrompt --> SAM2Image
TextPrompt --> Grounding --> BoxPrompt
SAM2Loader --> SAM2Image & SAM2Video
SAM2Image --> SAM2Video
SAM2Video --> TrackForward & TrackBackward
TrackForward & TrackBackward --> MaskViewer
MaskViewer -->|OK| SaveMasks
MaskViewer -->|Fix| MaskFix
MaskFix --> SAM2AddMask --> SAM2Video
SaveMasks --> MaskToVideo & Composite
```
### 4.2 节点详细说明
#### 4.2.1 输入节点
**`LoadVideo`**
- 输入: 视频路径 (mp4/avi/mov)
- 输出: 图像批次 (image batch), 帧率, 总帧数, 元数据
- 参数: `start_frame`, `end_frame`, `skip_frame` (抽帧)
**`FramePicker`**
- 功能: 从视频批次中选择一帧作为关键帧
- 参数: `frame_index` (默认 0, 即第一帧)
- 输出: 单张图像 + 对应的批次索引
#### 4.2.2 提示节点
**`PointPrompt`**
- 输入: 图像坐标列表 `[(x1,y1), (x2,y2), ...]`
- 参数: `labels` (1=正选前景, 0=反选背景)
- 输出: 结构化 prompt 对象
**`BoxPrompt`**
- 输入: 边界框 `[[x1,y1,x2,y2], ...]`
- 支持多框同时输入
- 可与 PointPrompt 混合使用
**`TextPrompt`**
- 输入: 自然语言描述,如 `"a person wearing red hat"`
- 依赖: Grounding DINO / YOLO-World 节点前置转换
- 输出: 自动生成的 BoxPrompt
#### 4.2.3 SAM2 核心节点
**`SAM2ModelLoader`**
- 加载 SAM2 模型权重:
- `sam2_hiera_tiny.pt` (轻量/预览)
- `sam2_hiera_small.pt` (平衡)
- `sam2_hiera_base_plus.pt` (高精度)
- `sam2_hiera_large.pt` (最佳质量)
- 输出: model 对象
**`SAM2ImagePredictor`**
- 功能: 对单帧生成分割掩码
- 输入: image, model, point_prompt / box_prompt / mask_prompt
- 输出: mask (1,H,W), 置信度分数, logits
- 参数: `multimask_output` (是否输出多候选 mask)
**`SAM2VideoPredictor`**
- 功能: 初始化视频追踪状态
- 输入: model, video_frames (image batch), initial_frame_index, initial_mask
- 内部逻辑:
1. 对视频所有帧预计算图像编码 (Image Encoder)
2. 在初始帧注入 mask 作为记忆
3. 构建时空记忆库
- 输出: video_state 对象
**`SAM2AddMaskHint`**
- 功能: 在指定帧追加/修正 mask 提示,用于人工修正回环
- 输入: video_state, frame_index, new_mask
- 输出: 更新后的 video_state
#### 4.2.4 追踪节点
**`TrackForward`**
- 输入: video_state, start_frame, end_frame
- 逻辑: 从 start_frame 的记忆向后续帧传播
- 输出: mask_sequence (从 start 到 end 的掩码序列)
**`TrackBackward`**
- 输入: video_state, start_frame, end_frame
- 逻辑: 从 start_frame 的记忆向前序帧反向传播
- 输出: mask_sequence
**`TrackRange (双向追踪)`**
- 封装 TrackForward + TrackBackward
- 以关键帧为中心,自动向两端传播
- 输出: 完整视频的 mask_sequence
#### 4.2.5 修正与输出节点
**`MaskViewer`**
- 功能: 可视化 mask 叠加结果,支持逐帧检查
- 显示: 原图 + 半透明 mask + 边界轮廓
- 交互: 标记问题帧索引
**`ManualMaskCorrection`**
- 输入: 原图, 当前错误 mask
- 功能: 提供简易画板,人工涂鸦修正 mask
- 输出: 修正后的 mask
- 触发: 修正后的 mask 通过 `SAM2AddMaskHint` 重新注入追踪流程
**`MaskSequenceToVideo`**
- 输入: mask_sequence (batch of masks)
- 参数: `color_map`, `alpha`, `fps`
- 输出: 合成视频文件
**`CompositeMask`**
- 输入: 原视频帧, mask_sequence
- 功能: 生成绿幕/透明通道/高亮边框等合成效果
- 输出: 合成后的图像批次
**`SaveMaskSequence`**
- 输入: mask_sequence
- 输出: 按帧保存的 PNG (8-bit 灰度或 1-bit 掩码)
- 可选: 保存为 numpy `.npy` 数组供下游使用
## 5. 工作流程 (Workflow)
### 5.1 标准流程:第一帧标注 + 双向追踪
```mermaid
sequenceDiagram
actor User
participant UI as ComfyUI
participant V as 视频输入
participant S2 as SAM2
participant T as 追踪器
participant Out as 输出
User->>V: 上传视频
V->>UI: 提取帧序列
User->>UI: 选择第 0 帧
User->>UI: 点/框/文本标注目标
UI->>S2: 生成初始 mask
S2->>UI: 返回分割结果预览
User->>UI: 确认初始分割
UI->>T: 初始化 Video Predictor + 注入初始 mask
par 前向追踪
T->>T: 从第0帧 → 最后一帧
and 后向追踪
T->>T: 从第0帧 → 第0帧 (若首帧则无)
end
T->>UI: 返回完整 mask sequence
User->>UI: 逐帧检查结果
alt 发现问题
User->>UI: 在帧 N 进行人工修正
UI->>S2: 注入修正 mask
UI->>T: 从帧 N 重新双向追踪
T->>UI: 更新 mask sequence
else 无问题
UI->>Out: 输出最终掩码 + 合成视频
end
```
### 5.2 中途关键帧修正流程
当视频较长或目标发生严重形变/遮挡时,可在中间帧插入新的关键帧进行修正:
1. **运行标准流程** 获取初版 mask sequence
2. **人工检查** 发现帧 `[N, N+k]` 区间出现追踪漂移
3. **暂停追踪**,在帧 `N` 进行交互式重新标注(点/框修正)
4. **以帧 N 为新锚点**,分别执行:
- `TrackForward`: N → N+k (覆盖原错误区间)
- `TrackBackward`: N → 0 (可选,若前面也有问题)
5. **合并 mask sequence**: 用新追踪结果替换原错误区间
6. **输出最终序列**
## 6. 关键技术细节
### 6.1 SAM2 视频追踪原理
SAM2 的视频分割基于**流式记忆机制**
1. **图像编码**: 每帧独立通过 Hiera Image Encoder 提取视觉特征
2. **记忆注意力**: 当前帧的解码通过 Memory Attention 模块查询历史记忆
3. **记忆库组成**:
- **对象记忆**: 先前帧的高分辨率 mask 嵌入
- **位置记忆**: 帧间时空位置编码
- **指针记忆**: 最近帧的特征缓存
4. **传播方式**: 逐帧顺序传播,当前帧的分割结果成为下一帧的记忆提示
### 6.2 双向追踪策略
```
视频帧: [0] [1] [2] ... [N-1] [N] [N+1] ... [T]
^关键帧 K
|
┌───────────┴───────────┐
▼ ▼
后向追踪 前向追踪
K → K-1 → ... → 0 K → K+1 → ... → T
```
- **单关键帧**: 默认第一帧,向两端传播
- **多关键帧**: 长视频可分段设置多个关键帧,各自追踪后合并
### 6.3 修正回环机制
```python
# 伪代码示意
def iterative_video_segmentation(video, prompts):
# 1. 初始分割
keyframe = video[0]
mask_0 = sam2_image_predict(keyframe, prompts)
# 2. 初始化视频追踪
state = sam2_video_init(video)
state.add_mask(frame_idx=0, mask=mask_0)
# 3. 双向追踪
masks = track_bidirectional(state, anchor=0)
# 4. 人工修正回环
while True:
bad_frames = human_inspect(masks)
if not bad_frames:
break
fix_frame = bad_frames[0]
new_prompt = human_correct(video[fix_frame], masks[fix_frame])
new_mask = sam2_image_predict(video[fix_frame], new_prompt)
# 重新注入并局部追踪
state.add_mask(frame_idx=fix_frame, mask=new_mask)
masks = track_bidirectional(state, anchor=fix_frame)
return masks
```
### 6.4 语义提示链路
文本提示需先转换为空间位置信息,再输入 SAM2
```
用户输入: "the black cat on the sofa"
Grounding DINO / YOLO-World
检测框: [x1, y1, x2, y2] + 置信度
SAM2 Box Prompt
分割 Mask
```
若检测结果不准确,用户可手动调整检测框或直接切换为点标注模式。
## 7. 数据流定义
### 7.1 节点间数据格式
| 数据类型 | 格式 | 说明 |
|---------|------|------|
| `IMAGE` | `torch.Tensor` (B,H,W,C) uint8/float32 | 图像批次ComfyUI 原生格式 |
| `MASK` | `torch.Tensor` (B,1,H,W) float32 | 二值或概率掩码 |
| `SAM2_MODEL` | 自定义对象 | 含 image_encoder, memory_attention, mask_decoder |
| `SAM2_STATE` | 自定义对象 | 视频追踪状态,含特征缓存与记忆库 |
| `POINTS` | `List[Tuple[int,int]]` | 坐标列表 |
| `LABELS` | `List[int]` | 1=前景, 0=背景 |
| `BOXES` | `Tensor[N,4]` | xyxy 格式检测框 |
| `MASK_SEQ` | `List[Tensor[1,H,W]]` | 帧序列对应的掩码列表 |
### 7.2 输入输出规范
**输入**
- 视频文件: 支持常见格式 (mp4, mov, avi, mkv)
- 分辨率建议: ≤1080p (SAM2 对高分辨率显存敏感)
- 帧率: 按需抽帧,非必要不逐帧 (如 30fps 视频可抽 5-10fps)
**输出**
- Mask 序列: 每帧一个 PNG 灰度图,文件名 `frame_{:05d}.png`
- 合成视频: 带透明通道的 RGBA 视频或叠加遮罩的预览视频
- 元数据: JSON 记录每帧的分割类别、置信度、人工修正标记
## 8. 异常处理与边界情况
| 场景 | 策略 |
|------|------|
| 目标遮挡 > 50% 帧 | 依赖记忆库推断,若失败则提示人工标注 |
| 目标出画再入画 | SAM2 可能丢失目标,需在重新出现时设置新关键帧 |
| 多目标分割 | 每目标独立 mask支持批量追踪 |
| 光线剧烈变化 | 时序一致性后处理,或中间帧修正 |
| 显存不足 | 自动启用半精度 (fp16) / 梯度检查点 / 降低分辨率 |
| 追踪漂移累积 | 分段设置关键帧,限制单次追踪长度 |
## 9. 系统扩展性
### 9.1 未来可扩展方向
1. **自动关键帧检测**: 基于光流或特征差异自动建议关键帧位置
2. **多目标并行追踪**: 同时追踪多个语义对象,输出独立 mask 通道
3. **在线学习**: 利用人工修正样本微调分割模型
4. **实时预览**: 降低分辨率快速追踪预览,确认后再全分辨率输出
5. **与 3D 结合**: 输出 mask 用于 NeRF/3DGS 的前景分离
### 9.2 节点生态集成
| 现有 ComfyUI 生态 | 用途 |
|------------------|------|
| ComfyUI-VideoHelperSuite | 视频加载/保存/帧处理 |
| ComfyUI-SAM2 / WAS Node Suite | SAM2 基础封装 |
| ComfyUI-Impact-Pack (Detector) | Grounding DINO / YOLO 接入 |
| ComfyUI-Advanced-ControlNet | 时序一致性约束 |
| ComfyUI-Frame-Interpolation | 帧间 mask 插值补全 |
## 10. 部署与运行建议
### 10.1 硬件要求
| 配置 | 推荐规格 |
|------|---------|
| GPU | NVIDIA RTX 4090 / A100 (24GB+ VRAM) |
| RAM | 32GB+ |
| 存储 | SSD视频与中间特征缓存较大 |
### 10.2 软件依赖
```text
pytorch >= 2.0
cuda >= 11.8
sam2 (Meta 官方仓库)
comfyui (最新版)
opencv-python
imageio-ffmpeg
```
### 10.3 性能优化
- **预编码缓存**: 视频所有帧的图像特征只需编码一次,建议缓存到磁盘
- **分块追踪**: 长视频分段处理,避免显存持续增长
- **fp16 推理**: SAM2 支持半精度,显存占用减半,精度损失极小
- **关键帧密度**: 根据目标运动速度动态调整,慢速运动 2-5s 一帧,快速/形变 0.5-1s 一帧
---
## 附录ComfyUI 工作流 JSON 结构示意
```json
{
"last_node_id": 42,
"last_link_id": 89,
"nodes": [
{ "id": 1, "type": "LoadVideo", ... },
{ "id": 2, "type": "FramePicker", ... },
{ "id": 10, "type": "SAM2ModelLoader", "inputs": { "model_name": "sam2_hiera_base_plus.pt" } },
{ "id": 20, "type": "PointPrompt", ... },
{ "id": 25, "type": "SAM2ImagePredictor", ... },
{ "id": 30, "type": "SAM2VideoPredictor", ... },
{ "id": 35, "type": "TrackRange", ... },
{ "id": 40, "type": "MaskViewer", ... },
{ "id": 41, "type": "SaveMaskSequence", ... }
],
"links": [
[1, 0, 2, 0, "IMAGE"],
[2, 0, 25, 0, "IMAGE"],
[10, 0, 25, 1, "SAM2_MODEL"],
[20, 0, 25, 2, "POINTS"],
[25, 0, 30, 0, "MASK"],
[30, 0, 35, 0, "SAM2_STATE"],
[35, 0, 40, 0, "MASK_SEQ"],
[40, 0, 41, 0, "MASK_SEQ"]
]
}
```
---
> **备注**: 本系统核心依赖 SAM2 的视频追踪能力。若 ComfyUI 生态中 SAM2 节点尚未完全支持 video predictor 的全部特性(如记忆注入、双向追踪),需基于 [facebookresearch/segment-anything-2](https://github.com/facebookresearch/segment-anything-2) 官方实现进行 ComfyUI 节点封装。