56MB轻量级SAM模型:浏览器端实时分割评测
摘要
基于MobileSAMv2构建的轻量级分割系统,其模型权重仅56MB,支持点、框、自动、模板匹配及文
实测MobileSAMv2:56MB轻量分割模型,5种Prompt方式在浏览器跑出毫秒级延迟
SAM 3 的技术路线清晰——更大参数量、更全场景、能识别语义概念。但代价同样明显:权重动辄数GB,本地推理至少需要24GB显存的GPU。对个人开发者而言,这条路线与“真正能跑”之间隔着一条难以逾越的鸿沟。
恰好手头有个工业质检需求,需要从传送带图片中精确抠出缺陷区域,云端推理的延迟根本无法忍受。那天晚上熬到凌晨两点,基于MobileSAMv2搭了一个Web Demo:
- 整个项目权重仅56MB(编码器40MB + 解码器16MB)
- 支持5种交互方式:点选、框选、自动分割、模板匹配、文本描述
- CPU推理达到毫秒级:M1笔记本上点分割180ms,自动分割4秒切出50个mask
- 浏览器打开
localhost:8000即可使用,无需特定显卡
先看5种Prompt方式的实际效果





MobileSAMv2的核心架构拆解
一句话总结:将原版SAM中632M参数的ViT-H编码器替换为5M参数的TinyViT,剩余部分保留提示引导的mask解码器进行精细调整。
| 原版SAM | SAM 3 | MobileSAMv2 | |
|---|---|---|---|
| 编码器 | ViT-H (632M) | 更大 | TinyViT (5M) |
| 总体积 | ~2.4 GB | GB级 | ~56 MB |
| CPU推理 | 不可行 | 不可行 | 毫秒级 |
| 本地部署 | 需A100 | 需A100/H100 | 笔记本即可 |
代价是mask质量下降1-2个IoU点,但作为提示驱动的工具完全够用。
56MB如何容纳「5种Prompt」
这个Demo与其他SAM项目最大的不同——并非一种prompt对应一个模型,而是同一个SAM编码器加上5种不同的prompt入口。
// 代码示意
// 图像编码只执行一次,特征缓存起来
// 之后任意prompt直接走解码器

核心技巧:图像编码只做一次,特征存储后复用;随后任何prompt都直接调用解码器,毫秒级返回。这是SAM系列模型比传统分割网络快一个数量级的根本原因。
1. 模型加载:将TinyViT植入SAM框架
这一步最反直觉,但思路其实很直接。
MobileSAMv2的权重文件中,编码器是TinyViT,解码器仍是原SAM结构。state_dict的key按image_encoder.*前缀区分。加载时分两段:
- 不带前缀的 → 整个SAM模型(mask_decoder + prompt_encoder直接使用)
- 带
image_encoder.前缀的 → 去掉前缀后注入TinyViT
加上strict=False容忍缺失/多余的key,两边都能成功装载。
SamPredictor处理点/框/模板,SamAutomaticMaskGenerator处理everything模式。两者共用同一个encoder实例,避免重复加载和前向计算。
2. 图像预处理:任意尺寸图片如何适配1024×1024网络
SAM的输入固定为1024×1024,任意分辨率图片都需要进行resize + pad:
- 长边等比缩放到1024
- 短边补黑边至1024
- 使用ImageNet的mean/std进行归一化
关键点:scale值必须保留。用户在800×600显示图上点击(x=400, y=300),喂给模型前需要乘以scale,否则坐标偏移。返回mask时也要按scale还原。这是一个极易出错的地方。
3. 五种Prompt的实现思路
五种后端接口总计不到400行代码,逐一说明思路。
3.1 点击分割(Point Prompt)
最基础的操作。在图上点击一个点,赋予前景/背景标签,SAM返回3个候选mask。
两个关键点:
- 必须开启
multimask_output=True,3个候选按粒度从粗到细排列 - 按住Shift点击是背景标签(label=0),前景分割会更干净
实测180ms(M1 CPU)。
3.2 框选分割(Box Prompt)
绘制一个矩形框将目标“框”住。multimask_output=False,只输出一个mask。框prompt的收敛性优于点,因此一个mask足够。
实测180ms。
3.3 自动分割(Everything)
该模式不传递任何prompt,模型自主将图中所有对象切分出来。
SAM内部处理方式:在图上铺设32×32的网格点,每个点预测一次,最后通过NMS合并。因此一张1024×1024的图需要执行1024次SAM解码。
优化思路:先将图缩放到1024再执行everything;按面积排序后返回前端,过滤掉太小的mask。
实测4.2s切出50个mask(M1 CPU)。
3.4 模板匹配(Template Prompt)
这个功能最值得介绍——**“用一张小图找出原图中所有同类物体”**。
思路分为两段:先用传统计算机视觉方法找到候选框,再用SAM在每个框中心点进行精修。
候选框的生成有两种方法:
- AKAZE特征点 + 单应性矩阵:抗旋转、抗尺度变化,复杂场景首选
- cv2.matchTemplate模板匹配:速度快但脆弱,物体形变严重时失效
AKAZE方案的精髓:模板图和原图分别提取特征点 → KNN匹配 → Lowe's ratio test过滤(m.distance < 0.7 * n.distance,0.7是经验值) → RANSAC计算单应性矩阵 → 将模板四个角投影到原图得到候选框。
几个反复调试出的数值:
- Lowe's ratio = 0.7:调到0.6会漏检,0.8全是误匹配
- RANSAC threshold = 5.0:重投影误差5像素
- NMS IoU = 0.5:太严会漏掉相邻物体
找到候选框后,用SAM在框中心点做一次point prompt,匹配加精修一步到位。
3.5 文本分割(Text Prompt)
最具“魔法感”的一个——用自然语言告诉模型你要分割什么。
仅靠SAM本身无法处理文本prompt(SAM只支持点和框),因此需要接入CLIPSeg做“文本→粗mask”。
两阶段Pipeline:

