facebook/sam3

Hugging Face Models Trending 模型

摘要

Meta 发布 SAM 3,一个统一的图像与视频可提示分割基础模型,支持文本或视觉提示进行检测、分割与跟踪,并首次可穷举分割开放词汇概念的所有实例,在新的 SA-CO 基准上达到人类表现的 75-80%。

Task: mask-generation Tags: transformers, safetensors, sam3_video, feature-extraction, sam3, mask-generation, en, license:other, eval-results, endpoints_compatible, region:us, deploy:azure
查看原文
查看缓存全文

缓存时间: 2026/10/11 12:30

facebook/sam3 · Hugging Face

来源:https://huggingface.co/facebook/sam3

SAM 3 是一个统一的基础模型,用于图像和视频中的可提示分割。它可以通过文本或视觉提示(如点、框和掩码)来检测、分割和跟踪对象。与前代 SAM 2 相比,SAM 3 引入了通过简短文本短语或示例穷举式分割开放词汇概念的所有实例的能力。与以往工作不同,SAM 3 能够处理规模大得多的开放词汇提示集。在我们新的 SA-CO 基准测试上,SAM 3 达到了人类表现的 75-80%,该基准测试包含 270K 个独特概念,比现有基准测试多 50 倍以上。

Hugging Face 🤗 演示应用:https://huggingface.co/spaces/akhaliq/sam3

https://huggingface.co/facebook/sam3#basic-usage 基本用法

import torch

####################################
# 图像
####################################
from PIL import Image
from sam3.model_builder import build_sam3_image_model
from sam3.model.sam3_image_processor import Sam3Processor

# 加载模型
model = build_sam3_image_model()
processor = Sam3Processor(model)

# 加载图像
image = Image.open("")
inference_state = processor.set_image(image)

# 使用文本提示模型
output = processor.set_text_prompt(state=inference_state, prompt="")

# 获取掩码、边界框和分数
masks, boxes, scores = output["masks"], output["boxes"], output["scores"]

####################################
# 视频
####################################
from sam3.model_builder import build_sam3_video_predictor

video_predictor = build_sam3_video_predictor()
video_path = ""  # 一个 JPEG 文件夹或一个 MP4 视频文件

# 启动会话
response = video_predictor.handle_request(
    request=dict(
        type="start_session",
        resource_path=video_path,
    )
)

response = video_predictor.handle_request(
    request=dict(
        type="add_prompt",
        session_id=response["session_id"],
        frame_index=0,  # 任意帧索引
        text="",
    )
)

output = response["outputs"]

官方代码已在 sam3 仓库中公开发布。

https://huggingface.co/facebook/sam3#usage-with-%F0%9F%A4%97-transformers 使用 🤗 Transformers

https://huggingface.co/facebook/sam3#sam3—promptable-concept-segmentation-pcs-for-images SAM3 - 图像的可提示概念分割(PCS)

SAM3 在图像上执行可提示概念分割(PCS),以文本和/或图像示例作为提示,返回图像中所有匹配对象实例的分割掩码。

https://huggingface.co/facebook/sam3#text-only-prompts 仅文本提示

>>> from transformers import Sam3Processor, Sam3Model
>>> import torch
>>> from PIL import Image
>>> import requests
>>> device = "cuda" if torch.cuda.is_available() else "cpu"
>>> model = Sam3Model.from_pretrained("facebook/sam3").to(device)
>>> processor = Sam3Processor.from_pretrained("facebook/sam3")
>>> # 加载图像
>>> image_url = "http://images.cocodataset.org/val2017/000000077595.jpg"
>>> image = Image.open(requests.get(image_url, stream=True).raw).convert("RGB")
>>> # 使用文本提示进行分割
>>> inputs = processor(images=image, text="ear", return_tensors="pt").to(device)
>>> with torch.no_grad():
...     outputs = model(**inputs)
>>> # 后处理结果
>>> results = processor.post_process_instance_segmentation(
...     outputs,
...     threshold=0.5,
...     mask_threshold=0.5,
...     target_sizes=inputs.get("original_sizes").tolist()
... )[0]
>>> print(f"找到 {len(results['masks'])} 个对象")
>>> # 结果包含:
>>> # - masks:调整为原始图像大小的二值掩码
>>> # - boxes:绝对像素坐标(xyxy 格式)的边界框
>>> # - scores:置信度分数

你可以使用如下辅助函数显示掩码:

import numpy as np
import matplotlib

def overlay_masks(image, masks):
    image = image.convert("RGBA")
    masks = 255 * masks.cpu().numpy().astype(np.uint8)
    n_masks = masks.shape[0]
    cmap = matplotlib.colormaps.get_cmap("rainbow").resampled(n_masks)
    colors = [
        tuple(int(c * 255) for c in cmap(i)[:3])
        for i in range(n_masks)
    ]
    for mask, color in zip(masks, colors):
        mask = Image.fromarray(mask)
        overlay = Image.new("RGBA", image.size, color + (0,))
        alpha = mask.point(lambda v: int(v * 0.5))
        overlay.putalpha(alpha)
        image = Image.alpha_composite(image, overlay)
    return image

然后你可以保存合成后的图像或在 notebook 中显示它:

>>> overlay_masks(image, results["masks"])

https://huggingface.co/facebook/sam3#single-bounding-box-prompt 单个边界框提示

使用边界框分割对象:

>>> # 框使用 xyxy 格式:像素坐标 [x1, y1, x2, y2]
>>> # 示例:笔记本电脑区域
>>> box_xyxy = [100, 150, 500, 450]
>>> input_boxes = [[box_xyxy]]  # [batch, num_boxes, 4]
>>> input_boxes_labels = [[1]]  # 1 = 正框
>>> inputs = processor(
...     images=image,
...     input_boxes=input_boxes,
...     input_boxes_labels=input_boxes_labels,
...     return_tensors="pt"
... ).to(device)
>>> with torch.no_grad():
...     outputs = model(**inputs)
>>> # 后处理结果
>>> results = processor.post_process_instance_segmentation(
...     outputs,
...     threshold=0.5,
...     mask_threshold=0.5,
...     target_sizes=inputs.get("original_sizes").tolist()
... )[0]

https://huggingface.co/facebook/sam3#multiple-box-prompts-positive-and-negative 多个框提示(正框和负框)

使用带有正负标签的多个框来细化概念:

>>> # 加载厨房图像
>>> kitchen_url = "http://images.cocodataset.org/val2017/000000136466.jpg"
>>> kitchen_image = Image.open(requests.get(kitchen_url, stream=True).raw).convert("RGB")
>>> # 定义两个正框(例如,烤箱上的旋钮和按钮)
>>> # 框使用 xyxy 格式 [x1, y1, x2, y2],像素坐标
>>> box1_xyxy = [59, 144, 76, 163]  # 旋钮框
>>> box2_xyxy = [87, 148, 104, 159]  # 按钮框
>>> input_boxes = [[box1_xyxy, box2_xyxy]]
>>> input_boxes_labels = [[1, 1]]  # 均为正框
>>> inputs = processor(
...     images=kitchen_image,
...     input_boxes=input_boxes,
...     input_boxes_labels=input_boxes_labels,
...     return_tensors="pt"
... ).to(device)
>>> with torch.no_grad():
...     outputs = model(**inputs)
>>> # 后处理结果
>>> results = processor.post_process_instance_segmentation(
...     outputs,
...     threshold=0.5,
...     mask_threshold=0.5,
...     target_sizes=inputs.get("original_sizes").tolist()
... )[0]
>>> overlay_masks(kitchen_image, results["masks"])

https://huggingface.co/facebook/sam3#combined-prompts-text–negative-box 组合提示(文本 + 负框)

使用文本提示配合负视觉提示来细化概念:

>>> # 分割"把手"但通过负框排除烤箱把手
>>> text = "handle"
>>> # 覆盖烤箱把手区域的负框(xyxy):[40, 183, 318, 204]
>>> oven_handle_box = [40, 183, 318, 204]
>>> input_boxes = [[oven_handle_box]]
>>> inputs = processor(
...     images=kitchen_image,
...     text=text,
...     input_boxes=input_boxes,
...     input_boxes_labels=[[0]],  # 0 = 负框(排除此区域)
...     return_tensors="pt"
... ).to(device)
>>> with torch.no_grad():
...     outputs = model(**inputs)
>>> # 后处理结果
>>> results = processor.post_process_instance_segmentation(
...     outputs,
...     threshold=0.5,
...     mask_threshold=0.5,
...     target_sizes=inputs.get("original_sizes").tolist()
... )[0]
>>> # 这将分割锅的把手但排除烤箱把手

https://huggingface.co/facebook/sam3#batched-inference-with-text-prompts 使用文本提示的批量推理

通过批处理,使用不同的文本提示处理多张图像:

