giovani_ex7 - Convolução: Novo algoritmo

Objetivos:

Consolidar os exercícios feitos na semana passada e exercitar um pouco mais a convolução discreta.
  1. Escrever a equação que é de fato implementada pela rotina iaconv da toolbox ia636. Observe que o José Antonio implementou corretamente a equação da convolução iaconv que aparece na toolbox ia636.

A equação que representa a implementação utilizada na função "iaconv" esta descrita abaixo:

Segue a função:

 1 def iaconv(f, h):
 2     f, h = asarray(f), asarray(h)
 3     if len(f.shape) == 1: f = f[NewAxis,:]
 4     if len(h.shape) == 1: h = h[NewAxis,:]
 5     if product(f.shape) < product(h.shape):
 6         f, h = h, f
 7     g = zeros(array(f.shape) + array(h.shape) - 1)
 8     for i in range(h.shape[0]):
 9         for j in range(h.shape[1]):
10             g[i:i+f.shape[0], j:j+f.shape[1]] += h[i,j] * f
11     return g

  1. Baseado no roteiro de aula feito na última sexta-feira (ia636-2009:convolucao), elaborar uma lição sobre convolução digital para posteriormente ser agregado à toolbox ia636 na seção de Lessons. Pode ser em portugues mesmo ou preferencialmente em ingles. Se alguma solução ficar muito boa e for aprovada para ser incorporada à toolbox ia636, os créditos do aluno ficarão registrados no rodapé da página da contribuição.

Convolução DIGITAL

Após Estudos, verifica-se que não há a necessidade de realizar loop para processar a convolução visto algumas funções em python que proporciona esta base. Esta questão não é trivial e portanto deverá ser escrito uma equação que apresente essa logica que foi implementada na rotina "giconv". Como a rotina já foi criada (e está em fase de testes), estou estudando a melhor maneira de criar tal equação que represente de fato o que foi feito. ( :: Está complicado!!! :: )
 1 # Função de convolução sem utilizar laço de repetição
 2 #------------------------------------------------------------------------
 3 def giconvM(f, k):
 4 
 5     nlink,ncolk = k.shape
 6     nlinf,ncolf = f.shape
 7 
 8     # Monta a nova imagem considerando as bordas como 0
 9     fe = concatenate((f,zeros([nlink-1,ncolf])),axis=0)
10     fe = concatenate((fe,zeros([fe.shape[0],ncolk-1])),axis=1)
11     nlinfe,ncolfe = fe.shape
12 
13     idviz,idorig = iameshgrid(range(k.size),range(fe.size)) # Cria a matriz de indices dos vizinhos e da origem
14     idkernel = range(k.size)                                # Posição de cada vizinho no vetor numerado sequencialmente
15     k1D = ravel(k)                                          # Transforma o kernel e imagem para 1 dimensão
16     f1D = ravel(fe)
17     fe1D = concatenate((f1D,zeros(f1D.size*k.size)),axis=1) # Concatena a matriz com zeros para igualar os indices
18     quociente,resto = divmod(idviz,ncolk)                   # 1 fase do calculo dos indices vizinhos
19     idvizinho = resto + (quociente * ncolfe) + idorig       # Indexando todos os vizinhos para todos os pixels
20     valor_viz = fe1D[idvizinho]                             # Pegando o valor dos pixels indexados pelos vizinhos
21     conv = dot(valor_viz,k1D)                               # Realizando o calculo final da convolução
22     conv = resize(conv,(nlinfe,ncolfe))                     # Redimensionando a imagem
23 
24     return conv[0:nlinf,0:ncolf]                            # retornando a matriz truncada
25 #------------------------------------------------------------------------
26 
27 # Função de convolução utilizando apenas um laço de repetição
28 #------------------------------------------------------------------------
29 def giconvB(f, k):
30 
31     nlink,ncolk = k.shape
32     nlinf,ncolf = f.shape
33 
34     # Monta a nova imagem considerando as bordas como 0
35     fe = concatenate((f,zeros([nlink-1,ncolf])),axis=0)
36     fe = concatenate((fe,zeros([fe.shape[0],ncolk-1])),axis=1)
37 
38     nlinfe,ncolfe = fe.shape
39 
40     idfe = resize(arange(fe.size),(nlinfe,ncolfe))          # Cria as indices da nova imagem
41     idfe = ravel(idfe[0:nlinf,0:ncolf])
42     k1D = ravel(k)                                          # Transforma o kernel e imagem para 1 dimensão
43     f1D = ravel(f)
44     fe1D = ravel(fe)
45     convolucao = zeros(f1D.size)
46 
47     # Realiza o processo da convolução
48     for x in range(k.size):
49         quociente,resto = divmod(x,ncolk)
50         ind = resto + (quociente * ncolfe) + idfe
51         ind = minimum(ind,fe1D.size-1)
52         convolucao += fe1D[ind]*k1D[x]
53 
54     return resize(convolucao,(nlinf,ncolf))                 # Redimensionando a imagem
55 #------------------------------------------------------------------------

