查看 Markdown

可提示分割

可提示分割把一次点击变成一张掩码:你指向一个对象,或者围着它画一个框,模型就返回它的轮廓。在 LibreYOLO 里它不是一个单独的任务键,而是一个模型层级,通过 LibreSAM 工厂函数加载,它的结果就是普通的分割 Results。

定义

可提示分割接受一张图像加一个空间提示,返回提示所指向的那个东西的掩码。这里不做 任何分类:没有类别列表,result.boxes 里装的是由掩码推出的紧致检测框,而不是 自成一体的检测结果。result.masks 承载掩码数据,result.masks.xy 是它的多边形。

提示就是接口。points[x, y] 像素坐标,每个对象一组,labels 把每个点标为 正(1,包含它)或负(0,排除它)。bboxes[x1, y1, x2, y2],每个框对应一张 掩码。点和框可以组合,这时它们按对象两两配对,长度必须一致。所有提示都不给就会走 分割一切那条路径,也就是在图上铺一个点网格。

单个点天生就是有歧义的。点在袖子上,可能指袖子、衬衫,也可能指人,所以 multimask=True 会为每个提示返回这三张整体与局部的掩码,而不是单独最好的那一张。 conf 按模型预测的 IoU 过滤,那是掩码质量分数,不是检测置信度。

LibreYOLO 没有 promptable 这个任务键。这一层注册为 segment,和实例分割用的是 同一个键。区分它们的是调用形式,这也是它有自己的工厂函数 LibreSAM() 的原因,它 和 LibreYOLO()LibreOpenVocab()LibreVLM() 并列。单一的 predict(image) 签名表达不了这些模型本来要服务的那个循环:set_image() 把图像编码器跑一次并缓存 嵌入向量,之后每次 source=Nonepredict() 调用只需付出提示解码的开销, reset_image() 则清空缓存。图像编码器是开销的大头,每张图只跑一次,所以对同一张 图的第二次提示会完全跳过它。

模型

有六个家族通过别名经 LibreSAM 加载。

SAM 是默认项,有 baselargehuge 三种尺寸,也可以 写成 blh

SAM 2,别名为 sam2-tinysam2-smallsam2-base-plussam2-large。LibreYOLO 支持它的图像路径。

SAM 3,别名为 sam3,是唯一接受文本概念提示的家族: text="yellow school bus" 会返回每一个匹配的实例。把 text= 传给其他任何家族都 会抛错,错误信息里会点名 SAM 3。它的权重来自 Meta,采用自定义的 SAM 许可证 (SAM License),而不是 LibreYOLO 的 MIT 许可,而且那个仓库是受限(gated)的: 先在模型页面接受条款,并在第一次下载之前用 hf auth login 完成认证。部署它之前 请先读 SAM 3

EdgeTAM,别名为 edgetam,是 SAM 2 的端侧变体。 LibreYOLO 支持它的图像路径。

MobileSAM,别名为 mobilesam,把 SAM 的 ViT-H 编码器 换成了蒸馏得到的 TinyViT 编码器。

PicoSAM3,别名为 picosam3,是一个紧凑的 CNN,面向边缘端 传感器上框提示的区域。框提示就是这里的全部契约:点、文本、掩码、multimask 和分割 一切都会抛错,错误信息会指向 SAM 2 或 SAM 3。

这一层的 extra 覆盖通过 transformers 加载的那四个家族:

bash
pip install "libreyolo[sam]"

MobileSAM 和 PicoSAM3 是 LibreYOLO 原生的移植版本,不装 transformers 也能跑。

预测

点提示与框提示
from libreyolo import LibreSAM, SAMPLE_IMAGE model = LibreSAM("base") # 点是以像素为单位的 [x, y],labels 里 1 为正,0 为负result = model.predict(SAMPLE_IMAGE, points=[640, 420], labels=[1])print(result.masks.xy)      # 多边形print(result.boxes.xyxy)    # 由掩码推出的紧致检测框 # 框提示每个框给出一张掩码result = model.predict(SAMPLE_IMAGE, bboxes=[300, 200, 900, 700])
编码一次,多次提示
from libreyolo import LibreSAM, SAMPLE_IMAGE model = LibreSAM("base") # set_image 把笨重的图像编码器跑一次并缓存下来model.set_image(SAMPLE_IMAGE)first = model.predict(points=[640, 420], labels=[1])second = model.predict(bboxes=[300, 200, 900, 700])model.reset_image()
分割一切
from libreyolo import LibreSAM, SAMPLE_IMAGE model = LibreSAM("base") # 不给提示就表示在整张图上铺一个点网格;每边 32 个点的默认# 网格约等于 1024 次解码器前向,在 CPU 上很慢result = model.predict(SAMPLE_IMAGE, points_per_side=8)print(len(result.masks))
歧义掩码
from libreyolo import LibreSAM, SAMPLE_IMAGE model = LibreSAM("base") # 一个点可能指袖子、衬衫,也可能指人;multimask=True 会返回# 这三张整体与局部的掩码,而不是最好的那一张result = model.predict(    SAMPLE_IMAGE, points=[640, 420], labels=[1], multimask=True)print(len(result.masks))

sourceset_image() 是二选一,不是先后两步:一次性调用就把图像传给 predict(),或者先调用 set_image(),再对每个提示调用 predict(source=None)。 给 predict()device= 会为这次调用以及之后每一次调用移动模型,并让所有已缓存 的嵌入向量失效。

分割一切是昂贵的那种模式。points_per_side 默认为 32,大约是在图上跑 1024 次 解码器前向;在 CPU 上做任何交互式的事情都该把它调低。在这种模式下,不设 conf 会套用该家族的网格阈值,而在有提示的路径下,不设 conf 则保留每一张掩码。两种 模式下都可以传 conf=0.0 关掉过滤,并用 max_det 限制返回多少张掩码。

这个版本不支持掩码提示,masks= 会抛错,而不是被忽略。track() 在这一层同样会 抛错:它们都是图像分割器,所以请逐帧调用 predict()。输入源和结果处理见 预测

训练

这一层没有任何家族能在 LibreYOLO 内部训练。train() 会抛错:请在上游微调,再把 得到的权重加载进来。

验证

这一层没有验证器,val() 会抛错。可提示的掩码没有固定的类别集合可供打分,所以 常规的检测和分割指标无从下手。给一张有提示的掩码打分,意味着拿它和你自己提供的 参考掩码去比,比的是你关心的那些提示。

导出

导出整体不在这一层的范围内,export() 会抛错,只有一个例外。 PicoSAM3 会把它那个原始的 96x96 区域 CNN 导出为 ONNX, 形式是 roi_image -> mask_logits;框裁剪和把掩码缩放回图像坐标的那一步留在 Python 里。其他每个家族都在 PyTorch 里通过 predict() 运行。库中其他地方可用的 格式见导出

已针对 LibreYOLO v1.5.0 验证。