🚀 纯前端抠图——实现抠图自由
📖 背景介绍
本文基于 segment-anything 实现“抠图自主选区”。此前我们做过基于模型的自动抠图,但主体是自动识别的,可能会漏保留我们想要的部分。主体选择与自动抠图最大的区别是:用户可以自主选择【保留】【删除】的部分。
Tips:本文主要阐述模型应用实践,对算法本身不做过多介绍。想了解更多算法细节,可直接访问下方 SAM 项目。
Tips:本文不展开讲解 onnxruntime-web;如果你还不了解它,可以先熟悉一下。
🎯 效果展示
先上效果图。下面对界面上的一些信息做必要的前置标注,顺序从上到下。
蓝色点:保留点。模型会自动推理该点所在的区域。虽然传入的是一个点,但结果是一个区域。可以类比地图应用:无论鼠标点在区域内的哪个位置,选中的都是整个区域。若多个保留点落在同一范围内,最终保留的仍是该区域本身。(传入模型的只是一个像素的 x、y 坐标,这里为便于理解做了可视化放大)
红色点:删除点,同上,只是从保留变为删除。
Refine 按钮:基于上次的结果,进一步细化蒙版,对结果进行调优。
预览区域:每次运行的结果图,本质是蒙版与原图叠加后的预览。
整体流程&模型参数介绍
Segment Anything Model 除了主体选取效果好,解码推理速度也是亮点。SAM 将整个流程分为两段:
- 第一段:获取图片特征(即 image_embed)。直译为“图像嵌入”,更贴近含义的说法是“特征”。
- 第二段:结合图像特征与保留点、删除点等提示,生成遮罩数据(即抠图结果)。
可以看到,第一阶段只需运行一次。SAM 将获取图像特征这一耗时步骤拆分出来,因此可以在交互阶段实现接近实时的选区效果。
Encoder 模型参数介绍
Encoder 模型,对应第一阶段执行的操作,即获取图片特征的过程。
模型输入
- image:图片的
ImageData数据。
模型输出
- image_embed:主干编码器的低分辨率特征图。供掩码解码器作为全局图像嵌入使用。
- high_res_feat1:较高分辨率的特征,用于细节/边界细化。
- high_res_feat2:中等分辨率特征,与上面特征一起提升掩码质量。
Decoder 模型参数介绍
Decoder 模型,对应第二阶段执行的操作,即获取遮罩数据的过程。
模型输入(Decoder)
- image_embed:主干编码器的低分辨率特征图,供掩码解码器作为全局图像嵌入使用。提供场景/语义信息,是解码的主条件。(Encoder 模型的输出)
- high_res_feat1:编码器的高分辨率细节特征,用于边界与细节细化。(Encoder 模型的输出)
- high_res_feat2:编码器的中等分辨率结构特征,与上两者共同提升掩码质量。(Encoder 模型的输出)
- point_coords:交互点的像素坐标,
[x, y]。 - point_labels:与
point_coords一一对应的标签,1=前景正点,0=背景负点。 - boxes:可选矩形提示,
[x1, y1, x2, y2]。无框可传全 0,这里通过“左上”“右下”两个点确定一个矩形。
- mask_input:迭代细化的先验掩码。首次推理传全 0;之后将上一轮输出的
low_res_masks中选中的一张回填到这里,可继续细化。