Os algoritmos de processamento de sinais definidos em tempo / espaço / frequência contínuos são tipicamente implementados amostrando o sinal em uma grade discreta e convertendo integrais em somas (e derivadas em diferenças). Os filtros espaciais são implementados por convolução com um núcleo de convolução (ou seja, soma ponderada de vizinhos).
Existe um enorme conhecimento sobre a filtragem de sinais amostrados no domínio do tempo; os filtros no domínio do tempo são implementados como filtros de resposta de impulso finito , em que a amostra de saída atual é calculada como uma soma ponderada das N amostras de entrada anteriores; ou filtros de resposta a impulso infinito, em que a saída atual é uma soma ponderada das entradas e saídas anteriores . Formalmente, os filtros de tempo discretos são descritos usando a transformação z , que é o analógico de tempo discreto da transformação Laplace . A transformação bilinear mapeia uma para a outra ( c2d
e d2c
no Matlab).
Como você avaliaria as funções em pontos arbitrários?
Quando você precisa do valor de um sinal em um ponto que não esteja diretamente na sua grade de amostragem, você interpola o valor de pontos próximos. A interpolação pode ser tão simples quanto escolher a amostra mais próxima, calcular uma média ponderada das amostras mais próximas ou ajustar uma função analítica arbitrariamente complicada aos dados amostrados e avaliar essa função nas coordenadas necessárias. Interpolar em uma grade mais fina e uniforme é aumentar a amostragem . Se o seu sinal (contínuo) original não contiver detalhes (ou seja, frequências) mais finos que metade da grade de amostragem, a função contínua poderá ser perfeitamente reconstruída a partir da versão amostrada (o teorema da amostragem de Nyquist-Shannon ). Para um exemplo de como você pode interpolar em 2D, consulteinterpolação bilinear .
No Matlab, você pode usar interp1
ou interp2
para interpolar dados 2D 1D ou amostrados regularmente (respectivamente) ou griddata
para interpolar dados 2D amostrados irregularmente.
Você teria um loop for passando por cada voxel e calculando a fórmula correspondente?
Sim, exatamente.
O Matlab evita que você precise fazer isso através de loops explícitos, porque foi projetado para operar em matrizes e vetores (ou seja, matrizes multidimensionais). No Matlab, isso é chamado de "vetorização". Integrais definidas pode ser aproximada com sum
, cumsum
, trapz
, cumtrapz
, etc.
Eu li o livro "Digital Image Processing" de Gonzalez e Woods, mas ainda estou perdido. Também li sobre a série de livros de Receitas Numéricas. Essa seria a maneira correta?
Sim, receitas numéricas seria um ótimo começo. É muito prático e abrange a maioria dos métodos numéricos de que você precisará. (Você descobrirá que o Matlab já implementa tudo o que precisa, mas as Receitas numéricas fornecerão um excelente histórico.)
Eu peguei uma classe "algoritmos e estruturas de dados", mas não vejo a relação entre o material apresentado lá e a implementação de algoritmos científicos.
O material tratado nos cursos "Algoritmos e estruturas de dados" tende a se concentrar em estruturas como listas, matrizes, árvores e gráficos contendo números inteiros ou seqüências de caracteres e operações como classificação e seleção: problemas para os quais normalmente existe um único resultado correto. Quando se trata de algoritmos científicos, isso é apenas metade da história. A outra metade diz respeito a métodos para estimar números reais e funções analíticas. Você encontrará isso em um curso sobre "Métodos Numéricos" (ou "Análise Numérica"; como este- role para baixo nos slides): como estimar funções especiais, como estimar integrais e derivadas, etc. Aqui uma das principais tarefas é estimar a precisão do seu resultado, e um padrão comum é repetir uma rotina que melhore uma estimar até que seja suficientemente preciso. (Você pode se perguntar como o Matlab sabe fazer algo tão simples quanto estimar um valor sin(x)
para alguns x
.)
Como um exemplo simples, aqui está um pequeno script que calcula uma transformação de radônio de uma imagem no Matlab. A transformação de radônio faz projeções de uma imagem sobre um conjunto de ângulos de projeção. Em vez de tentar calcular a projeção em um ângulo arbitrário, eu giro a imagem inteira usando imrotate
, para que a projeção seja sempre vertical. Em seguida, podemos fazer a projeção simplesmente usando sum
, uma vez que a sum
matriz retorna um vetor contendo a soma sobre cada coluna.
Você pode escrever o seu próprio, imrotate
se preferir, usando interp2
.
%%# Home-made Radon Tranform
%# load a density map (image).
A = phantom;
n_pixels = size(A, 1); %# image width (assume square)
%# At what rotation angles do we want to take projections?
n_thetas = 101;
thetas = linspace(0, 180, n_thetas);
result = zeros(n_thetas, n_pixels);
%# Loop over angles
for ii=1:length(thetas)
theta = thetas(ii);
rotated_image = imrotate(A, theta, 'crop');
result(ii, :) = sum(rotated_image);
end
%# display the result
imagesc(thetas, 1:n_pixels, result.');
xlabel('projection angle [degrees]');
O que antes era parte integrante da densidade ao longo de um raio é agora uma soma sobre uma coluna de uma imagem com amostragem discreta, que por sua vez foi encontrada interpolando a imagem original sobre um sistema de coordenadas transformado.