00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "contributors.h"
00017 #include "global.h"
00018 #include "img_distortion.h"
00019 #include "enc_statistics.h"
00020
00021
00022
00023 float compute_ssim (imgpel **refImg, imgpel **encImg, int height, int width, int win_height, int win_width, int comp)
00024 {
00025 static const float K1 = 0.01f, K2 = 0.03f;
00026 static float max_pix_value_sqd;
00027 float C1, C2;
00028 float win_pixels = (float) (win_width * win_height);
00029 #ifdef UNBIASED_VARIANCE
00030 float win_pixels_bias = win_pixels - 1;
00031 #else
00032 float win_pixels_bias = win_pixels;
00033 #endif
00034 float mb_ssim, meanOrg, meanEnc;
00035 float varOrg, varEnc, covOrgEnc;
00036 int imeanOrg, imeanEnc, ivarOrg, ivarEnc, icovOrgEnc;
00037 float cur_distortion = 0.0;
00038 int i, j, n, m, win_cnt = 0;
00039 int overlapSize = params->SSIMOverlapSize;
00040
00041 max_pix_value_sqd = (float) (img->max_imgpel_value_comp[comp] * img->max_imgpel_value_comp[comp]);
00042 C1 = K1 * K1 * max_pix_value_sqd;
00043 C2 = K2 * K2 * max_pix_value_sqd;
00044
00045 for (j = 0; j <= height - win_height; j += overlapSize)
00046 {
00047 for (i = 0; i <= width - win_width; i += overlapSize)
00048 {
00049 imeanOrg = 0;
00050 imeanEnc = 0;
00051 ivarOrg = 0;
00052 ivarEnc = 0;
00053 icovOrgEnc = 0;
00054
00055 for ( n = j;n < j + win_height;n ++)
00056 {
00057 for (m = i;m < i + win_width;m ++)
00058 {
00059 imeanOrg += refImg[n][m];
00060 imeanEnc += encImg[n][m];
00061 ivarOrg += refImg[n][m] * refImg[n][m];
00062 ivarEnc += encImg[n][m] * encImg[n][m];
00063 icovOrgEnc += refImg[n][m] * encImg[n][m];
00064 }
00065 }
00066
00067 meanOrg = (float) imeanOrg / win_pixels;
00068 meanEnc = (float) imeanEnc / win_pixels;
00069
00070 varOrg = ((float) ivarOrg - ((float) imeanOrg) * meanOrg) / win_pixels_bias;
00071 varEnc = ((float) ivarEnc - ((float) imeanEnc) * meanEnc) / win_pixels_bias;
00072 covOrgEnc = ((float) icovOrgEnc - ((float) imeanOrg) * meanEnc) / win_pixels_bias;
00073
00074 mb_ssim = (float) ((2.0 * meanOrg * meanEnc + C1) * (2.0 * covOrgEnc + C2));
00075 mb_ssim /= (float) (meanOrg * meanOrg + meanEnc * meanEnc + C1) * (varOrg + varEnc + C2);
00076
00077 cur_distortion += mb_ssim;
00078 win_cnt++;
00079 }
00080 }
00081
00082 cur_distortion /= (float) win_cnt;
00083
00084 if (cur_distortion >= 1.0 && cur_distortion < 1.01)
00085 cur_distortion = 1.0;
00086
00087 return cur_distortion;
00088 }
00089
00090
00091
00092
00093
00094
00095
00096 void find_ssim (ImageStructure *ref, ImageStructure *src, DistMetric *metricSSIM)
00097 {
00098 FrameFormat *format = &ref->format;
00099
00100 metricSSIM->value[0] = compute_ssim (ref->data[0], src->data[0], format->height, format->width, BLOCK_SIZE_8x8, BLOCK_SIZE_8x8, 0);
00101
00102 if (format->yuv_format != YUV400)
00103 {
00104 metricSSIM->value[1] = compute_ssim (ref->data[1], src->data[1], format->height_cr, format->width_cr, img->mb_cr_size_y, img->mb_cr_size_x, 1);
00105 metricSSIM->value[2] = compute_ssim (ref->data[2], src->data[2], format->height_cr, format->width_cr, img->mb_cr_size_y, img->mb_cr_size_x, 2);
00106 }
00107
00108 {
00109 accumulate_average(metricSSIM, dist->frame_ctr);
00110 accumulate_avslice(metricSSIM, img->type, stats->frame_ctr[img->type]);
00111 }
00112 }
00113