diff --git a/Base/include/Image.h b/Base/include/Image.h index cd81d9b..2550481 100644 --- a/Base/include/Image.h +++ b/Base/include/Image.h @@ -106,7 +106,7 @@ namespace FasTC { } double ComputePSNR(Image *other); - double ComputeMSSIM(Image *other); + double ComputeSSIM(Image *other, double *mssim = 0); // Function to allow derived classes to populate the pixel array. // This may involve decompressing a compressed image or otherwise diff --git a/Base/src/Image.cpp b/Base/src/Image.cpp index de8f2ac..07c6a9f 100644 --- a/Base/src/Image.cpp +++ b/Base/src/Image.cpp @@ -238,7 +238,7 @@ static Image FilterValid(const Image &img, uint32 size, do } template -double Image::ComputeSSIM(Image *other) { +double Image::ComputeSSIM(Image *other, double *mssim) { if(!other) { return -1.0; } @@ -361,7 +361,11 @@ double Image::ComputeSSIM(Image *other) { } } - double mssim = 0.0; + double minSSIM = 1.0; + if(mssim) { + *mssim = 0.0; + } + for(uint32 j = 0; j < h; j++) { for(uint32 i = 0; i < w; i++) { double m1sq = static_cast(mu1_sq(i, j)); @@ -372,13 +376,23 @@ double Image::ComputeSSIM(Image *other) { double s2sq = static_cast(sigma2_sq(i, j)); double s1s2 = static_cast(sigma12(i, j)); - mssim += + double ssim = ((2.0 * m1m2 + C1) * (2.0 * s1s2 + C2)) / ((m1sq + m2sq + C1) * (s1sq + s2sq + C2)); + + if(mssim) { + *mssim += ssim; + } + + minSSIM = ::std::min(ssim, minSSIM); } } - return mssim / static_cast(w * h); + if(mssim) { + *mssim /= static_cast(w * h); + } + + return minSSIM; } // !FIXME! These won't work for non-RGBA8 data. diff --git a/Base/test/TestImage.cpp b/Base/test/TestImage.cpp index baf5ed1..f1c2a68 100644 --- a/Base/test/TestImage.cpp +++ b/Base/test/TestImage.cpp @@ -164,5 +164,8 @@ TEST(Image, ComputeMSSIM) { } } - EXPECT_EQ(img.ComputeMSSIM(&img), 1.0); + double MSSIM; + double SSIM = img.ComputeSSIM(&img, &MSSIM); + EXPECT_EQ(SSIM, 1.0); + EXPECT_EQ(MSSIM, 1.0); }