mirror of
https://github.com/webmproject/libwebp.git
synced 2024-11-20 04:18:26 +01:00
fix SSIM metric ... by ignoring too-dark area
Roughly, if both the source and the reference areas are darker too dark (R/G/B <= ~6), they are ignored. One caveat: SSIM calculation won't work for U/V planes, which are 128-centered and not related to luminance. But WebPPlaneDistortion() enforces the conversion to RGB, if needed. Change-Id: I586c2579c475583b8c90c5baefd766b1d5aea591
This commit is contained in:
parent
2f51b614b0
commit
31b1e34342
@ -87,6 +87,7 @@ static int DiffScaleChannel(uint8_t* src1, int stride1,
|
|||||||
// bigger annoyance of having to open up internal details of libdsp...
|
// bigger annoyance of having to open up internal details of libdsp...
|
||||||
|
|
||||||
#define SSIM_KERNEL 3 // total size of the kernel: 2 * SSIM_KERNEL + 1
|
#define SSIM_KERNEL 3 // total size of the kernel: 2 * SSIM_KERNEL + 1
|
||||||
|
|
||||||
// struct for accumulating statistical moments
|
// struct for accumulating statistical moments
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t w; // sum(w_i) : sum of weights
|
uint32_t w; // sum(w_i) : sum of weights
|
||||||
@ -102,8 +103,10 @@ static WEBP_INLINE double SSIMCalculation(const DistoStats* const stats) {
|
|||||||
const uint32_t w2 = N * N;
|
const uint32_t w2 = N * N;
|
||||||
const uint32_t C1 = 20 * w2;
|
const uint32_t C1 = 20 * w2;
|
||||||
const uint32_t C2 = 60 * w2;
|
const uint32_t C2 = 60 * w2;
|
||||||
|
const uint32_t C3 = 8 * 8 * w2; // 'dark' limit ~= 6
|
||||||
const uint64_t xmxm = (uint64_t)stats->xm * stats->xm;
|
const uint64_t xmxm = (uint64_t)stats->xm * stats->xm;
|
||||||
const uint64_t ymym = (uint64_t)stats->ym * stats->ym;
|
const uint64_t ymym = (uint64_t)stats->ym * stats->ym;
|
||||||
|
if (xmxm + ymym >= C3) {
|
||||||
const int64_t xmym = (int64_t)stats->xm * stats->ym;
|
const int64_t xmym = (int64_t)stats->xm * stats->ym;
|
||||||
const int64_t sxy = (int64_t)stats->xym * N - xmym; // can be negative
|
const int64_t sxy = (int64_t)stats->xym * N - xmym; // can be negative
|
||||||
const uint64_t sxx = (uint64_t)stats->xxm * N - xmxm;
|
const uint64_t sxx = (uint64_t)stats->xxm * N - xmxm;
|
||||||
@ -117,6 +120,8 @@ static WEBP_INLINE double SSIMCalculation(const DistoStats* const stats) {
|
|||||||
assert(r >= 0. && r <= 1.0);
|
assert(r >= 0. && r <= 1.0);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
return 1.; // area is too dark to contribute meaningfully
|
||||||
|
}
|
||||||
|
|
||||||
static double SSIMGetClipped(const uint8_t* src1, int stride1,
|
static double SSIMGetClipped(const uint8_t* src1, int stride1,
|
||||||
const uint8_t* src2, int stride2,
|
const uint8_t* src2, int stride2,
|
||||||
|
@ -704,8 +704,10 @@ static WEBP_INLINE double SSIMCalculation(
|
|||||||
const uint32_t w2 = N * N;
|
const uint32_t w2 = N * N;
|
||||||
const uint32_t C1 = 20 * w2;
|
const uint32_t C1 = 20 * w2;
|
||||||
const uint32_t C2 = 60 * w2;
|
const uint32_t C2 = 60 * w2;
|
||||||
|
const uint32_t C3 = 8 * 8 * w2; // 'dark' limit ~= 6
|
||||||
const uint64_t xmxm = (uint64_t)stats->xm * stats->xm;
|
const uint64_t xmxm = (uint64_t)stats->xm * stats->xm;
|
||||||
const uint64_t ymym = (uint64_t)stats->ym * stats->ym;
|
const uint64_t ymym = (uint64_t)stats->ym * stats->ym;
|
||||||
|
if (xmxm + ymym >= C3) {
|
||||||
const int64_t xmym = (int64_t)stats->xm * stats->ym;
|
const int64_t xmym = (int64_t)stats->xm * stats->ym;
|
||||||
const int64_t sxy = (int64_t)stats->xym * N - xmym; // can be negative
|
const int64_t sxy = (int64_t)stats->xym * N - xmym; // can be negative
|
||||||
const uint64_t sxx = (uint64_t)stats->xxm * N - xmxm;
|
const uint64_t sxx = (uint64_t)stats->xxm * N - xmxm;
|
||||||
@ -719,6 +721,8 @@ static WEBP_INLINE double SSIMCalculation(
|
|||||||
assert(r >= 0. && r <= 1.0);
|
assert(r >= 0. && r <= 1.0);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
return 1.; // area is too dark to contribute meaningfully
|
||||||
|
}
|
||||||
|
|
||||||
double VP8SSIMFromStats(const VP8DistoStats* const stats) {
|
double VP8SSIMFromStats(const VP8DistoStats* const stats) {
|
||||||
return SSIMCalculation(stats, kWeightSum);
|
return SSIMCalculation(stats, kWeightSum);
|
||||||
|
Loading…
Reference in New Issue
Block a user