Implementação da Transformada de Hadamard
Felipe Augusto Rieck
Resumo[]
Este trabalho visa apresentar um estudo sobre a transformada de Hadamard e especificar um modelo de implemtenação para a linguagem Python. A implementação apresentará também o algorítmo para a geração das matrizes de Hadamard, muito úteis em diversas utilizações desta transformada.
Introdução[]
Também conhecida como transformada de Walsh-Hadamard, transformada de Walsh ou transformada de Walsh-Fourier, a transformada de Hadamard é uma classe genérica derivada das Transformadas Rápidas de Fourier (FFT). Segundo [Transformadas 3], esta transformada fornece uma maneira de medir o "bitwise" não linerar existente entre funções cujo domínio é uma representação de bits.
Criada pelo matemático francês Jacques Hadamard, esta transformada executa uma operação ortogonal, simetrica, involutária e linear em números reais de (ou em números complexos, embora as matrizes por ela geradas sejam puramente reais).
Esta transformada é comumente utilizada para:
- Compressão de imagens;
- Processamento de sinais;
- Entre outros.
Além dessas aplicações, a transformada de Hadamard pode ser utilizada para gerar números aleatórios pertencentes ao conjunto da distribuição Gaussiana. Além disso, esta transformada pode ser utilizada através de uma série de permutações randômicas a fim de causar ruido Gaussiano nos dados [Hadamard Transform 4].
Vantagens[]
Na transformada de Hadamard, a transformada e a sua inversa são inerentemente idênticas, facilitando assim a implementação de um algorítmo que retorne à imagem original. Assim, segundo [2], um algorítmo que calcule (a transformada de Hadamard de uma imagem) é o mesmo que pode ser utilizado para calcular (a imagem originante de uma transformada de Hadamard).
Além disso, a transformada de Hadamard é muito simples de computar já que necessita apenas de formulações matemáticas imples, como adição e subtração, e depois da divisão por N, que freqüentemente é uma potência de 2.
Desvantagens[]
Quando aplicada ao processamento de sinais, faz-se necessário ordenar a matriz de transformação utilizada pela transformada de Hadamard, pois esta desordenação pode acarretar em problemas na análise destes sinais.
Organização do trabalho[]
Este trabalho está organizado da seguinte forma: Na seção 3 é apresentada a transformada através de sua formulação matemática. Na seção 4 é abordada a aplicação desta transformada, e na seguite seção são verificados os resultados obtidos aravés da computação da transformada de Hadamar. Em seguida, na seção 6 é concluido este trabalho.
Transformada de Hadamard[]
A diferença da transformada de Fourier para a transformada de Hadamard, é a de que a primeira utiliza a trigonometria, enquanto a segunda consiste em uma série de funções básicas cujos valores são +1 ou -1.
A transformada de Hadamard, , de uma imagem de dimensões onde é dada pela fórmula:
onde , e é o j-ézimo bit da representação binária de z, ou seja, quando , sua representação binária é e o quinto número é 1 ().
Como citado anteriormente a transformada inversa é exatamente igual a transformada normal, apenas trocando de lugar os itens com , vindo a ficar:
- .
Os núcleos da transformada de Hadamard são simétricos divisíveis (podem ser separados), e são definidos por:
onde . Dessa forma, para se calcular a transformada de Hadamard bidimensional pode-se calcular duas verzes consecutivas a transformada de Hadamard unidimensional dada por:
- .
Matriz de transformação[]
Além do cálculo direto citado acima, a transformada de Hadamard pode ser obtida através do cálculo de sua matriz de transformação.
A menor matriz de transformação é a matriz , dada por:
- .
Dessa forma, através de métodos recursivos é possivel determinar uma matriz de transformação , para (valores múltiplos de 2). Uma matriz por exemplo é dada por:
Ou seja, de forma genérica, uma matriz é definida por:
- .
Assim, através desta matriz (a), aplica-se a fórmula:
e obtém-se a transformada de Hadamard (T) da imagem F.
Implementação[]
Neste trabalho será mostrado o cálculo de dois arrays de valores, um correspondente à própria transformada e outro correspondente à matriz de Hadamard entretanto somente será mostrada a implementação para transformada de Hadamard sem utilização das matrizes. Para a criação desta matriz, como visto anteriormente, se fa necessário utilizar uma função recursiva que calcula as matrizes até chegar à menor matriz possível: . Este cálculo é feito da seguinte forma:
def geraMatrizHadamard(N): ret = ones((N,N)) if N == 2: ret[0][0] = 1 ret[0][1] = 1 ret[1][0] = 1 ret[1][1] = -1 return ret aux = geraMatrizHadamard(N/2) dx = 0 dy = 0 for x in range(N): for y in range(N): if x >= N-N/2 and y >= N-N/2: ret[x][y] = -aux[x%(N/2)][y%(N/2)] else: ret[x][y] = aux[x%(N/2)][y%(N/2)] return ret
Esta função gera a matriz de forma recursiva tendo como base de entrada seu tamanho.
Para a implementação da transformada de Hadamard é necessário a implementação de uma função que calcule o j-ézimo bit de um valor fornecido, feito por:
def calculaB(i,z): resp = 0 a = z b = 2 for j in range(i+1): if a >= b: resp = a%b a = int(a/b) else: return a return resp
onde:
- i: é o j-ézimo bit; e,
- z: é o valor que será transformado em binário.
Assim fica possível definir a função que calcula a transformada com base nas funções auxiliares acima e as fórmulas citadas acima:
def Hadamard(f): if f.shape[0] != f.shape[1]: if f.shape[0] < f.shape[1]: f = f[0:f.shape[0]][0:f.shape[0]] else: f = f[0:f.shape[1]][0:f.shape[1]] N = f.shape[0] H = zeros((N,N)) for u in range(N): for v in range(N): soma = 0.0 for x in range(N): for y in range(N): somaExp = 0.0 for i in range(log2(N)): somaExp = somaExp + (calculaB(i,x)*calculaB(i,u) + calculaB(i,y)*calculaB(i,v)) soma = soma + f[x][y]*(pow(-1,somaExp)) H[u][v] = soma return H
Aplicação[]
As aplicações são inúmeras especialmente as voltadas para o processamento de sinais digitais, entre eles o som. Para esta pesquisa não foram encontradas aplicações voltadas diretamente ao processamento de imagens, exceto para compactação de images. Entretanto é interessante mostrar os resultados obtidos após a aplicação desta transformada.
Resultados[]
Toma-se como exemplo a seguinte imagem:
Após a aplicação da transformada, conforme citado acima, a imagem resultante fica:
Entretanto, para melhor visualização é feita a normalização logarítmica, obtendo, finalmente, a seguinte imagem:
Conclusões[]
A transformada de Hadamard se mostrou como uma ótima opção para ser aplicada como transformada (inclusive como possível substituta da transformada de Fourier). Sua simplicidade torna-a de fácil implementação inclusive em sistemas embarcados, uma vez que utiliza formulamentos matemáticos simples, como adição e multiplicação de valores. Entretanto, seu nível computacional avançado (excesso de for's) foi um dos grandes fatores que dificultaram a implementação desta em linguagens iunterpretadas, como o Python.
Referências[]
Coloque todas as referências citadas no texto...
[1] Guia de edição/formatação
[2] GONZALES, R. C., WOODS, R. E. Processamento de Imagens Digitais, Edgard Blücher, São Paulo SP.
[3] Transformadas (Núcleo de Processamento Digitial de Imagens)
[4] Hadamard Transform
Anexo[]
from ia636 import * from Numeric import * def geraMatrizHadamard(N): ret = ones((N,N)) if N == 2: ret[0][0] = 1 ret[0][1] = 1 ret[1][0] = 1 ret[1][1] = -1 return ret aux = geraMatrizHadamard(N/2) dx = 0 dy = 0 for x in range(N): for y in range(N): if x >= N-N/2 and y >= N-N/2: ret[x][y] = -aux[x%(N/2)][y%(N/2)] else: ret[x][y] = aux[x%(N/2)][y%(N/2)] return ret def numeroBits(z): resp = 1 a = z b = 2 while(1): if a >= b: resp = resp+1 a = int(a/b) else: return resp return resp def calculaB(i,z): resp = 0 a = z b = 2 for j in range(i+1): if a >= b: resp = a%b a = int(a/b) else: return a return resp def log2(x): valor = x soma = 0 while 1 != valor: valor = valor / 2.0 soma = soma + 1 return soma def Hadamard(f): if f.shape[0] != f.shape[1]: if f.shape[0] < f.shape[1]: f = f[0:f.shape[0]][0:f.shape[0]] else: f = f[0:f.shape[1]][0:f.shape[1]] N = f.shape[0] H = zeros((N,N)) for u in range(N): for v in range(N): soma = 0.0 for x in range(N): for y in range(N): somaExp = 0.0 for i in range(log2(N)): somaExp = somaExp + (calculaB(i,x)*calculaB(i,u) + calculaB(i,y)*calculaB(i,v)) soma = soma + f[x][y]*(pow(-1,somaExp)) H[u][v] = soma return H