UNPKG

2.9 kBJavaScriptView Raw
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/* eslint-env node */
25
26function Ssim() {}
27
28Ssim.prototype = {
29 // Implementation of Eq.2, a simple average of a vector and Eq.4., except the
30 // square root. The latter is actually an unbiased estimate of the variance,
31 // not the exact variance.
32 statistics: function(a) {
33 var accu = 0;
34 var i;
35 for (i = 0; i < a.length; ++i) {
36 accu += a[i];
37 }
38 var meanA = accu / (a.length - 1);
39 var diff = 0;
40 for (i = 1; i < a.length; ++i) {
41 diff = a[i - 1] - meanA;
42 accu += a[i] + (diff * diff);
43 }
44 return {mean: meanA, variance: accu / a.length};
45 },
46
47 // Implementation of Eq.11., cov(Y, Z) = E((Y - uY), (Z - uZ)).
48 covariance: function(a, b, meanA, meanB) {
49 var accu = 0;
50 for (var i = 0; i < a.length; i += 1) {
51 accu += (a[i] - meanA) * (b[i] - meanB);
52 }
53 return accu / a.length;
54 },
55
56 calculate: function(x, y) {
57 if (x.length !== y.length) {
58 return 0;
59 }
60
61 // Values of the constants come from the Matlab code referred before.
62 var K1 = 0.01;
63 var K2 = 0.03;
64 var L = 255;
65 var C1 = (K1 * L) * (K1 * L);
66 var C2 = (K2 * L) * (K2 * L);
67 var C3 = C2 / 2;
68
69 var statsX = this.statistics(x);
70 var muX = statsX.mean;
71 var sigmaX2 = statsX.variance;
72 var sigmaX = Math.sqrt(sigmaX2);
73 var statsY = this.statistics(y);
74 var muY = statsY.mean;
75 var sigmaY2 = statsY.variance;
76 var sigmaY = Math.sqrt(sigmaY2);
77 var sigmaXy = this.covariance(x, y, muX, muY);
78
79 // Implementation of Eq.6.
80 var luminance = (2 * muX * muY + C1) /
81 ((muX * muX) + (muY * muY) + C1);
82 // Implementation of Eq.10.
83 var structure = (sigmaXy + C3) / (sigmaX * sigmaY + C3);
84 // Implementation of Eq.9.
85 var contrast = (2 * sigmaX * sigmaY + C2) / (sigmaX2 + sigmaY2 + C2);
86
87 // Implementation of Eq.12.
88 return luminance * contrast * structure;
89 }
90};
91
92module.exports = Ssim;