SAM (Segment Anything):可提示的零樣本分割 - 點一下,就圈出危險區域

SAM (Segment Anything):可提示的零樣本分割 - 點一下,就圈出危險區域

傳統分割要為每一類危險物標一堆像素遮罩,且只認訓練過的類別;但溢出的油、掉落的貨、積水的地面千奇百怪,標不完。SAM 換掉整個提問方式:不綁類別,做「可提示 (promptable)」——你點一下、框一下,它就把那個東西的邊界描出來,沒看過的物件也行。本篇在筆電 CPU 上從零手刻 mini-SAM,忠實重現它的解耦架構(影像編碼一次、每個提示便宜解碼),在沒見過的場景上點提示分割拿到 mean IoU 0.949,並示範 SAM 招牌的「segment everything」自動全分割。


核心貢獻者

Alexander Kirillov 領銜、包含 Ross Girshick、Piotr Dollár 等 Meta AI (FAIR) 團隊於 2023 年發表 SAM《Segment Anything》。它的突破不只在模型,更在任務設計:把分割重新定義成「可提示 (promptable)」——輸入一張圖加一個提示(點、框、遮罩甚至文字),輸出對應的遮罩。搭配一台「資料引擎」滾出的 SA-1B(1,100 萬張圖、11 億個遮罩)這個史上最大分割資料集,SAM 學到的是一種通用的「描邊」能力,能對從沒見過的物件零樣本分割。它後來成了無數標註工具、醫療影像、影片編輯 (SAM 2) 的底層引擎。


為什麼要「可提示」的分割?

Day 47 的 CLIP 回答「整張畫面像不像這句話」,但工安現場常需要像素級的答案:那攤積水範圍多大、那塊油污邊界在哪、禁區被誰的腳踩進來。這是分割 (segmentation) 的地盤。

傳統語意分割(如 U-Net)有兩個硬傷:要為每一類標大量像素遮罩,而且只認訓練過的類別。可是廠區的「危險物」千奇百怪——溢出的化學液、掉落的棧板、破損的護欄、地上的積水——你不可能為每一種都標一份資料、訓一個模型。

SAM 的解法是把「認類別」整個拿掉:它不問「這是什麼」,只做「你指的那個東西,把邊界描出來」。你點一下、拉一個框,它就回一個遮罩——沒看過的東西照樣圈得出來。危險物的種類再多也不怕,因為它學的是通用的分割能力,不是固定的類別表。


誰在螢幕上點?SAM 的四種真實情境

「點一下」聽起來很互動,但監視器前面沒有人整天在點螢幕。SAM 的真實定位是「工具的工具」——四種情境,點擊的人各不相同:

情境誰在「點」頻率說明
標註加速(最大宗)標註人員建資料集期間手畫遮罩要描幾十個頂點,SAM 點一下完成;CVAT、Label Studio 等標註工具皆已內建
系統建置(一次性)工安主管/系統商裝機時點一次在固定攝影機畫面框出「禁區」,遮罩存下來永久使用,之後 runtime 沒有人再點
事後調查工安/調查人員出事才用調閱事故畫面,點油污算面積、圈損壞範圍——把「目測」變「精確量測」
自動管線(無人點)另一個模型逐幀Grounded-SAM 模式:偵測器吐出的框就是提示,SAM 把框精化成像素遮罩

所以 SAM 幾乎不會是第一線的即時系統,它是幕後角色。與前兩天主角的分工差異一句話講清:CLIP 用文字「找」畫面(人打字)、YOLO 即時「報」違規(全自動)、SAM 把框「描」成精確邊界——而 SAM 最大的經濟價值,其實是把 YOLO 的標註成本打下來,這正好接回 Day 46 的老問題:標籤太貴。


1. 資料集來源

資料集:合成多物件場景(自產 ground-truth 遮罩)

備註:SA-1B 的 11 億遮罩無法在筆電上重現,所以這裡用純 numpy 自己生多物件場景:一張 64×64 的畫布上隨機擺 2~4 個不同顏色/大小/位置的形狀,而且每個物件的精確遮罩我都知道(拿來當訓練與評估的答案)。它小到 CPU 幾分鐘跑完,又能演出 SAM 的靈魂——可提示 + 零樣本 + 解耦架構

實驗設計

  • 訓練:餵「影像 + 一個點提示(某物件內部一點)」,要模型輸出那個被點到物件的遮罩。
  • 零樣本評估:在全新隨機佈局的場景上點提示,量預測遮罩與真值的 IoU
  • 招牌示範:用一整排網格點當提示,做 SAM 的「segment everything」自動全分割。

2. 原理

2.1 關鍵是「可提示」這個任務

SAM 最聰明的地方,是把分割設計成一個萬用介面:不管你給點、給框、給文字,模型都要回一個合理的遮罩。訓練時就是逼它學會「把提示指向的那個連通物件描出來」。一旦學會這件通用的事,下游各種需求都變成「換個提示」而已——這跟 CLIP 把分類變成「換句話」是同一種哲學。

2.2 解耦架構:重編碼器跑一次,輕解碼器狂跑

SAM 的架構刻意拆成三塊,而且重量分配很不對稱:

Loading Diagram...
  • 影像編碼器很重、但只跑一次:一張圖進來,用 ViT 算出特徵——這步最貴。
  • 遮罩解碼器很輕、每個提示各跑一次:拿現成的影像特徵配上提示,幾乎瞬間吐出遮罩。
  • 妙處在互動:一張圖編碼一次,之後你狂點都很便宜——這就是 SAM 能做到「即時互動分割」的祕密。

2.3 零樣本從何而來?

