On Tue, May 11, 2021 at 1:08 PM myp...@gmail.com <myp...@gmail.com> wrote: > > On Mon, May 10, 2021 at 9:42 PM Xuewei Meng <928826...@qq.com> wrote: > > > > From: Xuewei Meng <xwmen...@gmail.com> > > > > Two modes are supported in guided filter, basic mode and fast mode. > > Basic mode is the initial pushed guided filter without optimization. > > Fast mode is implemented based on the basic one by sub-sampling method. > > The sub-sampling ratio which can be defined by users controls the > > algorithm complexity. The larger the sub-sampling ratio, the lower > > the algorithm complexity. > > > > Signed-off-by: Xuewei Meng <xwmen...@gmail.com> > > --- > > doc/filters.texi | 20 +++++++--- > > libavfilter/vf_guided.c | 104 > > ++++++++++++++++++++++++++++++++---------------- > > 2 files changed, 85 insertions(+), 39 deletions(-) > > > > diff --git a/doc/filters.texi b/doc/filters.texi > > index 03ca9ae..eb747cb 100644 > > --- a/doc/filters.texi > > +++ b/doc/filters.texi > > @@ -12963,12 +12963,22 @@ Apply guided filter for edge-preserving > > smoothing, dehazing and so on. > > The filter accepts the following options: > > @table @option > > @item radius > > -Set the radius in pixels. > > +Set the box radius in pixels. > > Allowed range is 1 to 20. Default is 3. > > > > @item eps > > -Set regularization parameter. > > -Allowed range is 0 to 1. Default is 0.1. > > +Set regularization parameter (with square). > > +Allowed range is 0 to 1. Default is 0.01. > > + > > +@item mode > > +Set filter mode. Can be @code{basic} or @code{fast}. > > +Default is @code{basic}. > > + > > +@item sub > > +Set subsampling ratio. > > +Allowed range is 1 to 64. > > +Default is always 1 for @code{basic} value of @var{mode} option, > > +and 4 for @code{fast} value of @var{mode} option. > > > > @item planes > > Set planes to filter. Default is first only. > > @@ -12987,8 +12997,8 @@ ffmpeg -i in.png -i in.png -filter_complex guided > > out.png > > > > @item > > Dehazing, structure-transferring filtering, detail enhancement with guided > > filter. > > -For the generation of guidance image, > > -see @url{http://kaiminghe.com/publications/pami12guidedfilter.pdf}. > > +For the generation of guidance image, refer to paper "Guided Image > > Filtering". > > +See: @url{http://kaiminghe.com/publications/pami12guidedfilter.pdf}. > > @example > > ffmpeg -i in.png -i guidance.png -filter_complex guided out.png > > @end example > > diff --git a/libavfilter/vf_guided.c b/libavfilter/vf_guided.c > > index 86c0db5..230fb7b 100644 > > --- a/libavfilter/vf_guided.c > > +++ b/libavfilter/vf_guided.c > > @@ -27,12 +27,20 @@ > > #include "internal.h" > > #include "video.h" > > > > +enum FilterModes { > > + BASIC, > > + FAST, > > + NB_MODES, > > +}; > > + > > typedef struct GuidedContext { > > const AVClass *class; > > FFFrameSync fs; > > > > int radius; > > float eps; > > + int mode; > > + int sub; > > > > int planes; > > > > @@ -51,9 +59,13 @@ typedef struct GuidedContext { > > #define FLAGS > > AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM > > > > static const AVOption guided_options[] = { > > - { "radius", "set the box radius", OFFSET(radius), > > AV_OPT_TYPE_INT, {.i64=3 }, 1, 20, FLAGS }, > > - { "eps", "set the regularization parameter (with square)", > > OFFSET(eps), AV_OPT_TYPE_FLOAT, {.dbl=0.01 }, 0.0, 1, FLAGS }, > > - { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, > > {.i64=1 }, 0, 0xF, FLAGS }, > > + { "radius", "set the box radius", > > OFFSET(radius), AV_OPT_TYPE_INT, {.i64 = 3 }, 1, 20, FLAGS > > }, > > + { "eps", "set the regularization parameter (with square)", > > OFFSET(eps), AV_OPT_TYPE_FLOAT, {.dbl = 0.01 }, 0.0, 1, FLAGS > > }, > > + { "mode", "set filtering mode (0: basic mode; 1: fast mode)", > > OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = BASIC}, 0, NB_MODES - 1, > > FLAGS, "mode" }, > > + { "basic", "basic guided filter", 0, > > AV_OPT_TYPE_CONST, {.i64 = BASIC}, 0, 0, FLAGS, > > "mode" }, > > + { "fast", "fast guided filter", 0, > > AV_OPT_TYPE_CONST, {.i64 = FAST }, 0, 0, FLAGS, > > "mode" }, > > + { "sub", "subsampling ratio", > > OFFSET(sub), AV_OPT_TYPE_INT, {.i64 = 1 }, 1, 64, FLAGS > > }, > > + { "planes", "set planes to filter", > > OFFSET(planes), AV_OPT_TYPE_INT, {.i64=1 }, 0, 0xF, FLAGS > > }, > > { NULL } > > }; > > > > @@ -147,6 +159,26 @@ static int config_input(AVFilterLink *inlink) > > return AVERROR(EINVAL); > > } > > > > + if (s->mode == BASIC) { > > + if (s->sub != 1) { > > + av_log(ctx, AV_LOG_WARNING, "Subsampling ratio is 1 in basic > > mode.\n"); > > + s->sub = 1; > > + } > > + } > > + else if (s->mode == FAST) { > > + if (s->sub == 1) { > > + av_log(ctx, AV_LOG_WARNING, "Subsampling ratio is larger than > > 1 in fast mode.\n"); > > + s->sub = 4; > > + } > > + if (s->radius >= s->sub) > > + s->radius = s->radius / s->sub; > > + else { > > + s->radius = 1; > > + } > > + } > > + else { > > + return AVERROR_BUG; > > + } > > > > s->depth = desc->comp[0].depth; > > s->width = ctx->inputs[0]->w; > > @@ -174,6 +206,10 @@ static int guided_##name(AVFilterContext *ctx, > > GuidedContext *s, > > const type *src = (const type *)ssrc; > > \ > > const type *srcRef = (const type *)ssrcRef; > > \ > > > > \ > > + int sub = s->sub; > > \ > > + int h = (height % sub) == 0 ? height / sub : height / sub + 1; > > \ > > + int w = (width % sub) == 0 ? width / sub : width / sub + 1; > > \ > > + > > \ > > ThreadData t; > > \ > > const int nb_threads = ff_filter_get_nb_threads(ctx); > > \ > > float *I; > > \ > > @@ -189,55 +225,55 @@ static int guided_##name(AVFilterContext *ctx, > > GuidedContext *s, > > float *meanA; > > \ > > float *meanB; > > \ > > > > \ > > - I = av_calloc(width * height, sizeof(float)); > > \ > > - II = av_calloc(width * height, sizeof(float)); > > \ > > - P = av_calloc(width * height, sizeof(float)); > > \ > > - IP = av_calloc(width * height, sizeof(float)); > > \ > > - meanI = av_calloc(width * height, sizeof(float)); > > \ > > - meanII = av_calloc(width * height, sizeof(float)); > > \ > > - meanP = av_calloc(width * height, sizeof(float)); > > \ > > - meanIP = av_calloc(width * height, sizeof(float)); > > \ > > + I = av_calloc(w * h, sizeof(float)); > > \ > > + II = av_calloc(w * h, sizeof(float)); > > \ > > + P = av_calloc(w * h, sizeof(float)); > > \ > > + IP = av_calloc(w * h, sizeof(float)); > > \ > > + meanI = av_calloc(w * h, sizeof(float)); > > \ > > + meanII = av_calloc(w * h, sizeof(float)); > > \ > > + meanP = av_calloc(w * h, sizeof(float)); > > \ > > + meanIP = av_calloc(w * h, sizeof(float)); > > \ > > > > \ > > - A = av_calloc(width * height, sizeof(float)); > > \ > > - B = av_calloc(width * height, sizeof(float)); > > \ > > - meanA = av_calloc(width * height, sizeof(float)); > > \ > > - meanB = av_calloc(width * height, sizeof(float)); > > \ > > + A = av_calloc(w * h, sizeof(float)); > > \ > > + B = av_calloc(w * h, sizeof(float)); > > \ > > + meanA = av_calloc(w * h, sizeof(float)); > > \ > > + meanB = av_calloc(w * h, sizeof(float)); > > \ > > > > \ > > if (!I || !II || !P || !IP || !meanI || !meanII || !meanP || > > \ > > !meanIP || !A || !B || !meanA || !meanB){ > > \ > > ret = AVERROR(ENOMEM); > > \ > > goto end; > > \ > > } > > \ > > - for (int i = 0;i < height;i++) { > > \ > > - for (int j = 0;j < width;j++) { > > \ > > - int x = i * width + j; > > \ > > - I[x] = src[i * src_stride + j] / maxval; > > \ > > + for (int i = 0;i < h;i++) { > > \ > > + for (int j = 0;j < w;j++) { > > \ > > + int x = i * w + j; > > \ > > + I[x] = src[(i * src_stride + j) * sub] / maxval; > > \ > > II[x] = I[x] * I[x]; > > \ > > - P[x] = srcRef[i * src_ref_stride + j] / maxval; > > \ > > + P[x] = srcRef[(i * src_ref_stride + j) * sub] / maxval; > > \ > > IP[x] = I[x] * P[x]; > > \ > > } > > \ > > } > > \ > > > > \ > > - t.width = width; > > \ > > - t.height = height; > > \ > > - t.srcStride = width; > > \ > > - t.dstStride = width; > > \ > > + t.width = w; > > \ > > + t.height = h; > > \ > > + t.srcStride = w; > > \ > > + t.dstStride = w; > > \ > > t.src = I; > > \ > > t.dst = meanI; > > \ > > - ctx->internal->execute(ctx, s->box_slice, &t, NULL, FFMIN(height, > > nb_threads)); \ > > + ctx->internal->execute(ctx, s->box_slice, &t, NULL, FFMIN(h, > > nb_threads)); \ > > t.src = II; > > \ > > t.dst = meanII; > > \ > > - ctx->internal->execute(ctx, s->box_slice, &t, NULL, FFMIN(height, > > nb_threads)); \ > > + ctx->internal->execute(ctx, s->box_slice, &t, NULL, FFMIN(h, > > nb_threads)); \ > > t.src = P; > > \ > > t.dst = meanP; > > \ > > - ctx->internal->execute(ctx, s->box_slice, &t, NULL, FFMIN(height, > > nb_threads)); \ > > + ctx->internal->execute(ctx, s->box_slice, &t, NULL, FFMIN(h, > > nb_threads)); \ > > t.src = IP; > > \ > > t.dst = meanIP; > > \ > > - ctx->internal->execute(ctx, s->box_slice, &t, NULL, FFMIN(height, > > nb_threads)); \ > > + ctx->internal->execute(ctx, s->box_slice, &t, NULL, FFMIN(h, > > nb_threads)); \ > > > > \ > > - for (int i = 0;i < height;i++) { > > \ > > - for (int j = 0;j < width;j++) { > > \ > > - int x = i * width + j; > > \ > > + for (int i = 0;i < h;i++) { > > \ > > + for (int j = 0;j < w;j++) { > > \ > > + int x = i * w + j; > > \ > > float varI = meanII[x] - (meanI[x] * meanI[x]); > > \ > > float covIP = meanIP[x] - (meanI[x] * meanP[x]); > > \ > > A[x] = covIP / (varI + eps); > > \ > > @@ -247,14 +283,14 @@ static int guided_##name(AVFilterContext *ctx, > > GuidedContext *s, > > > > \ > > t.src = A; > > \ > > t.dst = meanA; > > \ > > - ctx->internal->execute(ctx, s->box_slice, &t, NULL, FFMIN(height, > > nb_threads)); \ > > + ctx->internal->execute(ctx, s->box_slice, &t, NULL, FFMIN(h, > > nb_threads)); \ > > t.src = B; > > \ > > t.dst = meanB; > > \ > > - ctx->internal->execute(ctx, s->box_slice, &t, NULL, FFMIN(height, > > nb_threads)); \ > > + ctx->internal->execute(ctx, s->box_slice, &t, NULL, FFMIN(h, > > nb_threads)); \ > > > > \ > > for (int i = 0;i < height;i++) { > > \ > > for (int j = 0;j < width;j++) { > > \ > > - int x = i * width + j; > > \ > > + int x = i / sub * w + j / sub; > > \ > > dst[i * dst_stride + j] = meanA[x] * src[i * src_stride + j] + > > \ > > meanB[x] * maxval; > > \ > > } > > \ > > -- > > 1.9.1 > I think you submit version4 - version3 diff part for fast mode, it's > strange, you need to submit a full version 4 patch
Ignore the comments, guided filter have been merged _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".