/* * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. */ /* More information about these options at jshint.com/docs/options */ 'use strict'; /* This is an implementation of the algorithm for calculating the Structural * SIMilarity (SSIM) index between two images. Please refer to the article [1], * the website [2] and/or the Wikipedia article [3]. This code takes the value * of the constants C1 and C2 from the Matlab implementation in [4]. * * [1] Z. Wang, A. C. Bovik, H. R. Sheikh, and E. P. Simoncelli, "Image quality * assessment: From error measurement to structural similarity", * IEEE Transactions on Image Processing, vol. 13, no. 1, Jan. 2004. * [2] http://www.cns.nyu.edu/~lcv/ssim/ * [3] http://en.wikipedia.org/wiki/Structural_similarity * [4] http://www.cns.nyu.edu/~lcv/ssim/ssim_index.m */ function Ssim() {} Ssim.prototype = { // Implementation of Eq.2, a simple average of a vector and Eq.4., except the // square root. The latter is actually an unbiased estimate of the variance, // not the exact variance. statistics: function(a) { var accu = 0; var i; for (i = 0; i < a.length; ++i) { accu += a[i]; } var meanA = accu / (a.length - 1); var diff = 0; for (i = 1; i < a.length; ++i) { diff = a[i - 1] - meanA; accu += a[i] + (diff * diff); } return {mean : meanA, variance : accu / a.length}; }, // Implementation of Eq.11., cov(Y, Z) = E((Y - uY), (Z - uZ)). covariance: function(a, b, meanA, meanB) { var accu = 0; for (var i = 0; i < a.length; i += 1) { accu += (a[i] - meanA) * (b[i] - meanB); } return accu / a.length; }, calculate: function(x, y) { if (x.length !== y.length) { return 0; } // Values of the constants come from the Matlab code referred before. var K1 = 0.01; var K2 = 0.03; var L = 255; var C1 = (K1 * L) * (K1 * L); var C2 = (K2 * L) * (K2 * L); var C3 = C2 / 2; var statsX = this.statistics(x); var muX = statsX.mean; var sigmaX2 = statsX.variance; var sigmaX = Math.sqrt(sigmaX2); var statsY = this.statistics(y); var muY = statsY.mean; var sigmaY2 = statsY.variance; var sigmaY = Math.sqrt(sigmaY2); var sigmaXy = this.covariance(x, y, muX, muY); // Implementation of Eq.6. var luminance = (2 * muX * muY + C1) / ((muX * muX) + (muY * muY) + C1); // Implementation of Eq.10. var structure = (sigmaXy + C3) / (sigmaX * sigmaY + C3); // Implementation of Eq.9. var contrast = (2 * sigmaX * sigmaY + C2) / (sigmaX2 + sigmaY2 + C2); // Implementation of Eq.12. return luminance * contrast * structure; } };