Adjust B and watch how the orientation matrix (independent of the magnitudes one) is mapped
to the bins via bin = floor(θ / (180/B)), and how the magnitudes are summed into each bin.
bin = floor(θ / width)The hog function from scikit-image, used in the digit classification project, divides the image into small cells and, for each one, builds a histogram of gradient orientations weighted by magnitude — exactly the central step described in the section on the HOG descriptor in the chapter.
You have been tasked with implementing this computation for a single cell, using the magnitude and gradient orientation values already computed for each pixel in the cell (dispensing with the computation of partial derivatives).
Before this assignment, each pixel \((x,y)\) of the image undergoes:
\[ 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{signed}} = \operatorname{atan2}(G_y,G_x) \]
Since HOG disregards contrast polarity, the angle is folded into the unsigned interval:
\[ \theta = \theta_{\text{signed}} \bmod 180° \]
Repeating this for all pixels in an \(n\times n\) cell yields the two input matrices for this exercise: magnitudes \(|\nabla f|\) and orientations \(\theta \in [0°,180°)\).
| Step | Role |
|---|---|
| Gradient magnitude | Weights each pixel’s contribution — strong edges weigh more than weak noise |
| Unsigned orientation | Makes the descriptor invariant to contrast polarity (light→dark vs. dark→light) |
| Per-cell histogram | Summarizes the local edge distribution into a compact vector |
| L2 normalization | Reduces the descriptor’s sensitivity to global illumination and contrast variations |
The concatenation of the normalized histograms from all cells in the image — not implemented in this exercise — forms the complete HOG feature vector, used as input to the k-NN classifier in the chapter’s project.
Input:
Output:
| Input | Output | Observation |
|---|---|---|
| 2 2 1.0 2.0 3.0 4.0 10 100 170 20 |
5.00 5.00 0.7071 0.7071 |
Bin width 90°: \([0,90)\) and \([90,180)\); magnitudes 1 and 4 fall into bin 0, 2 and 3 into 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 |
Homogeneous cell: \(\epsilon\) avoids division by zero. |
Adjust B and watch how the orientation matrix (independent of the magnitudes one) is mapped
to the bins via bin = floor(θ / (180/B)), and how the magnitudes are summed into each bin.
bin = floor(θ / width)%%writefile EP07_05.py
# Python codeOverwriting EP07_05.py
TestSuite("EP07_05.py").run()✔️ EP07_05.cases already exists in casos/
📋 5 case(s) loaded from casos/EP07_05.cases
🔍 Testing Python: EP07_05.py
⚠️ EP07_05.py: Empty file (fewer than 3 lines). Tests skipped.