pub fn dct2d_f32(
src: &[f32],
dst: &mut [f32],
rows: usize,
cols: usize,
) -> StatusExpand description
Computes the 2D Discrete Cosine Transform (DCT-II) on a rows x cols image.
src and dst must have length at least rows * cols.
Examples found in repository?
examples/spatial_vision_processing.rs (line 144)
25fn main() {
26 println!("===============================================================================");
27 println!(" embedded-dsp 2D Spatial Processing & Embedded Vision ");
28 println!("===============================================================================");
29 println!();
30
31 // -----------------------------------------------------------------------------------------
32 // 1. Synthetic 8x8 Sensor Matrix with Block Feature & Salt-and-Pepper Noise
33 // -----------------------------------------------------------------------------------------
34 println!("--- 1. Synthetic 8x8 Image Matrix with Feature & Noise ---");
35 let mut raw_image = [0.0f32; 64];
36
37 // Create a 4x4 high-intensity square in the center
38 for r in 2..6 {
39 for c in 2..6 {
40 raw_image[r * 8 + c] = 20.0;
41 }
42 }
43
44 // Add salt-and-pepper impulsive noise pixels
45 raw_image[1] = 50.0; // Salt noise
46 raw_image[15] = 50.0; // Salt noise
47 raw_image[3 * 8 + 3] = 0.0; // Pepper noise inside feature
48 raw_image[6 * 8 + 2] = 50.0; // Salt noise
49
50 print_matrix_8x8("Raw 8x8 Sensor Image", &raw_image);
51
52 // -----------------------------------------------------------------------------------------
53 // 2. 2D Spatial Convolution (Gaussian Blur & Sharpening)
54 // -----------------------------------------------------------------------------------------
55 println!("\n--- 2. 2D Spatial Convolution (Smoothing & Sharpening) ---");
56 // 3x3 Gaussian Blur Kernel
57 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 // 3x3 Sharpening Kernel
73 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 // -----------------------------------------------------------------------------------------
88 // 3. Non-Linear 2D Filtering (Min, Max, Median Despeckling)
89 // -----------------------------------------------------------------------------------------
90 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 // 3x3 Median filter removes impulsive salt & pepper noise while preserving sharp boundaries
96 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 // Morphological erosion (Min) and dilation (Max)
107 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 // -----------------------------------------------------------------------------------------
126 // 4. 2D Sobel Edge Detection
127 // -----------------------------------------------------------------------------------------
128 println!("\n--- 4. 2D Sobel Edge Detection (Horizontal + Vertical Gradients) ---");
129 let mut edges = [0.0f32; 64];
130 // Threshold set to 15.0 to detect the boundaries of the central block
131 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 // -----------------------------------------------------------------------------------------
138 // 5. 2D DCT-II Transform & Energy Compaction (JPEG Block Transform)
139 // -----------------------------------------------------------------------------------------
140 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 // Reconstruct via 2D IDCT
154 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 // -----------------------------------------------------------------------------------------
165 // 6. Quantitative Image Quality Metrics (Histogram, MSE, PSNR)
166 // -----------------------------------------------------------------------------------------
167 println!("\n--- 6. Image Metrics: 2D Histogram, MSE, and PSNR ---");
168 let mut hist_bins = [0usize; 5]; // 5 bins covering range 0.0 .. 50.0
169 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 // -----------------------------------------------------------------------------------------
182 // 7. Q16.16 Fixed-Point Rasterizer & Scanline Interpolation
183 // -----------------------------------------------------------------------------------------
184 println!("\n--- 7. Q16.16 Fixed-Point Scanline Interpolation (MCU Graphics / Rasterizer) ---");
185 // Span of 10 pixels across scanline
186 let span = 10;
187 // Left endpoint: Depth z = 1.0 (Q16.16 = 65536), Texture u = 0.0, v = 0.0
188 // Right endpoint: Depth z = 5.0 (Q16.16 = 327680), Texture u = 1.0 (65536), v = 1.0 (65536)
189 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 // Fixed-Point arithmetic helpers
220 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}