--- 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 节点封装。