SSD (Single Shot MultiBox Detector)

SSD (Single Shot MultiBox Detector) - Object Detection

SSD (Single Shot MultiBox Detector) – Object Detection in un unico passo

SSD (Single Shot MultiBox Detector) è un modello di object detection single-stage, che rileva oggetti e bounding box in un unico passaggio, senza bisogno di un processo separato di region proposal (come Faster R-CNN).


🚀 Come funziona SSD?

SSD utilizza una rete convoluzionale (CNN) che genera contemporaneamente:

  • Bounding box degli oggetti nell'immagine.
  • Classi degli oggetti contenuti in ogni bounding box.

A differenza di YOLO, SSD genera più bounding box di varie dimensioni e proporzioni, chiamate default boxes o prior boxes.


Per ogni bounding box tra le k disponibili in una data posizione, SSD calcola:
  • c punteggi di classe (uno per ciascuna delle classi dell'oggetto).
  • 4 valori di offset (che rappresentano la variazione rispetto alla forma predefinita della box).
Per una feature map di dimensioni m × n, il numero totale di output generati è: (c+4)×k×m×n

🔹 Architettura SSD



SSD è basato su una rete VGG16 seguita da convoluzioni extra per predizioni a diverse scale.

  • Backbone CNN (es. VGG16) → Estrae feature.
  • Feature maps multi-scala → Per oggetti grandi e piccoli.
  • Bounding box regressor → Predice coordinate.
  • Classificatore → Assegna categorie agli oggetti.
  • Non-Maximum Suppression (NMS) → Filtra box duplicate.

📌 Loss Function nella SSD

La funzione di perdita della SSD combina due elementi fondamentali:

  • 📍 Loss sulla localizzazione (Smooth L1 Loss) – misura la precisione delle bounding boxes.
  • 📍 Loss sulla classificazione (Cross-Entropy Loss) – valuta l'accuratezza nella predizione delle classi.

La loss complessiva è calcolata come:



dove **α** è un peso di bilanciamento (solitamente 1.0).

🔹 1. Classificazione – Cross-Entropy Loss

La SSD assegna a ogni bounding box una classe, come "persona", "auto", "sfondo", ecc. Per valutare la qualità della classificazione, utilizza la **Softmax Cross-Entropy Loss**:

Lcls = - Σ y log(ŷ)

dove:

  • y = classe reale (ground truth).
  • ŷ = probabilità predetta dal modello.

🔹 2. Localizzazione – Smooth L1 Loss

La SSD prevede bounding boxes con coordinate (x, y, w, h). Per misurare la distanza tra la box predetta e quella reale, utilizza la **Smooth L1 Loss**:

Lloc = Σpositivi SmoothL1(ŷ - y)

La funzione Smooth L1 Loss è definita come:

SmoothL1(x) =

  • Se |x| < 10.5 x² (meno sensibile agli errori piccoli).
  • Se |x| ≥ 1|x| - 0.5 (evita gradienti esplosivi).

📍 Matching delle Bounding Boxes con IoU

La SSD utilizza la metrica **IoU (Intersection over Union)** per abbinare le bounding boxes predette alle ground truth:

  • Se **IoU > 0.5**, la box viene considerata un match positivo.
  • Se **IoU < 0.5**, è negativa o ignorata.

SSD implementa un metodo chiamato MultiBox Matching, che seleziona gli anchor boxes migliori per ogni oggetto rilevato.

🔹 Vantaggi e svantaggi

✅ Vantaggi

  • Più veloce di Faster R-CNN 🚀
  • Usa feature maps multi-scala per oggetti piccoli 🏆
  • Più preciso di YOLOv1 🔍

❌ Svantaggi

  • Non sempre preciso per oggetti molto vicini.
  • Inferiore a Faster R-CNN per oggetti piccoli.

📊 Confronto con altri algoritmi

Modello Tipo Velocità (FPS) Accuratezza (mAP) Real-Time?
Faster R-CNN Two-Stage ❌ ~5 FPS ✅ Alta ❌ No
YOLO v4 One-Stage ⚡ ~30 FPS 👍 Media ✅ Sì
SSD One-Stage ⚡ ~25 FPS 👍 Media ✅ Sì

📝 Implementazione SSD in PyTorch

Di seguito un'implementazione semplificata di SSD in PyTorch.


import torch
import torchvision
from torch import nn

class SSD(nn.Module):
    def __init__(self, num_classes=21):
        super(SSD, self).__init__()
        self.backbone = torchvision.models.vgg16(pretrained=True).features
        self.extra_layers = nn.Sequential(
            nn.Conv2d(512, 1024, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.Conv2d(1024, 512, kernel_size=3, padding=1),
            nn.ReLU(),
        )
        self.loc_head = nn.Conv2d(512, num_classes * 4, kernel_size=3, padding=1)
        self.cls_head = nn.Conv2d(512, num_classes * num_classes, kernel_size=3, padding=1)

    def forward(self, x):
        x = self.backbone(x)
        x = self.extra_layers(x)
        loc = self.loc_head(x)
        cls = self.cls_head(x)
        return loc, cls

# Esempio di input
model = SSD()
x = torch.randn(1, 3, 300, 300)
loc_preds, cls_preds = model(x)
print(loc_preds.shape, cls_preds.shape)
    

🎯 Conclusione

SSD è una delle soluzioni più bilanciate tra velocità e accuratezza per l’object detection. Se vuoi testarlo, prova ad allenarlo su dataset come PASCAL VOC o COCO!

Commenti

Post popolari in questo blog

Instance Segmentation: Cos'è e Come Funziona

U-Net: Architettura per la Segmentazione di Immagini