首页
/ Ultralytics SAM 核心模块详解:SAMModel、SAM2Model 与 SAM3Model 的架构、参数与源码实现

Ultralytics SAM 核心模块详解:SAMModel、SAM2Model 与 SAM3Model 的架构、参数与源码实现

2026-09-07 15:48:41作者:尤峻淳Whitney

本篇技术指南围绕 ultralytics/models/sam/modules/sam.py 中的三个核心模型类展开:SAMModel(静态图像分割)、SAM2Model(基于记忆机制的视频分割)与 SAM3Model(SAM3 变体)。读完后你将理解这三类模型如何组合图像编码器、提示编码器与掩码解码器,掌握其关键构造参数、forward_image/track_step 等核心方法的数据流,以及它们与 SAM 模型接口、构建函数之间的实际调用关系。

模块定位与类总览

ultralytics/models/sam/modules/sam.py 是 Ultralytics 中 Segment Anything 系列(SAM / SAM 2 / SAM 3)的模型主干定义文件,与官方 API 参考页 docs/en/reference/models/sam/modules/sam.md 一一对应。该文件内定义了三个类和一个模块级常量:

名称 位置 职责
NO_OBJ_SCORE sam.py#L22 值为 -1024.0 的占位分数,用于标记"目标缺失/被遮挡"帧的掩码 logit
SAMModel sam.py#L25 静态图像提示分割:组合 ImageEncoderViT + PromptEncoder + MaskDecoder
SAM2Model sam.py#L91 视频目标分割:在 SAM 头之外增加记忆注意力、记忆编码与对象指针机制
SAM3Model sam.py#L1025 继承 SAM2Model 的 SAM 3 变体,调整默认图像尺寸、backbone 步长与解码器结构

