TNI+VO · Exercice de Programmation

EP07_05 — 🔴 Histogramme des orientations d’une cellule HOG

7.18.5 EP07_05 🔴 Histogramme des orientations d’une cellule HOG

La fonction hog de scikit-image, utilisée dans le projet de classification de chiffres, divise l’image en petites cellules et, pour chacune, construit un histogramme des orientations du gradient pondéré par la magnitude — exactement l’étape centrale décrite dans la section sur le descripteur HOG du chapitre.

Vous êtes chargé d’implémenter ce calcul pour une seule cellule, à partir des valeurs de magnitude et d’orientation du gradient déjà calculées pour chaque pixel de la cellule (ce qui évite le calcul des dérivées partielles).

7.18.5.1 📋 Directives d’implémentation

  1. Dimensions : Lire les entiers \(n\) (la cellule a \(n \times n\) pixels) et \(B\) (nombre de compartiments de l’histogramme).
  2. Magnitudes : Lire \(n\) lignes avec chacune \(n\) valeurs réelles, représentant \(|\nabla f(x,y)|\) pour chaque pixel de la cellule.
  3. Orientations : Lire encore \(n\) lignes avec chacune \(n\) valeurs réelles, représentant \(\theta(x,y)\) en degrés, déjà converties dans l’intervalle non signé \([0^\circ, 180^\circ)\), comme conventionnellement utilisé par le HOG.
  4. Compartiments : Les \(B\) compartiments couvrent \([0^\circ, 180^\circ)\) en bandes égales de largeur \(180/B\) degrés. Un pixel avec une orientation \(\theta\) appartient au compartiment \(\lfloor \theta / (180/B) \rfloor\) ; si cet indice est égal à \(B\) (possible uniquement lorsque \(\theta\) est exactement \(180^\circ\), ce qui ne devrait pas se produire selon la directive du point 3), utilisez le compartiment \(B-1\).
  5. Histogramme brut : Pour chaque pixel, accumulez sa magnitude (et non son compte) dans le compartiment correspondant : \[ H[b] = \sum_{(x,y)\, :\, \text{bin}(\theta(x,y)) = b} |\nabla f(x,y)|. \]
  6. Normalisation L2 : Après avoir construit \(H\), normalisez-le pour obtenir \(\hat H\) : \[ \hat H[b] = \frac{H[b]}{\sqrt{\sum_{j=0}^{B-1} H[j]^2 + \epsilon}}, \qquad \epsilon = 10^{-6}. \]
  7. Sortie : Imprimez l’histogramme brut \(H\) (arrondi à 2 décimales) sur une ligne, suivi de l’histogramme normalisé \(\hat H\) (arrondi à 4 décimales) sur une autre ligne, tous deux avec les \(B\) valeurs séparées par des espaces, dans l’ordre des compartiments.

7.18.5.2 📌 Contraintes computationnelles

  • Binning non signé : l’intervalle des orientations est \([0,180)\), pas \([0,360)\) — les gradients dans des directions opposées (différence de \(180^\circ\)) contribuent au même compartiment, convention standard du HOG pour la détection d’objets.
  • Accumulation par magnitude, pas par compte : l’histogramme pondère chaque pixel par sa magnitude de gradient, il ne compte pas simplement combien de pixels tombent dans chaque compartiment.
  • Constante de stabilisation : le \(\epsilon = 10^{-6}\) dans le dénominateur de la normalisation évite la division par zéro lorsque la cellule est complètement homogène (toutes les magnitudes nulles).

7.18.5.3 📐 D’où proviennent les matrices d’entrée

Avant cet EP, chaque pixel \((x,y)\) de l’image passe par :

\[ 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{signé}} = \operatorname{atan2}(G_y,G_x) \]

Comme le HOG ignore la polarité du contraste, l’angle est replié dans l’intervalle non signé :

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

En répétant cela pour tous les pixels d’une cellule \(n\times n\), on obtient les deux matrices d’entrée de cet exercice : les magnitudes \(|\nabla f|\) et les orientations \(\theta \in [0°,180°)\).

7.18.5.4 🧠 Fondement théorique

Étape Rôle
Magnitude du gradient Pondère la contribution de chaque pixel — les bords forts pèsent plus que le bruit faible
Orientation non signée Rend le descripteur invariant à la polarité du contraste (clair→sombre vs. sombre→clair)
Histogramme par cellule Résume la distribution locale des bords en un vecteur compact
Normalisation L2 Réduit la sensibilité du descripteur aux variations globales d’éclairage et de contraste

La concaténation des histogrammes normalisés de toutes les cellules de l’image — non implémentée dans cet exercice — forme le vecteur de caractéristiques HOG complet, utilisé comme entrée du classifieur k-NN dans le projet du chapitre.

7.18.5.5 📦 Spécification d’entrée et de sortie (VPL)

Entrée :

  • Ligne 1 : entiers \(n\) et \(B\).
  • Les \(n\) lignes suivantes : \(n\) magnitudes réelles chacune.
  • Les \(n\) lignes suivantes : \(n\) orientations réelles (degrés, \([0,180)\)) chacune.

Sortie :

  • Ligne 1 : les \(B\) valeurs de l’histogramme brut, arrondies à 2 décimales.
  • Ligne 2 : les \(B\) valeurs de l’histogramme normalisé, arrondies à 4 décimales.

7.18.5.6 📌 Exemples

Entrée Sortie Observation
2 2
1.0 2.0
3.0 4.0
10 100
170 20
5.00 5.00
0.7071 0.7071
Bin de largeur 90° : \([0,90)\) et \([90,180)\) ; les magnitudes 1 et 4 tombent dans le bin 0, 2 et 3 dans le bin 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
Cellule homogène : \(\epsilon\) évite la division par zéro.
🎮 Simulateur EP07_05 : Histogramme d'orientations d'une cellule 🔴 cellule 3×3 fixe

Ajustez B et suivez comment la matrice d'orientations (indépendante de celle des magnitudes) est mappée vers les compartiments via bin = floor(θ / (180/B)), et comment les magnitudes sont additionnées dans chaque bin.

2
📄 Entrée (exactement comme le programme la lit via stdin)

🔢 Matrice des magnitudes |∇f|
📐 Matrice des orientations θ (degrés) — colorée par bin
📏 Où chaque θ tombe sur la règle [0°, 180°) — bin = floor(θ / largeur)
📊 Plages de chaque compartiment (largeur = 180° / B)
🧩 Chaque pixel : magnitude + orientation → bin
🧮 Calcul pas à pas (division entière + somme des magnitudes par bin)
Figure 7.25: Simulateur EP07_05 : Histogramme HOG d’une cellule (mapping des angles vers les bins)
%%writefile EP07_05.py
# Code Python
Overwriting EP07_05.py
TestSuite("EP07_05.py").run()
✔️ EP07_05.cases existe déjà dans casos/
📋 5 cas chargé(s) depuis casos/EP07_05.cases

🔍 Test de Python : EP07_05.py
⚠️ EP07_05.py : fichier vide (moins de 3 lignes). Tests ignorés.