Exercício 04 - Transformação Geométrica com iaffine

Autor: Wagner Machado do Amaral
Data: 30/03/2009

Enunciado: ia636-2009:exercicio4

Indice:

  • equacao - Equação matemática do uso indexado imagens no Python
  • iaffine - Estudo da função iaffine
  • iaffine_direto - Implementação de iaffine com mapeamento direto
  • iaffine_translacao - Função semelhante a iaffine que funciona também com translação

equacao - Equação matemática do uso indexado imagens no Python

O comando em Python a segui:

pode ser descrito matematicamente como:

iaffine - Estudo da função iaffine

  • Exemplo de escala de 1/2 em X e Y utilizando a função iaffine
 1 imgname = 'cameraman.pgm'
 2 I =adreadgray(imgname)
 3 adshow(I,title=imgname)
 4 
 5 T = array([ [0.5,0,0],[0,0.5,0],[0,0,1] ])
 6 I2 = iaffine(I,T)
 7 adshow(I2,title='iaffine: Escala de 1/2 em X e Y')
 8 
 9 T = array([ [2,0,0],[0,2,0],[0,0,1] ])
10 I3 = iaffine(I,T)
11 adshow(I3,title='iaffine: Escala de 2 em X e Y')

cameraman.pgm

iaffine: Escala de 1/2 em X e Y

iaffine: Escala de 2 em X e Y

Observe que ao diminuir a imagem por 1/2 em X e Y, aos pixels da parte vazia foram atribuidos os valores dos ultimos pixels da imagem.

  • iaffine_verbose : Função semelhante a iaffine que imprime cada passo da função

Não foi possível importar para o ambiente Adesso algumas das funções que iaffine utiliza. Por isso iaffine_verbose substitui algumas funções.

A função iaffine_verbose exibe na tela cada passo de sua execução, isso possibilita uma melhor compreensão de seu funcionamento.

 1 def iaffine_verbose(f, T):
 2 
 3   from numpy.linalg import inv
 4   from numpy import maximum, minimum
 5 
 6   print 'f:'
 7   print f
 8 
 9   faux = ravel(f)
10   print 'faux:'
11   print faux
12 
13   (m, n) = f.shape
14   (x, y) = iameshgrid(range(n),range(m))
15   print 'x:'
16   print x
17   print 'y:'
18   print y
19 
20   aux = concatenate((reshape(x, (1,m*n)), reshape(y, (1,m*n))))
21   print 'aux:'
22   print aux
23 
24   aux = concatenate((aux, zeros((1, m*n))))
25   print 'aux:'
26   print aux
27 
28   XY = dot(inv(T), aux)
29   print 'XY:'
30   print XY
31 
32   X, Y = XY[0,:], XY[1,:]
33   print 'X:'
34   print X
35   print 'Y:'
36   print Y
37 
38   X = maximum(0, minimum(n-1, X))
39   Y = maximum(0, minimum(m-1, Y))
40 
41   XYi = iasub2ind(f.shape, map(round, Y), map(round, X))
42   print 'XYi:'
43   print XYi
44 
45   g = take(faux, XYi)
46   print 'g:'
47   print g
48 
49   g = reshape(g, f.shape)
50   print 'g:'
51   print g
52 
53   return g

Veja abaixo um exemplo de escala de 2 em X e Y.

1 f = array([
2 ['A','B','C','D'],
3 ['E','F','G','H'],
4 ['I','J','K','L']
5 ])
6 T = array([ [2,0,0],[0,2,0],[0,0,1],  ])
7 
8 g = iaffine_verbose(f, T)
f:
[['A' 'B' 'C' 'D']
 ['E' 'F' 'G' 'H']
 ['I' 'J' 'K' 'L']]
faux:
['A' 'B' 'C' 'D' 'E' 'F' 'G' 'H' 'I' 'J' 'K' 'L']
x:
[[0 1 2 3]
 [0 1 2 3]
 [0 1 2 3]]
y:
[[0 0 0 0]
 [1 1 1 1]
 [2 2 2 2]]
aux:
[[0 1 2 3 0 1 2 3 0 1 2 3]
 [0 0 0 0 1 1 1 1 2 2 2 2]]
aux:
[[ 0.  1.  2.  3.  0.  1.  2.  3.  0.  1.  2.  3.]
 [ 0.  0.  0.  0.  1.  1.  1.  1.  2.  2.  2.  2.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]]
XY:
[[ 0.   0.5  1.   1.5  0.   0.5  1.   1.5  0.   0.5  1.   1.5]
 [ 0.   0.   0.   0.   0.5  0.5  0.5  0.5  1.   1.   1.   1. ]
 [ 0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0. ]]
X:
[ 0.   0.5  1.   1.5  0.   0.5  1.   1.5  0.   0.5  1.   1.5]
Y:
[ 0.   0.   0.   0.   0.5  0.5  0.5  0.5  1.   1.   1.   1. ]
XYi:
[0 1 1 2 4 5 5 6 4 5 5 6]
g:
['A' 'B' 'B' 'C' 'E' 'F' 'F' 'G' 'E' 'F' 'F' 'G']
g:
[['A' 'B' 'B' 'C']
 ['E' 'F' 'F' 'G']
 ['E' 'F' 'F' 'G']]

iaffine_direto - Implementação de iaffine com mapeamento direto

 1 def iaffine_direto(f, T):
 2 
 3   from numpy.linalg import inv
 4   from numpy import maximum, minimum
 5 
 6   faux = ravel(f)
 7 
 8   (m, n) = f.shape
 9   (x, y) = iameshgrid(range(n),range(m))
10 
11   aux = concatenate((reshape(x, (1,m*n)), reshape(y, (1,m*n))))
12 
13   aux = concatenate((aux, ones((1, m*n))))
14 
15   XY = dot(T, aux)
16 
17   X, Y = XY[0,:], XY[1,:]
18 
19   X = maximum(0, minimum(n-1, X))
20   Y = maximum(0, minimum(m-1, Y))
21 
22   XYi = iasub2ind(f.shape, map(round, Y), map(round, X))
23 
24   g = zeros( [1 , XYi.max()+1] )
25   put(g, XYi, faux)
26   g.resize(f.shape)
27   return g
 1 imgname = 'cameraman.pgm'
 2 I =adreadgray(imgname)
 3 adshow(I,title=imgname)
 4 
 5 T = array([ [0.5,0,0],[0,0.5,0],[0,0,1] ])
 6 I2 = iaffine_direto(I,T)
 7 adshow(I2,title='iaffine_direto: Escala de 1/2 em X e Y')
 8 
 9 T = array([ [2,0,0],[0,2,0],[0,0,1] ])
10 I3 = iaffine_direto(I,T)
11 adshow(I3,title='iaffine_direto: Escala de 2 em X e Y')

cameraman.pgm

iaffine_direto: Escala de 1/2 em X e Y

iaffine_direto: Escala de 2 em X e Y

iaffine_translacao - Função semelhante a iaffine que funciona também com translação

A matriz de translação T (conforme abaixo) que aprendemos na disciplina não funciona com a função iaffine

 1 T = array([ [1,0,50],[0,1,100],[0,0,1] ])
 2 print 'Matriz de transformação:'
 3 print T
 4 
 5 imgname = 'cameraman.pgm'
 6 
 7 I =adreadgray(imgname)
 8 adshow(I,title=imgname)
 9 
10 I2 = iaffine(I,T)
11 adshow(I2,title='Translação de 50 em X e 100 em Y com iaffine')
Matriz de transformação:
[[  1   0  50]
 [  0   1 100]
 [  0   0   1]]

cameraman.pgm

Translação de 50 em X e 100 em Y com iaffine

Isso ocorre porque a função iaffine monta cada ponto da imagem com coordenada homogênea igual a zero, isso anula Tx e Ty, conforme abaixo:

A função iaffine_translacao monta cada ponto da imagem com coordenada homogênea igual a 1, conforme abaixo:

Essa alteração entá na linha 13. aux = concatenate((aux, ones((1, m*n))))

Veja abaixo a mesma translação que foi aplicada acima utilizando iaffine agora funciona corretamente.

 1 def iaffine_translacao(f, T):
 2 
 3   from numpy.linalg import inv
 4   from numpy import maximum, minimum
 5 
 6   faux = ravel(f)
 7 
 8   (m, n) = f.shape
 9   (x, y) = iameshgrid(range(n),range(m))
10 
11   aux = concatenate((reshape(x, (1,m*n)), reshape(y, (1,m*n))))
12 
13   aux = concatenate((aux, ones((1, m*n))))
14 
15   XY = dot(inv(T), aux)
16 
17   X, Y = XY[0,:], XY[1,:]
18 
19   X = maximum(0, minimum(n-1, X))
20   Y = maximum(0, minimum(m-1, Y))
21 
22   XYi = iasub2ind(f.shape, map(round, Y), map(round, X))
23 
24   g = take(faux, XYi)
25 
26   g = reshape(g, f.shape)
27 
28   return g
1 T = array([ [1,0,50],[0,1,100],[0,0,1] ])
2 
3 imgname = 'cameraman.pgm'
4 
5 I =adreadgray(imgname)
6 adshow(I,title=imgname)
7 
8 I2 = iaffine_translacao(I,T)
9 adshow(I2,title='Translação de 50 em X e 100 em Y com iaffine_translacao')

cameraman.pgm

Translação de 50 em X e 100 em Y com iaffine_translacao