float compareSsim()

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;
}