Ultralytics SAM 模型接口全解析:统一 Segment Anything(SAM / SAM2 / SAM3)家族的 Python API 参考
【免费下载链接】ultralyticsUltralytics YOLO26, YOLO11, YOLOv8 — object detection, instance segmentation, semantic segmentation, image classification, pose estimation, object tracking项目地址: https://gitcode.com/GitHub_Trending/ul/ultralytics
本篇文章基于 Ultralytics 仓库中 docs/en/reference/models/sam/model.md 所对应的 API 参考页,以 ultralytics/models/sam/model.py 中的SAM类为主线,系统讲解它在推理、加载、任务调度上的接口设计、默认行为与底层实现。读完你不仅能熟练使用from ultralytics import SAM完成框选、点选、负点提示等 promptable 分割,还能理解该类如何通过一个入口同时兼容 SAM、SAM 2 与 SAM 3 三类权重,并掌握其背后的 Predictor 推理流水线。
一、ultralytics.models.sam.model模块定位
在 Ultralytics 的代码树中,models/sam/目录专门承载 Segment Anything 系列模型的封装与推理逻辑,其中 ultralytics/models/sam/model.py 是最上层的模型接口文件,定义了向用户暴露的SAM类;同目录的 predict.py 实现底层预测器,build.py 负责按权重构建具体网络结构,build_sam3.py 负责构建 SAM 3 交互模型。模块导出集中在 ultralytics/models/sam/init.py,对外提供SAM、Predictor、SAM2Predictor、SAM2VideoPredictor、SAM2DynamicInteractivePredictor、SAM3Predictor等符号;同时顶层包 ultralytics/init.py 将SAM与YOLO、FastSAM、RTDETR等并列导出,因此日常使用只需:
from ultralytics import SAM根据类注释(model.py),SAM类是面向"实时图像分割任务"的接口类,设计目标是promptable segmentation(可提示分割):支持以边界框、点、标签等作为提示来产生目标掩码,并具备zero-shot(零样本)迁移能力——它由基于 SA-1B 数据集的 Segment Anything 项目发展而来,可适应未见过的图像分布与任务。它沿用了标准的 Ultralytics 引擎接口(.predict()、.info()、task等),但仅用于推理(task固定为"segment"),不支持训练、验证与导出。
二、单一入口兼容三代模型:构造函数与权重加载
SAM继承自引擎基类Model(见 ultralytics/engine/model.py),构造签名非常简单:
def __init__(self, model: str = "sam_b.pt") -> None:默认权重为sam_b.pt。构造函数内部依次做了三件事(model.py):
- 扩展名校验:要求权重文件后缀必须是
.pt或.pth,否则抛出NotImplementedError("SAM prediction requires pre-trained *.pt or *.pth model.")。这与 YOLO 等可端到端训练/导出的任务不同——SAM 只接受预训练检查点。 - 版本探测:依据文件名
stem是否包含"sam2"/"sam3"设置布尔标志self.is_sam2、self.is_sam3。例如sam2_b.pt→is_sam2=True,sam3_l.pt→is_sam3=True,而sam_b.pt两者皆 False。 - 以
task="segment"调用父类初始化,使该模型归入实例分割任务体系。
_load:不同代际权重的构建分派
真正的网络加载发生在_load()(model.py):
if self.is_sam3: from .build_sam3 import build_interactive_sam3 self.model = build_interactive_sam3(weights) else: from .build import build_sam # slow import self.model = build_sam(weights)可见 SAM 3 权重走 build_sam3.py 中的build_interactive_sam3,而 SAM 1 / SAM 2 / MobileSAM 等统一走 build.py 的build_sam。其中 import 被刻意做成局部延迟导入,以加快包的整体加载速度。
支持的预定义权重
build.py 中的sam_model_map给出了所有内置可识别的权重名及其构建函数,既包括官方 SAM 系列,也覆盖 Meta 的 SAM 2 / SAM 2.1 检查点:
| 家族 | 预定义权重名 | 备注 |
|---|---|---|
| SAM 1(Meta 原始 SAM) | sam_h.pt、sam_l.pt、sam_b.pt | ViT-H/L/B 主干 |
| MobileSAM | mobile_sam.pt | 轻量化的移动端变体 |
| SAM 2 | sam2_t.pt、sam2_s.pt、sam2_b.pt、sam2_l.pt | Tiny/Small/Base/Large |
| SAM 2.1 | sam2.1_t.pt、sam2.1_s.pt、sam2.1_b.pt、sam2.1_l.pt | 复用 SAM 2 的构建函数 |
若传入的权重名不在此映射内,build_sam会抛出FileNotFoundError并列出可用模型。你也可以传入自定义.pt/.pth文件的路径,只要后缀合法即可,例如SAM("path/to/custom_checkpoint.pt")。
注意:尽管
sam_model_map支持sam_h.pt、mobile_sam.pt等,官方文档 docs/en/models/sam.md 中"可用模型"表格仅正式列出sam_b.pt与sam_l.pt两个权重,均只支持 Inference(✅),训练、验证、导出为 ❌。MobileSAM 的完整介绍见 docs/en/models/mobile-sam.md。
三、推理入口:predict与__call__
SAM.predict()是整个接口的核心(model.py):
def predict(self, source, stream: bool = False, bboxes=None, points=None, labels=None, **kwargs):参数含义:
source:图像或视频路径,也可以是PIL.Image或np.ndarray。stream:为True时开启实时流式处理。bboxes:用于"框提示"的边界框坐标列表,格式为 XYXY。points:用于"点提示"的坐标列表,格式为像素坐标。labels:点提示对应的标签列表;1表示前景(要分割的目标),0表示背景(排除区域)。**kwargs:透传给底层预测器的其它参数。
SAM.__call__(model.py)是predict的别名,因此model(...)与model.predict(...)等价。
默认覆盖参数(override)
在predict内部,方法先构造一组默认 override,再与用户传入的kwargs合并(用户值优先),这是理解 SAM 行为的关键:
overrides = {"conf": 0.25, "task": "segment", "mode": "predict", "imgsz": 1024} kwargs = {**overrides, **kwargs, "retina_masks": True} prompts = {"bboxes": bboxes, "points": points, "labels": labels} return super().predict(source, stream, prompts=prompts, **kwargs)| 默认项 | 值 | 含义 |
|---|---|---|
conf | 0.25 | 掩码质量分数过滤阈值 |
task | segment | 分割任务 |
mode | predict | 推理模式(SAM 不支持训练/导出) |
imgsz | 1024 | 输入边长(仅支持正方形) |
retina_masks | True(强制) | 保留原始分辨率掩码而非下采样掩码 |
也就是说,提示词bboxes/points/labels并不作为普通 kwargs 直接下传,而是统一打包成prompts字典交给引擎,再由引擎路由到对应预测器的prompt_inference流程。bboxes、points、labels之外,底层预测器同样支持masks作为"掩码提示"(用于基于上一轮输出的细化迭代),见 predict.py。
典型调用示例
以仓库自带的示例图 ultralytics/assets/zidane.jpg 为例(与 docs/en/models/sam.md 一致):
from ultralytics import SAM # 加载模型(默认 sam_b.pt,也可显式指定权重) model = SAM("sam_b.pt") # 打印模型结构信息(可选) model.info() # ① 边界框提示:一次框选一个目标 results = model("ultralytics/assets/zidane.jpg", bboxes=[439, 437, 524, 709]) # ② 单点提示:labels=[1] 表示该点是前景 results = model(points=[900, 370], labels=[1]) # ③ 多点提示:同一对象给出多个正点,增强鲁棒性 results = model(points=[[400, 370], [900, 370]], labels=[1, 1]) # ④ 单对象多提示的嵌套写法(注意三层括号) results = model(points=[[[400, 370], [900, 370]]], labels=[[1, 1]]) # ⑤ 负点提示:一个正点 + 一个负点,排除误分区域 results = model(points=[[[400, 370], [900, 370]]], labels=[[1, 0]])当bboxes、points、masks提示全部为空时,预测器会自动切换为"Segment Everything"(全图自动分割)模式(见 predict.py),即对整张图像做无提示的密集掩码生成:
# 全图分割:不给任何提示 model("path/to/image.jpg")对应的 CLI 用法为:
yolo predict model=sam_b.pt source=path/to/image.jpg所有返回的results都是标准 Results 对象,可直接访问results[0].masks获取掩码、results[0].boxes获取框(SAM 不产出类别,框中的cls仅为对齐 Ultralytics 结果格式的占位符,注释见 predict.py)。
四、task_map:如何自动选择正确的 Predictor
task_map是只读属性(model.py),返回"segment"任务对应的预测器类,其分派完全由构造时探测到的is_sam2/is_sam3标志决定:
return { "segment": {"predictor": SAM2Predictor if self.is_sam2 else SAM3Predictor if self.is_sam3 else Predictor} }也就是说,同一个SAM类在加载不同权重后会自动装配不同代际的预测器:
| 权重家族 | is_sam2 | is_sam3 | 实际使用的 Predictor |
|---|---|---|---|
sam_b.pt/sam_l.pt/mobile_sam.pt | False | False | Predictor(predict.py) |
sam2_t.pt/sam2_b.pt/sam2.1_* | True | False | SAM2Predictor(predict.py) |
sam3_* | False | True | SAM3Predictor |
预测器家族的类定义位于 predict.py(该文件被 docs/en/reference/models/sam/predict.md 文档化),并随 ultralytics/models/sam/init.py 对外暴露。SAM 2 系列还额外提供面向视频流的分割跟踪器SAM2VideoPredictor与支持运行中动态追加提示的SAM2DynamicInteractivePredictor,它们的行为在 docs/en/models/sam-2.md 中有完整示例。
五、info():模型结构信息
info()(model.py)委托给工具函数model_info:
def info(self, detailed: bool = False, verbose: bool = True): return model_info(self.model, detailed=detailed, verbose=verbose)detailed=True会输出各层/运算的详细信息;返回的元组内含模型字符串表示,info[0]即概要信息。- 该函数来自 ultralytics/utils/torch_utils.py,与 YOLO 系列共用同一套参数统计逻辑。
六、源码纵深:SAM背后的推理流水线
要从"会调用"进阶到"懂原理",需要理解SAM类如何对接 predict.py 中的Predictor。以下几点最能体现 SAM 与 YOLO 推理的根本差异:
1. 一次性编码 + 多轮提示
提示型分割的核心优化是图像只编码一次、可反复施加提示。Predictor提供set_image()/reset_image()(predict.py):set_image预处理图像并经get_im_features调用self.model.image_encoder(im)缓存特征到self.features;此后每次仅用轻量的 prompt encoder + mask decoder 产出新掩码,无需重跑图像编码器。因此更高效的交互写法是:
import cv2 from ultralytics.models.sam import Predictor as SAMPredictor overrides = {"conf": 0.25, "task": "segment", "mode": "predict", "imgsz": 1024, "model": "mobile_sam.pt"} predictor = SAMPredictor(overrides=overrides) # 设置图像:既支持文件路径,也支持 cv2 读入的 BGR ndarray predictor.set_image("ultralytics/assets/zidane.jpg") # 同一张图反复施加不同提示 results = predictor(bboxes=[439, 437, 524, 709]) # 框提示 results = predictor(points=[900, 370], labels=[1]) # 单点 results = predictor(points=[[[400, 370], [900, 370]]], labels=[[1, 0]]) # 正+负点 predictor.reset_image() # 清空图像与缓存特征Predictor.__init__中固定batch: 1并把retina_masks置 True;pre_transform使用LetterBox填充为正方形(auto=False, center=False),且断言只支持单图、不支持批处理(predict.py)。
2. 三段式网络结构
prompt_inference(predict.py)完整呈现了 SAM 的"图像编码器 + 提示编码器 + 掩码解码器"三段式推理:先取缓存特征,经_prepare_prompts把像素坐标的框/点按 letterbox 缩放比映射到 1024×1024 特征空间(并自动把缺省labels置为全1,即默认视为正点),随后调用self.model.prompt_encoder(...)生成 sparse/dense 嵌入,最后self.model.mask_decoder(...)输出掩码与质量分数。multimask_output为 True 时每个提示会返回多个候选掩码以消解歧义。SAM 2 的SAM2Predictor则改用model.forward_image+sam_prompt_encoder+sam_mask_decoder,并把 box 提示折叠进 point 序列(附加[2, 3]标签),同时维护多尺度高层特征high_res_feats(predict.py)。
3. 全图分割的参数面
generate()(predict.py)支撑"Segment Everything",它按参数网格采样点、逐批推理、裁剪区域投票并做 NMS 去重。常用可调参数包括:
| 参数 | 默认值 | 含义 |
|---|---|---|
points_stride | 32 | 图像每边采样点的间隔(越小点越密) |
points_batch_size | 64 | 每批处理的提示点数 |
conf_thres | 0.88 | 掩码质量分数过滤阈值 |
stability_score_thresh | 0.95 | 掩码稳定性分数阈值 |
crop_n_layers | 0 | 是否在图像裁剪块上额外预测(>0 提升细节) |
crop_nms_thresh | 0.7 | 裁剪块之间去重的 IoU 阈值 |
例如希望更细粒度地全图分割,可调用predictor(source="ultralytics/assets/zidane.jpg", crop_n_layers=1, points_stride=64)。完整签名见 predict.py。
4. 输入预处理与归一化
setup_model(predict.py)中 SAM 使用 ImageNet 风格均方差做归一化(mean=[123.675, 116.28, 103.53]、std=[58.395, 57.12, 57.375]),与通用检测模型不同;同时设置model.stride = 32、model.format = "sam",并提示channels_last=True不被支持。SAM 的imgsz只接受正方形,且推理 dtype 默认 float16(由self.model.fp16决定)。
七、与任务型分割模型的选型差异
值得强调的是,SAM 是一类通用提示分割基础模型,与"闭集实例分割"的 YOLO-seg 定位不同,二者并非替代关系:
- 提示驱动 / 零样本:SAM 可通过框、点、掩码提示分割任意未见过的对象类别,适合交互式标注、目标提案、边缘检测、图文掩码(text-to-mask)等下游任务;而 YOLO11/YOLO26 的
-seg系列在固定类别上速度与体积优势明显。 - 能力边界:在 Ultralytics 框架中,SAM 权重只支持预测推理;而 YOLO 分割模型支持训练、验证、导出与部署。官方在 docs/en/models/sam.md 中给出了 SAM-b 与各代 YOLO-seg 在体积、参数量与 CPU 耗时上的对比参考,供选型时查阅。
- 自动标注:SAM 常被用于"检测模型出框、SAM 出掩码"的自动标注流水线,即
auto_annotate工具(见 ultralytics/data/annotator.py),可快速把检测数据扩成实例分割训练集:
from ultralytics.data.annotator import auto_annotate auto_annotate(data="path/to/images", det_model="yolo26x.pt", sam_model="sam_b.pt")八、小结与导航
SAM类以极小的 API 面(构造、predict/__call__、info、task_map)屏蔽了 SAM / SAM 2 / SAM 3 在网络构建与推理细节上的差异:构造函数根据文件名后缀自动探测is_sam2/is_sam3,_load据此分派到build_sam或build_interactive_sam3,task_map再据此装配Predictor/SAM2Predictor/SAM3Predictor。理解这套分派机制,是排查自定义权重兼容性与扩展新预测器时的关键。
若需继续深入,可在本仓库中对照阅读:
- 类与接口实现:ultralytics/models/sam/model.py
- 底层预测器实现与
Predictor/generate全量参数:ultralytics/models/sam/predict.py、docs/en/reference/models/sam/predict.md - 权重注册表与网络构建:ultralytics/models/sam/build.py、ultralytics/models/sam/build_sam3.py
- 模型使用教程与能力对比:docs/en/models/sam.md、docs/en/models/sam-2.md、docs/en/models/sam-3.md
- 任务定义与 Results 对象:docs/en/tasks/segment.md、docs/en/modes/predict.md
【免费下载链接】ultralyticsUltralytics YOLO26, YOLO11, YOLOv8 — object detection, instance segmentation, semantic segmentation, image classification, pose estimation, object tracking项目地址: https://gitcode.com/GitHub_Trending/ul/ultralytics
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考