从源码结构看,三个类都不实现完整的 forward 推理闭环:SAMModel 的文档字符串明确注明 "All forward() operations are implemented in the SAMPredictor class",而 SAM2Model.forward() 直接抛出 NotImplementedError,提示改用 SAM2VideoPredictor 完成推理(见 sam.py#L350-L355)。也就是说,本文件定义的是"网络结构与单步计算原语",批量预处理、批推理与结果组织由上层预测器承担。

SAMModel:静态图像分割的三段式组合

SAMModel 是最基础的 SAM 实现,其 __init__ 接收四大组件(见 sam.py#L55-L80):

class SAMModel(nn.Module):
    mask_threshold: float = 0.0  # 掩码预测阈值

    def __init__(self,
                 image_encoder,   # ImageEncoderViT:将图像编码为特征嵌入
                 prompt_encoder,  # PromptEncoder:编码点/框/掩码等提示
                 mask_decoder,    # MaskDecoder:由图像嵌入与提示嵌入预测掩码
                 pixel_mean=(123.675, 116.28, 103.53),  # 输入像素归一化均值
                 pixel_std=(58.395, 57.12, 57.375)):    # 输入像素归一化标准差

几个值得注意的实现细节:

  1. 像素归一化以 buffer 注册pixel_meanpixel_std 通过 register_buffer(..., persistent=False) 注册,reshape 为 (-1, 1, 1) 后随模型移动设备,但不进入 checkpoint 状态字典,符合推理型模型的轻量持久化策略(sam.py#L79-L80)。
  2. mask_threshold = 0.0 作为类属性,是掩码 logit 二值化的默认阈值,供上层预测器取用。
  3. set_imgsz 适配任意输入尺寸sam.py#L82-L88):
def set_imgsz(self, imgsz):
    if hasattr(self.image_encoder, "set_imgsz"):
        self.image_encoder.set_imgsz(imgsz)
    self.prompt_encoder.input_image_size = imgsz
    self.prompt_encoder.image_embedding_size = [x // 16 for x in imgsz]  # 16 是 ViT 的固定 patch size
    self.image_encoder.img_size = imgsz[0]

注意 image_embedding_size 除以的 16 是 ViT 的固定 patch size——这也是该模型对输入尺寸的核心约束来源。

在构建侧,ultralytics/models/sam/build.pybuild_sam 展示了 SAMModel 的完整装配方式:ImageEncoderViTpatch_size=14 的视觉主干在构建层配置)+ PromptEncoder(embed_dim=..., image_embedding_size=..., input_image_size=..., mask_in_chans=16) + MaskDecoder(num_multimask_outputs=3, transformer=TwoWayTransformer(depth=2, mlp_dim=2048, num_heads=8), iou_head_depth=3, iou_head_hidden_dim=256)pixel_mean/pixel_std 传入与类默认值一致的 ImageNet 统计量(build.py#L199-L225)。num_multimask_outputs=3 意味着模型对单次提示最多输出 3 个候选掩码。

SAM2Model:记忆机制驱动的视频目标分割

SAM2Modelsam.py#L91)面向视频序列,核心思想是:当前帧的视觉特征先与历史帧的"记忆"做条件融合,再交给 SAM 风格的提示编码器和掩码解码器,从而保持时间一致性。

构造函数与四大组成部分

构造函数参数极多,按源码内注释可分为四个部分(sam.py#L163-L343):

部分 组件/参数 说明
Part 1 图像主干 image_encoderuse_high_res_features_in_samuse_obj_ptrs_in_encodermask_downsample 多尺度特征提取;启用对象指针时增加一个 Conv2d(1,1,k=4,s=4) 将掩码提示下采样到 stride 4 并缩放到 SAM logit 尺度
Part 2 记忆注意力 memory_attention memory_attention.d_model 确定 hidden_dim,将当前帧特征与过去帧记忆做交叉注意力
Part 3 记忆编码 memory_encodernum_maskmemmaskmem_tpos_encno_mem_embedsigmoid_scale/bias_for_mem_enc num_maskmem(可访问的记忆帧数)个记忆各带可学习时间位置编码;no_mem_embed/no_mem_pos_enc 是"无记忆"占位 token
Part 4 SAM 头 sam_prompt_encodersam_mask_decoderobj_ptr_proj 复用 SAM 风格提示编码器 + SAM2MaskDecoder 生成最终掩码与对象指针

常用参数及其默认值(摘自 __init__ 签名):num_maskmem=7image_size=512backbone_stride=16sigmoid_scale_for_mem_enc=1.0sigmoid_bias_for_mem_enc=0.0max_cond_frames_in_attn=-1max_obj_ptrs_in_encoder=16add_tpos_enc_to_obj_ptrs=Truepred_obj_scores=Falsememory_temporal_stride_for_eval=1compile_image_encoder=False。其中 compile_image_encoder=True 时会用 torch.compile(mode="max-autotune", fullgraph=True) 只编译 forward 函数(保留模块结构以便加载 checkpoint,首次前向较慢)。

_build_sam_headssam.py#L357-L402)是 SAM 头的工厂方法:

  • sam_image_embedding_size = image_size // backbone_stride(如 512/16=32);
  • 构建 PromptEncoder(embed_dim=hidden_dim, image_embedding_size=(N,N), input_image_size=(S,S), mask_in_chans=16)
  • 构建 SAM2MaskDecoder(num_multimask_outputs=3, transformer=SAM2TwoWayTransformer(depth=2, mlp_dim=2048, num_heads=8), iou_head_depth=3, iou_head_hidden_dim=256, ...)mask_in_chans=16 等超参数沿用 SAM 原始设计;
  • 对象指针投影 obj_ptr_proj 默认是 nn.Identity,启用 use_obj_ptrs_in_encoder 后变为线性层或 3 层 MLPuse_mlp_for_obj_ptr_proj=True 时)。

核心推理路径:forward_image 与 track_step

SAM2Model 的对外方法是 forward_imagetrack_step(文档字符串示例):

>>> model = SAM2Model(image_encoder, memory_attention, memory_encoder)
>>> image_batch = torch.rand(1, 3, 512, 512)
>>> features = model.forward_image(image_batch)
>>> track_results = model.track_step(0, True, features, None, None, None, {})

数据流如下:

  1. forward_imagesam.py#L599-L607):图像经 image_encoder 得到 backbone_out;若 use_high_res_features_in_sam=True,会预先用 sam_mask_decoder.conv_s0/conv_s1 投影 FPN level 0/1 特征,避免每次点击重复计算。
  2. track_stepsam.py#L919-L977)执行单帧跟踪步,内部 _track_step 依次调用:
    • _prepare_memory_conditioned_featuressam.py#L629):从 output_dictcond_frame_outputsnon_cond_frame_outputs 中选取最近的条件帧(select_closest_cond_frames)与最多 num_maskmem - 1 个非条件历史帧记忆,拼接对象指针(可选,带一维正弦时间位置编码)后送入 memory_attention;条件帧首次处理时若无记忆,则用 no_mem_embed 占位或按 directly_add_no_mem_embed 直接相加。
    • _forward_sam_headssam.py#L404):处理点提示(point_coords 形状 (B,P,2) 像素坐标、point_labels 中 1=正点击、0=负点击、-1=填充)、掩码提示(必要时双线性下采样到 mask_input_size),经 sam_prompt_encoder 得到稀疏/稠密嵌入,再交由 sam_mask_decoder 输出低/高分辨率多掩码与 IoU 估计;multimask_output=True 时按 IoU 选最优候选,同时抽取 obj_ptrobject_score_logits。若 pred_obj_scores 开启且判定目标未出现,掩码会被替换为 NO_OBJ_SCORE 占位。
    • _encode_memory_in_output_encode_new_memorysam.py#L793):将当前帧顶层特征与预测掩码(sigmoid 后按 sigmoid_scale_for_mem_enc/sigmoid_bias_for_mem_enc 缩放,可按 binarize_mask_from_pts_for_mem_enc 二值化)送入 memory_encoder,写入 current_out["maskmem_features"] 供后续帧使用;评估时可施加 _apply_non_overlapping_constraints(对重叠区域保留最高分对象,其余压低到 -10.0sam.py#L988-L1004)。
    • 特例路径:use_mask_input_as_output_without_sam=True 且有掩码输入时,走 _use_mask_as_outputsam.py#L552),直接以 20.0*x - 10.0 的 logit 映射把输入掩码当作输出,跳过 SAM 提示/解码流程(用于用户已确认掩码的校正帧)。
  3. 返回值 current_out 包含 pred_maskspred_masks_high_resobj_ptr,推理模式追加 object_score_logits,以及编码后的记忆特征。

另外两个辅助方法:set_binarize 供视频预测器在评估时切换掩码二值化;set_imgszsam.py#L1010-L1022)同步更新 image_encodersam_prompt_encoderinput_image_size/image_embedding_size/mask_input_size(均基于 backbone_stride 换算,注释标明 ViT patch size 固定为 16)。

build.py 中的真实超参数组合

SAM2Model 的实际使用参数在 ultralytics/models/sam/build.py#L278-L309_build_sam2 中给出,这是理解各布尔开关默认"关闭"与实际"开启"差异的关键:

image_encoder = ImageEncoder(trunk=Hiera(...), neck=FpnNeck(d_model=256, ...), scalp=1)
memory_attention = MemoryAttention(d_model=256, pos_enc_at_input=True, num_layers=4, ...)
memory_encoder = MemoryEncoder(out_dim=64)

sam2 = SAM2Model(
    image_encoder=image_encoder, memory_attention=memory_attention, memory_encoder=memory_encoder,
    num_maskmem=7, image_size=1024,
    sigmoid_scale_for_mem_enc=20.0, sigmoid_bias_for_mem_enc=-10.0,
    use_mask_input_as_output_without_sam=True, directly_add_no_mem_embed=True,
    use_high_res_features_in_sam=True, multimask_output_in_sam=True,
    iou_prediction_use_sigmoid=True, use_obj_ptrs_in_encoder=True,
    add_tpos_enc_to_obj_ptrs=True, only_obj_ptrs_in_the_past_for_eval=True,
    pred_obj_scores=True, pred_obj_scores_mlp=True, fixed_no_obj_ptr=True,
    multimask_output_for_tracking=True, use_multimask_token_for_obj_ptr=True,
    multimask_min_pt_num=0, multimask_max_pt_num=1, use_mlp_for_obj_ptr_proj=True,
    no_obj_embed_spatial=is_sam2_1, proj_tpos_enc_in_obj_ptrs=is_sam2_1,
    use_signed_tpos_enc_to_obj_ptrs=is_sam2_1,
    sam_mask_decoder_extra_args={
        "dynamic_multimask_via_stability": True,
        "dynamic_multimask_stability_delta": 0.05,
        "dynamic_multimask_stability_thresh": 0.98,
    },
)

可以看到:实际部署中 image_size 为 1024(而非类默认 512)、高分辨率特征、对象指针、目标分数预测、多掩码输出与"掩码输入直通"全部启用;is_sam2_1(checkpoint 名称含 sam2.1 时)额外开启 SAM 2.1 专属的三个开关。这些组合体现了类默认值"最小可用"、构建函数"完整特性"的分层设计。

SAM3Model:继承自 SAM2 的差异化变体

SAM3Model(SAM2Model)sam.py#L1025)复用 SAM2 的记忆跟踪骨架,主要差异有四:

  1. 默认几何参数image_size=1008backbone_stride=14(对应 SAM 3 的 ViT 主干 patch 尺寸),而 SAM2 默认是 512/16。
  2. 重建掩码解码器__init__ 末尾用 TwoWayTransformer(而非 SAM2 专用的 SAM2TwoWayTransformer)重建 sam_mask_decoder,其余解码器超参数(num_multimask_outputs=3mlp_dim=2048num_heads=8iou_head_depth=3iou_head_hidden_dim=256)保持一致(sam.py#L1104-L1121)。
  3. 图像前向接口不同forward_image 调用 image_encoder.forward_image_sam2(img_batch) 而非直接 image_encoder(img_batch)sam.py#L1123-L1131),即 SAM 3 的视觉主干通过 SAM 2 兼容接口输出多尺度特征。
  4. set_imgsz 额外同步记忆编码器:在父类逻辑之上更新 self.memory_encoder.mask_downsampler.interpol_size = [size // 14 * 16 for size in imgsz]sam.py#L1133-L1136)。
  5. 面积收缩抑制:新增 _suppress_shrinked_masksshrink_threshold=0.3)与 _suppress_object_pw_area_shrinkagesam.py#L1138-L1159),先按像素级非重叠约束计算每张掩码面积收缩比例,对收缩超过阈值的掩码整体压低到 -10.0,用于抑制多对象场景下被竞争对象"吃掉"大量区域的噪声掩码。

上下游调用链:从 SAM 接口到模型构建

将本文件放回整个包中看,调用关系如下:

  • 模型入口ultralytics/models/sam/model.py 中的 SAM 类要求权重为 .pt/.pth,并依据文件名中的 sam2/sam3 子串设置 is_sam2/is_sam3_load 中 SAM 3 走 build_sam3.pybuild_interactive_sam3(其内部在 build_sam3.py#L307 实例化 SAM3Model),SAM/SAM2 走 build.pybuild_samtask_map 按变体路由到 PredictorSAM2PredictorSAM3Predictor
  • 尺寸适配ultralytics/models/sam/predict.py#L573-L579 中,预测器在 source is None 或首次推理时调用 self.model.set_imgsz(self.imgsz)——这正是本文讲解的 set_imgsz 方法被触发的地方;视频跟踪路径(predict.py#L2612 附近)对 tracker.model 做同样处理。
  • 推理职责划分SAMModel/SAM2Model 只提供 forward_imagetrack_step 等原语,真正的逐帧状态管理(output_dict、条件帧/非条件帧划分、内存 bank 维护)位于 predict.py 的预测器与 SAM2VideoPredictor 中,这与源码中 "forward() operations moved to SAMPredictor" 的注释一致。

适用前提与使用注意事项

  • 本指南所述行为以当前仓库源码为准;SAM/SAM2/SAM3 仅支持加载预训练 .pt/.pth 权重,SAM(...) 构造函数对其它扩展名会直接抛出 NotImplementedError(见 model.py#L59-L60)。
  • SAMModel.set_imgsz 中 patch size 固定为 16(图像嵌入尺寸 = 输入尺寸/16),SAM2Model.set_imgsz 则基于 backbone_stride(SAM2 为 16、SAM3 为 14)换算嵌入与掩码输入尺寸;修改输入尺寸时必须经由预测器统一调用 set_imgsz,而不是手工改动编码器属性,否则提示编码器与解码器会失配。
  • 若直接以 SAM2Model(...) 最小参数集实例化(不经过 _build_sam2),use_obj_ptrs_in_encoderpred_obj_scores 等开关均为关闭状态,得到的将是"仅记忆融合"的简化形态;生产配置请以 build.py/build_sam3.py 中的参数组合为参考。
  • 相关文档可继续参考 API 参考页 docs/en/reference/models/sam/modules/sam.md 以及 SAM 模型总览页 docs/en/models/sam.md
登录后查看全文
热门项目推荐
相关项目推荐