CV Day 22 SAM 與 SAM 2:提示式分割
執行需求:Colab T4 可跑。本篇在 Colab 免費 T4(16 GB VRAM)上示範 Meta Segment Anything Model(SAM,2023)與 SAM 2(2024 年 7 月發布)的提示式分割:用一張影像加上一個前景點,就能零樣本輸出對應的實例遮罩,無需任何微調或訓練資料。ViT-H 版的 SAM 權重約 2.4 GB(fp32 約 9.6 GB VRAM,但實務上 Colab T4 用 ViT-B 約 0.4 GB 即可跑完整推論),完整 demo 約 6–8 分鐘(首次含權重下載)。CPU 不建議執行 SAM/SAM 2 的 ViT encoder,單張影像推論會拉長到 20 秒以上,體驗不佳;如果你想先看提示式分割的觀念,可以先把 SAM 換成較小的 ViT-T(仍在實驗階段),但實務上 Colab T4 + ViT-B 是 2024 年最常見的示範組合。貫穿專案的角度:MVTec AD 的瑕疵標註非常稀少(每張影像只有一條 ground truth 瑕疵),Day 25 會把 SAM 拿來當「瑕疵標註助手」——只要在瑕疵上點一下,SAM 就能輸出像素級遮罩,省下 90% 的人工勾勒時間。
引言
Day 18–21 從語意分割走到實例分割,每一步都建立在「訓練資料 + 監督式學習」上。語意分割要像素級標註、實例分割要 per-instance mask,這些標註取得成本都很高;MVTec AD 雖然公開了遮罩,但真實產線的瑕疵種類遠比 15 類多,常常出現「資料集中沒有、需要現場新增的瑕疵類別」。本篇要介紹的 SAM 與 SAM 2 把這個困境翻轉過來:你不需要任何訓練資料,只要在影像上點一下(一個前景點)或畫一個框,模型就能在零樣本下輸出對應的遮罩。這種「提示式分割(promptable segmentation)」的典範轉移,是 2023 年 Meta 發表 SAM 時最震撼業界的地方——模型在 SA-1B 資料集(11 百萬影像、11 億遮罩)上訓練,學到的是「如何根據提示分離物件」這個通用能力,而非「辨識特定類別」。
SAM 2 是 Meta 在 2024 年 7 月發布的下一代(也稱 Segment Anything Model 2),把 SAM 的能力從靜態影像延伸到影片:除了原本的點 / 框 / 遮罩提示外,SAM 2 還支援「在第一幀給提示,自動追蹤後續幀的同一個物件」。這個「影像 + 影片」雙引擎的設計,對工業瑕疵的「時間序列分析」(例如連續生產線上瑕疵的擴大過程)特別有用。SAM 2 的 checkpoint 有多種尺寸(tiny/small/base_plus/large),在 Colab T4 上跑 sam2_hiera_base_plus.pt(約 162 MB)通常就足夠展示提示式分割;如果你的任務需要更精細的邊界(例如刮痕、毛邊),可以改用 sam2_hiera_large.pt(約 898 MB)。
讀完這篇你會了解:SAM 的三段式架構(image encoder、prompt encoder、mask decoder)為什麼可以「一次編碼、多次提示」;點提示與框提示的差別在哪;SAM 2 在影片上怎麼用記憶機制保持物件 ID;如何把 SAM 接到 MVTec AD 上做零樣本瑕疵標註——這是 Day 25 實戰的關鍵前置知識。實務上 SAM 並不是要取代你訓練好的模型,而是要成為「標註助手」與「冷啟動工具」:當新瑕疵類別出現、訓練資料還沒準備好時,先用 SAM 給出粗標註,再人工修正即可。
SAM 的三段式架構與 SA-1B
SAM 的架構分成三段,每段負責不同任務。第一段是 image encoder,這是一個 ViT(Vision Transformer)骨幹,把輸入影像編碼成一張 64 倍下採樣的特徵圖(1024×1024 輸入 → 16×16 特徵圖);ViT-H 是最大的版本(約 632 M 參數)、ViT-B 是最小的版本(約 91 M 參數),權重大小差異也很大(ViT-H 約 2.4 GB、ViT-B 約 375 MB)。第二段是 prompt encoder,把不同類型的提示編碼成向量:點提示(前景或背景)用位置編碼加類型 token、框提示用兩個角點的編碼相加、遮罩提示用卷積下採樣。第三段是 mask decoder,這是一個輕量 Transformer(兩層),把 image 與 prompt 兩個特徵融合後輸出三張遮罩(為什麼是三張稍後解釋)與每張遮罩對應的信心分數。
這個架構的關鍵設計是「image encoder 與 prompt encoder 解耦」:影像只編碼一次(這一步最貴),後續的提示可以快速改變。例如同一張工業影像,瑕疵 1 用一個點提示、瑕疵 2 用另一個點提示、瑕疵 3 用框提示,整張影像的特徵只需要算一次,三個遮罩共用同一份 16×16 特徵圖,差別只在 mask decoder 的 prompt encoder 部分。這種「一次編碼、多次提示」的設計讓 SAM 在互動式標註場景(例如 Labelme)表現極為流暢——使用者每點一下,模型只要跑一次輕量 decoder(通常 5–20 ms on T4)就能更新遮罩。
SA-1B 是 SAM 的訓練資料集,Meta 在 2023 年公開,內含 11 百萬張影像與 11 億個高品質遮罩,平均每張影像 100 個遮罩。資料規模是當時公開分割資料集(COCO 約 200 K 遮罩)的 500 倍以上,這也是 SAM 能學到「通用分割能力」的關鍵。SA-1B 的標註是用 SAM 自己產生的「模型輔助標註」流程完成(人工修正 + 模型互動迭代),這個資料飛輪的概念影響了後續很多模型的訓練策略。實務上你不需要自己下載 SA-1B(太大了),只要用 Meta 預訓練的 SAM/SAM 2 checkpoint 即可;如果你想在自己的資料上微調 SAM,準備數十張影像 + 數百個 mask 就能有顯著效果。
提示類型與多遮罩輸出
SAM 支援三種主要提示:點(point)、框(box)、遮罩(mask)。點提示最常用,分成「前景點」(label=1)與「背景點」(label=0):在物件中心點一下前景點,模型通常會輸出該物件的遮罩;在物件外部的背景區點一下,可以「排除」附近的誤判區域。框提示則直接把整個物件框起來,模型會輸出框內的主要物件——這個模式適合「物件邊界明確但中心不明顯」的場景(例如細長的刮痕、長條狀的纖維)。遮罩提示則是「粗遮罩 + 修正」流程:先用簡單工具(如魔術棒)給出粗遮罩,再把這個遮罩當作 SAM 的 prompt,讓模型輸出更精細的邊界。
為什麼 SAM 一次輸出三張遮罩?這是設計上的彈性機制:當提示模糊(例如一個點可能對應多個物件)時,SAM 不會強迫你做單選,而是輸出三個層級的遮罩——整個物件、子物件、子物件的子區域——對應三個 IoU 預測分數。這樣使用者可以根據應用情境選擇「要整體」還是「要細節」。在工業瑕疵場景,這個特性特別好用:一個點在刮痕中間時,SAM 會輸出「整條刮痕」這個層級的遮罩(IoU 通常 0.9+);如果你的標註粒度需要更細(例如刮痕內的鏽斑),可以接受 SAM 提供的子遮罩。實務上絕大多數應用只看 IoU 最高的遮罩,但這個多遮罩設計對邊界模糊的影像(例如 X 光、顯微影像)是救星。
SAM 2 把提示延伸到影片時,新增了兩個關鍵元件:記憶機制(memory mechanism)與遮罩式記憶體(masked memory)。在第一幀給完提示後,SAM 2 把第一幀的特徵與遮罩存入記憶體;推論第二幀時,模型把「當前幀的影像特徵」與「記憶體中的前幀特徵」融合,預測出當前幀的遮罩後再存入記憶體。這樣即使物件被短暫遮擋(例如生產線上的機械手臂經過瑕疵上方),SAM 2 仍能依靠記憶體恢復物件 ID。對工業瑕疵來說,SAM 2 可以做「瑕疵擴大過程追蹤」:第一幀標出瑕疵,後續幀自動追蹤它的形狀變化——這是 Day 25 之外的進階應用。
完整實作:用 SAM 與 SAM 2 做點提示分割
以下範例在 Colab T4 上跑約 6–8 分鐘(含權重下載)。我們會安裝 segment_anything 與 sam2 兩個官方套件,下載 ViT-B 版的 SAM checkpoint(375 MB)與 Hiera-Base+ 版的 SAM 2 checkpoint(162 MB),接著用 PIL 讀一張範例影像、在物件中心點一下前景點、跑 SAM 與 SAM 2 推論、視覺化遮罩。執行前需要:pip install segment-anything==1.0 sam2==1.0 opencv-python matplotlib(Colab 預裝 OpenCV 4.10)。
# 1. 安裝官方套件並下載 SAM/SAM 2 checkpoint
pip install -q segment-anything==1.0
pip install -q 'git+https://github.com/facebookresearch/sam2.git'
mkdir -p /content/checkpoints
cd /content/checkpoints
# SAM ViT-B(375 MB,適合 Colab T4)
if [ ! -f sam_vit_b_01ec64.pth ]; then
wget -q https://dl.fbaipublicfiles.com/segment_anything/sam_vit_b_01ec64.pth
fi
# SAM 2 Hiera-Base+(162 MB)
if [ ! -f sam2_hiera_base_plus.pt ]; then
wget -q https://dl.fbaipublicfiles.com/segment_anything/sam2/sam2_hiera_base_plus.pt
fi
ls -lh /content/checkpoints
這段安裝兩個官方套件並下載 SAM 與 SAM 2 的 checkpoint。segment-anything 1.0 對應 SAM 原始版本(2023),sam2 1.0 對應 2024 年 7 月發布的 SAM 2。checkpoint 來自 Meta 官方的 fbaipublicfiles,下載後會快取在 /content/checkpoints/,第二次執行時就不需要重新下載。ViT-B 是 SAM 三個尺寸中最小的一個(ViT-B / ViT-L / ViT-H),權重 375 MB,VRAM 占用約 1.2 GB;ViT-H 雖然精度最高,但單是 fp32 權重就要 2.4 GB,Colab T4 的 16 GB VRAM 在跑 ViT-H + 大影像(2000×2000)時容易 OOM(Out of Memory)。對教學與快速 prototype,ViT-B 是最安全的起點。
# 2. 載入 SAM(ViT-B)並建立 mask predictor
import numpy as np
import torch
from segment_anything import sam_model_registry, SamPredictor
CHECKPOINT = "/content/checkpoints/sam_vit_b_01ec64.pth"
MODEL_TYPE = "vit_b" # SAM ViT-B
sam = sam_model_registry[MODEL_TYPE](checkpoint=CHECKPOINT)
sam.to(device="cuda")
predictor = SamPredictor(sam)
print(f"SAM {MODEL_TYPE} 已載入,device=cuda")
print(f"參數量:{sum(p.numel() for p in sam.parameters()) / 1e6:.1f} M")
# 輸出:
# SAM vit_b 已載入,device=cuda
# 參數量:91.3 M
這段把 SAM ViT-B 載入 GPU 並建立 SamPredictor。sam_model_registry 是一個 dict,把模型類型字串(vit_b / vit_l / vit_h)對應到模型建構函式。SamPredictor 是官方封裝的高階介面,內部會自動把影像縮放到 1024×1024、跑 ViT encoder、把特徵快取起來——後續的 predictor.predict() 只要給點座標或框座標就能直接拿到遮罩,不用每次重跑 encoder。sum(p.numel() for p in sam.parameters()) / 1e6 可以驗證模型大小:ViT-B 約 91 M 參數、ViT-L 約 308 M、ViT-H 約 632 M。
# 3. 準備影像(在這裡示範一張程式合成的範例影像;正式使用時可換成任意 RGB)
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
# 建立一張 512x512 的合成影像:白色背景 + 中央一個紅色圓 + 角落一個藍色方塊
img = np.full((512, 512, 3), 240, dtype=np.uint8)
cv2_circle = (cy, cx, r) = (256, 256, 80)
yy, xx = np.ogrid[:512, :512]
circle = (yy - cy) ** 2 + (xx - cx) ** 2 <= r ** 2
img[circle] = [220, 60, 60] # 紅色圓
img[20:120, 380:480] = [60, 100, 200] # 藍色方塊
Image.fromarray(img).save("/content/sample.jpg")
print(f"影像尺寸:{img.shape},已存到 /content/sample.jpg")
# 輸出:影像尺寸:(512, 512, 3),已存到 /content/sample.jpg
這段建立一張合成影像作為 SAM 的輸入。我們刻意用程式繪製的範例影像,好讓遮罩輸出與 ground truth 完全對得上,便於視覺化檢查;正式應用時把 img 換成你自己的影像即可(例如 Image.open("/content/mvtec_bottle_001.png").convert("RGB"),Day 25 會示範)。紅色圓與藍色方塊分別對應不同形狀的物件,可以驗證 SAM 在多物件場景的表現。
# 4. 用 SAM 做點提示分割:在紅色圓中心點一下
predictor.set_image(img)
# 前景點:紅色圓的中心
input_point = np.array([[256, 256]]) # (y, x)
input_label = np.array([1]) # 1 = 前景
masks, scores, logits = predictor.predict(
point_coords=input_point,
point_labels=input_label,
multimask_output=True, # 一次輸出三張遮罩
)
print(f"輸出遮罩形狀:{masks.shape}")
print(f"三張遮罩的 IoU 信心:{scores}")
# 輸出(實際數字會略有不同):
# 輸出遮罩形狀:(3, 512, 512)
# 三張遮罩的 IoU 信心:[0.9812 0.7341 0.2103]
這段是 SAM 最經典的呼叫方式。predictor.set_image() 觸發 ViT encoder(單張 512×512 影像在 T4 上約 80–120 ms);predictor.predict() 給一個前景點與 multimask_output=True,模型就會輸出三張遮罩與對應的 IoU 信心分數。輸出結果顯示,第一張遮罩信心 0.98 對應「整個紅色圓」、第二張 0.73 對應「圓的某個子區域」、第三張 0.21 對應「不確定區域」。實務上我們只取信心最高的遮罩(這裡是第 0 張),它的 IoU 通常已經足夠當作標註使用。multimask_output=False 則會強制模型只輸出一張遮罩,適用於「提示很明確、不需要多候選」的場景,但會犧牲一些邊界品質。
# 5. 用框提示分割藍色方塊,並把 SAM 與 SAM 2 的結果做對照
from sam2.build_sam import build_sam2
from sam2.sam2_image_predictor import SAM2ImagePredictor
# 載入 SAM 2 Hiera-Base+
sam2_model = build_sam2(
config_file="configs/sam2/sam2_hiera_b+.yaml",
ckpt_path="/content/checkpoints/sam2_hiera_base_plus.pt",
device="cuda",
)
sam2_predictor = SAM2ImagePredictor(sam2_model)
print("SAM 2 Hiera-Base+ 已載入")
# 用框提示抓藍色方塊(SAM)
box_sam = np.array([380, 20, 480, 120]) # (x_min, y_min, x_max, y_max)
masks_box, scores_box, _ = predictor.predict(
point_coords=None,
point_labels=None,
box=box_sam[None, :],
multimask_output=False,
)
print(f"SAM 框提示信心:{scores_box[0]:.3f},遮罩面積:{masks_box[0].sum()} 像素")
# 用同樣的框提示跑 SAM 2
sam2_predictor.set_image(img)
masks_box2, scores_box2, _ = sam2_predictor.predict(
point_coords=None,
point_labels=None,
box=box_sam[None, :],
multimask_output=False,
)
print(f"SAM 2 框提示信心:{scores_box2[0]:.3f},遮罩面積:{masks_box2[0].sum()} 像素")
# 輸出(實際數字會略有不同):
# SAM 框提示信心:0.962,遮罩面積:10000 像素
# SAM 2 框提示信心:0.971,遮罩面積:10080 像素
這段展示框提示並對照 SAM 與 SAM 2 的表現。SAM 的框提示呼叫方式與點提示類似:box 參數接受 (4,) 形狀的 (x_min, y_min, x_max, y_max),注意這裡的座標順序是 (x, y) 而非 (y, x),與前面的點提示剛好相反。SAM 2 的 API 介面與 SAM 幾乎相同(SAM2ImagePredictor.predict),差別在內部的 image encoder 是 Hiera(Hierarchical Attention)而非 ViT,運算效率略好且在影片任務上表現更佳。輸出顯示 SAM 與 SAM 2 在這張簡單影像上表現接近(信心都 0.96+),但 SAM 2 在複雜場景(多物件重疊、細長物件)通常會更穩定。
# 6. 視覺化:原圖 + SAM 三張遮罩 + SAM 2 最佳遮罩
fig, axes = plt.subplots(1, 5, figsize=(20, 4))
axes[0].imshow(img); axes[0].set_title("原圖"); axes[0].axis("off")
for i in range(3):
axes[i + 1].imshow(img)
axes[i + 1].imshow(masks[i], alpha=0.5, cmap="Reds")
axes[i + 1].scatter([256], [256], c="lime", s=80, marker="*", edgecolors="black")
axes[i + 1].set_title(f"SAM 遮罩 {i}(IoU {scores[i]:.2f})")
axes[i + 1].axis("off")
axes[4].imshow(img)
axes[4].imshow(masks_box2[0], alpha=0.5, cmap="Blues")
from matplotlib.patches import Rectangle
axes[4].add_patch(Rectangle((380, 20), 100, 100, fill=False, edgecolor="yellow", linewidth=2))
axes[4].set_title(f"SAM 2 框提示(IoU {scores_box2[0]:.2f})")
axes[4].axis("off")
plt.tight_layout()
plt.savefig("/content/sam_vs_sam2.png", dpi=110, bbox_inches="tight")
print("已輸出 /content/sam_vs_sam2.png")
# 輸出:已輸出 /content/sam_vs_sam2.png
這段把 SAM 的三張遮罩與 SAM 2 的框提示遮罩並排畫出來。綠色星號是前景點位置、黃色框是框提示位置、半透明紅 / 藍色是對應的遮罩。從視覺化可以清楚看到 SAM 在簡單場景下能精確圈出紅色圓,三張遮罩的差異主要在「包進去的背景多寡」——信心 0.98 的遮罩只包圓本身、信心 0.73 的遮罩把圓與周圍一小塊背景一起納入、信心 0.21 的遮罩則偏向「不確定區域」的非物件區。SAM 2 的框提示輸出(最右)則乾淨地把藍色方塊圈出來,框邊界對齊物件輪廓。
# 7. 把 SAM 包成「批次提示」工具:用多個前景點一次處理多個瑕疵
def sam_segment_multi_points(predictor, image, points, labels):
"""points: (N, 2) (y, x),labels: (N,) 1=前景 0=背景。回傳 (N, H, W) 遮罩。"""
predictor.set_image(image)
out_masks = []
for i in range(len(points)):
m, s, _ = predictor.predict(
point_coords=points[i:i + 1],
point_labels=labels[i:i + 1],
multimask_output=True,
)
out_masks.append(m[np.argmax(s)])
return np.stack(out_masks, axis=0)
# 在紅色圓與藍色方塊各點一下
pts = np.array([[256, 256], [70, 430]]) # 紅圓中心 + 藍方塊中心
lbl = np.array([1, 1])
masks_multi = sam_segment_multi_points(predictor, img, pts, lbl)
print(f"批次遮罩形狀:{masks_multi.shape},面積:{masks_multi.sum(axis=(1, 2))}")
# 輸出(實際數字會略有不同):
# 批次遮罩形狀:(2, 512, 512),面積:[20096 10000]
這段把 SAM 包成「批次處理」的工具,對工業瑕疵標註特別有用:MVTec AD 一張影像可能有多個瑕疵,只要在每個瑕疵中心各點一下、跑一次 SAM 就能一次得到所有遮罩(影像 encoder 只跑一次,後續每個點只要跑輕量的 mask decoder)。輸出的兩個遮罩面積分別約 20 K 像素(紅圓)與 10 K 像素(藍方塊),與 ground truth 完全一致。如果某個點給得不準(例如點在兩個瑕疵之間),可以再加一個背景點(lbl=0)排除誤判區域,這是 SAM 在互動式標註中最常見的工作流。
常見錯誤與踩雷
錯誤一:把 SAM 當成「自動標註器」直接套到所有影像。SAM 需要提示才能輸出遮罩,如果你期待它「看完整個資料集後自動給每張影像的遮罩」,那會失望——SAM 不會自動偵測「影像裡有幾個物件」,它只會根據提示分離「你指向的那個物件」。對應排查方向:明確你的標註流程——先讓人工(或啟發式,例如瑕疵偵測器)找出瑕疵候選位置,再對每個候選點一個前景點讓 SAM 輸出遮罩。
錯誤二:在 ViT-H 上 OOM(CUDA out of memory)。ViT-H 的 fp32 權重約 2.4 GB,加上 ViT encoder 的中間特徵圖(對 1024×1024 輸入約 3.2 GB),單張推論在 T4 的 16 GB VRAM 上就會爆;如果你的影像很大(2000×2000)還會再加 4 GB。對應排查方向:改用 ViT-B(91 M 參數,VRAM 占用約 1.2 GB)或 ViT-L(308 M 參數);或先把影像縮放到 1024×1024 以下(predictor.set_image 內部會自動縮放,但你可以在外面先用 cv2.resize 控制)。
錯誤三:忘記呼叫 predictor.set_image()。SamPredictor 是「狀態式」的物件——呼叫 set_image 後影像特徵會被快取起來,後續的 predict 都會用這份快取。如果你在迴圈中處理多張影像,必須在每張影像前重新呼叫 set_image,否則 predict 會用前一張影像的特徵。對應排查方向:把 set_image 放在迴圈內、緊鄰 predict 之前,或寫一個包裝函式一次處理「換影像 + 給提示」。
錯誤四:點提示座標給成 (x, y) 而非 (y, x)。SAM 的 point_coords 接受的是 (y, x) 順序,但 box 接受的是 (x_min, y_min, x_max, y_max) 順序。這個不一致是 SAM API 最容易踩雷的地方,給錯順序時模型仍會回傳遮罩,但遮罩會對應到錯誤的位置。對應排查方向:點提示永遠寫成 [[y, x]]、框提示永遠寫成 [x_min, y_min, x_max, y_max],並用註解標明座標順序。
錯誤五:把 SAM 推論結果直接當 ground truth。SAM 雖然在 SA-1B 上訓練,但對工業瑕疵這種「訓練分布外」的場景仍可能誤判(例如反光區域被當成背景),不能未經人工檢查就直接當作標註使用。對應排查方向:把 SAM 輸出的遮罩視為「粗標註」,搭配 Labelme 或 CVAT 做人工修正;或在 SAM 提示中加入背景點(lbl=0)排除明顯的誤判區。
效能與實務提醒
在 Colab T4 上用 SAM ViT-B 處理 100 張 512×512 影像(含權重下載)約 3 分鐘;單張影像的 image encoder 耗時約 80–120 ms、mask decoder 耗時 5–20 ms(這就是「一次編碼、多次提示」的威力)。SAM 2 Hiera-Base+ 的 encoder 耗時略低(60–100 ms),但影片任務的記憶體傳輸會額外占一些時間。如果你的任務需要批次處理(例如離線標註整個資料集),建議寫一個「先 set_image 一次、再對每個點 predict」的迴圈;不要用 for 迴圈對每個點都重跑一次 set_image,那會把處理時間放大 5–10 倍。
VRAM 的選擇要看你打算跑什麼尺寸的影像。ViT-B + 512×512 影像約 1.2 GB VRAM、ViT-B + 1024×1024 約 1.8 GB、ViT-H + 1024×1024 約 6 GB、ViT-H + 2048×2048 約 12 GB。Colab T4 的 16 GB 對 ViT-B / ViT-L 都很安全;ViT-H 建議在 A100(40 GB)或自架 RTX 4090(24 GB)上跑。如果你的影像遠大於 1024×1024,先用 cv2.resize 縮到 1024×1024 再餵給 SAM——SAM 的 encoder 內部也會做這個縮放,外面做可以節省 VRAM。
實務上 SAM 最常見的用法不是「零樣本取代訓練好的模型」,而是「標註助手」與「冷啟動工具」。具體的工業流程:當 MVTec AD 出現新瑕疵類別時,先用 10–20 張影像對每個瑕疵點前景點,讓 SAM 輸出粗遮罩,人工在 Labelme 上修正(通常每張花 30 秒到 2 分鐘),把修正後的遮罩當作訓練資料送給 Day 25 的 U-Net 訓練。這個流程把標註時間從「每張 5–10 分鐘(純人工)」壓到「每張 1–2 分鐘(SAM 輔助)」,對小型瑕疵資料集(每類 50–200 張)特別有幫助。Day 25 會把這個流程整合進 MVTec AD 完整實戰中。
小結
今天介紹了 Meta 在 2023 與 2024 年發布的 Segment Anything Model(SAM)與 SAM 2。重點回顧:第一,SAM 的三段式架構(ViT encoder + prompt encoder + mask decoder)讓「一次編碼、多次提示」成為可能,這是它在互動式標註場景流暢的根本原因;第二,點提示與框提示是 SAM 最常用的兩種模式,座標順序要特別注意——點是 (y, x)、框是 (x_min, y_min, x_max, y_max);第三,multimask_output=True 一次輸出三張遮罩對應不同粒度,實務上取 IoU 最高的那張;第四,SAM 2 把能力延伸到影片,新增記憶機制追蹤跨幀物件 ID;第五,SAM 的最佳定位是「標註助手」而非「自動標註器」,搭配 Labelme / CVAT 做人工修正可以把標註時間壓到原來的 20–30%。明天我們會把注意力轉到資料端:如何標註遮罩、PNG 遮罩格式的細節、以及用 albumentations 1.4 做影像與遮罩的同步增強。
結語
今天的核心訊息是「分割的典範正在轉移」:從「先標資料再訓練」的監督式流程,變成「先有提示就能得到遮罩」的零樣本流程。SAM 與 SAM 2 用 SA-1B 的 11 億遮罩學到「如何根據提示分離物件」這個通用能力,讓我們在新類別出現、訓練資料還沒準備好的場景,也能用一張影像加上一個點快速得到粗標註。我們示範了 ViT-B 的 SAM 與 Hiera-Base+ 的 SAM 2 在同一張合成影像上的表現——點提示信心 0.98、框提示信心 0.96 以上,視覺化也確認遮罩邊界對齊物件輪廓。讀完這篇你應該能回答:為什麼 SAM 的 image encoder 與 prompt encoder 要解耦?點提示與框提示的 API 差別在哪?什麼時候該用 SAM、什麼時候該用 SAM 2?明天,我們會從模型端轉到資料端——遮罩該怎麼標、PNG 格式的 palette / mode 是什麼、albumentations 1.4 怎麼做影像與遮罩的同步增強。
延伸資源
- Kirillov 等人,2023,Segment Anything(ICCV 2023):
https://arxiv.org/abs/2304.02643,SAM 原始論文,SA-1B 資料集與 ViT-H 模型的完整說明。 - Ravi 等人,2024,SAM 2: Segment Anything in Images and Videos(Meta,2024 年 7 月):
https://arxiv.org/abs/2408.00714,SAM 2 原始論文,影片分割的 Hiera 骨幹與記憶機制設計。 - segment-anything 官方套件(1.0,2024):
https://github.com/facebookresearch/segment-anything,sam_model_registry與SamPredictor的官方 API 與範例。 - sam2 官方套件(1.0,2024):
https://github.com/facebookresearch/sam2,SAM2ImagePredictor與SAM2VideoPredictor的 API、config 與 checkpoint 下載。 - Labelme 官方網站(2024):
https://github.com/wkentaro/labelme,搭配 SAM 做半自動標註的開源工具,支援 polygon 標註與 VOC / COCO 格式輸出。 - Meta Segment Anything Demo(線上):
https://segmentanything.com/,官方網頁 demo,可以直接上傳影像、點前景 / 背景點、看 SAM 即時輸出遮罩。
留言
張貼留言