spatial_vision_processing/
spatial_vision_processing.rs1use embedded_dsp::*;
13
14fn print_matrix_8x8(label: &str, mat: &[f32; 64]) {
15 println!(" {}:", label);
16 for r in 0..8 {
17 print!(" [");
18 for c in 0..8 {
19 print!("{:>5.1} ", mat[r * 8 + c]);
20 }
21 println!("]");
22 }
23}
24
25fn main() {
26 println!("===============================================================================");
27 println!(" embedded-dsp 2D Spatial Processing & Embedded Vision ");
28 println!("===============================================================================");
29 println!();
30
31 println!("--- 1. Synthetic 8x8 Image Matrix with Feature & Noise ---");
35 let mut raw_image = [0.0f32; 64];
36
37 for r in 2..6 {
39 for c in 2..6 {
40 raw_image[r * 8 + c] = 20.0;
41 }
42 }
43
44 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);
51
52 println!("\n--- 2. 2D Spatial Convolution (Smoothing & Sharpening) ---");
56 let gaussian_kernel: [f32; 9] = [1.0, 2.0, 1.0, 2.0, 4.0, 2.0, 1.0, 2.0, 1.0];
58 let mut blurred_image = [0.0f32; 64];
59 let status = convolve2d_f32(
60 &raw_image,
61 &mut blurred_image,
62 8,
63 8,
64 &gaussian_kernel,
65 3,
66 3,
67 true,
68 );
69 println!(" Gaussian 3x3 Convolution Status: {:?}", status);
70 print_matrix_8x8("Gaussian Filtered Image (Smoothed)", &blurred_image);
71
72 let sharpen_kernel: [f32; 9] = [0.0, -1.0, 0.0, -1.0, 5.0, -1.0, 0.0, -1.0, 0.0];
74 let mut sharpened_image = [0.0f32; 64];
75 convolve2d_f32(
76 &blurred_image,
77 &mut sharpened_image,
78 8,
79 8,
80 &sharpen_kernel,
81 3,
82 3,
83 false,
84 );
85 print_matrix_8x8("Sharpened Image", &sharpened_image);
86
87 println!("\n--- 3. Non-Linear 2D Filtering (Despeckling & Morphological Filters) ---");
91 let mut median_cleaned = [0.0f32; 64];
92 let mut min_filtered = [0.0f32; 64];
93 let mut max_filtered = [0.0f32; 64];
94
95 nonlin2d_filter_f32(
97 &raw_image,
98 &mut median_cleaned,
99 8,
100 8,
101 3,
102 NonlinFilterType::Median,
103 );
104 print_matrix_8x8("3x3 Median Filtered Image (Noise Removed)", &median_cleaned);
105
106 nonlin2d_filter_f32(
108 &median_cleaned,
109 &mut min_filtered,
110 8,
111 8,
112 3,
113 NonlinFilterType::Min,
114 );
115 nonlin2d_filter_f32(
116 &median_cleaned,
117 &mut max_filtered,
118 8,
119 8,
120 3,
121 NonlinFilterType::Max,
122 );
123 println!(" Morphological Erosion (Min) & Dilation (Max) computed successfully.");
124
125 println!("\n--- 4. 2D Sobel Edge Detection (Horizontal + Vertical Gradients) ---");
129 let mut edges = [0.0f32; 64];
130 sobel_edge_detection_f32(&median_cleaned, &mut edges, 8, 8, 15.0);
132 print_matrix_8x8(
133 "Sobel Binary Edge Map (1.0 = Edge, 0.0 = Background)",
134 &edges,
135 );
136
137 println!("\n--- 5. 2D Discrete Cosine Transform (DCT-II) & Inverse DCT-II ---");
141 let mut dct_coeffs = [0.0f32; 64];
142 let mut reconstructed_image = [0.0f32; 64];
143
144 dct2d_f32(&median_cleaned, &mut dct_coeffs, 8, 8);
145 println!(
146 " 2D DCT DC Coefficient (Top-Left Energy) = {:.2}",
147 dct_coeffs[0]
148 );
149 println!(" Top 2x2 Low-Frequency DCT Coefficients:");
150 println!(" [{:>7.2}, {:>7.2}]", dct_coeffs[0], dct_coeffs[1]);
151 println!(" [{:>7.2}, {:>7.2}]", dct_coeffs[8], dct_coeffs[9]);
152
153 idct2d_f32(&dct_coeffs, &mut reconstructed_image, 8, 8);
155 let mut recon_diff = 0.0f32;
156 for i in 0..64 {
157 recon_diff += (reconstructed_image[i] - median_cleaned[i]).abs();
158 }
159 println!(
160 " 2D IDCT Exact Reconstruction Absolute Error Sum: {:.2e}",
161 recon_diff
162 );
163
164 println!("\n--- 6. Image Metrics: 2D Histogram, MSE, and PSNR ---");
168 let mut hist_bins = [0usize; 5]; histogram_2d_f32(&raw_image, &mut hist_bins, 0.0, 50.0);
170 println!(
171 " 2D Image Intensity Histogram (5 bins across 0..50): {:?}",
172 hist_bins
173 );
174
175 let mse = mse_2d_f32(&raw_image, &median_cleaned);
176 let psnr = psnr_2d_f32(&raw_image, &median_cleaned, 50.0);
177 println!(" Raw Noisy vs Median Cleaned Image:");
178 println!(" • Mean Squared Error (MSE) : {:.2}", mse);
179 println!(" • Peak Signal-to-Noise Ratio (PSNR): {:.2} dB", psnr);
180
181 println!("\n--- 7. Q16.16 Fixed-Point Scanline Interpolation (MCU Graphics / Rasterizer) ---");
185 let span = 10;
187 let left_z = to_q16(1.0) as u32;
190 let right_z = to_q16(5.0) as u32;
191 let left_u = to_q16(0.0) as u32;
192 let right_u = to_q16(1.0) as u32;
193 let left_v = to_q16(0.0) as u32;
194 let right_v = to_q16(1.0) as u32;
195
196 let mut scanline = ScanlineInterp::new(left_z, right_z, left_u, right_u, left_v, right_v, span);
197
198 println!(" Interpolating 10 Pixels Across Fixed-Point Scanline (Q16.16):");
199 println!(
200 " {:<5} {:<12} {:<12} {:<12}",
201 "Pixel", "Depth (z)", "Texcoord (u)", "Texcoord (v)"
202 );
203 println!(" --------------------------------------------------");
204
205 for px in 0..=span {
206 let z_val = from_q16(scanline.z() as i32);
207 let u_val = from_q16(scanline.u() as i32);
208 let v_val = from_q16(scanline.v() as i32);
209
210 if px == 0 || px == 5 || px == span {
211 println!(
212 " {:<5} {:<12.3} {:<12.3} {:<12.3}",
213 px, z_val, u_val, v_val
214 );
215 }
216 scanline.step();
217 }
218
219 let a_q16 = to_q16(3.5);
221 let b_q16 = to_q16(2.0);
222 let prod_q16 = mul_q16(a_q16, b_q16);
223 let div_res_q16 = div_q16(a_q16, b_q16);
224 let lerp_res_q16 = lerp_q16(a_q16, b_q16, 5, 10);
225
226 println!("\n Q16.16 Arithmetic Verification:");
227 println!(
228 " • mul_q16(3.5, 2.0) = {:.3} (expected 7.000)",
229 from_q16(prod_q16)
230 );
231 println!(
232 " • div_q16(3.5, 2.0) = {:.3} (expected 1.750)",
233 from_q16(div_res_q16)
234 );
235 println!(
236 " • lerp_q16(3.5, 2.0) = {:.3} (expected 2.750)",
237 from_q16(lerp_res_q16)
238 );
239
240 println!();
241 println!("===============================================================================");
242 println!(" 2D Spatial & Vision Pipeline Execution Complete! ");
243 println!("===============================================================================");
244}