DIP+CV · Programming Exercise

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

  1. Image dimensions: Read the integers \(L\) (rows) and \(C\) (columns) from \(f\).
  2. Dimensions of \(b\): Read the integers \(L_B\) (rows) and \(C_B\) (columns) of the weighted structuring element.
  3. Weights: Read the matrix \(b\) of integer weights (which may be negative, zero, or positive), row by row.
  4. Data: Read the matrix \(f\) (the original image), row by row.
  5. 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)\).
  6. Weighted dilation: Compute \[ g_{dil}(y,x) = \max\Big(f(y,x),\ \max_{(v_y,v_x)\ \text{valid}} \big(f(v_y,v_x) + b(by,bx)\big)\Big) \]
  7. 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) \]
  8. 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 no clipping in this EP.
  • Hint: To remove overflow messages when exceeding uint8 limits, include at the beginning of the code:
import warnings
warnings.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.

4.9.7.5 📌 Examples

Input Output Observation
3
3
3
3
0 1 0
1 2 1
0 1 0
10 20 30
40 50 60
70 80 90
50 60 61
80 90 91
81 91 92
8 9 19
9 10 20
39 40 50
Central weight \(2\) accelerates growth in dilation and shrinkage in erosion
⛰️ Simulator EP04_07: Weights in the Structuring Element dil1 / ero1

Adjust the weights of the structuring element b with the sliders and observe the effect of dilation and erosion with weights on the matrix f.

Weights b (Adjust Sliders per Cell)
Original f
dil1(f, b) (Dilation)
ero1(f, b) (Erosion)
Figure 4.36: EP04_07 Simulator: Dilation and Erosion with Weights (mm.dil1 / mm.ero1)
%%writefile EP04_07.py
# Python code
Overwriting EP04_07.py
TestSuite("EP04_07.py").run()
✔️ EP04_07.cases already exists in casos/
📋 3 case(s) loaded from casos/EP04_07.cases

🔍 Testing Python: EP04_07.py
⚠️ EP04_07.py: Empty file (fewer than 3 lines). Tests skipped.