EP04_07 — ⛰️ Weighted Dilation and Erosion (mm.dil1 / mm.ero1)
4.9.7 EP04_07 ⛰️ Weighted Dilation and Erosion (mm.dil1 / mm.ero1)
So far, the structuring element only indicated “this neighbor counts” or “does not count” — but in digital elevation models (used in GIS and urban drainage planning), each neighbor should have a different weight depending on the distance or the direction of the terrain. The weighted versions of dilation and erosion, implemented in morph.py as mm::dil1(f, b) and mm::ero1(f, b), sum (or subtract) the weight of each neighbor before taking the maximum (or minimum) — generalizing everything done in the previous EPs. See Figure 4.36 for a simulation of this EP.
4.9.7.1 📋 Implementation Guidelines
Image dimensions: Read the integers \(L\) (rows) and \(C\) (columns) from \(f\).
Dimensions of \(b\): Read the integers \(L_B\) (rows) and \(C_B\) (columns) of the weighted structuring element.
Weights: Read the matrix \(b\) of integer weights (which may be negative, zero, or positive), row by row.
Data: Read the matrix \(f\) (the original image), row by row.
Neighborhood without padding: For each pixel \((y,x)\), iterate over all positions \((by,bx)\) of \(b\) (not only where it would equal \(1\) — here every weight participates), using the same offset as in previous EPs: \[
v_y = y + by + o_y,\quad v_x = x + bx + o_x,\quad o_y=-\tfrac{L_B}{2}+0{,}5,\quad o_x=-\tfrac{C_B}{2}+0{,}5
\]Discard every \((v_y,v_x)\) outside \([0,L)\times[0,C)\).
Weighted erosion: Compute, using the same \(b\) and without reflection: \[
g_{ero}(y,x) = \min\Big(f(y,x),\ \min_{(v_y,v_x)\ \text{valid}} \big(f(v_y,v_x) - b(by,bx)\big)\Big)
\]
Output: Display first the complete matrix \(g_{dil}\), and then the complete matrix \(g_{ero}\).
4.9.7.2 📌 Computational Constraints
Neither reflects \(b\) — the weighted version does not use reflection, even in dilation (unlike mm::dil0).
All weights participate: There is no “\(B=1\)” filter here; even weight \(0\) is included in the computation.
No padding: neighbors outside the image are ignored, never virtually filled.
Type: The output may contain negative values or values greater than \(255\) — there is noclipping in this EP.
Hint: To remove overflow messages when exceeding uint8 limits, include at the beginning of the code:
import warningswarnings.filterwarnings("ignore")
4.9.7.3 🧠 Theoretical Foundation
Concept
Meaning
Visual Impact
Positive weight
“Pulls” the neighbor’s value upward in dilation
Simulates terrain rising in that direction
Negative weight
Reduces the neighbor’s contribution
Simulates distance or directional attenuation
Weighted duality
\(\text{ero1}(f,b) = -\text{dil1}(-f,b)\)
The symmetry between the two operations is maintained even with weights
4.9.7.4 📦 Input and Output Specification (VPL)
Input:
Line 1: Integer \(L\).
Line 2: Integer \(C\).
Line 3: Integer \(L_B\).
Line 4: Integer \(C_B\).
Next \(L_B\) lines: integer elements (may be negative) of the matrix \(b\).
Next \(L\) lines: integer elements of the matrix \(f\).
Output:
First, the matrix \(g_{dil}\) in \(L\) rows and \(C\) columns.
Then, the matrix \(g_{ero}\) in \(L\) rows and \(C\) columns.