EDI+VA · Esercizio di Programmazione

EP07_05 — 🔴 Istogramma delle Orientazioni di una Cella HOG

7.18.5 EP07_05 🔴 Istogramma delle Orientazioni di una Cella HOG

La funzione hog di scikit-image, impiegata nel progetto di classificazione delle cifre, divide l’immagine in piccole celle e, per ciascuna, costruisce un istogramma delle orientazioni del gradiente ponderato per la magnitudine — esattamente il passaggio centrale descritto nella sezione sul descrittore HOG del capitolo.

Sei stato incaricato di implementare questo calcolo per una singola cella, a partire dai valori di magnitudine e orientazione del gradiente già calcolati per ogni pixel della cella (tralasciando il calcolo delle derivate parziali).

7.18.5.1 📋 Linee Guida di Implementazione

  1. Dimensioni: Leggere gli interi \(n\) (la cella ha \(n \times n\) pixel) e \(B\) (numero di contenitori dell’istogramma).
  2. Magnitudini: Leggere \(n\) righe con \(n\) valori reali ciascuna, che rappresentano \(|\nabla f(x,y)|\) per ogni pixel della cella.
  3. Orientazioni: Leggere altre \(n\) righe con \(n\) valori reali ciascuna, che rappresentano \(\theta(x,y)\) in gradi, già convertiti nell’intervallo non orientato \([0^\circ, 180^\circ)\), come convenzionalmente utilizzato dal HOG.
  4. Contenitori: I \(B\) contenitori coprono \([0^\circ, 180^\circ)\) in fasce uguali di larghezza \(180/B\) gradi. Un pixel con orientazione \(\theta\) appartiene al contenitore \(\lfloor \theta / (180/B) \rfloor\); se questo indice è uguale a \(B\) (possibile solo quando \(\theta\) è esattamente \(180^\circ\), cosa che non dovrebbe verificarsi secondo la direttiva del punto 3), utilizzare il contenitore \(B-1\).
  5. Istogramma grezzo: Per ogni pixel, accumulare la sua magnitudine (non il suo conteggio) nel contenitore corrispondente: \[ H[b] = \sum_{(x,y)\, :\, \text{bin}(\theta(x,y)) = b} |\nabla f(x,y)|. \]
  6. Normalizzazione L2: Dopo aver costruito \(H\), normalizzarlo per ottenere \(\hat H\): \[ \hat H[b] = \frac{H[b]}{\sqrt{\sum_{j=0}^{B-1} H[j]^2 + \epsilon}}, \qquad \epsilon = 10^{-6}. \]
  7. Output: Stampare l’istogramma grezzo \(H\) (arrotondato a 2 cifre decimali) su una riga, seguito dall’istogramma normalizzato \(\hat H\) (arrotondato a 4 cifre decimali) su un’altra riga, entrambi con i \(B\) valori separati da spazi, nell’ordine dei contenitori.

7.18.5.2 📌 Vincoli Computazionali

  • Binning non orientato: l’intervallo delle orientazioni è \([0,180)\), non \([0,360)\) — i gradienti in direzioni opposte (differenza di \(180^\circ\)) contribuiscono allo stesso contenitore, convenzione standard del HOG per il rilevamento di oggetti.
  • Accumulo per magnitudine, non per conteggio: l’istogramma pondera ogni pixel per la sua magnitudine del gradiente, non conta semplicemente quanti pixel cadono in ciascun contenitore.
  • Costante di stabilizzazione: l’\(\epsilon = 10^{-6}\) al denominatore della normalizzazione evita la divisione per zero quando la cella è completamente omogenea (tutte le magnitudini nulle).

7.18.5.3 📐 Da dove provengono le matrici di ingresso

Prima di questo EP, ogni pixel \((x,y)\) dell’immagine passa attraverso:

\[ G_x = f(x+1,y)-f(x-1,y), \qquad G_y = f(x,y+1)-f(x,y-1) \]

