Durum Segmentasyonu Maske R-CNN
Type: Build + Learn
Languages: Python
Prerequisites: Phase 4 Lesson 06 (YOLO), Phase 4 Lesson 07 (U-Net)
Time: ~75 minutes
Öğrenme Hedefleri
- Mask R-CNN mimarisinin sonundan sona kadar izlenmesi: omurgan, FPN, RPN, RoIAlign, kutu başı, mask başı
- RoIAlign' i baştan başlatın ve RoIPool' un neden artık kullanılmadığını açıklayın.
- Şimşek görgü tanesini kullan
maskrcnn_resnet50_fpn_v2üretim kalitesi maskeleri için önceden eğitilmiş model ve çıkış biçimini doğru şekilde okuyun - Küçük özel veri kümesine ince ayarlama Maske R-CNN, kutu ve maske başlarını değiştirerek omurganı dondurarak
Sorun
Semantik bölünme size sınıf başına bir maske verir. Bir nesne bölünmesi iki nesne bir sınıfı paylaşırken bile size bir nesne başına bir maske verir. bireyleri saymak, çerçeveleri takip etmek ve şeyleri ölçmek (duvardaki her tuğla, mikroskop görüntüsündeki her hücre) hepsi örnek bölünmesini gerektirir.
Mask R-CNN (He et al., 2017) bu durumu, örnek segmentasyonunu tespit-daha-mask olarak yeniden çerçevelemekle çözdü. Tasarım o kadar temizti ki önümüzdeki beş yıl boyunca neredeyse her örnek segmentasyon kağıdı Mask R-CNN variansıydı ve meşale görme uygulaması hala küçük ve orta ölçekli veri kümeleri için üretim öntanımlısıdır.
Zorlu mühendislik sorunu örnekleme: köşeleri piksel sınırlarına uymayan bir önerme kutusu içinde sabit boyutlu bir özellik bölgesi nasıl kesilir?
Anlaşım
Mimarlık
flowchart LR
IMG["Input"] --> BB["ResNet<br/>backbone"]
BB --> FPN["Feature<br/>Pyramid Network"]
FPN --> RPN["Region<br/>Proposal<br/>Network"]
FPN --> RA["RoIAlign"]
RPN -->|"top-K proposals"| RA
RA --> BH["Box head<br/>(class + refine)"]
RA --> MH["Mask head<br/>(14x14 conv)"]
BH --> NMS["NMS"]
MH --> NMS
NMS --> OUT["boxes +<br/>classes + masks"]
style BB fill:#dbeafe,stroke:#2563eb
style FPN fill:#fef3c7,stroke:#d97706
style RPN fill:#fecaca,stroke:#dc2626
style OUT fill:#dcfce7,stroke:#16a34aAnlamak için beş parça:
- BackboneResNet-50 veya ResNet-101 ImageNet üzerinde eğitilmiştir. 4, 8, 16, 32 adımlarında özellik haritalarının bir hiyerarşisini üretir.
- FPN (Feature Pyramid Network) üst-yağı + her seviyede C kanalları semantik zengin özellikler veren yan bağlantılar.
- RPN (Region Proposal Network) her demir pozisyonunda "burada bir nesne var mı?" ve "saldırı nasıl düzeltirim?" diye tahmin eden küçük bir konfor başlığı.
- RoIAlign FPN düzeyinde herhangi bir kutudan sabit boyutlu (örneğin 7x7) bir özellik patçası örneklemesi.
- Heads kutuyu temizleyen ve bir sınıf seçen iki katmanlı kutu başı, ek olarak bir küçük konfor başı çıkartır
28x28Her teklif için ikili maske.
RoIAlign neden RoIPool değil?
Orijinal Fast R-CNN, bir önerme kutusunu bir çubuğa ayırarak, her hücreden maksimum özelliği alan ve tüm koordinatları tam sayılarla yuvarlayan RoIPool'u kullandı. Bu yuvarlaklık, özellik haritasını giriş pixel koordinatlarından tam bir özellik haritası pixel küçük bir görüntüde 224x224'e kadar yanlış ayarlar.
RoIPool:
box (34.7, 51.3, 98.2, 142.9)
round -> (34, 51, 98, 142)
split grid -> round each cell boundary
misalignment accumulates at every step
RoIAlign:
box (34.7, 51.3, 98.2, 142.9)
sample at exact float coordinates using bilinear interpolation
no rounding anywhereRoIAlign, AP maskesi COCO'da 3-4 puan ücretsiz olarak kaldırıyor. Yerleşim konusunda önem veren her detektör şimdi bunu YOLOv7 seg, RT-DETR, Mask2Former gibi kullanıyor.
RPN'de bir paragraf
Özellik haritasının her pozisyonunda, farklı boyut ve şekillerdeki K demir kutularını yerleştirin. Her bir demir için bir nesne puanı ve bir geri dönüş oranı tahmin edin. En üst 1000 kutuyu puanla tut, NMS'i IoU 0.7'de uygula ve hayatta kalanları başlarına teslim et. RPN kendi mini kaybı ile eğitilmiştir Ders 6 ' dan YOLO kaybı ile aynı yapı , sadece iki sınıf (objek / hiç nesne).
Maske başı
Her öneride (RoIAlign'den sonra) maskede küçük bir FCN bulunur: dört 3x3 konvu, 2x deconv, son 1x1 konvu üretir.num_classes28x28Bu, maske tahminini sınıflandırmadan ayırır.
Son ikili maskesi üretmek için 28x28 maskesini önerinin orijinal piksel boyutuna kadar örnekleyin.
Kayıplar
Mask R-CNN'in toplam 4 kayıpı var:
L = L_rpn_cls + L_rpn_box + L_box_cls + L_box_reg + L_maskL_rpn_cls- Evet .L_rpn_boxRPN önerileri için nesnelik + kutu gerileme.L_box_clsbaş sınıflandırıcısında (C+1) sınıflar üzerindeki çapraz entropi (geriye bakış da dahil olmak üzere).L_box_regbaş kutuyu düzeltmek için düzgün L1.L_mask28x28 maske çıkışında pixel başına ikili çapraz entropi.
Her kayıpın kendi varsayılan ağırlığı vardır; meşale görme uygulaması onları yapılandırıcı argümanları olarak ortaya çıkarır.
Çıktı biçimi
torchvision.models.detection.maskrcnn_resnet50_fpn_v2Dict listesi, her görüntü için bir dict listesi gönderir:
{
"boxes": (N, 4) in (x1, y1, x2, y2) pixel coordinates,
"labels": (N,) class IDs, 0 = background so indices are 1-based,
"scores": (N,) confidence scores,
"masks": (N, 1, H, W) float masks in [0, 1] — threshold at 0.5 for binary,
}Maske tam görüntü çözünürlüğünde zaten. 28x28 baş çıkışı içten olarak örneklendi.
Yapın
Adım 1: Baştan başlayan RoIAline
Bu Mask R-CNN'in kod olarak anlaması, prozeden daha kolay olan bir bileşeni.
pythonimport torch
import torch.nn.functional as F
def roi_align_single(feature, box, output_size=7, spatial_scale=1 / 16.0):
"""
feature: (C, H, W) single-image feature map
box: (x1, y1, x2, y2) in original image pixel coordinates
output_size: side of the output grid (7 for box head, 14 for mask head)
spatial_scale: reciprocal of the feature map stride
"""
C, H, W = feature.shape
x1, y1, x2, y2 = [c * spatial_scale - 0.5 for c in box]
bin_w = (x2 - x1) / output_size
bin_h = (y2 - y1) / output_size
grid_y = torch.linspace(y1 + bin_h / 2, y2 - bin_h / 2, output_size)
grid_x = torch.linspace(x1 + bin_w / 2, x2 - bin_w / 2, output_size)
yy, xx = torch.meshgrid(grid_y, grid_x, indexing="ij")
gx = 2 * (xx + 0.5) / W - 1
gy = 2 * (yy + 0.5) / H - 1
grid = torch.stack([gx, gy], dim=-1).unsqueeze(0)
sampled = F.grid_sample(feature.unsqueeze(0), grid, mode="bilinear",
align_corners=False)
return sampled.squeeze(0)Her sayı iki çizgilik bir şekilde örneklenmiş bir pozisyonda.
Adım 2: Torchvision'in RoIAlign ile karşılaştır
pythonfrom torchvision.ops import roi_align
feature = torch.randn(1, 16, 50, 50)
boxes = torch.tensor([[0, 10, 20, 100, 90]], dtype=torch.float32) # (batch_idx, x1, y1, x2, y2)
ours = roi_align_single(feature[0], boxes[0, 1:].tolist(), output_size=7, spatial_scale=1/4)
theirs = roi_align(feature, boxes, output_size=(7, 7), spatial_scale=1/4, sampling_ratio=1, aligned=True)[0]
print(f"shape ours: {tuple(ours.shape)}")
print(f"shape theirs: {tuple(theirs.shape)}")
print(f"max|diff|: {(ours - theirs).abs().max().item():.3e}")- Evet .
sampling_ratio=1vealigned=True, iki kişi de içe eşleşir .1e-5- Evet .
Adım 3: Önceden eğitilmiş bir maske R-CNN yükleyin
pythonimport torch
from torchvision.models.detection import maskrcnn_resnet50_fpn_v2, MaskRCNN_ResNet50_FPN_V2_Weights
model = maskrcnn_resnet50_fpn_v2(weights=MaskRCNN_ResNet50_FPN_V2_Weights.DEFAULT)
model.eval()
print(f"params: {sum(p.numel() for p in model.parameters()):,}")
print(f"classes (including background): {len(model.roi_heads.box_predictor.cls_score.out_features * [0])}")46M parametreleri, 91 sınıf (COCO). Birinci sınıf (id 0) arka plan; modelin aslında algıladığı her şey id 1'den başlar.
Dördüncü adım: Tahminleri çalıştır
pythonwith torch.no_grad():
x = torch.randn(3, 400, 600)
predictions = model([x])
p = predictions[0]
print(f"boxes: {tuple(p['boxes'].shape)}")
print(f"labels: {tuple(p['labels'].shape)}")
print(f"scores: {tuple(p['scores'].shape)}")
print(f"masks: {tuple(p['masks'].shape)}")Maske tenzörü şekillidir .(N, 1, H, W). 0.5 ' den bir nesne için ikili bir maske elde etmek için:
pythonbinary_masks = (p['masks'] > 0.5).squeeze(1) # (N, H, W) booleanAdım 5: Özel sınıf sayımı için başları değiştirin
Genel ince ayarlama tarifi: omurganı, FPN ve RPN'i yeniden kullanın; iki sınıflandırıcı başını değiştirin.
pythonfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor
from torchvision.models.detection.mask_rcnn import MaskRCNNPredictor
def build_custom_maskrcnn(num_classes):
model = maskrcnn_resnet50_fpn_v2(weights=MaskRCNN_ResNet50_FPN_V2_Weights.DEFAULT)
in_features = model.roi_heads.box_predictor.cls_score.in_features
model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)
in_features_mask = model.roi_heads.mask_predictor.conv5_mask.in_channels
hidden_layer = 256
model.roi_heads.mask_predictor = MaskRCNNPredictor(in_features_mask, hidden_layer, num_classes)
return model
custom = build_custom_maskrcnn(num_classes=5)
print(f"custom cls_score.out_features: {custom.roi_heads.box_predictor.cls_score.out_features}")num_classesArka plan sınıfı içermelidir, bu nedenle 4 nesne sınıfı olan bir veri kümesi kullanır num_classes=5- Evet .
Adım 6: Eğitmeye gerek olmayan şeyleri dondur
Küçük veri kümelerinde omurganı ve FPN'yi dondur. Sadece RPN nesnelik + geri dönüş ve iki baş öğrenir.
pythondef freeze_backbone_and_fpn(model):
# torchvision Mask R-CNN packs the FPN inside `model.backbone` (as
# `model.backbone.fpn`), so iterating `model.backbone.parameters()` covers
# both the ResNet feature layers and the FPN lateral/output convs.
for p in model.backbone.parameters():
p.requires_grad = False
return model
custom = freeze_backbone_and_fpn(custom)
trainable = sum(p.numel() for p in custom.parameters() if p.requires_grad)
print(f"trainable after freeze: {trainable:,}")500 görüntü verisi kümelerinde bu, yakınlık ve aşırı uyum arasındaki fark.
Kullan
Mask R-CNN için torchvision'deki tam eğitim döngüsü 40 satırdır ve görevler arasında değişim veri kümeleri ve git arasında anlamlı bir değişim yoktur.
pythondef train_step(model, images, targets, optimizer):
model.train()
loss_dict = model(images, targets)
losses = sum(loss for loss in loss_dict.values())
optimizer.zero_grad()
losses.backward()
optimizer.step()
return {k: v.item() for k, v in loss_dict.items()}- Evet .
targetslistede resim başına diktler olmalı.boxes- Evet .labelsvemasks(Tüm(num_instances, H, W)Modeldeki ikili tenzorlar) eğitim sırasında dört kayıpın diktini ve eval sırasında tahminlerin bir listesini gönderir.model.training- Evet .
- Evet .
pycocotoolsevaluator hem kutular için hem de maskeler için mAP@IoU=0.5:0.95 üretir; kutu başının veya maske başının şişek boynuz olup olmadığını bilmek için her iki numara da gerekir.
Gönder
Bu ders şunları ortaya çıkarır:
outputs/prompt-instance-vs-semantic-router.mdüç soru soran ve örnek vs. semantik vs. panoptik ve başlangıç için tam model seçen bir istek.outputs/skill-mask-rcnn-head-swapper.mdyeni bir teknolojiye göre, herhangi bir meşale görme algılama modeli üzerinde başları değiştirmek için 10 satır kod oluşturan bir becerinum_classes- Evet .
Egzersizler
- (Easy)RoIAlign ' i kontrol et .
torchvision.ops.roi_align100 rastgele kutuda. Maksimum mutlak farkı bildirin. RoIPool (2017 öncesi davranış) da çalıştırın ve sınırın yakınındaki kutularda ~ 1-2 özellik haritası pikselinden ayrılır. - (Medium)- Güzel sesli .
maskrcnn_resnet50_fpn_v250 resimden oluşan özel bir veri kümesi (her iki sınıf: balonlar, balıklar, çukurlar, logolar) - (Hard)Mask R-CNN'in maskesi başını 28x28 yerine 56x56 oranında tahmin eden bir maskeden değiştirin. mAP@IoU=0.75 ön ve sonrasını ölçün. Kazanç (veya bir eksikliğin) neden beklenen sınır-tamam / hafıza değişikliğine uyduğunu açıklayın.
Anahtar Terimler
| Term | What people say | What it actually means |
|---|---|---|
| Mask R-CNN | "Detection plus masks" | Faster R-CNN + a small FCN head that predicts a 28x28 mask per proposal per class |
| FPN | "Feature pyramid" | Top-down + lateral connections that give every stride level C channels of semantic-rich features |
| RPN | "Region proposer" | A small conv head that produces ~1000 object/no-object proposals per image |
| RoIAlign | "No-rounding crop" | Bilinearly samples a fixed-size feature grid from any float-coordinate box |
| RoIPool | "Pre-2017 crop" | Same purpose as RoIAlign but rounds box coordinates; obsolete |
| Mask AP | "Instance mAP" | Average precision computed with mask IoU instead of box IoU; the COCO instance segmentation metric |
| Binary mask head | "Per-class mask" | Predicts one binary mask per class for each proposal; only the predicted class's channel is kept |
| Background class | "Class 0" | The catch-all "no object" class; indices for real classes start at 1 |
Daha Fazla Okumak
- Mask R-CNN (He et al., 2017) makale; RoIAlign'in 3. bölümünde eleştirel bir okuma bulunmaktadır.
- FPN: Feature Pyramid Networks (Lin et al., 2017) FPN kağıdı; her modern dedektör onu kullanır
- torchvision Mask R-CNN tutorial ince ayarlama döngüsüne ilişkin referans
- Detectron2 model zoo Neredeyse her tespit ve segmentasyon varianti için eğitimli ağırlıklar ile üretim uygulamalar
This free lesson is part of the AI Engineering from Scratch curriculum. Read the full explanation, run the lesson code, and verify the result in the interactive reader or from the repository source.
Browse the complete course catalog or open this lesson on GitHub.