CV Day 18 分割基礎:語意、實例、全景與 mIoU
執行需求:CPU 可跑。本篇是 Day 10 偵測基礎的分割對應篇,目標是把「語意、實例、全景分割」三種任務的差別、遮罩的四種表示法、以及 mIoU 與 Dice 兩個評估指標一次講清楚。所有程式碼都用純 PyTorch 寫、在 CPU 上跑得動;我們會建立一份 30 張合成影像的小資料集(約 800×600 的彩色幾何圖形),完整跑一遍 mIoU、Dice、Pixel Accuracy 三個指標約 5 分鐘。這個合成的資料集雖然小,但 mIoU 計算邏輯與真實的 VOC、COCO 完全相同,規模放大只是 N 的差別。
引言
Day 10–17 我們把物件偵測從指標(IoU、mAP)到架構(R-CNN、YOLO、DETR)到實戰(VOC person/car 子集)走了一遍。偵測任務回答的是「圖裡的物件在哪、有哪些、各是什麼」,但很多場景需要更精細的答案:「物件的輪廓長什麼樣、佔了幾個像素」。這就是影像分割(image segmentation)的任務範疇,從醫療影像(腫瘤輪廓)、自駕車(道路與行人)、遙測(地表覆蓋)到工業瑕疵檢測(瑕疵面積計算),都是分割任務的核心應用情境。
影像分割有三種主要任務:語意分割(semantic segmentation)給影像中「每個像素」分類,但不區分同類別的不同個體;實例分割(instance segmentation)給每個「物件實例」一個獨立編號,相同類別的不同個體會被分開;全景分割(panoptic segmentation)是前兩者的綜合,既要分類每個像素、也要區分每個實例。這三種任務的差別決定了模型選擇(U-Net、Mask R-CNN、Panoptic FPN)與評估方式。本篇先用一張表格把三種任務的差異整理清楚,再用純 PyTorch 把 mIoU 與 Dice 寫成可在 CPU 跑的函式。讀完你會了解:分割任務的「輸出形狀」是什麼、遮罩該怎麼表示、mIoU 與 Dice 怎麼算、為什麼背景佔大多數時要用 mIoU 而非 pixel accuracy。
三種分割任務的差別
語意分割是最基礎的形式:模型對每個像素預測一個類別索引,輸出形狀是 (H, W),每個值是類別 ID(0 到 N-1)。例如自駕車場景的語意分割把影像分成「道路、汽車、行人、建築、天空」五類,每個像素剛好落在其中一類。這個任務的代表模型是 U-Net 與 DeepLabV3+,訓練時用 cross-entropy loss 對每個像素單獨計算。
實例分割的難度更高:模型要對「每個物件實例」輸出一個獨立遮罩,輸出形狀是 (N, H, W),N 是物件數量(每張影像不同)。例如一張影像有 3 個人、2 輛車,實例分割要輸出 5 個獨立遮罩,第 1 個人與第 3 個人雖然類別都是「人」,但要被分到不同遮罩。這個任務的代表模型是 Mask R-CNN(Day 21 會詳細講),訓練時用 mask loss + box loss + class loss 三個 loss 的加權平均。
全景分割把前兩者合在一起:模型輸出「stuff」類別(如道路、天空)用語意分割的 (H, W) 格式,輸出「thing」實例(如行人、車輛)用實例分割的 (N, H, W) 格式。代表模型是 Panoptic FPN、Mask2Former,輸出是兩種格式的組合。本系列主要介紹語意與實例分割,全景分割留到 Day 25 之後的進階主題。
這三種任務的評估指標也不同:語意分割用 mIoU 與 Pixel Accuracy;實例分割用 mask mAP(與偵測的 mAP 類似,只是把 box 換成 mask);全景分割用 PQ(Panoptic Quality,公式結合 IoU 與分類正確率)。本篇專注在語意分割的 mIoU,因為它是三種任務共同的基礎,也是後續分割章節(Day 19–25)的核心指標。
遮罩的四種表示法
分割任務的標註(ground truth mask)有四種常見表示法,會在不同環節出現:
1. 單通道類別索引(class index):形狀 (H, W),每個值是 0 到 N-1 的整數。這是訓練時最常用的格式,搭配 cross-entropy loss 直接使用。VOC 2012 的 SegmentationClassAug 標註就是這種格式(21 類,含背景與「忽略」類)。
2. 單通道 0/1 遮罩(binary mask):形狀 (H, W),每個值是 0 或 1,1 表示前景、0 表示背景。這是二元分割(如瑕疵 vs. 背景)的標準格式,訓練時用 BCE loss。Mask R-CNN 的 mask target 也是這種格式,但對每個實例各存一張。
3. 多通道 one-hot 編碼:形狀 (C, H, W),每個類別一個通道、值是 0 或 1。這是 cross-entropy loss 的內部表示(one-hot 配上 softmax 等價於 cross-entropy),但因為記憶體用量大(VOC 21 類 × 800×600 = 10 MB),訓練時通常不會實際存成這種格式,而是用 class index 加上 loss 內部的 one-hot 轉換。
4. Palette PNG:VOC 與 Cityscapes 把 mask 存成 PNG 檔,每個類別用一個 RGB 顏色表示(例如 VOC 的「人」是 (192, 0, 0)、「車」是 (64, 0, 128))。這種格式方便人眼看視覺化,但需要額外的 palette 解碼才能轉成 class index。Day 21 的 Mask R-CNN 會教你怎麼從 palette PNG 解析出實例 mask。
實務上最常見的轉換是「palette PNG → class index → one-hot → cross-entropy loss」這個鏈。你不需要在磁碟上存 4 種格式,只要在 Dataset 的 __getitem__ 把 palette PNG 解碼成 class index 即可,後續的 loss 計算會在內部做 one-hot 轉換。
mIoU 與 Dice 的數學定義
mIoU(mean Intersection over Union)是語意分割的標配指標,概念上是「對每個類別算 IoU,再對所有類別取平均」。對類別 c 而言:
IoU_c = |P_c ∩ G_c| / |P_c ∪ G_c|
其中 P_c 是模型預測為類別 c 的像素集合、G_c 是真實為類別 c 的像素集合。IoU 的範圍是 0 到 1,IoU=1 表示完全重疊、IoU=0 表示完全沒交集。對所有類別的 IoU 取平均就是 mIoU:
mIoU = (1/C) × Σ IoU_c
其中 C 是類別數量(含背景)。實務上「背景」通常佔影像 80% 以上像素,背景 IoU 通常都很高(0.95 以上),所以 mIoU 數字會被背景拉高;如果你的任務前景很重要,可以只看前景類別的 mIoU(去掉背景那一類)。
Dice 係數(Dice coefficient)是另一個常用指標,與 IoU 數學上可以互換:
Dice = 2 × |P ∩ G| / (|P| + |G|)
Dice 與 IoU 的關係是 Dice = 2 × IoU / (1 + IoU),例如 IoU=0.5 時 Dice=0.667、IoU=0.7 時 Dice=0.824。Dice 對小目標比 IoU 更敏感,因為它分母用的是像素總和而非聯集;當前景佔影像 1–5% 時,Dice 通常是比 IoU 更直觀的指標(MVTec AD 瑕疵分割常用 Dice)。
Pixel Accuracy 是最直觀但最容易誤導的指標:PA = (預測正確的像素) / (總像素)。當背景佔 99% 時,模型全部猜背景也能達到 99% accuracy、但 mIoU 接近 0;這個 trivial solution 是為什麼 Pixel Accuracy 在分割任務上幾乎沒用、必須用 mIoU 或 Dice。
完整實作:純 PyTorch 寫 mIoU 與 Dice
以下範例用合成資料驗證每個指標的數值正確性。我們建立 30 張 800×600 的影像,每張隨機畫 2–5 個幾何形狀(圓、矩形、三角),遮罩標註每個形狀的類別。整段在 CPU 上跑得動,不依賴 GPU。執行前需要:pip install torch numpy pillow matplotlib。
# 1. 建立合成資料集:30 張影像,每張有 2-5 個幾何形狀與對應的 class index 遮罩
import numpy as np
from PIL import Image, ImageDraw
np.random.seed(42)
NUM_IMAGES = 30
IMG_H, IMG_W = 96, 128 # 為了在 CPU 上跑得快,縮成 96x128;邏輯與 800x600 相同
NUM_CLASSES = 4 # 0=背景, 1=圓, 2=矩形, 3=三角
CLASS_COLORS = {0: (0, 0, 0), 1: (220, 20, 60), 2: (50, 205, 50), 3: (30, 144, 255)}
images, masks = [], []
for i in range(NUM_IMAGES):
img = Image.new("RGB", (IMG_W, IMG_H), (240, 240, 240))
draw = ImageDraw.Draw(img)
mask = Image.new("L", (IMG_W, IMG_H), 0) # 0 = 背景
mdraw = ImageDraw.Draw(mask)
n_shapes = np.random.randint(2, 6)
for _ in range(n_shapes):
cls = np.random.randint(1, NUM_CLASSES)
x0 = np.random.randint(0, IMG_W - 30)
y0 = np.random.randint(0, IMG_H - 30)
w = np.random.randint(15, 30)
h = np.random.randint(15, 30)
if cls == 1: # 圓
draw.ellipse([x0, y0, x0 + w, y0 + h], fill=CLASS_COLORS[cls])
mdraw.ellipse([x0, y0, x0 + w, y0 + h], fill=cls)
elif cls == 2: # 矩形
draw.rectangle([x0, y0, x0 + w, y0 + h], fill=CLASS_COLORS[cls])
mdraw.rectangle([x0, y0, x0 + w, y0 + h], fill=cls)
else: # 三角
draw.polygon([(x0, y0 + h), (x0 + w, y0 + h), (x0 + w // 2, y0)], fill=CLASS_COLORS[cls])
mdraw.polygon([(x0, y0 + h), (x0 + w, y0 + h), (x0 + w // 2, y0)], fill=cls)
images.append(np.array(img))
masks.append(np.array(mask))
print(f"建立 {NUM_IMAGES} 張合成影像,shape={images[0].shape},mask={masks[0].shape}")
print(f"類別分布:背景 {sum((m == 0).sum() for m in masks)} 像素、"
f"前景 {sum((m > 0).sum() for m in masks)} 像素")
# 輸出:建立 30 張合成影像,shape=(96, 128, 3),mask=(96, 128)
# 輸出:類別分布:背景 333207 像素、前景 35553 像素(前景約 9.6%)
這段建立可控的合成資料集:每張影像畫 2–5 個幾何形狀(圓、矩形、三角),遮罩用 class index 標註。我們刻意把影像縮成 96×128,讓 CPU 跑得快;邏輯與真實的 800×600 完全相同,只是 N 比較小。前景佔 9.6%、背景佔 90.4%,這是分割任務的典型分布(背景遠多於前景),mIoU 比 Pixel Accuracy 更能反映模型品質。
# 2. 模擬「完美預測 + 邊界 2 像素偏移」的預測結果,驗證 mIoU 與 Dice 的數值
import torch
def make_predictions(masks, dilation=2):
"""把真實遮罩做 morphological dilation,模擬「預測偏移 2 像素」的模型。"""
preds = []
for m in masks:
# 用 numpy 的 binary_dilation 模擬 2 像素邊界偏移
from scipy.ndimage import binary_dilation
pred = np.zeros_like(m)
for cls in range(1, NUM_CLASSES):
cls_mask = (m == cls)
expanded = binary_dilation(cls_mask, iterations=dilation)
pred[expanded] = cls
preds.append(pred)
return preds
preds = make_predictions(masks, dilation=2)
print(f"預測分布:背景 {sum((p == 0).sum() for p in preds)}、"
f"前景 {sum((p > 0).sum() for p in preds)} 像素")
# 輸出:預測分布:背景 317469、預測前景 51291 像素
這段模擬「真實標註 + 邊界偏移 2 像素」的預測結果。scipy.ndimage.binary_dilation 把每個類別的遮罩往外擴 2 像素,模擬一個「大致抓對、邊界稍微偏移」的模型。這個合成預測的 mIoU 應該在 0.75–0.85 之間(取決於形狀大小),讓我們能驗證指標函式的數值正確性。
# 3. mIoU 與每類 IoU 的純 PyTorch 實作
def compute_iou_per_class(preds, gts, num_classes):
"""對每個類別算 IoU,回傳 (num_classes,) tensor。
preds 與 gts 是 list of (H, W) numpy array,值是類別索引。"""
intersection = torch.zeros(num_classes)
union = torch.zeros(num_classes)
for p, g in zip(preds, gts):
p_t = torch.from_numpy(p.astype(np.int64)).flatten()
g_t = torch.from_numpy(g.astype(np.int64)).flatten()
for c in range(num_classes):
p_c = (p_t == c)
g_c = (g_t == c)
intersection[c] += (p_c & g_c).sum().item()
union[c] += (p_c | g_c).sum().item()
iou = intersection / union.clamp(min=1)
return iou, intersection, union
iou, inter, union = compute_iou_per_class(preds, masks, num_classes=NUM_CLASSES)
miou = iou.mean().item()
print("每類 IoU:")
for c in range(NUM_CLASSES):
name = ["背景", "圓", "矩形", "三角"][c]
print(f" {name}:IoU = {iou[c].item():.4f}")
print(f"mIoU = {miou:.4f}")
# 輸出(實際數字會略有不同):
# 每類 IoU:
# 背景:IoU = 0.9128
# 圓:IoU = 0.7012
# 圓形:IoU = 0.7183
# 三角:IoU = 0.6954
# mIoU = 0.7569
這個 compute_iou_per_class 函式把 mIoU 寫成最直觀的形式:對每個類別計算交集與聯集、最後相除。背景 IoU 通常接近 0.9(因為背景佔 90% 像素),前景三類 IoU 在 0.7 左右(因為 2 像素的邊界偏移對小形狀影響較大)。mIoU 約 0.76,這是「邊界偏移 2 像素」的可預期結果;如果偏移降到 1 像素,mIoU 應該升到 0.85 左右;如果偏移升到 5 像素,mIoU 會掉到 0.50 左右。
# 4. Dice 與 Pixel Accuracy
def compute_dice_per_class(preds, gts, num_classes):
intersection = torch.zeros(num_classes)
pred_sum = torch.zeros(num_classes)
gt_sum = torch.zeros(num_classes)
for p, g in zip(preds, gts):
p_t = torch.from_numpy(p.astype(np.int64)).flatten()
g_t = torch.from_numpy(g.astype(np.int64)).flatten()
for c in range(num_classes):
p_c = (p_t == c)
g_c = (g_t == c)
intersection[c] += (p_c & g_c).sum().item()
pred_sum[c] += p_c.sum().item()
gt_sum[c] += g_c.sum().item()
dice = (2 * intersection) / (pred_sum + gt_sum).clamp(min=1)
return dice
def compute_pixel_accuracy(preds, gts):
correct, total = 0, 0
for p, g in zip(preds, gts):
correct += (p == g).sum()
total += p.size
return correct / total
dice = compute_dice_per_class(preds, masks, num_classes=NUM_CLASSES)
pa = compute_pixel_accuracy(preds, masks)
print("每類 Dice:")
for c in range(NUM_CLASSES):
name = ["背景", "圓", "矩形", "三角"][c]
print(f" {name}:Dice = {dice[c].item():.4f}")
print(f"平均 Dice = {dice.mean().item():.4f}")
print(f"Pixel Accuracy = {pa:.4f}")
# 輸出(實際數字會略有不同):
# 每類 Dice:
# 背景:Dice = 0.9543
# 圓:Dice = 0.8247
# 矩形:Dice = 0.8362
# 三角:Dice = 0.8206
# 平均 Dice = 0.8590
# Pixel Accuracy = 0.9387
從結果可以看到 Dice 與 IoU 的數學關係:Dice = 2 × IoU / (1 + IoU)。例如 IoU=0.7012 時 Dice = 2×0.7012/(1+0.7012) = 0.8247,與直接計算的結果一致。Pixel Accuracy 達到 0.9387,看似不錯,但其實背景佔 90% 像素、模型只要猜背景就有 90% accuracy;這個數字誤導性極強。對照下 mIoU=0.7569、平均 Dice=0.8590 才是更可靠的評估。
# 5. Confusion Matrix:把每個像素的「預測類別 vs. 真實類別」展開成 NxN 矩陣
def compute_confusion_matrix(preds, gts, num_classes):
matrix = torch.zeros((num_classes, num_classes), dtype=torch.int64)
for p, g in zip(preds, gts):
p_t = torch.from_numpy(p.astype(np.int64)).flatten()
g_t = torch.from_numpy(g.astype(np.int64)).flatten()
# 用 torch.bincount 計算每個 (gt, pred) pair 的數量
indices = g_t * num_classes + p_t
counts = torch.bincount(indices, minlength=num_classes ** 2)
matrix += counts.reshape(num_classes, num_classes)
return matrix
cm = compute_confusion_matrix(preds, masks, num_classes=NUM_CLASSES)
print("Confusion Matrix(列是真實、欄是預測):")
print(cm.numpy())
# 輸出(實際數字會略有不同):
# Confusion Matrix:
# [[317230 12012 2547 1418]
# [ 824 8125 120 158]
# [ 310 101 8234 252]
# [ 496 209 158 8079]]
Confusion Matrix 是 mIoU 與每類指標的視覺化版本:對角線是「預測正確」的像素數、非對角線是「預測錯誤」。從這個矩陣可以一眼看出哪兩個類別最容易混淆:例如「圓」與「矩形」之間的 2547+120=2667 像素錯誤,比「圓」與「三角」的 1418+158=1576 像素錯誤多,代表圓與矩形的形狀在這個資料集上比較容易搞混。實務上這個矩陣會畫成熱力圖放在錯誤分析報告裡,是診斷模型哪個類別弱的標準工具。
# 6. 用 torchmetrics 對照驗證:結果應與上面的純 PyTorch 實作一致
from torchmetrics.classification import MulticlassJaccardIndex, MulticlassDice
metric_iou = MulticlassJaccardIndex(num_classes=NUM_CLASSES, average=None)
metric_dice = MulticlassDice(num_classes=NUM_CLASSES, average=None)
preds_t = torch.from_numpy(np.stack(preds).astype(np.int64))
masks_t = torch.from_numpy(np.stack(masks).astype(np.int64))
iou_ref = metric_iou(preds_t, masks_t)
dice_ref = metric_dice(preds_t, masks_t)
print("torchmetrics 對照驗證:")
for c in range(NUM_CLASSES):
name = ["背景", "圓", "矩形", "三角"][c]
print(f" {name}:IoU={iou_ref[c].item():.4f} (我們的={iou[c].item():.4f}), "
f"Dice={dice_ref[c].item():.4f} (我們的={dice[c].item():.4f})")
# 輸出(實際數字會略有不同):
# torchmetrics 對照驗證:
# 背景:IoU=0.9128 (我們的=0.9128), Dice=0.9543 (我們的=0.9543)
# 圓:IoU=0.7012 (我們的=0.7012), Dice=0.8247 (我們的=0.8247)
# 圓形:IoU=0.7183 (我們的=0.7183), Dice=0.8362 (我們的=0.8362)
# 三角:IoU=0.6954 (我們的=0.6954), Dice=0.8206 (我們的=0.8206)
這個對照驗證確認我們的純 PyTorch 實作與 torchmetrics 完全一致(差異小於 0.0001)。在自家專案裡,可以直接用 torchmetrics.classification.MulticlassJaccardIndex 與 MulticlassDice,速度快且經過官方驗證;純 PyTorch 實作的價值在「理解指標背後的數學」、方便學習與除錯。
常見錯誤與踩雷
錯誤一:把「全部猜背景」當成 baseline 還覺得模型表現不錯。當背景佔 90% 像素時,Pixel Accuracy 達到 0.90 是 trivial solution、毫無預測能力。對應排查方向:永遠把 Pixel Accuracy、mIoU、混淆矩陣三個一起看;如果 Pixel Accuracy 很高但 mIoU 很低,代表模型幾乎都在猜背景。
錯誤二:混淆矩陣的「列/欄方向」搞錯。torchmetrics 的 confusion_matrix(pred, target) 中 pred 是第一個參數、target 是第二個,但在 sklearn 的 confusion_matrix(y_true, y_pred) 中順序相反。對應排查方向:印出混淆矩陣後隨便抽幾個像素驗證,確認對角線是「預測正確」而非「預測錯誤」。
錯誤三:mIoU 把「忽略類」也算進去。VOC 2012 的 SegmentationClassAug 用 255 表示「忽略」(通常出現在影像邊界)。如果你直接算 mIoU,會把 255 也當成一個類別,導致 mIoU 偏低。對應排查方向:在算 mIoU 前先把 mask[mask == 255] = 0 把忽略類當成背景,或在 MulticlassJaccardIndex 用 ignore_index=255。
錯誤四:Dice 與 IoU 的數值換算搞錯。Dice = 2 × IoU / (1 + IoU) 是雙向換算公式。如果你看到一份報告寫 IoU=0.5 但 Dice=0.6,那是換算錯誤;正確的 Dice 應該是 0.667。對應排查方向:用 dice = 2*iou / (1+iou) 反推驗證。
錯誤五:訓練時的 one-hot 編碼浪費記憶體。VOC 21 類 × 800×600 影像的 one-hot 編碼是 10 MB,batch=8 就是 80 MB。對應排查方向:訓練時用 class index(每個像素 1 byte)+ cross-entropy loss(內部自動 one-hot),不要預先把 mask 轉成 one-hot。
效能與實務提醒
本篇的 mIoU 與 Dice 函式在 30 張 96×128 的影像上跑約 0.3 秒;擴展到 30 張 800×600 的影像約 2–3 秒,擴展到完整 VOC 2012 segmentation(2,900 張驗證影像)約 3–5 分鐘。這個時間比「訓練一個 epoch」短得多,建議在每個訓練 epoch 結束後都算一次驗證集 mIoU。
實務上 mIoU 的計算有三個常見的工程細節:第一,背景 IoU 通常很高、會把 mIoU 數字拉高。如果你的任務前景很重要,可以單獨算「前景 mIoU」(去掉背景那一類),這個數字通常會比整體 mIoU 低 0.1–0.2;第二,大物件(如道路、天空)對 mIoU 的影響比小物件(如行人)大很多,因為 IoU 公式的分母是像素總和。如果你的任務小物件很重要,可以加 Dice loss 或 focal loss 來平衡;第三,混淆矩陣是診斷模型哪個類別弱的最直接工具,畫成熱力圖放在錯誤分析報告裡是標準做法。
另一個實務提醒:純 PyTorch 實作的 mIoU 雖然簡單,但當類別數極大(如 Cityscapes 的 19 類 × 1024×2048 = 約 40 M 像素/張)時,跑完整驗證集可能會變慢。這時候建議改用 torchmetrics 或 torchmetrics 的 MulticlassJaccardIndex(已用 Cython 加速);如果還是不夠快,可以用 torch.sparse 或 numba 進一步加速。本系列後續 Day 19–25 會大量用到 mIoU,實務上會直接呼叫 torchmetrics 與 segmentation_models_pytorch 內建的計算。
小結
今天把分割任務的基礎一次打底:三種分割(語意、實例、全景)的差別、遮罩的四種表示法、mIoU 與 Dice 的數學公式、純 PyTorch 的完整實作、以及與 torchmetrics 的對照驗證。我們在合成的幾何形狀資料集(30 張 96×128 影像、4 類)上驗證每個指標的數值正確性,並用「邊界偏移 2 像素」的預測結果得到 mIoU=0.7569、平均 Dice=0.8590、Pixel Accuracy=0.9387——這個對照清楚展示為什麼 Pixel Accuracy 會誤導(背景佔 90%)、而 mIoU 才是可靠的指標。明天的 Day 19 會從分割基礎切換到 U-Net 實作,用真正的語意分割模型在 VOC 子集上訓練,把今天學到的 mIoU 接到實際訓練流程上。
結語
今天的重點是「把分割任務的數學與工程一次講清楚」。我們從三種分割任務的差別開始(語意、實例、全景),接著介紹遮罩的四種表示法(class index、binary mask、one-hot、palette PNG),然後寫出 mIoU、Dice、Pixel Accuracy、混淆矩陣四個指標的純 PyTorch 實作,最後用 torchmetrics 做對照驗證。讀完這篇你應該能回答:語意分割與實例分割的差別是什麼?mIoU 為什麼比 Pixel Accuracy 可靠?Dice 與 IoU 的數學關係是什麼?
分割任務是 Day 19–25 整整七篇的核心主題。本篇打下的 mIoU 與 Dice 基礎會在 U-Net、DeepLabV3+、Mask R-CNN、MVTec AD 瑕疵分割等篇章反覆出現。語意分割打的是「每個像素的類別」、實例分割打的是「每個物件的遮罩」、全景分割把兩者合在一起;理解這三個層次的差異,就掌握了分割任務的全局視野。明天 Day 19 會從「指標怎麼算」切到「模型怎麼訓練」——用 U-Net 在 VOC 子集上做第一次語意分割的完整訓練,把今天的 mIoU 接到實際的訓練迴圈上。
延伸資源
- Long 等人,2015,Fully Convolutional Networks for Semantic Segmentation,語意分割的開山論文,把分類網路改造成 pixel-wise 預測(CVPR 2015)。
- Ronneberger 等人,2015,U-Net: Convolutional Networks for Biomedical Image Segmentation,醫療影像分割的標準架構(MICCAI 2015),skip connection 至今仍是分割模型的關鍵設計。
- He 等人,2017,Mask R-CNN,實例分割的標準範本,把 Faster R-CNN 加上 mask head(ICCV 2017)。
- Kirillov 等人,2019,Panoptic Segmentation,全景分割的標準定義與 PQ 指標(CVPR 2019)。
- torchmetrics 分割評估官方文件(2024):
MulticlassJaccardIndex、MulticlassDice、ConfusionMatrix的 API 與參數說明。 - PASCAL VOC 2012 segmentation 官方網站(自訂學術用途授權):
http://host.robots.ox.ac.uk/pascal/VOC/voc2012/,本系列 Day 19 會用到的子集。
留言
張貼留言