]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/vf_vaguedenoiser.c
avfilter: Constify all AVFilters
[ffmpeg] / libavfilter / vf_vaguedenoiser.c
index b323ce54796a2b9e9c07c21021ad876f2b211e4f..481fc774e51dbefd7e487ed1d89ffdf123719c86 100644 (file)
@@ -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),