in cpp/testutils/src/comparison/Ssim.cpp [109:146]
float compareSsim(
const image::pixel::Specification& spec,
const std::vector<std::unique_ptr<image::Scanline>>& imgA,
const std::vector<std::unique_ptr<image::Scanline>>& imgB) {
const auto height = imgA.size();
SPECTRUM_ERROR_IF(height < ssimWindowSize, error::ImageTooSmall);
const auto width = imgA[0]->width();
SPECTRUM_ERROR_IF(width < ssimWindowSize, error::ImageTooSmall);
// validate images
SPECTRUM_ERROR_IF(height != imgB.size(), error::ImageSizesDontMatch);
for (int y = 0; y < height; y += 1) {
SPECTRUM_ERROR_IF(imgA[y]->width() != width, error::ImageSizesDontMatch);
SPECTRUM_ERROR_IF(imgB[y]->width() != width, error::ImageSizesDontMatch);
SPECTRUM_ERROR_IF(
imgA[y]->specification() != spec, error::ImageWrongSpecification);
SPECTRUM_ERROR_IF(
imgB[y]->specification() != spec, error::ImageWrongSpecification);
}
// the mean SSIM of all windows in the image
float meanSsim = 0.0f;
int run = 1;
// compute the mean SSIM
for (int y = 0; y <= height - ssimWindowSize; y += ssimWindowStep) {
for (int x = 0; x <= width - ssimWindowSize; x += ssimWindowStep) {
const float windowSsim = ssimWindowMean(spec, imgA, imgB, x, y);
// numerically stable mean
meanSsim = meanSsim + (windowSsim - meanSsim) / run;
run += 1;
}
}
return meanSsim;
}