.


Processamento digital de imagens
Transformações Geométricas: Determinação de parâmetros


Exercício: estimativa de parâmetros

Dado um conjunto de pontos homólogos, com coordenadas conhecidas em duas imagens, se deseja calcular os parâmetros de uma transformação geométrica usando polinômio de primeira ordem para transformar a geometria de uma das imagens (Direita B) para a geometria da segunda imagem (esquerda A).

Para isto, unsado o Multyispec, leia pares de pontos homólogos (o mesmo ponto nas duas imagerns) e crie uma tabela similar à listada abaixo, e salve em um arquivo ASCII.
  
        684.2   ,   323.0    ,    345.2  ,   345.5
        553.7   ,  1184.2    ,    224.7  ,  1208.0
       2216.5   ,  1069.7    ,   1886.0  ,  1075.7 
       2388.0   ,   483.7    ,   2051.0  ,   488.0
       1386.5   ,   347.0    ,   1047.7  ,   362.5
       1637.5   ,  1288.0    ,   1309.2  ,  1300.5
  
O primeiro passo consiste em ler essa tabela ASCII (no exemplo a seguir foi armazenada como "pontos.txt") do seu disco e carregar na memoria. Veja o código a seguir, ele tem:

Se tudo deu certo, você verá a tabela na área de diálogo do Pyzo, e um gráfico como este:

  
import numpy as np
import matplotlib.pyplot as plt

# FUNCAO de leitura de tabela com 4 colunas
def ler_pontos(nome):
    Nptos=0
    Ncolunas=4                # sabemos que a tabela tem 4 colunas

    # abrir um arquivo e ler todas suas linhas. 
    # A cada linha lida, acumulamos Nptos para contar quantas linhas 
    # existem e poder dimensionar a tabela para os dados
    with open(nome, 'r', encoding='utf-8') as arquivo:
        for linha in arquivo:
            Nptos=Nptos+1     # conta linhas
    print(Nptos, 'linhas')

    Ta = np.zeros((Nptos, Ncolunas),dtype = float)   # criação de tabela vazia
    c=0     # contador de linhas, para copiar na tabela cada linha lida
    with open(nome, 'r', encoding='utf-8') as arquivo:
        for linha in arquivo:
            L = linha.strip()    # uma linha inteira, com espaços e todos os carateres
            #print(L)
            B = [float(x) for x in L.split(',')]   # separa a linha em floats separados por vírgulas
            #print(B)
            Ta[c,0:4]=B[0:4]   # copia a linha lida (vetor) na tabela
            c=c+1
    #print(Ta)

    return(Ta,Nptos)


## programa ###################################################################

# nome = "tabela.txt"
nome="tabela_foto1a1.txt"
P, npontos=ler_pontos(nome)
npt,nc=P.shape      # tamanho da matriz npt=nro de pontos, nv=numero colunas 4)

print('Num ptos=',npt, '  : ncolunas= ', nc)
print(P)
print('********************************************************************')

# comentario: plotamos os pontos
plt.scatter(P[:,0], P[:,1], marker='^' )
plt.scatter(P[:,2], P[:,3], marker='o' )
plt.show()


  
Agora vamos calcular os parâmetros com base nessa tabela. A tabela contém:
x_imagem A, Y_imagemA, X_imagemB, Y_imagemB
Você também poderia ter:
Linha_imagem A, Coluna_imagemA, Linha_imagemB, Coluna_imagemB
tome cuidado na ordem na que você criou sua tabela.

Nesta parte do programa as coordenadas da primeira coluna X_imagemA são armazenadas nas linhas pares (0,2,4,5...) do vetor Y e as coordenadas Y_imagemA da segunda coluna são armazenadas nas linhas ímpares.
   
## Separar as coordenadas de campo e construir vetor Y (2*num_pontos, 1)

Q= np.zeros((2*npt,1),dtype = int)       # aloca espaco de vetor
Y = np.zeros((2*npt,1),dtype = float)       # aloca espaco de vetor
for i in range(npt):    # Copia uma coordenada na linha par, outra na impar
    Y[2*i  ,0]=P[i,2]
    Y[2*i+1,0]=P[i,3]
print('Vetor de coord de imagem BASE') #mostrar, pode apagar depois
print(Y)

  	

você deve ter uma saída como esta abaixo. Confira as coordenadas com a tabela.
  
Vetor de coord de imagem de ENTRADA
[[ 345.25]
 [ 345.5 ]
 [ 224.75]
 [1208.  ]
 [1886.  ]
 [1075.75]
 [2051.  ]
 [ 488.  ]
 [1047.75]
 [ 362.5 ]
 [1309.25]
 [1300.5 ]]
  

Agora Usamos a mesma lógica para preencher a matriz X com as coordenadas da segunda imagem (terceira e quarta colunas, índicex 2 e 3). Verifique na área de diálogo os valores da tabela.
	  
## Construir matriz de coordenadas de tela com as coordenadas 2 e 3 da matriz P

X = np.zeros( ( 2*npt,6) )  # cria matriz com zeros com 2NPT linhas e 6 colunas
#print(X)
for i in range(npt):        # preenche a matriz  x1 x2 1 0 0 0 ; 0 0 0  x1 x2 1]
    X[2*i,0 ]=P[i,0]
    X[2*i,1 ]=P[i,1]
    X[2*i,2 ]=1
    X[2*i+1,3]=P[i,0]
    X[2*i+1,4]=P[i,1]
    X[2*i+1,5]=1
print('Matriz coord de imagem BASE')
print(X)
  
Agora podemos proceder a calcular os parâmetros, segundo a teoria mostrada na sala de aulas:

  1. Y = X * A
  2. A = inv(X_transp * X)* X_transp * Y

    para multiplicaçãod e vetores e matrizes, bem como a manipulação de matrozes, podemos usar a biblioteca numpy (dor, linalg.inv, transpose).
       
    ## solucao do sistema
    
    ## transpor matriz X
    Xt= np.transpose(X)
    print('Matriz transposta')
    print(Xt)
    ## produto vetorial= dot (dot product)
    C=np.dot(Xt,X)
    print(C.shape)
    
    D=np.linalg.inv(C)  # inverter matriz 6x6
     
    B=np.dot(Xt,Y)
    A=np.dot(D,B)
    print('solucao')
    print(A)
    
    	
    FInalmente, com os parâmetros, podemos calcular os valores estimados de Y, as coordenadas da primeira imagem, com base nas coordenadas da segunda imagem e calcualr a diferença entre as coordenadas prteditas pelo modelo y as coordenadas observadas, para avaliar se o modelo está predizendo bem as posições.
    	   
    ## calcule residuos
    R= np.dot(X,A)
    
    Dif=Y - R		# diferença entre REAL e estimad
    print('real, estimados, diferenca')
    for i in range(npt):
        print(": %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f " % (  Y[2*i], R[2*i], Dif[2*i] , Y[2*i+1], R[2*i+1], Dif[2*i+1] ) )
      	

    Um bom resultado seria caracterizado por diferenças pequenas entre os valores observados e os calculados. como ficou o resultado na sua avaliação? Qual é a distância de cada ponto considerando as coordenadas observadas e as calculadas ? Qual a distância média ?