SAM 不是「認得很多類別」,而是根本不認類別。因為 SA-1B 的 11 億遮罩涵蓋了海量物件,模型被逼著學會一種與類別無關的通用描邊能力——「把提示指向的連通區域,依邊界切出來」。這種能力對沒見過的物件一樣有效,所以是零樣本。

2.4 歧義處理

點在一個人的襯衫上,你要的是襯衫、還是整個人?SAM 的答案是一次輸出 3 個遮罩(整體 / 部分 / 子部分)並各給信心分,讓下游自己挑。(本篇的 mini 版簡化成單遮罩,但這個「一提示、多解讀」的設計值得記住。)


3. 實戰

Python 程式碼實作

# SAM 式解耦:編碼器很重(跑一次),解碼器很輕(每個提示跑一次)
class ImageEncoder(nn.Module):     # 3 層卷積,保持解析度 -> 影像特徵
    def forward(self, x): return self.net(x)
class MaskDecoder(nn.Module):      # 影像特徵 + 提示熱圖 -> 遮罩
    def forward(self, feat, prompt):
        return self.net(torch.cat([feat, prompt], 1))

# 提示 = 點擊位置的高斯熱圖(SAM 用點/框編碼器,這裡用熱圖當代理)
def point_heatmap(px, py, sigma=3.0):
    yy, xx = np.mgrid[0:H, 0:W]
    return np.exp(-((xx-px)**2 + (yy-py)**2) / (2*sigma**2))

# 訓練:對「被點到的物件遮罩」做二元交叉熵
logits = dec(enc(imgs), prompts)
loss = F.binary_cross_entropy_with_logits(logits, gt_masks)

# 推論:一張圖編碼一次,之後每個點提示便宜解碼
feat = enc(image)                             # 貴,只做一次
mask = torch.sigmoid(dec(feat, point_heatmap(px, py))) > 0.5

程式碼重點:

  • 解耦是靈魂:enc(image) 只算一次,之後每個提示只跑輕量的 dec——這是「編碼一次、狂點都便宜」的來源。
  • 提示用高斯熱圖:把「點在哪」變成一張模型看得懂的空間圖(SAM 用專門的點/框編碼器,熱圖是 CPU 友善的代理)。
  • 損失盯著「被點到的那個物件」:同一張圖點不同地方,答案就不同——這正是「可提示」的訓練訊號。
  • 評估用 IoU:預測遮罩與真值的交集除以聯集。

IoU=ABAB\text{IoU} = \frac{|A \cap B|}{|A \cup B|}


4. 模型評估

一張圖、不同點擊,分出不同物件

可提示分割

同一張圖只編碼一次,黃色星號點在哪,遮罩(白色)就精準蓋住哪個物件——點粉紅三角形給三角形、點黃方塊給方塊。這就是「點一下就圈出危險物」的原型

零樣本:全新場景照樣點得準(mean IoU 0.949)

零樣本分割

在 150 個訓練時從沒見過的隨機佈局上點提示,平均 IoU = 0.949,單張多落在 0.92~0.99。模型學到的顯然不是「背這幾個場景」,而是通用的「把點到的東西描邊」能力——換了佈局照樣有效。

Segment Everything:一次編碼,狂點全分割

自動全分割

把一整排網格點都當提示、再用 NMS 去掉重複遮罩(SAM 的自動模式就是這樣),一張圖就被切成一塊塊物件。誠實說:mini 版邊界會有點毛、相鄰物件偶爾過度切分(大三角形被拆成兩塊)——真實 SAM 靠 ViT-H 與 11 億遮罩,邊界利得多;但「一次編碼、數十個便宜提示、自動全分割」的運作方式一模一樣

工安視角的解讀

  • 點危險物 → 要邊界、更要面積:點一下溢出的油污或積水,拿到精確遮罩就能換算面積、判斷是否超標——這是純偵測框(Day 49 的 YOLO)給不了的像素級資訊。
  • 框禁區 → 自動監看闖入:用框提示把「禁區」一次圈成遮罩,之後任何人的腳一旦落進這片遮罩就告警,不必為「禁區」這個抽象概念訓練任何分類器。
  • 三者分工:CLIP 找(用文字撈出可疑畫面)、SAM 圈(把危險物/區域精準描邊)、YOLO 即時報(邊緣攝影機逐幀告警)——工安視覺系統通常是這條流水線的組合。
  • 誠實提醒:本篇是合成形狀的玩具規模;真實 SAM 吃的是複雜實照、邊界更精細。但「可提示 + 零樣本 + 解耦」這套核心設計,大小模型一致。

5. 總結

我們學習了 SAM (Segment Anything):

  • 換一個任務:不做「認類別的分割」,做「可提示的分割」——給點/框,回遮罩,通用介面。
  • 解耦架構:重量級影像編碼器只跑一次,輕量級遮罩解碼器每個提示便宜跑,換來即時互動。
  • 零樣本:靠 11 億遮罩學到與類別無關的通用描邊能力,沒見過的物件照樣分割。
  • 實驗結論:從零手刻的 mini-SAM,在沒見過的場景點提示分割 mean IoU 0.949,並重現了「segment everything」自動全分割。
  • 工安啟示:點危險物拿精確邊界與面積、框禁區自動監看闖入;它在視覺流水線裡負責「精準描邊」這一棒。

下一篇從「更強」轉向「更省」:上面這些模型再厲害,塞不進廠區那台巴掌大的邊緣攝影機也是白搭。模型壓縮——知識蒸餾、剪枝、量化:如何把一個 YOLO 瘦身到能在邊緣裝置上即時跑,還不掉太多精度?