From 973843d8e8d640294e0fa3ffcc069ade3b24090e Mon Sep 17 00:00:00 2001 From: zvezdochiot Date: Mon, 9 Jan 2023 07:38:46 +0300 Subject: [PATCH] 0.2.8: fixed vifp1 and added mse-c and psnr-c --- README.md | 6 +- man/man1/stbimmetrics.1 | 6 +- src/metricsnhw.h | 4 +- src/metricspsnr.h | 157 +++++++++++++++++++++++++++++++++++++++- src/metricsum.h | 4 +- src/smallfry.h | 40 ++++------ src/ssim.h | 6 +- src/stbimmetrics.c | 30 +++++--- src/ycbcr.h | 4 +- 9 files changed, 208 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index d9d611a..cf9ba90 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ Includes metrics: - MSE / MAX^2, MAX = 255 - PSNR +- MSE / MAX^2 of correlation, MAX = 255 +- PSNR of correlation - [SSIM](https://github.com/rolinh/VQMT) - [VIFP1](https://github.com/rolinh/VQMT) - [SMALLFRY](https://github.com/dwbuiten/smallfry) @@ -135,8 +137,10 @@ 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 * ![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.mse-c.png) MSE-C: 0.006495, UM: - +* ![metric](https://raw.githubusercontent.com/ImageProcessing-ElectronicPublications/stb-image-metrics-demo/main/images/lena.quant444.psnr-c.png) PSNR-C: 21.873943, UM: - * ![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.vifp1.png) VIFP1: 0.170903, 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 diff --git a/man/man1/stbimmetrics.1 b/man/man1/stbimmetrics.1 index 4fa661f..47ed045 100644 --- a/man/man1/stbimmetrics.1 +++ b/man/man1/stbimmetrics.1 @@ -1,4 +1,4 @@ -.TH "StbImMetrics" 1 0.2.7 "9 Jan 2023" "User Manual" +.TH "StbImMetrics" 1 0.2.8 "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 + - MSE / MAX^2 of correlation, MAX = 255 + - PSNR of correlation - SSIM - VIFP1 - SMALLFRY @@ -39,6 +41,8 @@ stbimmetrics [options] ${IMAGE_ORIG_PATH} ${IMAGE_COMPARE_PATH} [metric.out.png] metric (default psnr): mse - MSE / MAX^2, MAX = 255 psnr - PSNR + mse-c - MSE / MAX^2 of correlation, MAX = 255 + psnr-c - PSNR of correlation ssim - SSIM vifp1 - VIFP 1 layer smallfry - SMALLFRY diff --git a/src/metricsnhw.h b/src/metricsnhw.h index 894ae4f..036ffb8 100644 --- a/src/metricsnhw.h +++ b/src/metricsnhw.h @@ -6,7 +6,7 @@ **************************************************************************** * Metrics NHW * * file: metricsnhw.h * -* version: 0.2.7 * +* version: 0.2.8 * * * **************************************************************************** ***************************************************************************/ @@ -18,7 +18,7 @@ #ifndef __METRICS_NHW__H #define __METRICS_NHW__H -#define METRICSNHW_VERSION "0.2.7" +#define METRICSNHW_VERSION "0.2.8" #ifdef METRICS_STATIC #define METRICSAPI static diff --git a/src/metricspsnr.h b/src/metricspsnr.h index 2f2de6d..0785f12 100644 --- a/src/metricspsnr.h +++ b/src/metricspsnr.h @@ -2,7 +2,7 @@ **************************************************************************** * Metrics PSNR * * file: metricspsnr.h * -* version: 0.2.7 * +* version: 0.2.8 * * * **************************************************************************** ***************************************************************************/ @@ -14,7 +14,7 @@ #ifndef __METRICS_PSNR__H #define __METRICS_PSNR__H -#define METRICS_PSNR_VERSION "0.2.7" +#define METRICS_PSNR_VERSION "0.2.8" #ifdef METRICS_STATIC #define METRICSAPI static @@ -27,6 +27,8 @@ extern "C" { #endif METRICSAPI float metrics_mse(unsigned char *ref, unsigned char *cmp, unsigned char* delta, int height, int width, int channels); METRICSAPI float metrics_psnr(unsigned char *ref, unsigned char *cmp, unsigned char* delta, int height, int width, int channels); +METRICSAPI float metrics_mse_cor(unsigned char *ref, unsigned char *cmp, unsigned char* delta, int height, int width, int channels); +METRICSAPI float metrics_psnr_cor(unsigned char *ref, unsigned char *cmp, unsigned char* delta, int height, int width, int channels); #ifdef __cplusplus } #endif @@ -101,6 +103,157 @@ METRICSAPI float metrics_psnr(unsigned char *ref, unsigned char *cmp, unsigned c return psnr; } +METRICSAPI float metrics_mse_cor(unsigned char *ref, unsigned char *cmp, unsigned char* delta, int height, int width, int channels) +{ + float im1, im2; + float sum1, sum2, sum1l, sum2l, suml, sum, error; + float sum12, sumq1, sumq2, q12, sum12l, sumq1l, sumq2l, sumq, cor; + int y, x, d; + size_t k, n; + + n = width * height; + + k = 0; + sum1 = 0.0f; + sum2 = 0.0f; + for (y = 0; y < height; y++) + { + sum1l = 0.0f; + sum2l = 0.0f; + for (x = 0; x < width; x++) + { + for (d = 0; d < channels; d++) + { + im1 = (float)ref[k]; + im2 = (float)cmp[k]; + sum1l += im1; + sum2l += im2; + k++; + } + } + sum1 += sum1l; + sum2 += sum2l; + } + sum1 /= (float)k; + sum2 /= (float)k; + + k = 0; + sum12 = 0.0f; + sumq1 = 0.0f; + sumq2 = 0.0f; + for (y = 0; y < height; y++) + { + sum12l = 0.0f; + sumq1l = 0.0f; + sumq2l = 0.0f; + for (x = 0; x < width; x++) + { + for (d = 0; d < channels; d++) + { + im1 = (float)ref[k]; + im1 -= sum1; + im2 = (float)cmp[k]; + im2 -= sum2; + q12 = (im1 * im2); + sum12l += q12; + sumq1l += (im1 * im1); + sumq2l += (im2 * im2); + k++; + } + } + sum12 += sum12l; + sumq1 += sumq1l; + sumq2 += sumq2l; + } + sumq = sqrt(sumq1 * sumq2); + if (sumq > 0.0f) + { + cor = sum12 / sumq; + } else { + cor = (sumq1 == sumq2) ? 1.0f : 0.0f; + } + cor = (cor < 0.0f) ? -cor : cor; + sumq1 /= k; + sumq2 /= k; + sumq1 = sqrt(sumq1); + sumq2 = sqrt(sumq2); + q12 = (sumq1 + sumq2); + if (q12 > 0.0f) + { + sumq1 *= (2.0f / q12); + sumq2 *= (2.0f / q12); + } + else + { + sumq1 = 1.0f; + sumq2 = 1.0f; + } + k = 0; + sum = 0.0f; + for (y = 0; y < height; y++) + { + suml = 0.0f; + for (x = 0; x < width; x++) + { + for (d = 0; d < channels; d++) + { + im1 = (float)ref[k]; + im1 -= sum1; + im1 *= sumq2; + im2 = (float)cmp[k]; + im2 -= sum2; + im2 *= sumq1; + error = (im1 > im2) ? (im1 - im2) : (im2 - im1); + suml += error * error; + if (delta) delta[k] = (unsigned char)error; + k++; + } + } + sum += suml; + } + sum /= (float)height; + sum /= (float)width; + sum /= (float)channels; + sum /= 255.0f; + sum /= 255.0f; + + return sum; +} + +METRICSAPI float metrics_psnr_cor(unsigned char *ref, unsigned char *cmp, unsigned char* delta, int height, int width, int channels) +{ + int y, x, d; + size_t k; + float mse, psnr, t, sum1, sum2, sum1l, sum2l; + + mse = metrics_mse_cor(ref, cmp, delta, height, width, channels); + psnr = 10.0f * log10( 1.0f / mse); + + if (delta) + { + k = 0; + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + for (d = 0; d < channels; d++) + { + t = (float)delta[k]; + t /= 255.0f; + t *= t; + t += mse; + t *= 0.5f; + t = (t > 0.0f) ? (10.0f * log10( 1.0f / t)) : 255.0f; + delta[k] = (unsigned char)((t < 255.0f) ? t : 255); + k++; + } + } + } + } + + return psnr; +} + #endif /* METRICS_PSNR_IMPLEMENTATION */ #endif // __METRICS_PSNR__H diff --git a/src/metricsum.h b/src/metricsum.h index cc308a9..5448252 100644 --- a/src/metricsum.h +++ b/src/metricsum.h @@ -2,7 +2,7 @@ **************************************************************************** * Metrics UM * * file: metricsum.h * -* version: 0.2.7 * +* version: 0.2.8 * * * **************************************************************************** ***************************************************************************/ @@ -15,7 +15,7 @@ #ifndef __METRICS_UM__H #define __METRICS_UM__H -#define METRICS_VERSION "0.2.7" +#define METRICS_VERSION "0.2.8" #ifdef METRICS_STATIC #define METRICSAPI static diff --git a/src/smallfry.h b/src/smallfry.h index 1963505..e053ea0 100644 --- a/src/smallfry.h +++ b/src/smallfry.h @@ -18,7 +18,7 @@ **************************************************************************** * Metrics PSNR * * file: metricspsnr.h * -* version: 0.2.7 * +* version: 0.2.8 * * * **************************************************************************** ***************************************************************************/ @@ -31,7 +31,7 @@ #ifndef __METRICS_SMALLFRY__H #define __METRICS_SMALLFRY__H -#define METRICS_SMALLFRY_VERSION "0.2.7" +#define METRICS_SMALLFRY_VERSION "0.2.8" #ifdef METRICS_STATIC #define METRICSAPI static @@ -390,7 +390,6 @@ METRICSAPI float metric_cor (unsigned char *ref, unsigned char *cmp, unsigned ch float im1, im2; float sum1, sum2, sum1l, sum2l; float sum12, sumq1, sumq2, q12, sum12l, sumq1l, sumq2l, sumq, cor; - float suma1l, suma2l, suma1, suma2; int y, x, d; size_t k, n; @@ -424,15 +423,11 @@ METRICSAPI float metric_cor (unsigned char *ref, unsigned char *cmp, unsigned ch sum12 = 0.0f; sumq1 = 0.0f; sumq2 = 0.0f; - suma1 = 0.0f; - suma2 = 0.0f; for (y = 0; y < height; y++) { sum12l = 0.0f; sumq1l = 0.0f; sumq2l = 0.0f; - suma1l = 0.0f; - suma2l = 0.0f; for (x = 0; x < width; x++) { for (d = 0; d < channels; d++) @@ -442,8 +437,6 @@ METRICSAPI float metric_cor (unsigned char *ref, unsigned char *cmp, unsigned ch im2 = (float)cmp[k]; im2 -= sum2; q12 = (im1 * im2); - suma1l += ((im1 < 0) ? -im1 : im1); - suma2l += ((im2 < 0) ? -im2 : im2); sum12l += q12; sumq1l += (im1 * im1); sumq2l += (im2 * im2); @@ -453,8 +446,6 @@ METRICSAPI float metric_cor (unsigned char *ref, unsigned char *cmp, unsigned ch sum12 += sum12l; sumq1 += sumq1l; sumq2 += sumq2l; - suma1 += suma1l; - suma2 += suma2l; } sumq = sqrt(sumq1 * sumq2); if (sumq > 0.0f) @@ -466,18 +457,20 @@ METRICSAPI float metric_cor (unsigned char *ref, unsigned char *cmp, unsigned ch cor = (cor < 0.0f) ? -cor : cor; if (delta) { - suma1 /= k; - suma2 /= k; - q12 = (suma1 + suma2); + sumq1 /= k; + sumq2 /= k; + sumq1 = sqrt(sumq1); + sumq2 = sqrt(sumq2); + q12 = (sumq1 + sumq2); if (q12 > 0.0f) { - suma1 *= (2.0f / q12); - suma2 *= (2.0f / q12); + sumq1 *= (2.0f / q12); + sumq2 *= (2.0f / q12); } else { - suma1 = 1.0f; - suma2 = 1.0f; + sumq1 = 1.0f; + sumq2 = 1.0f; } k = 0; for (y = 0; y < height; y++) @@ -488,21 +481,16 @@ METRICSAPI float metric_cor (unsigned char *ref, unsigned char *cmp, unsigned ch { im1 = (float)ref[k]; im1 -= sum1; - im1 *= suma2; + im1 *= sumq2; im2 = (float)cmp[k]; im2 -= sum2; - im2 *= suma1; - q12 = (im1 > im2) ? (im1 - im2) : (im2 > im1); + im2 *= sumq1; + q12 = (im1 > im2) ? (im1 - im2) : (im2 - im1); q12 = 255.0f - q12; delta[k] = (unsigned char)((q12 < 255.0f) ? q12 : 255); k++; } } - sum12 += sum12l; - sumq1 += sumq1l; - sumq2 += sumq2l; - suma1 += suma1l; - suma2 += suma2l; } } diff --git a/src/ssim.h b/src/ssim.h index 47d874b..7262d70 100644 --- a/src/ssim.h +++ b/src/ssim.h @@ -6,7 +6,7 @@ **************************************************************************** * Metrics SSIM * * file: ssim.h * -* version: 0.2.7 * +* version: 0.2.8 * * * **************************************************************************** ***************************************************************************/ @@ -19,7 +19,7 @@ #ifndef SSIM_H_ #define SSIM_H_ -#define METRICS_SSIM_VERSION "0.2.7" +#define METRICS_SSIM_VERSION "0.2.8" #ifdef METRICS_STATIC #define METRICSAPI static @@ -374,7 +374,7 @@ METRICSAPI float metric_vifp1(unsigned char *ref, unsigned char *cmp, unsigned c 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; + sv = (g < 0.0f) ? s2 : sv; g = (g < 0.0f) ? 0.0f : g; sv = (sv < eps) ? eps : sv; //vifp1 diff --git a/src/stbimmetrics.c b/src/stbimmetrics.c index 44e354d..5c950ca 100644 --- a/src/stbimmetrics.c +++ b/src/stbimmetrics.c @@ -20,16 +20,18 @@ void immetrics_usage(char* prog, char* metric) printf("usage: %s [options] image_in_orig image_in_comp [metric_out.png]\n", prog); printf("options:\n"); 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\tmse -\t MSE / MAX^2, MAX = 255\n"); + printf("\t\tpsnr -\t PSNR\n"); + printf("\t\tmse-c -\t MSE / MAX^2 of correlation, MAX = 255\n"); + printf("\t\tpsnr-c -\t PSNR of correlation\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"); + 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"); printf("\t-q\tquiet mode\n"); printf("\t-u\tUM mode (Universal scale of Metrics)\n"); printf("\t-y\tYCbCr mode\n"); @@ -191,6 +193,14 @@ int main(int argc, char **argv) { neatness = metrics_psnr(data_orig, data_comp, data_m, height, width, channels); } + else if (strcmp(metric, "mse-c") == 0) + { + neatness = metrics_mse_cor(data_orig, data_comp, data_m, height, width, channels); + } + else if (strcmp(metric, "psnr-c") == 0) + { + neatness = metrics_psnr_cor(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); @@ -242,7 +252,7 @@ int main(int argc, char **argv) else { printf("UM: %f\n", neatness); - } + } } else { diff --git a/src/ycbcr.h b/src/ycbcr.h index 7cfdac3..1689422 100644 --- a/src/ycbcr.h +++ b/src/ycbcr.h @@ -2,7 +2,7 @@ **************************************************************************** * YCbCr Filter * * file: ycbcr.h * -* version: 0.2.7 * +* version: 0.2.8 * * * **************************************************************************** ***************************************************************************/ @@ -13,7 +13,7 @@ #ifndef __YCBCR__H #define __YCBCR__H -#define YCBCR_VERSION "0.2.7" +#define YCBCR_VERSION "0.2.8" #ifdef METRICS_STATIC #define METRICSAPI static