几个需要特别注意的点:
- CLIPSeg输出为352×352,必须resize回原图尺寸。第一次没注意,mask边缘锯齿严重
- 阈值0.3偏激进,宁可多召回,NMS会兜底
- 网格点比例:每15000像素一个点,单区域最多20个。否则撒点N²爆炸
- NMS阈值0.5太严会保留重复,太松会漏——最终固定在0.5跑了一个月没变过
实测2.1s找到10个目标(含CLIPSeg推理时间)。
4. ONNX导出:让CPU推理再快50%
导出过程一开始失败,报错RuntimeError: Only tensors, lists, tuples of tensors, or dictionary of tensors can be traced。原因是SAM内部某处使用了int(x.item()),trace模式下被当作常量处理。
解决思路:将与图像尺寸相关的crop/resize全部移到模型外部,模型只做纯前向计算,裁剪/缩放由调用方的Python端处理。
第二个坑是dynamic shape。point_coords的N必须声明为动态轴,否则换一个点数就会shape mismatch。ONNX导出时用dynamic_axes显式声明。
加速效果:ONNX推理比PyTorch快30%-50%,主要消除了Python端的dispatch开销。
5. 性能数据(M1 MacBook Pro, CPU only)
| 模式 | 1024×1024 | 1920×1080 | 4K |
|---|---|---|---|
| Point | 180ms | 220ms | 380ms |
| Box | 180ms | 220ms | 380ms |
| Everything (50 mask) | 4.2s | 5.1s | 8.7s |
| Text (top_k=10) | 2.1s | 2.6s | 4.5s |
Point/Box均在200ms以内,人眼几乎无感知。
6. 几个不致命但很烦人的坑
- CLIPSeg首次加载需要下载约1.3GB模型。启动时采用异步加载,不要阻塞
/health接口 - mask边界有时会漏出物体。将
multimask_output=True时的3个候选都绘制出来,让用户选择分数最高的 - Canvas在高DPI屏下模糊。需要按
devicePixelRatio缩放canvas尺寸和绘图比例 - everything模式返回上百个mask。前端按面积排序展示,否则页面卡死
- Safari下base64图片的onload事件不触发。原因是base64中包含换行符,需要
.replace(/s/g, '') - AKAZE在低纹理图上提取不到特征点(纯色背景)。fallback到模板匹配方案
7. 如何从零搭建
如果你想参考这个方案,按以下顺序操作:
pip install fastapi uvicorn torch torchvision opencv-python-headless Pillow transformers onnxruntime- 拉取MobileSAMv2源码,
pip install -e . - 下载两个权重文件:
mobile_sam.pt(40MB)+Prompt_guided_Mask_Decoder.pt(16MB),总共56MB - FastAPI创建5个
/segment/*接口,前端使用原生HTML + Canvas单文件 python3 backend/app.py,浏览器打开http://localhost:8000
写在后面
MobileSAMv2带来的最大启示是:大模型不必从头训练,把最重的部分替换掉,保留精修模块,能力可以保留95%。这个思路套用到很多场景都成立。
SAM 3那种“全员大模型”路线当然是未来方向,但对个人开发者、对边缘设备、对今天就要跑起来的需求,56MB + 毫秒级响应 + 5种prompt方式仍然是更务实的选择。
后续计划尝试:
- 将mask解码器进一步蒸馏到更小
- 实现视频版的track anything
- 在移动端用NCNN / MNN部署,目标是达到30fps
来源:互联网
本网站新闻资讯均来自公开渠道,力求准确但不保证绝对无误,内容观点仅代表作者本人,与本站无关。若涉及侵权,请联系我们处理。本站保留对声明的修改权,最终解释权归本站所有。