use embedded_dsp::*;
fn print_matrix_8x8(label: &str, mat: &[f32; 64]) {
println!(" {}:", label);
for r in 0..8 {
print!(" [");
for c in 0..8 {
print!("{:>5.1} ", mat[r * 8 + c]);
}
println!("]");
}
}
fn main() {
println!("===============================================================================");
println!(" embedded-dsp 2D Spatial Processing & Embedded Vision ");
println!("===============================================================================");
println!();
println!("--- 1. Synthetic 8x8 Image Matrix with Feature & Noise ---");
let mut raw_image = [0.0f32; 64];
for r in 2..6 {
for c in 2..6 {
raw_image[r * 8 + c] = 20.0;
}
}
raw_image[1] = 50.0; raw_image[15] = 50.0; raw_image[3 * 8 + 3] = 0.0; raw_image[6 * 8 + 2] = 50.0;
print_matrix_8x8("Raw 8x8 Sensor Image", &raw_image);
println!("\n--- 2. 2D Spatial Convolution (Smoothing & Sharpening) ---");
let gaussian_kernel: [f32; 9] = [1.0, 2.0, 1.0, 2.0, 4.0, 2.0, 1.0, 2.0, 1.0];
let mut blurred_image = [0.0f32; 64];
let status = convolve2d_f32(
&raw_image,
&mut blurred_image,
8,
8,
&gaussian_kernel,
3,
3,
true,
);
println!(" Gaussian 3x3 Convolution Status: {:?}", status);
print_matrix_8x8("Gaussian Filtered Image (Smoothed)", &blurred_image);
let sharpen_kernel: [f32; 9] = [0.0, -1.0, 0.0, -1.0, 5.0, -1.0, 0.0, -1.0, 0.0];
let mut sharpened_image = [0.0f32; 64];
convolve2d_f32(
&blurred_image,
&mut sharpened_image,
8,
8,
&sharpen_kernel,
3,
3,
false,
);
print_matrix_8x8("Sharpened Image", &sharpened_image);
println!("\n--- 3. Non-Linear 2D Filtering (Despeckling & Morphological Filters) ---");
let mut median_cleaned = [0.0f32; 64];
let mut min_filtered = [0.0f32; 64];
let mut max_filtered = [0.0f32; 64];
nonlin2d_filter_f32(
&raw_image,
&mut median_cleaned,
8,
8,
3,
NonlinFilterType::Median,
);
print_matrix_8x8("3x3 Median Filtered Image (Noise Removed)", &median_cleaned);
nonlin2d_filter_f32(
&median_cleaned,
&mut min_filtered,
8,
8,
3,
NonlinFilterType::Min,
);
nonlin2d_filter_f32(
&median_cleaned,
&mut max_filtered,
8,
8,
3,
NonlinFilterType::Max,
);
println!(" Morphological Erosion (Min) & Dilation (Max) computed successfully.");
println!("\n--- 4. 2D Sobel Edge Detection (Horizontal + Vertical Gradients) ---");
let mut edges = [0.0f32; 64];
sobel_edge_detection_f32(&median_cleaned, &mut edges, 8, 8, 15.0);
print_matrix_8x8(
"Sobel Binary Edge Map (1.0 = Edge, 0.0 = Background)",
&edges,
);
println!("\n--- 5. 2D Discrete Cosine Transform (DCT-II) & Inverse DCT-II ---");
let mut dct_coeffs = [0.0f32; 64];
let mut reconstructed_image = [0.0f32; 64];
dct2d_f32(&median_cleaned, &mut dct_coeffs, 8, 8);
println!(
" 2D DCT DC Coefficient (Top-Left Energy) = {:.2}",
dct_coeffs[0]
);
println!(" Top 2x2 Low-Frequency DCT Coefficients:");
println!(" [{:>7.2}, {:>7.2}]", dct_coeffs[0], dct_coeffs[1]);
println!(" [{:>7.2}, {:>7.2}]", dct_coeffs[8], dct_coeffs[9]);
idct2d_f32(&dct_coeffs, &mut reconstructed_image, 8, 8);
let mut recon_diff = 0.0f32;
for i in 0..64 {
recon_diff += (reconstructed_image[i] - median_cleaned[i]).abs();
}
println!(
" 2D IDCT Exact Reconstruction Absolute Error Sum: {:.2e}",
recon_diff
);
println!("\n--- 6. Image Metrics: 2D Histogram, MSE, and PSNR ---");
let mut hist_bins = [0usize; 5]; histogram_2d_f32(&raw_image, &mut hist_bins, 0.0, 50.0);
println!(
" 2D Image Intensity Histogram (5 bins across 0..50): {:?}",
hist_bins
);
let mse = mse_2d_f32(&raw_image, &median_cleaned);
let psnr = psnr_2d_f32(&raw_image, &median_cleaned, 50.0);
println!(" Raw Noisy vs Median Cleaned Image:");
println!(" • Mean Squared Error (MSE) : {:.2}", mse);
println!(" • Peak Signal-to-Noise Ratio (PSNR): {:.2} dB", psnr);
println!("\n--- 7. Q16.16 Fixed-Point Scanline Interpolation (MCU Graphics / Rasterizer) ---");
let span = 10;
let left_z = to_q16(1.0) as u32;
let right_z = to_q16(5.0) as u32;
let left_u = to_q16(0.0) as u32;
let right_u = to_q16(1.0) as u32;
let left_v = to_q16(0.0) as u32;
let right_v = to_q16(1.0) as u32;
let mut scanline = ScanlineInterp::new(left_z, right_z, left_u, right_u, left_v, right_v, span);
println!(" Interpolating 10 Pixels Across Fixed-Point Scanline (Q16.16):");
println!(
" {:<5} {:<12} {:<12} {:<12}",
"Pixel", "Depth (z)", "Texcoord (u)", "Texcoord (v)"
);
println!(" --------------------------------------------------");
for px in 0..=span {
let z_val = from_q16(scanline.z() as i32);
let u_val = from_q16(scanline.u() as i32);
let v_val = from_q16(scanline.v() as i32);
if px == 0 || px == 5 || px == span {
println!(
" {:<5} {:<12.3} {:<12.3} {:<12.3}",
px, z_val, u_val, v_val
);
}
scanline.step();
}
let a_q16 = to_q16(3.5);
let b_q16 = to_q16(2.0);
let prod_q16 = mul_q16(a_q16, b_q16);
let div_res_q16 = div_q16(a_q16, b_q16);
let lerp_res_q16 = lerp_q16(a_q16, b_q16, 5, 10);
println!("\n Q16.16 Arithmetic Verification:");
println!(
" • mul_q16(3.5, 2.0) = {:.3} (expected 7.000)",
from_q16(prod_q16)
);
println!(
" • div_q16(3.5, 2.0) = {:.3} (expected 1.750)",
from_q16(div_res_q16)
);
println!(
" • lerp_q16(3.5, 2.0) = {:.3} (expected 2.750)",
from_q16(lerp_res_q16)
);
println!();
println!("===============================================================================");
println!(" 2D Spatial & Vision Pipeline Execution Complete! ");
println!("===============================================================================");
}