>>> cat_url = "http://images.cocodataset.org/val2017/000000077595.jpg"
>>> kitchen_url = "http://images.cocodataset.org/val2017/000000136466.jpg"
>>> images = [
...     Image.open(requests.get(cat_url, stream=True).raw).convert("RGB"),
...     Image.open(requests.get(kitchen_url, stream=True).raw).convert("RGB")
... ]
>>> text_prompts = ["ear", "dial"]
>>> inputs = processor(images=images, text=text_prompts, return_tensors="pt").to(device)
>>> with torch.no_grad():
...     outputs = model(**inputs)
>>> # 为两张图像后处理结果
>>> results = processor.post_process_instance_segmentation(
...     outputs,
...     threshold=0.5,
...     mask_threshold=0.5,
...     target_sizes=inputs.get("original_sizes").tolist()
... )
>>> print(f"图像 1:找到 {len(results[0]['masks'])} 个对象")
>>> print(f"图像 2:找到 {len(results[1]['masks'])} 个对象")

https://huggingface.co/facebook/sam3#batched-mixed-prompts 批量混合提示

在同一批次中为不同的图像使用不同类型的提示:

>>> # 图像 1:文本提示 "laptop"
>>> # 图像 2:视觉提示(旋钮框)
>>> box2_xyxy = [59, 144, 76, 163]
>>> inputs = processor(
...     images=images,
...     text=["laptop", None],  # 仅第一张图像有文本
...     input_boxes=[None, [box2_xyxy]],  # 仅第二张图像有框
...     input_boxes_labels=[None, [1]],  # 第二张图像为正框
...     return_tensors="pt"
... ).to(device)
>>> with torch.no_grad():
...     outputs = model(**inputs)
>>> # 为两张图像后处理结果
>>> results = processor.post_process_instance_segmentation(
...     outputs,
...     threshold=0.5,
...     mask_threshold=0.5,
...     target_sizes=inputs.get("original_sizes").tolist()
... )
>>> # 两张图像在单次前向传播中处理完成

https://huggingface.co/facebook/sam3#semantic-segmentation-output 语义分割输出

SAM3 除了实例掩码外,还提供语义分割输出:

>>> inputs = processor(images=image, text="ear", return_tensors="pt").to(device)
>>> with torch.no_grad():
...     outputs = model(**inputs)
>>> # 实例分割掩码
>>> instance_masks = torch.sigmoid(outputs.pred_masks)  # [batch, num_queries, H, W]
>>> # 语义分割(单通道)
>>> semantic_seg = outputs.semantic_seg  # [batch, 1, H, W]
>>> print(f"实例掩码:{instance_masks.shape}")
>>> print(f"语义分割:{semantic_seg.shape}")

https://huggingface.co/facebook/sam3#sam3-video—promptable-concept-segmentation-pcs-for-videos SAM3 Video - 视频的可提示概念分割(PCS)

SAM3 Video 在视频上执行可提示概念分割(PCS),以文本作为提示,在视频帧中检测并跟踪所有匹配的对象实例。

https://huggingface.co/facebook/sam3#pre-loaded-video-inference 预加载视频推理

使用文本提示处理所有帧已加载的视频:

>>> from transformers import Sam3VideoModel, Sam3VideoProcessor
>>> from accelerate import Accelerator
>>> import torch
>>> device = Accelerator().device
>>> model = Sam3VideoModel.from_pretrained("facebook/sam3").to(device, dtype=torch.bfloat16)
>>> processor = Sam3VideoProcessor.from_pretrained("facebook/sam3")
>>> # 加载视频帧
>>> from transformers.video_utils import load_video
>>> video_url = "https://huggingface.co/datasets/hf-internal-testing/sam2-fixtures/resolve/main/bedroom.mp4"
>>> video_frames, _ = load_video(video_url)
>>> # 初始化视频推理会话
>>> inference_session = processor.init_video_session(
...     video=video_frames,
...     inference_device=device,
...     processing_device="cpu",
...     video_storage_device="cpu",
...     dtype=torch.bfloat16,
... )
>>> # 添加文本提示以检测和跟踪对象
>>> text = "person"
>>> inference_session = processor.add_text_prompt(
...     inference_session=inference_session,
...     text=text,
... )
>>> # 处理视频中的所有帧
>>> outputs_per_frame = {}
>>> for model_outputs in model.propagate_in_video_iterator(
...     inference_session=inference_session, max_frame_num_to_track=50
... ):
...     processed_outputs = processor.postprocess_outputs(inference_session, model_outputs)
...     outputs_per_frame[model_outputs.frame_idx] = processed_outputs
>>> print(f"已处理 {len(outputs_per_frame)} 帧")
已处理 51 帧
>>> # 访问特定帧的结果
>>> frame_0_outputs = outputs_per_frame[0]
>>> print(f"检测到 {len(frame_0_outputs['object_ids'])} 个对象")
>>> print(f"对象 ID:{frame_0_outputs['object_ids'].tolist()}")
>>> print(f"分数:{frame_0_outputs['scores'].tolist()}")
>>> print(f"边界框形状(XYXY 格式,绝对坐标):{frame_0_outputs['boxes'].shape}")
>>> print(f"掩码形状:{frame_0_outputs['masks'].shape}")

