Skip to main content

dct2d_f32

Function dct2d_f32 

Source
pub fn dct2d_f32(
    src: &[f32],
    dst: &mut [f32],
    rows: usize,
    cols: usize,
) -> Status
Expand 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}