SAM-SAM2-SAM3系列(一):Segment Anything Model(SAM)技术详解与实战
SAM-SAM2-SAM3系列(一):Segment Anything Model(SAM)技术详解与实战 ----------- 本文
SAM-SAM2-SAM3系列(二):Segment Anything 2(SAM 2)技术详解,以及SAM2对 SAM的升级点 ----------- 见后续博客
SAM-SAM2-SAM3系列(三):Segment Anything 3(SAM 3)技术详解,以及SAM3对 SAM2的升级点 ----------- 见后续博客
1. 背景与核心理念
目标:把“分割任何东西”变成通用能力,不再依赖类别、数据集或任务配方。
方法:把分割问题转化为**可提示(promptable)的通用交互式任务——用户或上游模块用“点/框/粗掩膜”等提示(prompts)**指向目标,模型即时生成像素级掩膜。
关键收益:
强泛化:对未见物体/领域仍具备可用的零样本分割能力。
人机协同:正/负点快速迭代,几次点击即可达到可交付质量。
工程友好:图像特征可预计算缓存,交互延迟低,便于前端/边缘部署。
2. 总览:数据引擎 + 模型结构
2.1 数据引擎(Data Engine)
阶段式采集:先由标注员在工具中交互式圈出前景;模型不断加入“人-机-回路”,提出候选掩膜、再由标注员修正——越用越强。
规模:数以千万计的图片,十亿量级的掩膜(常简称 SA-1B)。
结果:覆盖物体外观与边界形态的“广度”,帮助模型学习到更可迁移的分割先验。
2.2 模型结构(Promptable Segmentation)
图像编码器:大 ViT 将整图编码为密集图像特征(一次计算,多次复用)。
提示编码器:把稀疏提示(正/负点、框)编码为向量,把稠密提示(已有粗掩膜)编码为低分辨率特征。
掩膜解码器:轻量 Transformer 解码头,融合图像特征与提示,一次生成多张掩膜候选,并伴随一个 IoU 质量预测头,自动选出最优结果;也可把多候选展示给前端交互选择。
设计要点:
多掩膜候选解决“歧义”(同一提示可能存在多种合理分割)。
IoU 预测提供自估计的“质量分”,便于自动管线筛选和阈值化处理。
特征缓存让交互过程只用跑轻量解码器,延迟可控。
3. 快速上手:安装与两种使用姿势
说明:下述示例基于官方 PyTorch 实现的常见用法;请按仓库说明下载相应 checkpoint(如
sam_vit_h_*.pth
/sam_vit_b_*.pth
等)。
3.1 安装(两种方式任选一种)
方式 A:从源码安装
# 建议用 Python 3.9+ 与 PyTorch >= 1.13
pip install --upgrade pip
pip install opencv-python pycocotools matplotlib# 从官方仓库安装(示意)
pip install git+https://github.com/facebookresearch/segment-anything
方式 B:本地克隆便于二开
git clone https://github.com/facebookresearch/segment-anything.git
cd segment-anything
pip install -e .
3.2 交互式预测(点/框/掩膜提示)
import cv2, numpy as np
from segment_anything import sam_model_registry, SamPredictorimage_bgr = cv2.imread("demo.jpg")
image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)sam = sam_model_registry["vit_h"](checkpoint="sam_vit_h_4b8939.pth")
predictor = SamPredictor(sam)# 1) 预计算并缓存整图特征
predictor.set_image(image_rgb)# 2) 正/负点提示(point_labels:1=前景,0=背景)
point_coords = np.array([[450, 320], [520, 330]], dtype=np.float32) # (x,y)
point_labels = np.array([1, 0], dtype=np.int32)# 3) 可选:框提示 [x0, y0, x1, y1]
box = np.array([400, 250, 650, 500], dtype=np.float32)masks, scores, logits = predictor.predict(point_coords=point_coords,point_labels=point_labels,box=box,multimask_output=True # 返回多候选
)# 可视化第一张候选
mask = masks[0].astype(np.uint8) * 255
overlay = image_bgr.copy()
overlay[mask > 0] = (0.5 * overlay[mask > 0] + 0.5 * np.array([0, 255, 0])).astype(np.uint8)
cv2.imwrite("sam_overlay.jpg", overlay)
关键注意
set_image()
输入 RGB,坐标用 (x, y) 顺序。multimask_output=True
会返回 3 张左右候选;利用scores
或IoU
预测值选择最优。交互迭代:把上一轮的
logits
作为mask_input
传回,可继续加点细化。
3.3 自动掩膜生成(大图批量切分/候选区域建议)
from segment_anything import sam_model_registry, SamAutomaticMaskGeneratorsam = sam_model_registry["vit_h"](checkpoint="sam_vit_h_4b8939.pth")
mask_generator = SamAutomaticMaskGenerator(model=sam,points_per_side=32,pred_iou_thresh=0.86,stability_score_thresh=0.92,crop_n_layers=1,crop_n_points_downscale_factor=2,min_mask_region_area=1000, # 过滤小碎片
)image = cv2.cvtColor(cv2.imread("demo.jpg"), cv2.COLOR_BGR2RGB)
masks = mask_generator.generate(image) # list[dict], 每个包含 'segmentation'、'area'、'bbox'、'predicted_iou' 等
参数提示
points_per_side:越大越密集,召回更高、速度更慢。
stability_score_thresh:提高可抑制“边缘不稳”的掩膜。
min_mask_region_area:清理噪声小片段,利于工程后处理。
4. 工程集成:与检测/跟踪/分析的协同
4.1 “检测框 → 精细分割”两段式
在业务系统中,常先用高吞吐的 检测器(YOLO/RT-DETR/PP-YOLOE 等) 提供候选框,再将框作为 SAM 的 box 提示 做精细轮廓,既稳态高效又边界更准。
def refine_boxes_with_sam(predictor, image_rgb, det_boxes):predictor.set_image(image_rgb) # 只做一次refined_masks, refined_scores = [], []for (x0, y0, x1, y1) in det_boxes:masks, scores, _ = predictor.predict(point_coords=None,point_labels=None,box=np.array([x0, y0, x1, y1], dtype=np.float32),multimask_output=True)k = int(np.argmax(scores))refined_masks.append(masks[k])refined_scores.append(float(scores[k]))return refined_masks, refined_scores
应用实例
高速事件(抛洒物/落石/烟火):检测框粗定位 → SAM 精细轮廓 → 面积/形状/纹理统计 → 规则/大模型过滤。
车道/车身擦碰分析:对关键物体做实例级掩膜,支持更稳的几何量计算(宽度、长度、遮挡比等)。
4.2 掩膜到 YOLO/COCO 标注的相互转换
掩膜 → YOLO 检测框(归一化 xcycwh)
def mask_to_yolo_bbox(mask, img_w, img_h):ys, xs = np.where(mask > 0)if len(xs) == 0: # 空掩膜return Nonex0, x1 = xs.min(), xs.max()y0, y1 = ys.min(), ys.max()xc = (x0 + x1) / 2.0 / img_wyc = (y0 + y1) / 2.0 / img_hw = (x1 - x0 + 1) / img_wh = (y1 - y0 + 1) / img_hreturn (xc, yc, w, h)
掩膜 → COCO/RLE 或多边形(简例)
import cv2def mask_to_polygons(mask):contours, _ = cv2.findContours(mask.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)polys = []for c in contours:if len(c) >= 3:polys.append(c.reshape(-1, 2).tolist()) # 每个多边形为 [ [x,y], ... ]return polys
5. 性能优化与部署实践
5.1 推理侧加速
特征缓存:同一帧/图多次交互时,仅首次
set_image()
计算图像特征;后续交互只跑解码器(低延迟)。图像缩放:多数情况下把长边缩放到 ~1024 像素即可,极大降低计算量;需要像素级精度时再局部放大/裁剪。
候选控制:关闭
multimask_output
或仅保留 IoU 分最高候选,减少后处理负担。
5.2 边缘端(RK3588 等)
选择小模型:官方 ViT-H 体积较大;在算力受限平台建议考虑 轻量化变体(如社区的 MobileSAM 等)或采用“小 ViT”权重。
裁剪与分块:超大图可网格化分块 + 邻块合并,局部精细、全局均衡。
流水线:检测→SAM 的两段式在 RK3588 等平台尤为实用:检测器用 RKNN/NCNN/TVM 加速,SAM 选轻量化版本做少量实例细化。
ONNX/RKNN 导出:把图像编码器与解码器拆导成两个子图(静态输入尺寸更友好);注意 ViT 中 GELU/LayerNorm/Attention 的算子兼容性与精度核对(必要时做算子替换或 FP16/INT8 校准)。
内存控制:预估一次前向的特征图占用,避免与其他任务抢显存/内存导致抖动。
工程建议:在边缘端先落小样例 POC(少数目标、低分辨率、固定视角),验证延迟与质量再扩展到全量。
6. 训练与微调(进阶)
官方模型已在超大规模数据上训练,多数业务无需再训。若需领域适配,可考虑:
轻量微调:仅对解码头做 LoRA/Adapter;冻结大部分编码器参数,成本更低、稳定性更好。
提示数据合成:把业务数据的 GT 掩膜随机采样出正/负点、框与稠密 mask 提示,模拟真实交互过程。
评估指标:以 mIoU / Dice 为主,结合稳定性分与边界 F-score,更符合交互迭代特性。
提醒:端到端从零训练的代价高昂,且容易因数据分布窄而损失泛化;更推荐“冻结大干、微调小头”。
7. 在视频与流式场景中的使用
缓存复用:同一摄像头、相近帧,目标外观变化不大时,可复用前景框 + SAM 掩膜作为初始化提示,减少每帧计算。
多帧一致性:对相邻帧掩膜做时序一致性约束或简单的时序滤波(面积/质心/形状平滑)。
与跟踪器融合:检测-分割后得到的掩膜可提供更稳定的外观模板,提升 ReID/跟踪稳定度。
8. 常见坑与排查
颜色通道:OpenCV 默认 BGR,SAM 需 RGB,记得转换。
坐标顺序:
point_coords
是(x, y)
;很多库返回(row=y, col=x)
,注意别写反。尺度失配:
box
/points
必须是原图坐标(非缩放后)。如果先缩放了图像,请同步缩放提示。边界毛刺:尝试提升
stability_score_thresh
;或在掩膜后做形态学处理(开闭运算)。小物体缺失:增大
points_per_side
或降低min_mask_region_area
,必要时提高输入分辨率。多候选歧义大:结合
scores
/predicted_iou
自动选优,或在前端增加一轮“负点”抑制背景。延迟忽高忽低:检查是否重复跑了图像编码;确保特征缓存生效。
9. 典型参数“即插即用”清单
交互分割:
multimask_output=True
,用户选择;自动管线可用np.argmax(scores)
。自动生成:
points_per_side=24~48
,pred_iou_thresh=0.86±0.03
,stability_score_thresh=0.9±0.05
,min_mask_region_area=500~2000
。大图策略:长边 1024/1536;若目标细节要求高,用滑窗 512/768,步长取 1/2 窗口,并在重叠区做优先级融合(IoU 高/面积大优先)。
10. 与你的业务(智慧交通/收费门架/事件检测)的落地配方
检测候选:用现有 YOLO 系列在低延迟下发现可能的事件区域(抛洒物、烟火、落石、行人上路等)。
SAM 精化:把候选框喂给 SAM,得到精细掩膜与质量分。
规则与大模型复核:基于掩膜的面积、长宽比、纹理统计、道路拓扑(车道/应急车道 polygon)做第一层规则,再将疑难样本交给轻量多模态模型做二次过滤(二分类/问答)。
终端优先级:RK3588 端优先用轻量化 SAM;云端批处理或离线质检用大 SAM 版本保证质量上限。
数据回流:抽取误检/漏检片段进行 SAM 交互式精修,回灌小模型训练与轻量化大模型蒸馏,形成正反馈闭环。
11. 小结与展望
SAM 把“分割”从“任务特定”提升为“可提示的通用模块”,在标注提效、快速迭代与跨域泛化上极具工程价值。
在生产系统建议采用“检测→SAM 精化”的级联式部署,并充分利用特征缓存与参数化自动生成器控制召回-速度的平衡。
对于边缘端,优先评估轻量化变体与分块策略;对领域适配,优先考虑解码头的轻量微调。
若面向视频与流式场景,结合跟踪与时序一致性,可获得更稳定的实例级掩膜。
合规与许可:使用前请阅读官方仓库的 License 与模型/数据集使用条款,确保满足商用/分发的合规要求。
12. 附录:常用实用代码片段
(1)从交互 logits 继续细化
masks, scores, logits = predictor.predict(point_coords=pc1, point_labels=pl1, multimask_output=True)
best = np.argmax(scores)
refined_masks, _, _ = predictor.predict(point_coords=pc2, point_labels=pl2,mask_input=logits[best][None, :, :], # 继续细化multimask_output=False
)
(2)掩膜后处理(开运算去毛刺)
def smooth_mask(mask, k=3):kernel = np.ones((k, k), np.uint8)opened = cv2.morphologyEx(mask.astype(np.uint8), cv2.MORPH_OPEN, kernel)return (opened > 0).astype(np.uint8)
(3)大图分块 + 合并简例
def tile_image(img, tile=768, stride=384):H, W = img.shape[:2]patches = []for y in range(0, max(1, H - tile + 1), stride):for x in range(0, max(1, W - tile + 1), stride):patches.append(((x, y), img[y:y+tile, x:x+tile]))return patchesdef paste_mask(global_mask, local_mask, x, y):h, w = local_mask.shape[:2]global_mask[y:y+h, x:x+w] = np.maximum(global_mask[y:y+h, x:x+w], local_mask)return global_mask
(4)批量可视化与导出
def draw_and_save(image_bgr, mask, out_path):overlay = image_bgr.copy()overlay[mask > 0] = (0.5 * overlay[mask > 0] + 0.5 * np.array([0, 255, 0])).astype(np.uint8)cv2.imwrite(out_path, overlay)
如果你愿意,我可以按你的硬件环境(如 RK3588 / A40 / T4)与现有检测器,给出一份端到端部署脚本(含模型选择、参数表与性能预估),或者把本文整理为一篇可直接发布的 Markdown/公众号文章版式(含插图与目录)。