From 4447402fdded7c8979adde9242bf87e09aaf1d37 Mon Sep 17 00:00:00 2001 From: zvezdochiot Date: Mon, 9 Jan 2023 02:37:55 +0300 Subject: [PATCH] 0.2.7: ssim and vifp1 --- README.md | 31 +-- man/man1/stbimmetrics.1 | 10 +- src/dependencies.c | 6 +- src/metricsnhw.h | 4 +- src/metricspsnr.h | 4 +- src/metricsum.h | 4 +- src/smallfry.h | 4 +- src/ssim.h | 407 ++++++++++++++++++++++++++++++++++++++++ src/stbimmetrics.c | 37 ++-- src/ycbcr.h | 4 +- 10 files changed, 472 insertions(+), 39 deletions(-) create mode 100644 src/ssim.h diff --git a/README.md b/README.md index 8154f4d..d9d611a 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ Includes metrics: - MSE / MAX^2, MAX = 255 - PSNR +- [SSIM](https://github.com/rolinh/VQMT) +- [VIFP1](https://github.com/rolinh/VQMT) - [SMALLFRY](https://github.com/dwbuiten/smallfry) - [SHARPENBAD](https://github.com/ImageProcessing-ElectronicPublications/libsmallfry) - [Correlation](https://github.com/ImageProcessing-ElectronicPublications/libsmallfry) @@ -15,13 +17,15 @@ Includes metrics: The value of MSE metrics is from 0.0 (minimum difference) to 1.0 (maximum difference). -The value of PSNR metrics is from 1.0 (maximum difference) to inf. +The value of PSNR metrics is from 0.0 (maximum difference) to inf. -The value of SHARPENBAD metrics is from 1.0 (minimum difference) to -1.0 (maximum difference). +The value of [SSIM](https://github.com/rolinh/VQMT) and [VIFP1](https://github.com/rolinh/VQMT) metrics is from 1.0 (minimum difference) to 0.0 (maximum difference). -The value of Correlation metrics is from 1.0 (minimum difference) to 0.0 (maximum difference). +The value of [SHARPENBAD](https://github.com/ImageProcessing-ElectronicPublications/libsmallfry) metrics is from 1.0 (minimum difference) to -1.0 (maximum difference). -The value of NHW metrics is from 0.0 (minimum difference) to 1.0 (maximum difference) ([origin project code](https://github.com/rcanut/NHW_Neatness_Metrics/issues/1)). +The value of [Correlation](https://github.com/ImageProcessing-ElectronicPublications/libsmallfry) metrics is from 1.0 (minimum difference) to 0.0 (maximum difference). + +The value of [NHW metrics](https://github.com/rcanut/NHW_Neatness_Metrics/issues/1) is from 0.0 (minimum difference) to 1.0 (maximum difference). ## build @@ -69,6 +73,7 @@ stbnhwmetrics ${IMAGE_ORIG_PATH} ${IMAGE_COMPARE_PATH} [metric.out.png] - `metricspsnr.h` - metrics PSNR and MSE - `metricsum.h` - ["Universal Scale" of metrics (UM)](https://github.com/ImageProcessing-ElectronicPublications/jpeg-recompress) - `smallfry.h` - metrics [SMALLFRY, SHARPENBAD and Correlation](https://github.com/ImageProcessing-ElectronicPublications/libsmallfry) +- `ssim.h` - metrics [SSIM and VIFP1](https://github.com/rolinh/VQMT) - `stb/` - [stb](https://github.com/nothings/stb.git) - `stbimmetrics.c` - CLI program. - `ycbcr.h` - [YCbCr color space](https://en.wikipedia.org/wiki/YCbCr). @@ -128,14 +133,16 @@ Save png: lena.quant444.psnr.png ``` -* ![metric](https://raw.githubusercontent.com/ImageProcessing-ElectronicPublications/stb-image-metrics-demo/main/images/lena.quant444.mse.png) MSE: 0.013604, UM: -1.218735 -* ![metric](https://raw.githubusercontent.com/ImageProcessing-ElectronicPublications/stb-image-metrics-demo/main/images/lena.quant444.psnr.png) PSNR: 18.663233, UM: -1.317894 -* ![metric](https://raw.githubusercontent.com/ImageProcessing-ElectronicPublications/stb-image-metrics-demo/main/images/lena.quant444.smallfry.png) SMALLFRY: 83.753342, UM -0.653625 -* ![metric](https://raw.githubusercontent.com/ImageProcessing-ElectronicPublications/stb-image-metrics-demo/main/images/lena.quant444.shbad.png) SHARPENBAD: -0.213132, UM: -0.575435 -* ![metric](https://raw.githubusercontent.com/ImageProcessing-ElectronicPublications/stb-image-metrics-demo/main/images/lena.quant444.cor.png) Corelation: 0.953666, UM: -0.644979 -* ![metric](https://raw.githubusercontent.com/ImageProcessing-ElectronicPublications/stb-image-metrics-demo/main/images/lena.quant444.nhw-n.png) NHW-N: 0.072673, UM: 0.144120 -* ![metric](https://raw.githubusercontent.com/ImageProcessing-ElectronicPublications/stb-image-metrics-demo/main/images/lena.quant444.nhw-c.png) NHW-C: 0.145290, UM: -0.042954 -* ![metric](https://raw.githubusercontent.com/ImageProcessing-ElectronicPublications/stb-image-metrics-demo/main/images/lena.quant444.nhw-r.png) NHW-R: 0.116387, UM: -0.109872 +* ![metric](https://raw.githubusercontent.com/ImageProcessing-ElectronicPublications/stb-image-metrics-demo/main/images/lena.quant444.mse.png) MSE: 0.013604 +* ![metric](https://raw.githubusercontent.com/ImageProcessing-ElectronicPublications/stb-image-metrics-demo/main/images/lena.quant444.psnr.png) PSNR: 18.663233 +* ![metric](https://raw.githubusercontent.com/ImageProcessing-ElectronicPublications/stb-image-metrics-demo/main/images/lena.quant444.ssim.png) SSIM: 0.618509, UM: -0.239359 +* ![metric](https://raw.githubusercontent.com/ImageProcessing-ElectronicPublications/stb-image-metrics-demo/main/images/lena.quant444.vifp1.png) VIFP1: 0.806863, UM: - +* ![metric](https://raw.githubusercontent.com/ImageProcessing-ElectronicPublications/stb-image-metrics-demo/main/images/lena.quant444.smallfry.png) SMALLFRY: 83.753342 +* ![metric](https://raw.githubusercontent.com/ImageProcessing-ElectronicPublications/stb-image-metrics-demo/main/images/lena.quant444.shbad.png) SHARPENBAD: -0.213132 +* ![metric](https://raw.githubusercontent.com/ImageProcessing-ElectronicPublications/stb-image-metrics-demo/main/images/lena.quant444.cor.png) Corelation: 0.953666 +* ![metric](https://raw.githubusercontent.com/ImageProcessing-ElectronicPublications/stb-image-metrics-demo/main/images/lena.quant444.nhw-n.png) NHW-N: 0.072673 +* ![metric](https://raw.githubusercontent.com/ImageProcessing-ElectronicPublications/stb-image-metrics-demo/main/images/lena.quant444.nhw-c.png) NHW-C: 0.145290 +* ![metric](https://raw.githubusercontent.com/ImageProcessing-ElectronicPublications/stb-image-metrics-demo/main/images/lena.quant444.nhw-r.png) NHW-R: 0.116387 --- diff --git a/man/man1/stbimmetrics.1 b/man/man1/stbimmetrics.1 index 0c037e2..4fa661f 100644 --- a/man/man1/stbimmetrics.1 +++ b/man/man1/stbimmetrics.1 @@ -1,4 +1,4 @@ -.TH "StbImMetrics" 1 0.2.5 "8 Jan 2023" "User Manual" +.TH "StbImMetrics" 1 0.2.7 "9 Jan 2023" "User Manual" .SH NAME stbimmetrics @@ -9,6 +9,8 @@ This utility compares two graphics files based on metrics. Includes metrics: - MSE / MAX^2, MAX = 255 - PSNR + - SSIM + - VIFP1 - SMALLFRY - SHARPENBAD - correlation @@ -18,7 +20,9 @@ Includes metrics: The value of MSE metrics is from 0.0 (minimum difference) to 1.0 (maximum difference). -The value of PSNR metrics is from 1.0 (maximum difference) to inf. +The value of PSNR metrics is from 0.0 (maximum difference) to inf. + +The value of SSIM and VIPF1 metrics is from 1.0 (minimum difference) to 0.0 (maximum difference). The value of SHARPENBAD metrics is from 1.0 (minimum difference) to -1.0 (maximum difference). @@ -35,6 +39,8 @@ stbimmetrics [options] ${IMAGE_ORIG_PATH} ${IMAGE_COMPARE_PATH} [metric.out.png] metric (default psnr): mse - MSE / MAX^2, MAX = 255 psnr - PSNR + ssim - SSIM + vifp1 - VIFP 1 layer smallfry - SMALLFRY shbad - SHARPENBAD cor - correlation diff --git a/src/dependencies.c b/src/dependencies.c index 18e6dee..611ce4a 100644 --- a/src/dependencies.c +++ b/src/dependencies.c @@ -3,12 +3,14 @@ #define METRICS_UM_IMPLEMENTATION #define YCBCR_IMPLEMENTATION #define METRICS_PSNR_IMPLEMENTATION -#define METRICS_NHW_IMPLEMENTATION +#define METRICS_SSIM_IMPLEMENTATION #define METRICS_SMALLFRY_IMPLEMENTATION +#define METRICS_NHW_IMPLEMENTATION #include "stb/stb_image.h" #include "stb/stb_image_write.h" #include "metricsum.h" #include "ycbcr.h" #include "metricspsnr.h" -#include "metricsnhw.h" +#include "ssim.h" #include "smallfry.h" +#include "metricsnhw.h" diff --git a/src/metricsnhw.h b/src/metricsnhw.h index b22e949..894ae4f 100644 --- a/src/metricsnhw.h +++ b/src/metricsnhw.h @@ -6,7 +6,7 @@ **************************************************************************** * Metrics NHW * * file: metricsnhw.h * -* version: 0.2.6 * +* version: 0.2.7 * * * **************************************************************************** ***************************************************************************/ @@ -18,7 +18,7 @@ #ifndef __METRICS_NHW__H #define __METRICS_NHW__H -#define METRICSNHW_VERSION "0.2.6" +#define METRICSNHW_VERSION "0.2.7" #ifdef METRICS_STATIC #define METRICSAPI static diff --git a/src/metricspsnr.h b/src/metricspsnr.h index 07adb57..2f2de6d 100644 --- a/src/metricspsnr.h +++ b/src/metricspsnr.h @@ -2,7 +2,7 @@ **************************************************************************** * Metrics PSNR * * file: metricspsnr.h * -* version: 0.2.6 * +* version: 0.2.7 * * * **************************************************************************** ***************************************************************************/ @@ -14,7 +14,7 @@ #ifndef __METRICS_PSNR__H #define __METRICS_PSNR__H -#define METRICS_PSNR_VERSION "0.2.6" +#define METRICS_PSNR_VERSION "0.2.7" #ifdef METRICS_STATIC #define METRICSAPI static diff --git a/src/metricsum.h b/src/metricsum.h index a2557ad..cc308a9 100644 --- a/src/metricsum.h +++ b/src/metricsum.h @@ -2,7 +2,7 @@ **************************************************************************** * Metrics UM * * file: metricsum.h * -* version: 0.2.6 * +* version: 0.2.7 * * * **************************************************************************** ***************************************************************************/ @@ -15,7 +15,7 @@ #ifndef __METRICS_UM__H #define __METRICS_UM__H -#define METRICS_VERSION "0.2.6" +#define METRICS_VERSION "0.2.7" #ifdef METRICS_STATIC #define METRICSAPI static diff --git a/src/smallfry.h b/src/smallfry.h index e8d5a68..1963505 100644 --- a/src/smallfry.h +++ b/src/smallfry.h @@ -18,7 +18,7 @@ **************************************************************************** * Metrics PSNR * * file: metricspsnr.h * -* version: 0.2.6 * +* version: 0.2.7 * * * **************************************************************************** ***************************************************************************/ @@ -31,7 +31,7 @@ #ifndef __METRICS_SMALLFRY__H #define __METRICS_SMALLFRY__H -#define METRICS_SMALLFRY_VERSION "0.2.6" +#define METRICS_SMALLFRY_VERSION "0.2.7" #ifdef METRICS_STATIC #define METRICSAPI static diff --git a/src/ssim.h b/src/ssim.h new file mode 100644 index 0000000..47d874b --- /dev/null +++ b/src/ssim.h @@ -0,0 +1,407 @@ +/* +https://github.com/rolinh/VQMT +*/ + +/*************************************************************************** +**************************************************************************** +* Metrics SSIM * +* file: ssim.h * +* version: 0.2.7 * +* * +**************************************************************************** +***************************************************************************/ + +#include +#include +#include +#include + +#ifndef SSIM_H_ +#define SSIM_H_ + +#define METRICS_SSIM_VERSION "0.2.7" + +#ifdef METRICS_STATIC +#define METRICSAPI static +#else +#define METRICSAPI extern +#endif + +#ifdef __cplusplus +extern "C" { +#endif +METRICSAPI float metric_ssim(unsigned char *ref, unsigned char *cmp, unsigned char* delta, int height, int width, int channels); +METRICSAPI float metric_vifp1(unsigned char *ref, unsigned char *cmp, unsigned char* delta, int height, int width, int channels); +#ifdef __cplusplus +} +#endif + +#ifdef METRICS_SSIM_IMPLEMENTATION + +static float gaussblur(float *vec, float *gaussmat, int iradius) +{ + int j; + float imc, sc; + + //gauss 1d + imc = vec[iradius - 1]; + sc = imc * gaussmat[0]; + for (j = 1; j < iradius; j++) + { + imc = vec[iradius - 1 - j]; + sc += imc * gaussmat[j]; + imc = vec[iradius - 1 + j]; + sc += imc * gaussmat[j]; + } + + return sc; +} + +METRICSAPI float metric_ssim(unsigned char *ref, unsigned char *cmp, unsigned char* delta, int height, int width, int channels) +{ + size_t k, kx[13], ky[13], kf, line, size; + int y, x, d, yf, xf; + int i, j, iradius = 7; + float imc, sc, radius = 1.5f; + float gaussmat[7], vec1[13], vec2[13]; + float sum, suml, t, tt; + float g1, g2, s1, s2, s12; + float iq1, iq2, iq12, gq1, gq2, gq12; + float t1, t2, fs, fg, ssim = 0.0f; + float C1 = 6.5025f, C2 = 58.5225f; + + line = width * channels; + size = height * line; + + //gaussmat + for (i = 0; i < iradius; i++) + { + sum = 0; + for (j = 0; j <= 50; j++) + { + t = (float)i; + t -= 0.5f; + t += 0.02f * j; + tt = -(t * t) / (2.0f * radius * radius); + sum += exp(tt); + } + gaussmat[i] = sum / 50.0f; + } + sum = gaussmat[0]; + for (i = 1; i < iradius; i++) + { + sum += 2.0f * gaussmat[i]; + } + for (i = 0; i < iradius; i++) + { + gaussmat[i] /= sum; + } + + //ssim + k = 0; + sum = 0.0f; + for (y = 0; y < height; y++) + { + ky[6] = k; + for (i = 1; i < 7; i++) + { + + ky[6 - i] = ky[6 - i + 1] - (((y - i) < 0) ? 0 : line); + ky[6 + i] = ky[6 + i - 1] + (((y + i) < height) ? line : 0); + } + suml = 0.0f; + for (x = 0; x < width; x++) + { + kx[6] = k - ky[6]; + for (j = 1; j < 7; j++) + { + + kx[6 - j] = kx[6 - j + 1] - (((x - j) < 0) ? 0 : channels); + kx[6 + j] = kx[6 + j - 1] + (((x + j) < width) ? channels : 0); + } + for (d = 0; d < channels; d++) + { + //gauss of ref = g1 + for (i = 0; i < 13; i++) + { + for (j = 0; j < 13; j++) + { + kf = ky[i] + kx[j] + d; + vec1[j] = (float)ref[kf]; + } + //gauss 1d + vec2[i] = gaussblur(vec1, gaussmat, 7); + } + //gauss 1d + g1 = gaussblur(vec2, gaussmat, 7); + //gauss of cmp = g2 + for (i = 0; i < 13; i++) + { + for (j = 0; j < 13; j++) + { + kf = ky[i] + kx[j] + d; + vec1[j] = (float)cmp[kf]; + } + //gauss 1d + vec2[i] = gaussblur(vec1, gaussmat, 7); + } + //gauss 1d + g2 = gaussblur(vec2, gaussmat, 7); + //gauss of ref*ref = s1 + for (i = 0; i < 13; i++) + { + for (j = 0; j < 13; j++) + { + kf = ky[i] + kx[j] + d; + vec1[j] = (float)ref[kf] * (float)ref[kf]; + } + //gauss 1d + vec2[i] = gaussblur(vec1, gaussmat, 7); + } + //gauss 1d + s1 = gaussblur(vec2, gaussmat, 7); + //gauss of cmp*cmp = s2 + for (i = 0; i < 13; i++) + { + for (j = 0; j < 13; j++) + { + kf = ky[i] + kx[j] + d; + vec1[j] = (float)cmp[kf]*(float)cmp[kf]; + } + //gauss 1d + vec2[i] = gaussblur(vec1, gaussmat, 7); + } + //gauss 1d + s2 = gaussblur(vec2, gaussmat, 7); + //gauss of ref*cmp = s12 + for (i = 0; i < 13; i++) + { + for (j = 0; j < 13; j++) + { + kf = ky[i] + kx[j] + d; + vec1[j] = (float)ref[kf]*(float)cmp[kf]; + } + //gauss 1d + vec2[i] = gaussblur(vec1, gaussmat, 7); + } + //gauss 1d + s12 = gaussblur(vec2, gaussmat, 7); + // ssim_map = fs * fg; + // fs = (2*s12 + C2))/(s1 + s2 + C2); + // fg = (2*gq12 + C1)/(gq1 + gq2 + C1); + iq1 = (float)ref[k] * (float)ref[k]; + iq2 = (float)cmp[k] * (float)cmp[k]; + iq12 = (float)ref[k] * (float)cmp[k]; + gq1 = g1 * g1; + gq2 = g2 * g2; + gq12 = g1 * g2; + s1 -= gq1; + s2 -= gq2; + s12 -= gq12; + t1 = 2.0f * s12 + C2; + t2 = s1 + s2 + C2; + fs = (t2 > 0.0f) ? (t1 / t2) : 1.0f; + t1 = 2.0f * gq12 + C1; + t2 = gq1 + gq2 + C1; + fg = (t2 > 0.0f) ? (t1 / t2) : 1.0f; + ssim = fs * fg; + suml += ssim; + if (delta) + { + ssim *= 255.0f; + delta[k] = (unsigned char)((ssim < 0.0f) ? 0 : (ssim < 255.0f) ? ssim : 255); + } + k++; + } + } + sum += suml; + } + sum /= (float)k; + + return sum; +} + +METRICSAPI float metric_vifp1(unsigned char *ref, unsigned char *cmp, unsigned char* delta, int height, int width, int channels) +{ + size_t k, kx[13], ky[13], kf, line, size; + int y, x, d, yf, xf; + int i, j, iradius = 7; + float imc, sc, radius = 1.5f; + float gaussmat[7], vec1[13], vec2[13]; + float sum, suml, t, tt; + float g1, g2, s1, s2, s12; + float iq1, iq2, iq12, gq1, gq2, gq12; + float g, sv, nd, dd, numl, denl, num, den, vifp1 = 0.0f;; + float eps = 1e-10f, sigma_nsq = 2.0f; + + line = width * channels; + size = height * line; + + //gaussmat + for (i = 0; i < iradius; i++) + { + sum = 0; + for (j = 0; j <= 50; j++) + { + t = (float)i; + t -= 0.5f; + t += 0.02f * j; + tt = -(t * t) / (2.0f * radius * radius); + sum += exp(tt); + } + gaussmat[i] = sum / 50.0f; + } + sum = gaussmat[0]; + for (i = 1; i < iradius; i++) + { + sum += 2.0f * gaussmat[i]; + } + for (i = 0; i < iradius; i++) + { + gaussmat[i] /= sum; + } + + //vifp1 + k = 0; + num = 0.0f; + den = 0.0f; + for (y = 0; y < height; y++) + { + ky[6] = k; + for (i = 1; i < 7; i++) + { + + ky[6 - i] = ky[6 - i + 1] - (((y - i) < 0) ? 0 : line); + ky[6 + i] = ky[6 + i - 1] + (((y + i) < height) ? line : 0); + } + numl = 0.0f; + denl = 0.0f; + for (x = 0; x < width; x++) + { + kx[6] = k - ky[6]; + for (j = 1; j < 7; j++) + { + + kx[6 - j] = kx[6 - j + 1] - (((x - j) < 0) ? 0 : channels); + kx[6 + j] = kx[6 + j - 1] + (((x + j) < width) ? channels : 0); + } + for (d = 0; d < channels; d++) + { + //gauss of ref = g1 + for (i = 0; i < 13; i++) + { + for (j = 0; j < 13; j++) + { + kf = ky[i] + kx[j] + d; + vec1[j] = (float)ref[kf]; + } + //gauss 1d + vec2[i] = gaussblur(vec1, gaussmat, 7); + } + //gauss 1d + g1 = gaussblur(vec2, gaussmat, 7); + //gauss of cmp = g2 + for (i = 0; i < 13; i++) + { + for (j = 0; j < 13; j++) + { + kf = ky[i] + kx[j] + d; + vec1[j] = (float)cmp[kf]; + } + //gauss 1d + vec2[i] = gaussblur(vec1, gaussmat, 7); + } + //gauss 1d + g2 = gaussblur(vec2, gaussmat, 7); + //gauss of ref*ref = s1 + for (i = 0; i < 13; i++) + { + for (j = 0; j < 13; j++) + { + kf = ky[i] + kx[j] + d; + vec1[j] = (float)ref[kf] * (float)ref[kf]; + } + //gauss 1d + vec2[i] = gaussblur(vec1, gaussmat, 7); + } + //gauss 1d + s1 = gaussblur(vec2, gaussmat, 7); + //gauss of cmp*cmp = s2 + for (i = 0; i < 13; i++) + { + for (j = 0; j < 13; j++) + { + kf = ky[i] + kx[j] + d; + vec1[j] = (float)cmp[kf]*(float)cmp[kf]; + } + //gauss 1d + vec2[i] = gaussblur(vec1, gaussmat, 7); + } + //gauss 1d + s2 = gaussblur(vec2, gaussmat, 7); + //gauss of ref*cmp = s12 + for (i = 0; i < 13; i++) + { + for (j = 0; j < 13; j++) + { + kf = ky[i] + kx[j] + d; + vec1[j] = (float)ref[kf]*(float)cmp[kf]; + } + //gauss 1d + vec2[i] = gaussblur(vec1, gaussmat, 7); + } + //gauss 1d + s12 = gaussblur(vec2, gaussmat, 7); + // ssim_map = fs * fg; + // fs = (2*s12 + C2))/(s1 + s2 + C2); + // fg = (2*gq12 + C1)/(gq1 + gq2 + C1); + iq1 = (float)ref[k] * (float)ref[k]; + iq2 = (float)cmp[k] * (float)cmp[k]; + iq12 = (float)ref[k] * (float)cmp[k]; + gq1 = g1 * g1; + gq2 = g2 * g2; + gq12 = g1 * g2; + s1 -= gq1; + s2 -= gq2; + s12 -= gq12; + //prefilter + s1 = (s1 < 0.0f) ? 0.0f : s1; + s2 = (s2 < 0.0f) ? 0.0f : s2; + g = s12 / (s1 + eps); + sv = s2 - g * s12; + g = (s1 < eps) ? 0.0f : g; + sv = (s1 < eps) ? s2 : sv; + s1 = (s1 < eps) ? 0.0f : s1; + g = (s2 < eps) ? 0.0f : g; + sv = (s2 < eps) ? 0.0f : sv; + sv = (g < 0.0f) ? 0.0f : g; + g = (g < 0.0f) ? 0.0f : g; + sv = (sv < eps) ? eps : sv; + //vifp1 + // num=num+sum(sum(log10(1+g.^2.*s1./(sv+sigma_nsq)))); + nd = log10(1.0f + g * g * s1 /(sv + sigma_nsq)) / log(10.0f); + numl += nd; + // den=den+sum(sum(log10(1+s1./sigma_nsq))); + dd = log10(1.0f + s1 / sigma_nsq) / log(10.0f); + denl += dd; + if (delta) + { + vifp1 = (dd > 0.0f) ? (nd / dd) : 1.0f; + vifp1 *= 255.0f; + delta[k] = (unsigned char)((vifp1 < 0.0f) ? 0 : (vifp1 < 255.0f) ? vifp1 : 255); + } + k++; + } + } + num += numl; + den += denl; + + } + sum = (den > 0.0f) ? (num / den) : 1.0f; + + return sum; +} + +#endif /* METRICS_SSIM_IMPLEMENTATION */ + +#endif /* SSIM_H_ */ diff --git a/src/stbimmetrics.c b/src/stbimmetrics.c index fb6042f..44e354d 100644 --- a/src/stbimmetrics.c +++ b/src/stbimmetrics.c @@ -10,8 +10,9 @@ #include "metricsum.h" #include "ycbcr.h" #include "metricspsnr.h" -#include "metricsnhw.h" +#include "ssim.h" #include "smallfry.h" +#include "metricsnhw.h" void immetrics_usage(char* prog, char* metric) { @@ -21,9 +22,11 @@ void immetrics_usage(char* prog, char* metric) printf("\t-m STR\tmetric (default %s):\n", metric); printf("\t\tmse -\t MSE / MAX^2, MAX = 255\n"); printf("\t\tpsnr -\t PSNR\n"); + printf("\t\tssim -\t SSIM\n"); printf("\t\tsmallfry -\t SMALLFRY\n"); printf("\t\tshbad -\t SHARPENBAD\n"); printf("\t\tcor -\t correlation\n"); + printf("\t\tvifp1 -\t VIFP 1 layer\n"); printf("\t\tnhw-n -\t NHW neatness\n"); printf("\t\tnhw-c -\t NHW convolutional\n"); printf("\t\tnhw-r -\t NHW relative\n"); @@ -188,22 +191,14 @@ int main(int argc, char **argv) { neatness = metrics_psnr(data_orig, data_comp, data_m, height, width, channels); } - else if (strcmp(metric, "nhw-c") == 0) - { - neatness = metrics_nhw_convolutional(data_orig, data_comp, data_m, height, width, channels); - } - else if (strcmp(metric, "nhw-n") == 0) - { - neatness = metrics_nhw_neatness(data_orig, data_comp, data_m, height, width, channels); - } - else if (strcmp(metric, "nhw-r") == 0) - { - neatness = metrics_nhw_relative(data_orig, data_comp, data_m, height, width, channels); - } else if (strcmp(metric, "smallfry") == 0) { neatness = metric_smallfry(data_orig, data_comp, data_m, height, width, channels); } + else if (strcmp(metric, "ssim") == 0) + { + neatness = metric_ssim(data_orig, data_comp, data_m, height, width, channels); + } else if (strcmp(metric, "shbad") == 0) { neatness = metric_sharpenbad(data_orig, data_comp, data_m, height, width, channels); @@ -212,6 +207,22 @@ int main(int argc, char **argv) { neatness = metric_cor(data_orig, data_comp, data_m, height, width, channels); } + else if (strcmp(metric, "vifp1") == 0) + { + neatness = metric_vifp1(data_orig, data_comp, data_m, height, width, channels); + } + else if (strcmp(metric, "nhw-c") == 0) + { + neatness = metrics_nhw_convolutional(data_orig, data_comp, data_m, height, width, channels); + } + else if (strcmp(metric, "nhw-n") == 0) + { + neatness = metrics_nhw_neatness(data_orig, data_comp, data_m, height, width, channels); + } + else if (strcmp(metric, "nhw-r") == 0) + { + neatness = metrics_nhw_relative(data_orig, data_comp, data_m, height, width, channels); + } else { fprintf(stderr, "ERROR: unknow metric %s.\n", metric); diff --git a/src/ycbcr.h b/src/ycbcr.h index 307c58c..7cfdac3 100644 --- a/src/ycbcr.h +++ b/src/ycbcr.h @@ -2,7 +2,7 @@ **************************************************************************** * YCbCr Filter * * file: ycbcr.h * -* version: 0.2.6 * +* version: 0.2.7 * * * **************************************************************************** ***************************************************************************/ @@ -13,7 +13,7 @@ #ifndef __YCBCR__H #define __YCBCR__H -#define YCBCR_VERSION "0.2.6" +#define YCBCR_VERSION "0.2.7" #ifdef METRICS_STATIC #define METRICSAPI static