https://huggingface.co/facebook/sam3#streaming-video-inference 流式视频推理

对于实时应用,Transformers 中的 SAM3 Video 实现支持在视频帧到达时进行处理:

>>> # 初始化流式推理会话
>>> streaming_inference_session = processor.init_video_session(
...     inference_device=device,
...     processing_device="cpu",
...     video_storage_device="cpu",
...     dtype=torch.bfloat16,
... )
>>> # 添加文本提示
>>> text = "person"
>>> streaming_inference_session = processor.add_text_prompt(
...     inference_session=streaming_inference_session,
...     text=text,
... )
>>> # 逐帧处理(流式模式)
>>> streaming_outputs_per_frame = {}
>>> for frame_idx, frame in enumerate(video_frames[:50]):  # 处理前 50 帧
...     # 首先使用 processor 处理帧
...     inputs = processor(images=frame, device=device, return_tensors="pt")
...
...     # 使用流式推理处理帧 - 传递处理后的 pixel_values
...     model_outputs = model(
...         inference_session=streaming_inference_session,
...         frame=inputs.pixel_values[0],  # 提供处理后的帧 - 这将启用流式模式
...         reverse=False,
...     )
...
...     # 使用 original_sizes 后处理输出,以正确处理分辨率
...     processed_outputs = processor.postprocess_outputs(
...         streaming_inference_session,
...         model_outputs,
...         original_sizes=inputs.original_sizes,  # 流式推理必需
...     )
...     streaming_outputs_per_frame[frame_idx] = processed_outputs
...
...     if (frame_idx + 1) % 10 == 0:
...         print(f"已处理 {frame_idx + 1} 帧...")
>>> print(f"✓ 流式推理完成!共处理 {len(streaming_outputs_per_frame)} 帧")
✓ 流式推理完成!共处理 50 帧
>>> # 访问结果
>>> frame_0_outputs = streaming_outputs_per_frame[0]
>>> print(f"第一帧检测到 {len(frame_0_outputs['object_ids'])} 个对象")
>>> print(f"边界框为 XYXY 格式(绝对像素坐标):{frame_0_outputs['boxes'].shape}")
>>> print(f"掩码为原始视频分辨率:{frame_0_outputs['masks'].shape}")

⚠️ 流式推理质量说明:流式推理会禁用移除未匹配和重复对象的热启动启发式方法,因为这些方法需要访问未来帧才能做出准确的决策。与预加载视频推理相比,这可能导致更多的误检和重复对象跟踪。如果所有帧都可用,请使用预加载视频推理以获得最佳效果。

https://huggingface.co/facebook/sam3#sam3-tracker—promptable-visual-segmentation-pvs-for-images SAM3 Tracker - 图像的可提示视觉分割(PVS)

Sam3Tracker 在图像上执行可提示视觉分割(PVS),接收交互式视觉提示(点、框、掩码),每次提示分割一个特定的对象实例。它是 SAM2 的更新版本,保持了相同的 API 但提供了更好的性能,可以作为 SAM2 工作流的直接替代品。

https://huggingface.co/facebook/sam3#automatic-mask-generation-with-pipeline 使用 Pipeline 的自动掩码生成

>>> from transformers import pipeline
>>> generator = pipeline("mask-generation", model="facebook/sam3", device=0)
>>> image_url = "https://huggingface.co/datasets/hf-internal-testing/sam2-fixtures/resolve/main/truck.jpg"
>>> outputs = generator(image_url, points_per_batch=64)
>>> len(outputs["masks"])  # 生成的掩码数量

https://huggingface.co/facebook/sam3#basic-image-segme 基本图像分割

相似文章

SAM 3: Segment Anything with Concepts

Papers with Code Trending

SAM 3 引入了一个统一的模型,用于基于提示的概念分割与跟踪,通过解耦的识别与定位架构以及可扩展的数据引擎,实现了最先进的性能。