\[ |\nabla f| = \sqrt{G_x^2+G_y^2}, \qquad \theta_{\text{segnalato}} = \operatorname{atan2}(G_y,G_x) \]

Poiché il HOG ignora la polarità del contrasto, l’angolo viene raddoppiato nell’intervallo non orientato:

\[ \theta = \theta_{\text{segnalato}} \bmod 180° \]

Ripetendo questo per tutti i pixel di una cella \(n\times n\), si ottengono le due matrici di ingresso di questo esercizio: magnitudini \(|\nabla f|\) e orientazioni \(\theta \in [0°,180°)\).

7.18.5.4 🧠 Fondamenti Teorici

Fase Ruolo
Magnitudine del gradiente Pondera il contributo di ogni pixel — i bordi forti pesano più del rumore debole
Orientazione non orientata Rende il descrittore invariante alla polarità del contrasto (chiaro→scuro vs. scuro→chiaro)
Istogramma per cella Riassume la distribuzione locale dei bordi in un vettore compatto
Normalizzazione L2 Riduce la sensibilità del descrittore alle variazioni globali di illuminazione e contrasto

La concatenazione degli istogrammi normalizzati di tutte le celle dell’immagine — non implementata in questo esercizio — forma il vettore di caratteristiche HOG completo, utilizzato come ingresso del classificatore k-NN nel progetto del capitolo.

7.18.5.5 📦 Specifica di Ingresso e Uscita (VPL)

Ingresso:

  • Riga 1: Interi \(n\) e \(B\).
  • Prossime \(n\) righe: \(n\) magnitudini reali ciascuna.
  • Prossime \(n\) righe: \(n\) orientazioni reali (gradi, \([0,180)\)) ciascuna.

Uscita:

  • Riga 1: i \(B\) valori dell’istogramma grezzo, arrotondati a 2 cifre decimali.
  • Riga 2: i \(B\) valori dell’istogramma normalizzato, arrotondati a 4 cifre decimali.

7.18.5.6 📌 Esempi

Ingresso Uscita Osservazione
2 2
1.0 2.0
3.0 4.0
10 100
170 20
5.00 5.00
0.7071 0.7071
Contenitore di larghezza 90°: \([0,90)\) e \([90,180)\); le magnitudini 1 e 4 cadono nel contenitore 0, 2 e 3 nel contenitore 1.
2 4
0.0 0.0
0.0 0.0
0 0
0 0
0.00 0.00 0.00 0.00
0.0000 0.0000 0.0000 0.0000
Cella omogenea: \(\epsilon\) evita la divisione per zero.
🎮 Simulatore EP07_05: Istogramma delle Orientazioni di una Cella 🔴 cella 3×3 fissa

Regola B e osserva come la matrice delle orientazioni (indipendente da quella delle magnitudini) viene mappata nei compartimenti tramite bin = floor(θ / (180/B)), e come le magnitudini vengono sommate in ciascun bin.

2
📄 Input (esattamente come il programma legge da stdin)

🔢 Matrice delle magnitudini |∇f|
📐 Matrice delle orientazioni θ (gradi) — colorata per bin
📏 Dove ciascun θ cade sul righello [0°, 180°) — bin = floor(θ / larghezza)
📊 Intervalli di ciascun compartimento (larghezza = 180° / B)
🧩 Ogni pixel: magnitudine + orientazione → bin
🧮 Calcolo passo passo (floor della divisione + somma delle magnitudini per bin)
Figura 7.25: Simulatore EP07_05: Istogramma HOG di una Cella (mappatura degli angoli ai bins)
%%writefile EP07_05.py
# Codice Python
Overwriting EP07_05.py
TestSuite("EP07_05.py").run()
✔️ EP07_05.cases esiste già in casos/
📋 5 caso/i caricato/i da casos/EP07_05.cases

🔍 Test di Python: EP07_05.py
⚠️ EP07_05.py: file vuoto (meno di 3 righe). Test saltati.