SSIM over the luminance channel with a single-scale 8×8 window. Not as good as MS-SSIM but fast and plenty accurate for our "did this PR move the image closer to truth" check.
(
reference: &[[f32; 3]],
candidate: &[[f32; 3]],
width: u32,
height: u32,
)
| 138 | /// Not as good as MS-SSIM but fast and plenty accurate for our |
| 139 | /// "did this PR move the image closer to truth" check. |
| 140 | fn compute_ssim_luminance( |
| 141 | reference: &[[f32; 3]], |
| 142 | candidate: &[[f32; 3]], |
| 143 | width: u32, |
| 144 | height: u32, |
| 145 | ) -> f32 { |
| 146 | const WINDOW: usize = 8; |
| 147 | // SSIM's stability constants (from the original Wang et al. paper, |
| 148 | // scaled to the 0..1 luminance range we use). |
| 149 | const K1: f32 = 0.01; |
| 150 | const K2: f32 = 0.03; |
| 151 | const L: f32 = 1.0; // dynamic range for normalized images |
| 152 | let c1 = (K1 * L) * (K1 * L); |
| 153 | let c2 = (K2 * L) * (K2 * L); |
| 154 | |
| 155 | let w = width as usize; |
| 156 | let h = height as usize; |
| 157 | if w < WINDOW || h < WINDOW { |
| 158 | return 1.0; // too small to analyze meaningfully; treat as identical |
| 159 | } |
| 160 | |
| 161 | let mut sum = 0f64; |
| 162 | let mut count = 0u64; |
| 163 | |
| 164 | // Non-overlapping 8×8 windows. Sliding windows would be more |
| 165 | // accurate but 8× slower; for regression testing the blocky |
| 166 | // version is plenty — we care about directional signal, not a |
| 167 | // perfect Wang-et-al reproduction. |
| 168 | let mut y = 0usize; |
| 169 | while y + WINDOW <= h { |
| 170 | let mut x = 0usize; |
| 171 | while x + WINDOW <= w { |
| 172 | let (mean_r, mean_c, var_r, var_c, cov) = |
| 173 | window_luminance_stats(reference, candidate, w, x, y, WINDOW); |
| 174 | let num = (2.0 * mean_r * mean_c + c1) * (2.0 * cov + c2); |
| 175 | let den = (mean_r * mean_r + mean_c * mean_c + c1) * (var_r + var_c + c2); |
| 176 | sum += (num / den) as f64; |
| 177 | count += 1; |
| 178 | x += WINDOW; |
| 179 | } |
| 180 | y += WINDOW; |
| 181 | } |
| 182 | |
| 183 | if count == 0 { |
| 184 | 1.0 |
| 185 | } else { |
| 186 | (sum / count as f64) as f32 |
| 187 | } |
| 188 | } |
| 189 | |
| 190 | /// Mean and variance of luminance in an N×N window plus the |
| 191 | /// covariance between reference and candidate. Returned as f32s. |
no test coverage detected