mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-04-08 18:28:19 +00:00
avfilter/vf_vaguedenoiser: add new type of threshold
This commit is contained in:
parent
6c57b0d63a
commit
bd6336b970
@ -19476,6 +19476,20 @@ Partial of full denoising (limited coefficients shrinking), from 0 to 100. Defau
|
|||||||
|
|
||||||
@item planes
|
@item planes
|
||||||
A list of the planes to process. By default all planes are processed.
|
A list of the planes to process. By default all planes are processed.
|
||||||
|
|
||||||
|
@item type
|
||||||
|
The threshold type the filter will use.
|
||||||
|
|
||||||
|
It accepts the following values:
|
||||||
|
@table @samp
|
||||||
|
@item universal
|
||||||
|
Threshold used is same for all decompositions.
|
||||||
|
|
||||||
|
@item bayes
|
||||||
|
Threshold used depends also on each decomposition coefficients.
|
||||||
|
@end table
|
||||||
|
|
||||||
|
Default is universal.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@section vectorscope
|
@section vectorscope
|
||||||
|
@ -38,6 +38,7 @@ typedef struct VagueDenoiserContext {
|
|||||||
float threshold;
|
float threshold;
|
||||||
float percent;
|
float percent;
|
||||||
int method;
|
int method;
|
||||||
|
int type;
|
||||||
int nsteps;
|
int nsteps;
|
||||||
int planes;
|
int planes;
|
||||||
|
|
||||||
@ -60,7 +61,7 @@ typedef struct VagueDenoiserContext {
|
|||||||
|
|
||||||
void (*thresholding)(float *block, const int width, const int height,
|
void (*thresholding)(float *block, const int width, const int height,
|
||||||
const int stride, const float threshold,
|
const int stride, const float threshold,
|
||||||
const float percent, const int nsteps);
|
const float percent);
|
||||||
} VagueDenoiserContext;
|
} VagueDenoiserContext;
|
||||||
|
|
||||||
#define OFFSET(x) offsetof(VagueDenoiserContext, x)
|
#define OFFSET(x) offsetof(VagueDenoiserContext, x)
|
||||||
@ -74,6 +75,9 @@ static const AVOption vaguedenoiser_options[] = {
|
|||||||
{ "nsteps", "set number of steps", OFFSET(nsteps), AV_OPT_TYPE_INT, {.i64=6 }, 1, 32, FLAGS },
|
{ "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 },
|
{ "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 },
|
{ "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 }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -333,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,
|
static void hard_thresholding(float *block, const int width, const int height,
|
||||||
const int stride, const float threshold,
|
const int stride, const float threshold,
|
||||||
const float percent, const int unused)
|
const float percent)
|
||||||
{
|
{
|
||||||
const float frac = 1.f - percent * 0.01f;
|
const float frac = 1.f - percent * 0.01f;
|
||||||
int y, x;
|
int y, x;
|
||||||
@ -348,7 +352,7 @@ 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,
|
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 frac = 1.f - percent * 0.01f;
|
||||||
const float shift = threshold * 0.01f * percent;
|
const float shift = threshold * 0.01f * percent;
|
||||||
@ -368,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,
|
static void qian_thresholding(float *block, const int width, const int height,
|
||||||
const int stride, const float threshold,
|
const int stride, const float threshold,
|
||||||
const float percent, const int unused)
|
const float percent)
|
||||||
{
|
{
|
||||||
const float percent01 = percent * 0.01f;
|
const float percent01 = percent * 0.01f;
|
||||||
const float tr2 = threshold * threshold * percent01;
|
const float tr2 = threshold * threshold * percent01;
|
||||||
@ -389,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)
|
static void filter(VagueDenoiserContext *s, AVFrame *in, AVFrame *out)
|
||||||
{
|
{
|
||||||
int p, y, x, i, j;
|
int p, y, x, i, j;
|
||||||
@ -452,7 +473,28 @@ static void filter(VagueDenoiserContext *s, AVFrame *in, AVFrame *out)
|
|||||||
v_low_size0 = (v_low_size0 + 1) >> 1;
|
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--) {
|
while (nsteps_invert--) {
|
||||||
const int idx = s->vlowsize[p][nsteps_invert] + s->vhighsize[p][nsteps_invert];
|
const int idx = s->vlowsize[p][nsteps_invert] + s->vhighsize[p][nsteps_invert];
|
||||||
|
Loading…
Reference in New Issue
Block a user