X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Fvf_vaguedenoiser.c;h=481fc774e51dbefd7e487ed1d89ffdf123719c86;hb=a04ad248a05e7b613abe09b3bb067f555108d794;hp=b323ce54796a2b9e9c07c21021ad876f2b211e4f;hpb=b8eb0827f053230dd919bc73e25381b47b4fe1a7;p=ffmpeg diff --git a/libavfilter/vf_vaguedenoiser.c b/libavfilter/vf_vaguedenoiser.c index b323ce54796..481fc774e51 100644 --- a/libavfilter/vf_vaguedenoiser.c +++ b/libavfilter/vf_vaguedenoiser.c @@ -38,6 +38,7 @@ typedef struct VagueDenoiserContext { float threshold; float percent; int method; + int type; int nsteps; int planes; @@ -60,7 +61,7 @@ typedef struct VagueDenoiserContext { void (*thresholding)(float *block, const int width, const int height, const int stride, const float threshold, - const float percent, const int nsteps); + const float percent); } VagueDenoiserContext; #define OFFSET(x) offsetof(VagueDenoiserContext, x) @@ -70,10 +71,13 @@ static const AVOption vaguedenoiser_options[] = { { "method", "set filtering method", OFFSET(method), AV_OPT_TYPE_INT, {.i64=2 }, 0, 2, FLAGS, "method" }, { "hard", "hard thresholding", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "method" }, { "soft", "soft thresholding", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "method" }, - { "garrote", "garotte thresholding", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "method" }, + { "garrote", "garrote thresholding", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "method" }, { "nsteps", "set number of steps", OFFSET(nsteps), AV_OPT_TYPE_INT, {.i64=6 }, 1, 32, FLAGS }, { "percent", "set percent of full denoising", OFFSET(percent),AV_OPT_TYPE_FLOAT, {.dbl=85}, 0,100, FLAGS }, { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=15 }, 0, 15, FLAGS }, + { "type", "set threshold type", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0 }, 0, 1, FLAGS, "type" }, + { "universal", "universal (VisuShrink)", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "type" }, + { "bayes", "bayes (BayesShrink)", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "type" }, { NULL } }; @@ -104,8 +108,8 @@ static const float synthesis_high[9] = { static int query_formats(AVFilterContext *ctx) { static const enum AVPixelFormat pix_fmts[] = { - AV_PIX_FMT_GRAY8, - AV_PIX_FMT_GRAY16, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, + AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, @@ -121,6 +125,11 @@ static int query_formats(AVFilterContext *ctx) AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_NONE }; AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); @@ -328,7 +337,7 @@ static void invert_step(const float *input, float *output, float *temp, const in static void hard_thresholding(float *block, const int width, const int height, const int stride, const float threshold, - const float percent, const int unused) + const float percent) { const float frac = 1.f - percent * 0.01f; int y, x; @@ -343,22 +352,14 @@ static void hard_thresholding(float *block, const int width, const int height, } static void soft_thresholding(float *block, const int width, const int height, const int stride, - const float threshold, const float percent, const int nsteps) + const float threshold, const float percent) { const float frac = 1.f - percent * 0.01f; const float shift = threshold * 0.01f * percent; - int w = width; - int h = height; - int y, x, l; - - for (l = 0; l < nsteps; l++) { - w = (w + 1) >> 1; - h = (h + 1) >> 1; - } + int y, x; for (y = 0; y < height; y++) { - const int x0 = (y < h) ? w : 0; - for (x = x0; x < width; x++) { + for (x = 0; x < width; x++) { const float temp = FFABS(block[x]); if (temp <= threshold) block[x] *= frac; @@ -371,7 +372,7 @@ static void soft_thresholding(float *block, const int width, const int height, c static void qian_thresholding(float *block, const int width, const int height, const int stride, const float threshold, - const float percent, const int unused) + const float percent) { const float percent01 = percent * 0.01f; const float tr2 = threshold * threshold * percent01; @@ -392,6 +393,23 @@ static void qian_thresholding(float *block, const int width, const int height, } } +static float bayes_threshold(float *block, const int width, const int height, + const int stride, const float threshold) +{ + float mean = 0.f; + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + mean += block[x] * block[x]; + } + block += stride; + } + + mean /= width * height; + + return threshold * threshold / (FFMAX(sqrtf(mean - threshold), FLT_EPSILON)); +} + static void filter(VagueDenoiserContext *s, AVFrame *in, AVFrame *out) { int p, y, x, i, j; @@ -455,7 +473,28 @@ static void filter(VagueDenoiserContext *s, AVFrame *in, AVFrame *out) v_low_size0 = (v_low_size0 + 1) >> 1; } - s->thresholding(s->block, width, height, width, s->threshold, s->percent, s->nsteps); + if (s->type == 0) { + s->thresholding(s->block, width, height, width, s->threshold, s->percent); + } else { + for (int n = 0; n < s->nsteps; n++) { + float threshold; + float *block; + + if (n == s->nsteps - 1) { + threshold = bayes_threshold(s->block, s->hlowsize[p][n], s->vlowsize[p][n], width, s->threshold); + s->thresholding(s->block, s->hlowsize[p][n], s->vlowsize[p][n], width, threshold, s->percent); + } + block = s->block + s->hlowsize[p][n]; + threshold = bayes_threshold(block, s->hhighsize[p][n], s->vlowsize[p][n], width, s->threshold); + s->thresholding(block, s->hhighsize[p][n], s->vlowsize[p][n], width, threshold, s->percent); + block = s->block + s->vlowsize[p][n] * width; + threshold = bayes_threshold(block, s->hlowsize[p][n], s->vhighsize[p][n], width, s->threshold); + s->thresholding(block, s->hlowsize[p][n], s->vhighsize[p][n], width, threshold, s->percent); + block = s->block + s->hlowsize[p][n] + s->vlowsize[p][n] * width; + threshold = bayes_threshold(block, s->hhighsize[p][n], s->vhighsize[p][n], width, s->threshold); + s->thresholding(block, s->hhighsize[p][n], s->vhighsize[p][n], width, threshold, s->percent); + } + } while (nsteps_invert--) { const int idx = s->vlowsize[p][nsteps_invert] + s->vhighsize[p][nsteps_invert]; @@ -571,7 +610,7 @@ static const AVFilterPad vaguedenoiser_outputs[] = { { NULL } }; -AVFilter ff_vf_vaguedenoiser = { +const AVFilter ff_vf_vaguedenoiser = { .name = "vaguedenoiser", .description = NULL_IF_CONFIG_SMALL("Apply a Wavelet based Denoiser."), .priv_size = sizeof(VagueDenoiserContext),