Students
Advertisement

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:

Imagem Original

Após a aplicação da transformada, conforme citado acima, a imagem resultante fica:

Resultado da aplicação da transformada de Hadamard

Entretanto, para melhor visualização é feita a normalização logarítmica, obtendo, finalmente, a seguinte imagem:

Resultado da normalização por log

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
Advertisement