PDI+VC · Exercício de Programação

EP04_07 — ⛰️ Dilatação e Erosão com Pesos (mm.dil1 / mm.ero1)

4.9.7 EP04_07 ⛰️ Dilatação e Erosão com Pesos (mm.dil1 / mm.ero1)

Até agora, o elemento estruturante só dizia “este vizinho conta” ou “não conta” — mas em modelos digitais de elevação (usados em SIG e em planejamento de drenagem urbana), cada vizinho deveria ter um peso diferente dependendo da distância ou da direção do relevo. As versões ponderadas da dilatação e da erosão, implementadas em morph.py como mm::dil1(f, b) e mm::ero1(f, b), somam (ou subtraem) o peso de cada vizinho antes de tomar o máximo (ou mínimo) — generalizando tudo o que foi feito nos EPs anteriores. Ver na Figura 4.36 uma simulação deste EP.

4.9.7.1 📋 Diretrizes de Implementação

  1. Dimensões da imagem: Ler os inteiros \(L\) (linhas) e \(C\) (colunas) de \(f\).
  2. Dimensões de \(b\): Ler os inteiros \(L_B\) (linhas) e \(C_B\) (colunas) do elemento estruturante ponderado.
  3. Pesos: Ler a matriz \(b\) de pesos inteiros (podem ser negativos, zero ou positivos), linha a linha.
  4. Dados: Ler a matriz \(f\) (a imagem original), linha a linha.
  5. Vizinhança sem padding: Para cada pixel \((y,x)\), percorrer todas as posições \((by,bx)\) de \(b\) (não apenas onde valeria \(1\) — aqui todo peso participa), usando o mesmo deslocamento dos EPs anteriores: \[ 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 \] Descartar todo \((v_y,v_x)\) fora de \([0,L)\times[0,C)\).
  6. Dilatação ponderada: Calcular \[ g_{dil}(y,x) = \max\Big(f(y,x),\ \max_{(v_y,v_x)\ \text{válido}} \big(f(v_y,v_x) + b(by,bx)\big)\Big) \]
  7. Erosão ponderada: Calcular, usando o mesmo \(b\) e sem refletir: \[ g_{ero}(y,x) = \min\Big(f(y,x),\ \min_{(v_y,v_x)\ \text{válido}} \big(f(v_y,v_x) - b(by,bx)\big)\Big) \]
  8. Saída: Exibir primeiro a matriz \(g_{dil}\) completa, e depois a matriz \(g_{ero}\) completa.

4.9.7.2 📌 Restrições Computacionais

  • Nenhuma das duas reflete \(b\) — a versão ponderada não usa reflexão, mesmo na dilatação (diferente de mm::dil0).
  • Todos os pesos participam: Não existe aqui o filtro “\(B=1\)”; mesmo peso \(0\) entra na conta.
  • Sem padding: vizinhos fora da imagem são ignorados, nunca virtualmente preenchidos.
  • Tipo: A saída pode conter valores negativos ou maiores que \(255\) — não há clipping neste EP.
  • Dica: Para remover mensagens de overflow ao ultrapassar limites do tipo uint8, incluir no início do código:
import warnings
warnings.filterwarnings("ignore")

4.9.7.3 🧠 Fundamentação Teórica

Conceito Significado Impacto Visual
Peso positivo “Puxa” o valor do vizinho para cima na dilatação Simula relevo que sobe naquela direção
Peso negativo Reduz a contribuição do vizinho Simula distância ou atenuação direcional
Dualidade ponderada \(\text{ero1}(f,b) = -\text{dil1}(-f,b)\) A simetria entre as duas operações se mantém mesmo com pesos

4.9.7.4 📦 Especificação de Entrada e Saída (VPL)

Entrada:

  • Linha 1: Inteiro \(L\).
  • Linha 2: Inteiro \(C\).
  • Linha 3: Inteiro \(L_B\).
  • Linha 4: Inteiro \(C_B\).
  • Próximas \(L_B\) linhas: elementos inteiros (podem ser negativos) da matriz \(b\).
  • Próximas \(L\) linhas: elementos inteiros da matriz \(f\).

Saída:

  • Primeiro a matriz \(g_{dil}\) em \(L\) linhas e \(C\) colunas.
  • Em seguida a matriz \(g_{ero}\) em \(L\) linhas e \(C\) colunas.

4.9.7.5 📌 Exemplos

Entrada Saída Observação
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
Peso central \(2\) acelera o crescimento na dilatação e o encolhimento na erosão
⛰️ Simulador EP04_07: Pesos no Elemento Estruturante dil1 / ero1

Ajuste os pesos do elemento estruturante b com os controles deslizantes e observe o efeito da dilatação e erosão com pesos sobre a matriz f.

Pesos b (Ajuste os Sliders por Célula)
f Original
dil1(f, b) (Dilatação)
ero1(f, b) (Erosão)
Figura 4.36: Simulador EP04_07: Dilatação e Erosão com Pesos (mm.dil1 / mm.ero1)
%%writefile EP04_07.cpp
// sua solução
Overwriting EP04_07.cpp
TestSuite("EP04_07.cpp").run()
✔️ EP04_07.cases já existe em casos/
📋 3 caso(s) carregado(s) de casos/EP04_07.cases

🔍 Testando C++: EP04_07.cpp
⚠️ EP04_07.cpp: Arquivo sem conteúdo (menos de 3 linhas). Testes ignorados.