1/* 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. 7 */ 8 9/* More information about these options at jshint.com/docs/options */ 10'use strict'; 11 12/* This is an implementation of the algorithm for calculating the Structural 13 * SIMilarity (SSIM) index between two images. Please refer to the article [1], 14 * the website [2] and/or the Wikipedia article [3]. This code takes the value 15 * of the constants C1 and C2 from the Matlab implementation in [4]. 16 * 17 * [1] Z. Wang, A. C. Bovik, H. R. Sheikh, and E. P. Simoncelli, "Image quality 18 * assessment: From error measurement to structural similarity", 19 * IEEE Transactions on Image Processing, vol. 13, no. 1, Jan. 2004. 20 * [2] http://www.cns.nyu.edu/~lcv/ssim/ 21 * [3] http://en.wikipedia.org/wiki/Structural_similarity 22 * [4] http://www.cns.nyu.edu/~lcv/ssim/ssim_index.m 23 */ 24 25function Ssim() {} 26 27Ssim.prototype = { 28 // Implementation of Eq.2, a simple average of a vector and Eq.4., except the 29 // square root. The latter is actually an unbiased estimate of the variance, 30 // not the exact variance. 31 statistics: function(a) { 32 var accu = 0; 33 var i; 34 for (i = 0; i < a.length; ++i) { 35 accu += a[i]; 36 } 37 var meanA = accu / (a.length - 1); 38 var diff = 0; 39 for (i = 1; i < a.length; ++i) { 40 diff = a[i - 1] - meanA; 41 accu += a[i] + (diff * diff); 42 } 43 return {mean : meanA, variance : accu / a.length}; 44 }, 45 46 // Implementation of Eq.11., cov(Y, Z) = E((Y - uY), (Z - uZ)). 47 covariance: function(a, b, meanA, meanB) { 48 var accu = 0; 49 for (var i = 0; i < a.length; i += 1) { 50 accu += (a[i] - meanA) * (b[i] - meanB); 51 } 52 return accu / a.length; 53 }, 54 55 calculate: function(x, y) { 56 if (x.length !== y.length) { 57 return 0; 58 } 59 60 // Values of the constants come from the Matlab code referred before. 61 var K1 = 0.01; 62 var K2 = 0.03; 63 var L = 255; 64 var C1 = (K1 * L) * (K1 * L); 65 var C2 = (K2 * L) * (K2 * L); 66 var C3 = C2 / 2; 67 68 var statsX = this.statistics(x); 69 var muX = statsX.mean; 70 var sigmaX2 = statsX.variance; 71 var sigmaX = Math.sqrt(sigmaX2); 72 var statsY = this.statistics(y); 73 var muY = statsY.mean; 74 var sigmaY2 = statsY.variance; 75 var sigmaY = Math.sqrt(sigmaY2); 76 var sigmaXy = this.covariance(x, y, muX, muY); 77 78 // Implementation of Eq.6. 79 var luminance = (2 * muX * muY + C1) / 80 ((muX * muX) + (muY * muY) + C1); 81 // Implementation of Eq.10. 82 var structure = (sigmaXy + C3) / (sigmaX * sigmaY + C3); 83 // Implementation of Eq.9. 84 var contrast = (2 * sigmaX * sigmaY + C2) / (sigmaX2 + sigmaY2 + C2); 85 86 // Implementation of Eq.12. 87 return luminance * contrast * structure; 88 } 89}; 90