/* * Copyright (c) 2016, Alliance for Open Media. All rights reserved. * * This source code is subject to the terms of the BSD 2 Clause License and * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License * was not distributed with this source code in the LICENSE file, you can * obtain it at www.aomedia.org/license/software. If the Alliance for Open * Media Patent License 1.0 was not distributed with this source code in the * PATENTS file, you can obtain it at www.aomedia.org/license/patent. * * This code was originally written by: Gregory Maxwell, at the Daala * project.
*/
staticvoid od_bin_fdct8x8(tran_low_t *y, int ystride, const int16_t *x, int xstride) { int i, j;
(void)xstride;
aom_fdct8x8(x, y, ystride); for (i = 0; i < 8; i++) for (j = 0; j < 8; j++)
*(y + ystride * i + j) = (*(y + ystride * i + j) + 4) >> 3;
}
#if CONFIG_AV1_HIGHBITDEPTH staticvoid hbd_od_bin_fdct8x8(tran_low_t *y, int ystride, const int16_t *x, int xstride) { int i, j;
(void)xstride;
aom_highbd_fdct8x8(x, y, ystride); for (i = 0; i < 8; i++) for (j = 0; j < 8; j++)
*(y + ystride * i + j) = (*(y + ystride * i + j) + 4) >> 3;
} #endif// CONFIG_AV1_HIGHBITDEPTH
staticdouble calc_psnrhvs(constunsignedchar *src, int _systride, constunsignedchar *dst, int _dystride, double _par, int _w, int _h, int _step, constdouble _csf[8][8],
uint32_t _shift, int buf_is_hbd, int16_t pix_max, int luma) { double ret; const uint8_t *_src8 = src; const uint8_t *_dst8 = dst; const uint16_t *_src16 = CONVERT_TO_SHORTPTR(src); const uint16_t *_dst16 = CONVERT_TO_SHORTPTR(dst);
DECLARE_ALIGNED(16, int16_t, dct_s[8 * 8]);
DECLARE_ALIGNED(16, int16_t, dct_d[8 * 8]);
DECLARE_ALIGNED(16, tran_low_t, dct_s_coef[8 * 8]);
DECLARE_ALIGNED(16, tran_low_t, dct_d_coef[8 * 8]); double mask[8][8]; int pixels; int x; int y; float sum1; float sum2; float delt;
(void)_par;
ret = pixels = 0;
sum1 = sum2 = delt = 0.0f; for (y = 0; y < _h; y++) { for (x = 0; x < _w; x++) { if (!buf_is_hbd) {
sum1 += _src8[y * _systride + x];
sum2 += _dst8[y * _dystride + x];
} else {
sum1 += _src16[y * _systride + x] >> _shift;
sum2 += _dst16[y * _dystride + x] >> _shift;
}
}
} if (luma) delt = (sum1 - sum2) / (_w * _h); /*In the PSNR-HVS-M paper[1] the authors describe the construction of their masking table as "we have used the quantization table for the color component Y of JPEG [6] that has been also obtained on the basis of CSF. Note that the values in quantization table JPEG have been normalized and then squared." Their CSF matrix (from PSNR-HVS) was also constructed from the JPEG matrices. I can not find any obvious scheme of normalizing to produce their table, but if I multiply their CSF by 0.3885746225901003 and square the result I get their masking table. I have no idea where this constant comes from, but deviating from it too greatly hurts MOS agreement.
[1] Nikolay Ponomarenko, Flavia Silvestri, Karen Egiazarian, Marco Carli, Jaakko Astola, Vladimir Lukin, "On between-coefficient contrast masking of DCT basis functions", CD-ROM Proceedings of the Third International Workshop on Video Processing and Quality Metrics for Consumer Electronics VPQM-07, Scottsdale, Arizona, USA, 25-26 January, 2007, 4 p.
Suggested in aomedia issue#2363: 0.3885746225901003 is a reciprocal of the maximum coefficient (2.573509) of the old JPEG based matrix from the paper. Since you are not using that,
divide by actual maximum coefficient. */ for (x = 0; x < 8; x++) for (y = 0; y < 8; y++)
mask[x][y] = (_csf[x][y] / _csf[1][0]) * (_csf[x][y] / _csf[1][0]); for (y = 0; y < _h - 7; y += _step) { for (x = 0; x < _w - 7; x += _step) { int i; int j; int n = 0; double s_gx = 0; double s_gy = 0; double g = 0; double s_gmean = 0; double s_gvar = 0; double s_mask = 0; for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { if (!buf_is_hbd) {
dct_s[i * 8 + j] = _src8[(y + i) * _systride + (j + x)];
dct_d[i * 8 + j] = _dst8[(y + i) * _dystride + (j + x)];
} else {
dct_s[i * 8 + j] = _src16[(y + i) * _systride + (j + x)] >> _shift;
dct_d[i * 8 + j] = _dst16[(y + i) * _dystride + (j + x)] >> _shift;
}
dct_d[i * 8 + j] += (int)(delt + 0.5f);
}
} for (i = 1; i < 7; i++) { for (j = 1; j < 7; j++) {
s_gx = (dct_s[(i - 1) * 8 + j - 1] * 3 -
dct_s[(i - 1) * 8 + j + 1] * 3 + dct_s[i * 8 + j - 1] * 10 -
dct_s[i * 8 + j + 1] * 10 + dct_s[(i + 1) * 8 + j - 1] * 3 -
dct_s[(i + 1) * 8 + j + 1] * 3) /
(pix_max * 16.f);
s_gy = (dct_s[(i - 1) * 8 + j - 1] * 3 -
dct_s[(i + 1) * 8 + j - 1] * 3 + dct_s[(i - 1) * 8 + j] * 10 -
dct_s[(i + 1) * 8 + j] * 10 + dct_s[(i - 1) * 8 + j + 1] * 3 -
dct_s[(i + 1) * 8 + j + 1] * 3) /
(pix_max * 16.f);
g = sqrt(s_gx * s_gx + s_gy * s_gy); if (g > 0.1f) n++;
s_gmean += g;
}
}
s_gvar = 1.f / (36 - n + 1) * s_gmean / 36.f; #if CONFIG_AV1_HIGHBITDEPTH if (!buf_is_hbd) {
od_bin_fdct8x8(dct_s_coef, 8, dct_s, 8);
od_bin_fdct8x8(dct_d_coef, 8, dct_d, 8);
} else {
hbd_od_bin_fdct8x8(dct_s_coef, 8, dct_s, 8);
hbd_od_bin_fdct8x8(dct_d_coef, 8, dct_d, 8);
} #else
od_bin_fdct8x8(dct_s_coef, 8, dct_s, 8);
od_bin_fdct8x8(dct_d_coef, 8, dct_d, 8); #endif// CONFIG_AV1_HIGHBITDEPTH for (i = 0; i < 8; i++) for (j = (i == 0); j < 8; j++)
s_mask += dct_s_coef[i * 8 + j] * dct_s_coef[i * 8 + j] * mask[i][j];
s_mask = sqrt(s_mask * s_gvar) / 8.f; for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { double err;
err = fabs((double)(dct_s_coef[i * 8 + j] - dct_d_coef[i * 8 + j])); if (i != 0 || j != 0)
err = err < s_mask / mask[i][j] ? 0 : err - s_mask / mask[i][j];
ret += (err * _csf[i][j]) * (err * _csf[i][j]);
pixels++;
}
}
}
} if (pixels <= 0) return 0;
ret /= pixels;
ret += 0.04 * delt * delt; return ret;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.