Skip to content

Commit dbfb887

Browse files
committed
feat: drop SAM 1 (vit_h/l/b) and SAM 2.0 model types; keep only SAM 2.1 and SAM 3; bump v1.9.4
1 parent 6e9a06b commit dbfb887

5 files changed

Lines changed: 69 additions & 123 deletions

File tree

README.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -89,21 +89,22 @@ Core packages (`torch`, `torchvision`, `numpy`) are already provided by ComfyUI
8989
9090
### 3. Place SAM model checkpoints
9191
92-
Download SAM / SAM2 / SAM2.1 / SAM3 weights and place them in:
92+
Download SAM 2.1 / SAM 3 weights and place them in:
9393
9494
```
95-
ComfyUI/models/sams/ ← SAM ViT-H/L/B, SAM3
96-
ComfyUI/models/sam2/ ← SAM2, SAM2.1
95+
ComfyUI/models/sams/ ← SAM 3
96+
ComfyUI/models/sam2/ ← SAM 2.1
9797
```
9898
9999
| Model | File | Source |
100100
|-------|------|--------|
101-
| SAM ViT-H | `sam_vit_h_4b8939.pth` | [Meta AI](https://github.com/facebookresearch/segment-anything) |
102101
| SAM2.1 Large | `sam2.1_hiera_large.pt` | [Meta AI](https://github.com/facebookresearch/sam2) |
103102
| SAM3 | `sam3_hiera_large.pt` | [Meta AI](https://github.com/facebookresearch/sam3) |
104103

105104
The **SAM Model Loader** node auto-detects model type from the filename.
106105

106+
> **Note:** Legacy SAM 1 (ViT-H/L/B) and the original SAM 2.0 line are no longer supported. Only SAM 2.1 and SAM 3 are exposed.
107+
107108
### 4. (Optional) ViTMatte matting
108109

109110
For the highest-quality edge refinement (hair, fur, glass, lace):
@@ -158,12 +159,12 @@ All nodes appear in the ComfyUI menu under **MaskEditControl/** categories.
158159

159160
#### SAM Model Loader (MEC)
160161

161-
Loads SAM / SAM2 / SAM2.1 / SAM3 checkpoints with optional VRAM offload.
162+
Loads SAM 2.1 / SAM 3 checkpoints with optional VRAM offload.
162163

163164
| Parameter | Default | Description |
164165
|-----------|---------|-------------|
165166
| `model_name` || Checkpoint filename (auto-listed from `models/sams/` and `models/sam2/`) |
166-
| `model_type` | `auto` | Force type: `sam_vit_h`, `sam_vit_l`, `sam_vit_b`, `sam2`, `sam2.1`, `sam3`, or `auto` |
167+
| `model_type` | `auto` | Force type: `sam2.1`, `sam3`, or `auto` |
167168
| `device` | `cuda` | `cuda` / `cpu` |
168169
| `offload_to_cpu` | `false` | Keep model on CPU, move to GPU only during inference (saves ~2–4 GB VRAM) |
169170
| `dtype` | `float16` | `float16` / `bfloat16` / `float32` |
@@ -174,7 +175,7 @@ Loads SAM / SAM2 / SAM2.1 / SAM3 checkpoints with optional VRAM offload.
174175

175176
#### SAM Mask Generator (MEC)
176177

177-
Runs SAM/SAM2/SAM3 inference with point + bbox prompts, iterative refinement, and auto-negative point sampling.
178+
Runs SAM 2.1 / SAM 3 inference with point + bbox prompts, iterative refinement, and auto-negative point sampling.
178179

179180
| Parameter | Default | Description |
180181
|-----------|---------|-------------|
@@ -216,7 +217,7 @@ Run SAM inference and view **all 3 candidate masks** side-by-side with IoU score
216217

217218
#### Unified Segmentation (MEC)
218219

219-
One-node dispatcher for **SAM1, SAM2/2.1, SAM3, SeC, VideoMaMa** with automatic image vs. video detection.
220+
One-node dispatcher for **SAM 2.1, SAM 3, SeC, VideoMaMa** with automatic image vs. video detection.
220221

221222
| Parameter | Default | Description |
222223
|-----------|---------|-------------|
@@ -894,7 +895,7 @@ All 47 nodes at a glance:
894895

895896
| # | Node | Category | VRAM Tier | What it does |
896897
|---|------|----------|-----------|-------------|
897-
| 1 | SAM Model Loader | SAM | 2 | Load SAM/SAM2/SAM3 checkpoints |
898+
| 1 | SAM Model Loader | SAM | 2 | Load SAM 2.1 / SAM 3 checkpoints |
898899
| 2 | SAM Mask Generator | SAM | 2 | SAM inference with point + bbox prompts |
899900
| 3 | SAM Multi-Mask Picker | SAM | 2 | View all 3 SAM candidates, pick interactively |
900901
| 4 | Unified Segmentation | SAM | 2 | One-node dispatcher for all segmentation backends |
@@ -1180,7 +1181,7 @@ ComfyUI-CustomNodePacks/
11801181
│ ├── spline_mask_editor.js # Frontend: spline drawing canvas (normalized coords)
11811182
│ └── universal_reroute.js # Frontend: Nuke-style dot
11821183
├── nodes/
1183-
│ ├── sam_model_loader.py # SAM/SAM2/SAM3 model loader
1184+
│ ├── sam_model_loader.py # SAM 2.1 / SAM 3 model loader
11841185
│ ├── sam_mask_generator.py # SAM inference engine
11851186
│ ├── sam_multi_mask_picker.py # Multi-mask picker + JS widget
11861187
│ ├── sam_vitmatte_pipeline.py # SAM → ViTMatte end-to-end pipeline

nodes/mask_propagate_video.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ def _sam2_video(self, images, src_mask, source_frame, sam_model, points_json):
218218
model = model_info["model"]
219219
model_type = model_info["model_type"]
220220

221-
if model_type not in ("sam2", "sam2.1"):
221+
if model_type != "sam2.1":
222222
return self._static(src_mask, B)
223223

224224
try:

nodes/sam_model_loader.py

Lines changed: 34 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
"""
2-
SAMModelLoaderMEC – Load SAM2/SAM2.1/SAM3 (or original SAM) checkpoints.
2+
SAMModelLoaderMEC – Load SAM2.1 / SAM3 checkpoints.
33
44
Supports:
5-
- SAM2 / SAM2.1 via official sam2 package (pip install SAM-2)
6-
- SAM3 via sam2 package (uses SAM2 infrastructure)
7-
- Original SAM (vit_h/l/b) via segment_anything package
5+
- SAM 2.1 via official sam2 package (pip install SAM-2)
6+
- SAM 3 via sam2 package (uses SAM2 infrastructure)
87
- .safetensors / .pt / .pth checkpoint formats
98
- Optional CPU-offload to save VRAM
109
- Automatic model type detection from filename
1110
- Auto-download from HuggingFace Hub when model not found locally
11+
12+
NOTE: Legacy SAM 1 (vit_h/l/b) and the original SAM 2.0 line are no
13+
longer supported; only SAM 2.1 and SAM 3 are exposed.
1214
"""
1315

1416
import os
@@ -90,19 +92,18 @@ def restore_device(sam_wrapper):
9092

9193
# ── Official SAM2 config mapping for build_sam2 ──────────────────────
9294
# Keys match filename stems; values are config paths for the official
93-
# sam2 package (pip install SAM-2).
95+
# sam2 package (pip install SAM-2). Only SAM 2.1 configs are exposed —
96+
# SAM 2.0 has been removed from the supported model set.
9497
SAM2_CONFIGS = {
95-
"sam2_hiera_tiny": "configs/sam2/sam2_hiera_t.yaml",
96-
"sam2_hiera_small": "configs/sam2/sam2_hiera_s.yaml",
97-
"sam2_hiera_base": "configs/sam2/sam2_hiera_b+.yaml",
98-
"sam2_hiera_large": "configs/sam2/sam2_hiera_l.yaml",
9998
"sam2.1_hiera_tiny": "configs/sam2.1/sam2.1_hiera_t.yaml",
10099
"sam2.1_hiera_small": "configs/sam2.1/sam2.1_hiera_s.yaml",
101100
"sam2.1_hiera_base": "configs/sam2.1/sam2.1_hiera_b+.yaml",
102101
"sam2.1_hiera_large": "configs/sam2.1/sam2.1_hiera_l.yaml",
103102
}
104103

105104
# ── HuggingFace Hub auto-download registry ────────────────────────────
105+
# Only SAM 2.1 checkpoints are listed; SAM 2.0 and original SAM 1
106+
# (vit_h/l/b) have been retired.
106107
_DOWNLOAD_REGISTRY = {
107108
"sam2.1_hiera_large.pt": {
108109
"repo_id": "facebook/sam2.1-hiera-large",
@@ -120,37 +121,6 @@ def restore_device(sam_wrapper):
120121
"repo_id": "facebook/sam2.1-hiera-tiny",
121122
"filename": "sam2.1_hiera_tiny.pt",
122123
},
123-
"sam2_hiera_large.pt": {
124-
"repo_id": "facebook/sam2-hiera-large",
125-
"filename": "sam2_hiera_large.pt",
126-
},
127-
"sam2_hiera_base_plus.pt": {
128-
"repo_id": "facebook/sam2-hiera-base-plus",
129-
"filename": "sam2_hiera_base_plus.pt",
130-
},
131-
"sam2_hiera_small.pt": {
132-
"repo_id": "facebook/sam2-hiera-small",
133-
"filename": "sam2_hiera_small.pt",
134-
},
135-
"sam2_hiera_tiny.pt": {
136-
"repo_id": "facebook/sam2-hiera-tiny",
137-
"filename": "sam2_hiera_tiny.pt",
138-
},
139-
"sam_vit_h_4b8939.pth": {
140-
"repo_id": "ybelkada/segment-anything",
141-
"filename": "checkpoints/sam_vit_h_4b8939.pth",
142-
"subfolder": "checkpoints",
143-
},
144-
"sam_vit_l_0b3195.pth": {
145-
"repo_id": "ybelkada/segment-anything",
146-
"filename": "checkpoints/sam_vit_l_0b3195.pth",
147-
"subfolder": "checkpoints",
148-
},
149-
"sam_vit_b_01ec64.pth": {
150-
"repo_id": "ybelkada/segment-anything",
151-
"filename": "checkpoints/sam_vit_b_01ec64.pth",
152-
"subfolder": "checkpoints",
153-
},
154124
}
155125

156126

@@ -166,9 +136,8 @@ def _detect_config(model_name):
166136
normalized_name = name.replace(".", "").replace("_", "")
167137
if normalized_key in normalized_name:
168138
return config
169-
# Heuristic fallback
170-
is_21 = "2.1" in name or "2_1" in name
171-
prefix = "configs/sam2.1/sam2.1" if is_21 else "configs/sam2/sam2"
139+
# Heuristic fallback — SAM 2.1 is the only supported SAM2 variant.
140+
prefix = "configs/sam2.1/sam2.1"
172141
if "tiny" in name or "_t." in name:
173142
return f"{prefix}_hiera_t.yaml"
174143
if "small" in name or "_s." in name:
@@ -180,17 +149,14 @@ def _detect_config(model_name):
180149

181150

182151
class SAMModelLoaderMEC:
183-
"""Load a Segment Anything Model (SAM / SAM2 / SAM2.1 / SAM3).
152+
"""Load a Segment Anything Model (SAM 2.1 or SAM 3).
184153
185154
Uses the official ``sam2`` Python package (pip install SAM-2) for
186-
SAM2/2.1/SAM3 models. Falls back to ``segment_anything`` for
187-
original SAM (ViT-H/L/B).
155+
both architectures. Legacy SAM 1 (vit_h/l/b) and the original
156+
SAM 2.0 line are not supported.
188157
"""
189158

190-
SUPPORTED_TYPES = [
191-
"auto", "sam2", "sam2.1", "sam3",
192-
"sam_vit_h", "sam_vit_l", "sam_vit_b",
193-
]
159+
SUPPORTED_TYPES = ["auto", "sam2.1", "sam3"]
194160

195161
@classmethod
196162
def INPUT_TYPES(cls):
@@ -225,9 +191,8 @@ def INPUT_TYPES(cls):
225191
"default": "auto",
226192
"tooltip": (
227193
"Model architecture. 'auto' detects from filename.\n"
228-
"sam2/sam2.1: Segment Anything 2 (requires sam2 package)\n"
229-
"sam3: SAM3 (uses SAM2 infrastructure)\n"
230-
"sam_vit_*: Original SAM (requires segment_anything)"
194+
"sam2.1: Segment Anything 2.1 (requires sam2 package)\n"
195+
"sam3: SAM3 (uses SAM2 infrastructure)"
231196
),
232197
}),
233198
"device": (["auto", "cuda", "cpu"], {"default": "auto"}),
@@ -271,7 +236,7 @@ def _scan_extra_paths(cls, model_files):
271236
FUNCTION = "load"
272237
CATEGORY = "MaskEditControl/SAM"
273238
DESCRIPTION = (
274-
"Load SAM/SAM2/SAM2.1/SAM3 model. "
239+
"Load SAM 2.1 or SAM 3 model. "
275240
"Auto-detects architecture from filename. "
276241
"Supports VRAM offload."
277242
)
@@ -295,15 +260,17 @@ def load(self, model_name: str, model_type: str, device: str,
295260
sam_model = None
296261
load_method = "unknown"
297262

298-
if detected_type in ("sam2", "sam2.1", "sam3"):
299-
sam_model, load_method = self._load_sam2_family(
300-
model_path, clean_name, detected_type, torch_dtype, device, offload_to_cpu
301-
)
302-
else:
303-
sam_model, load_method = self._load_original_sam(
304-
model_path, detected_type, torch_dtype, device, offload_to_cpu
263+
if detected_type not in ("sam2.1", "sam3"):
264+
raise ValueError(
265+
f"Unsupported SAM model_type '{detected_type}'. "
266+
f"Only 'sam2.1' and 'sam3' are supported. "
267+
f"Legacy SAM 1 (vit_h/l/b) and SAM 2.0 have been removed."
305268
)
306269

270+
sam_model, load_method = self._load_sam2_family(
271+
model_path, clean_name, detected_type, torch_dtype, device, offload_to_cpu
272+
)
273+
307274
if sam_model is None:
308275
sam_model, load_method = self._load_generic_fallback(
309276
model_path, torch_dtype, device, offload_to_cpu
@@ -456,20 +423,14 @@ def _detect_type(model_name):
456423
return "sam3"
457424
if "sam2.1" in name or "sam2_1" in name:
458425
return "sam2.1"
459-
if "sam2" in name:
460-
return "sam2"
461-
if "vit_h" in name:
462-
return "sam_vit_h"
463-
if "vit_l" in name:
464-
return "sam_vit_l"
465-
if "vit_b" in name:
466-
return "sam_vit_b"
467-
return "sam2"
468-
469-
# ── SAM2 / SAM2.1 / SAM3 ─────────────────────────────────────────
426+
# Default everything else (including unlabelled checkpoints) to
427+
# SAM 2.1 — SAM 2.0 / SAM 1 are no longer supported.
428+
return "sam2.1"
429+
430+
# ── SAM 2.1 / SAM 3 ──────────────────────────────────────────────
470431
def _load_sam2_family(self, model_path, model_name, model_type,
471432
torch_dtype, device, offload):
472-
"""Load SAM2/2.1/SAM3 model using the official sam2 package.
433+
"""Load SAM 2.1 / SAM 3 model using the official sam2 package.
473434
474435
Strategy:
475436
1. Load state_dict from any format (safetensors/pt/pth)
@@ -548,24 +509,6 @@ def _load_state_dict(model_path):
548509
sd = sd["model"]
549510
return sd
550511

551-
# ── Original SAM ──────────────────────────────────────────────────
552-
@staticmethod
553-
def _load_original_sam(model_path, detected_type, torch_dtype, device, offload):
554-
try:
555-
from segment_anything import sam_model_registry
556-
arch_map = {"sam_vit_h": "vit_h", "sam_vit_l": "vit_l", "sam_vit_b": "vit_b"}
557-
arch = arch_map.get(detected_type, "vit_h")
558-
model = sam_model_registry[arch](checkpoint=model_path)
559-
model = model.to(torch_dtype)
560-
if not offload:
561-
model = model.to(device)
562-
return model, "sam_registry"
563-
except ImportError:
564-
logger.debug("[MEC] segment_anything not available")
565-
except Exception as e:
566-
logger.debug(f"[MEC] Original SAM failed: {e}")
567-
return None, "failed"
568-
569512
# ── Generic fallback ──────────────────────────────────────────────
570513
@staticmethod
571514
def _load_generic_fallback(model_path, torch_dtype, device, offload):

nodes/utils.py

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -514,31 +514,33 @@ def get_sam_predictor(model, model_type, img_np):
514514
"""Create the correct SAM predictor for the given model type and set image.
515515
516516
Args:
517-
model: loaded SAM model object (SAM2Base or SamModel)
518-
model_type: str ("sam2", "sam2.1", "sam3", "sam_vit_h", etc.)
517+
model: loaded SAM model object (SAM2Base)
518+
model_type: str ("sam2.1" or "sam3")
519519
img_np: uint8 (H, W, 3) RGB image
520520
521521
Returns: predictor object or None
522+
523+
NOTE: Only SAM 2.1 and SAM 3 are supported. Legacy SAM 1
524+
(vit_h/l/b) and the original SAM 2.0 line have been removed.
522525
"""
523526
predictor = None
524527

525-
if model_type in ("sam2", "sam2.1", "sam3"):
526-
try:
527-
from sam2.sam2_image_predictor import SAM2ImagePredictor
528-
predictor = SAM2ImagePredictor(model)
529-
except ImportError:
530-
logger.error(
531-
"[MEC] sam2 package not found. Install with:\n"
532-
" pip install git+https://github.com/facebookresearch/sam2.git"
533-
)
534-
return None
535-
else:
536-
try:
537-
from segment_anything import SamPredictor
538-
predictor = SamPredictor(model)
539-
except ImportError:
540-
logger.error("[MEC] segment_anything package not found.")
541-
return None
528+
if model_type not in ("sam2.1", "sam3"):
529+
logger.error(
530+
f"[MEC] Unsupported SAM model_type '{model_type}'. "
531+
f"Only 'sam2.1' and 'sam3' are supported."
532+
)
533+
return None
534+
535+
try:
536+
from sam2.sam2_image_predictor import SAM2ImagePredictor
537+
predictor = SAM2ImagePredictor(model)
538+
except ImportError:
539+
logger.error(
540+
"[MEC] sam2 package not found. Install with:\n"
541+
" pip install git+https://github.com/facebookresearch/sam2.git"
542+
)
543+
return None
542544

543545
if predictor is not None:
544546
try:

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[project]
22
name = "comfyui-customnodepacks"
3-
description = "Custom node packs for ComfyUI: FolderIncrementer (auto-versioning) + MaskEditControl (pinpoint mask editing with SAM2/SAM3, per-axis erode/expand, point editor, bbox tools, video mask propagation)."
4-
version = "1.9.3"
3+
description = "Custom node packs for ComfyUI: FolderIncrementer (auto-versioning) + MaskEditControl (pinpoint mask editing with SAM 2.1 / SAM 3, per-axis erode/expand, point editor, bbox tools, video mask propagation)."
4+
version = "1.9.4"
55
license = { file = "MIT-License" }
66
requires-python = ">=3.10"
77
readme = "README.md"

0 commit comments

Comments
 (0)