Veremos adiante, uma abordagem simples apresentando a convolução:

f: 
[[ 7 10 13 15 16]
 [18 30 20 18 13]
 [11 12 15 20 19]
 [14 18 13 18 20]]

 h: 
[[ 0.111  0.111  0.111]
 [ 0.111  0.111  0.111]
 [ 0.111  0.111  0.111]]

 y: 
[[ 15.096  16.983  16.539  11.211   5.328]
 [ 16.761  18.204  17.316  11.988   5.772]
 [  9.213  10.656  11.655   8.547   4.329]
 [  4.995   5.439   5.661   4.218   2.22 ]]

Outro caso, apresentando a questão de apenas 1 impulso:

f: 
[[0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 0 1 0]
 [0 0 0 0 0]]

 gaussian5x5: 
[[ 1  4  6  4  1]
 [ 4 16 24 16  4]
 [ 6 24 36 24  6]
 [ 4 16 24 16  4]
 [ 1  4  6  4  1]]

 y: 
[[ 24.  36.  24.   6.   0.]
 [ 16.  24.  16.   4.   0.]
 [  4.   6.   4.   1.   0.]
 [  0.   0.   0.   0.   0.]]

Este caso, apresenta o filtro laplaciano:

f: 
[[0 0 0 0 0 0 0]
 [0 0 1 1 1 0 0]
 [0 0 1 1 1 0 0]
 [0 0 1 1 1 0 0]
 [0 0 0 0 0 0 0]]

 h: 
[[ 0  1  0]
 [ 1 -4  1]
 [ 0  1  0]]

 y: 
[[ 1. -2. -1. -2.  1.  0.  0.]
 [ 1. -1.  0. -1.  1.  0.  0.]
 [ 1. -2. -1. -2.  1.  0.  0.]
 [ 0.  1.  1.  1.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.]]

Trabalhando com Imagem:

Imagem Original

Imagem Suavizada 3x3


  1. Utilize seu programa de convolução feito na lição anterior com filtros de dimensão 3x3 e 5x5. Utilize também, para efeitos de comparação, a função iaconv da toolbox ia636. Aplique estes filtros em dois casos: um filtro de suavização e um filtro de realce de detalhes. Escolha as máscaras de convolução apropriadas e a imagem para aplicar estes filtros.
  • OBS: Os resultados obtidos neste exercício ainda está sobre análise pois aparentemente estão bastante estranhos!!!!

1°Caso: Filtro de suavização

Filtros utilizados:

 Suaviação 3x3:
[[ 0.111  0.111  0.111]
 [ 0.111  0.111  0.111]
 [ 0.111  0.111  0.111]]

 Gaussiana 5x5:
[[ 1  4  6  4  1]
 [ 4 16 24 16  4]
 [ 6 24 36 24  6]
 [ 4 16 24 16  4]
 [ 1  4  6  4  1]]

 Função iaconv 3x3 - n° Amostra: 8 - Média: 0.003629 
 Função giconvM 3x3 - n° Amostra: 8 - Média: 0.114188 
 Função giconvB 3x3 - n° Amostra: 8 - Média: 0.013615 

 Função iaconv 5x5 - n° Amostra: 8 - Média: 0.009143 
 Função giconvM 5x5 - n° Amostra: 8 - Média: 0.285986 
 Função giconvB 5x5 - n° Amostra: 8 - Média: 0.033136

Imagem Filtrada giconvM3x3 tmp: 0.113430

Imagem Filtrada giconvM5x5 tmp: 0.286031

Imagem Filtrada giconvB3x3 tmp: 0.011470

Imagem Filtrada giconvB5x5 tmp: 0.031937

Imagem Filtrada iaconv3x3 tmp: 0.003630

Imagem Filtrada iaconv5x5 tmp: 0.009085

2°Caso: Filtro de realce de detalhes

Filtros utilizados:

 laplace 3x3:
[[ 0  1  0]
 [ 1 -4  1]
 [ 0  1  0]]

 Função iaconv 3x3 - n° Amostra: 8 - Média: 0.003660 
 Função giconvB 3x3 - n° Amostra: 8 - Média: 0.012068

Imagem Original

Imagem Laplace giconvB3x3 tmp: 0.011147

Imagem Laplace iaconv3x3 tmp: 0.003685