Processamento de Sinais Geoespaciais: Convolução 2D em Rust para Sensoriamento Remoto Massivo
Neste artigo, exploramos a formulação clássica de processamento de sinais digitais (DSP) estabelecida por B.P. Lathi, expandida para o domínio bidimensional espacial. A convolução discreta 2D entre um sinal \(f[m, n]\) e um kernel \(h[m, n]\) é dada por:
\[ y[m, n] = f[m, n] * h[m, n] = \sum_{j=-\infty}^{\infty} \sum_{i=-\infty}^{\infty} f[i, j] \cdot h[m - i, n - j] \]
Representação Visual
Abaixo, a demonstração da janela deslizante do kernel de convolução sobre o grid espacial.
<video controls width="100%">
<source src="../../videos/convolution.mp4" type="video/mp4">
</video>Implementação Determinística em Rust
Focando em Cache-Locality e abstração de custo zero, implementamos o kernel operando em arrays flat estáticos, evitando completamente alocações dinâmicas na heap (como Vec ou Box).
// Convolução 2D determinística (Zero-Heap Allocation)
const WIDTH: usize = 5;
const HEIGHT: usize = 5;
const K_SIZE: usize = 3;
type ImageGrid = [f64; WIDTH * HEIGHT];
type Kernel = [f64; K_SIZE * K_SIZE];
fn convolve_2d(input: &ImageGrid, kernel: &Kernel) -> ImageGrid {
let mut output = [0.0; WIDTH * HEIGHT];
let offset = (K_SIZE / 2) as isize;
for y in 0..HEIGHT as isize {
for x in 0..WIDTH as isize {
let mut sum = 0.0;
for ky in 0..K_SIZE as isize {
for kx in 0..K_SIZE as isize {
let img_y = y + ky - offset;
let img_x = x + kx - offset;
if img_y >= 0 && img_y < HEIGHT as isize && img_x >= 0 && img_x < WIDTH as isize {
let img_idx = (img_y as usize) * WIDTH + (img_x as usize);
let kernel_idx = (ky as usize) * K_SIZE + (kx as usize);
sum += input[img_idx] * kernel[kernel_idx];
}
}
}
output[(y as usize) * WIDTH + (x as usize)] = sum;
}
}
output
}
fn main() {
let image: ImageGrid = [1.0; 25]; // Exemplo flat
let edge_kernel: Kernel = [
-1.0, -1.0, -1.0,
-1.0, 8.0, -1.0,
-1.0, -1.0, -1.0,
];
let result = convolve_2d(&image, &edge_kernel);
println!("Valor central filtrado: {}", result[12]);
}Visualização do Kernel com Jupyter / Python
Para validar a intuição matemática, podemos visualizar a topologia tridimensional de um kernel (como o filtro passa-altas de borda usado acima) utilizando o ecossistema Python com Plotly. O Quarto suporta a execução nativa destas células: