Signed-off-by: Paul B Mahol <one...@gmail.com> --- doc/filters.texi | 21 ++++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_convolution.c | 133 +++++++++++++++++++++++++++++++++++ 4 files changed, 156 insertions(+)
diff --git a/doc/filters.texi b/doc/filters.texi index c2d7bac51d..00f5d38406 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -13396,6 +13396,27 @@ kerndeint=map=1 @end example @end itemize +@section kirsch +Apply kirsch operator to input video stream. + +The filter accepts the following option: + +@table @option +@item planes +Set which planes will be processed, unprocessed planes will be copied. +By default value 0xf, all planes will be processed. + +@item scale +Set value which will be multiplied with filtered result. + +@item delta +Set value which will be added to filtered result. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section lagfun Slowly update darker pixels. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index b930a00d8b..fbb4e29bd0 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -298,6 +298,7 @@ OBJS-$(CONFIG_INFLATE_FILTER) += vf_neighbor.o OBJS-$(CONFIG_INTERLACE_FILTER) += vf_tinterlace.o OBJS-$(CONFIG_INTERLEAVE_FILTER) += f_interleave.o OBJS-$(CONFIG_KERNDEINT_FILTER) += vf_kerndeint.o +OBJS-$(CONFIG_KIRSCH_FILTER) += vf_convolution.o OBJS-$(CONFIG_LAGFUN_FILTER) += vf_lagfun.o OBJS-$(CONFIG_LENSCORRECTION_FILTER) += vf_lenscorrection.o OBJS-$(CONFIG_LENSFUN_FILTER) += vf_lensfun.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 616962690b..d9d36554c4 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -283,6 +283,7 @@ extern AVFilter ff_vf_inflate; extern AVFilter ff_vf_interlace; extern AVFilter ff_vf_interleave; extern AVFilter ff_vf_kerndeint; +extern AVFilter ff_vf_kirsch; extern AVFilter ff_vf_lagfun; extern AVFilter ff_vf_lenscorrection; extern AVFilter ff_vf_lensfun; diff --git a/libavfilter/vf_convolution.c b/libavfilter/vf_convolution.c index c238dae925..7b655ae25b 100644 --- a/libavfilter/vf_convolution.c +++ b/libavfilter/vf_convolution.c @@ -159,6 +159,55 @@ static void filter16_sobel(uint8_t *dstp, int width, } } +static void filter16_kirsch(uint8_t *dstp, int width, + float scale, float delta, const int *const matrix, + const uint8_t *c[], int peak, int radius, + int dstride, int stride) +{ + uint16_t *dst = (uint16_t *)dstp; + const uint16_t *c0 = (const uint16_t *)c[0], *c1 = (const uint16_t *)c[1], *c2 = (const uint16_t *)c[2]; + const uint16_t *c3 = (const uint16_t *)c[3], *c5 = (const uint16_t *)c[5]; + const uint16_t *c6 = (const uint16_t *)c[6], *c7 = (const uint16_t *)c[7], *c8 = (const uint16_t *)c[8]; + int x; + + for (x = 0; x < width; x++) { + int sum0 = c0[x] * 5 + c1[x] * 5 + c2[x] * 5 + + c3[x] * -3 + c5[x] * -3 + + c6[x] * -3 + c7[x] * -3 + c8[x] * -3; + int sum1 = c0[x] * -3 + c1[x] * 5 + c2[x] * 5 + + c3[x] * 5 + c5[x] * -3 + + c6[x] * -3 + c7[x] * -3 + c8[x] * -3; + int sum2 = c0[x] * -3 + c1[x] * -3 + c2[x] * 5 + + c3[x] * 5 + c5[x] * 5 + + c6[x] * -3 + c7[x] * -3 + c8[x] * -3; + int sum3 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 + + c3[x] * 5 + c5[x] * 5 + + c6[x] * 5 + c7[x] * -3 + c8[x] * -3; + int sum4 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 + + c3[x] * -3 + c5[x] * 5 + + c6[x] * 5 + c7[x] * 5 + c8[x] * -3; + int sum5 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 + + c3[x] * -3 + c5[x] * -3 + + c6[x] * 5 + c7[x] * 5 + c8[x] * 5; + int sum6 = c0[x] * 5 + c1[x] * -3 + c2[x] * -3 + + c3[x] * -3 + c5[x] * -3 + + c6[x] * -3 + c7[x] * 5 + c8[x] * 5; + int sum7 = c0[x] * 5 + c1[x] * 5 + c2[x] * -3 + + c3[x] * -3 + c5[x] * -3 + + c6[x] * -3 + c7[x] * -3 + c8[x] * 5; + + sum0 = FFMAX(sum0, sum1); + sum2 = FFMAX(sum2, sum3); + sum4 = FFMAX(sum4, sum5); + sum6 = FFMAX(sum6, sum7); + sum0 = FFMAX(sum0, sum2); + sum4 = FFMAX(sum4, sum6); + sum0 = FFMAX(sum0, sum4); + + dst[x] = av_clip(FFABS(sum0) * scale + delta, 0, peak); + } +} + static void filter_prewitt(uint8_t *dst, int width, float scale, float delta, const int *const matrix, const uint8_t *c[], int peak, int radius, @@ -214,6 +263,54 @@ static void filter_sobel(uint8_t *dst, int width, } } +static void filter_kirsch(uint8_t *dst, int width, + float scale, float delta, const int *const matrix, + const uint8_t *c[], int peak, int radius, + int dstride, int stride) +{ + const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2]; + const uint8_t *c3 = c[3], *c5 = c[5]; + const uint8_t *c6 = c[6], *c7 = c[7], *c8 = c[8]; + int x; + + for (x = 0; x < width; x++) { + int sum0 = c0[x] * 5 + c1[x] * 5 + c2[x] * 5 + + c3[x] * -3 + c5[x] * -3 + + c6[x] * -3 + c7[x] * -3 + c8[x] * -3; + int sum1 = c0[x] * -3 + c1[x] * 5 + c2[x] * 5 + + c3[x] * 5 + c5[x] * -3 + + c6[x] * -3 + c7[x] * -3 + c8[x] * -3; + int sum2 = c0[x] * -3 + c1[x] * -3 + c2[x] * 5 + + c3[x] * 5 + c5[x] * 5 + + c6[x] * -3 + c7[x] * -3 + c8[x] * -3; + int sum3 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 + + c3[x] * 5 + c5[x] * 5 + + c6[x] * 5 + c7[x] * -3 + c8[x] * -3; + int sum4 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 + + c3[x] * -3 + c5[x] * 5 + + c6[x] * 5 + c7[x] * 5 + c8[x] * -3; + int sum5 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 + + c3[x] * -3 + c5[x] * -3 + + c6[x] * 5 + c7[x] * 5 + c8[x] * 5; + int sum6 = c0[x] * 5 + c1[x] * -3 + c2[x] * -3 + + c3[x] * -3 + c5[x] * -3 + + c6[x] * -3 + c7[x] * 5 + c8[x] * 5; + int sum7 = c0[x] * 5 + c1[x] * 5 + c2[x] * -3 + + c3[x] * -3 + c5[x] * -3 + + c6[x] * -3 + c7[x] * -3 + c8[x] * 5; + + sum0 = FFMAX(sum0, sum1); + sum2 = FFMAX(sum2, sum3); + sum4 = FFMAX(sum4, sum5); + sum6 = FFMAX(sum6, sum7); + sum0 = FFMAX(sum0, sum2); + sum4 = FFMAX(sum4, sum6); + sum0 = FFMAX(sum0, sum4); + + dst[x] = av_clip_uint8(FFABS(sum0) * scale + delta); + } +} + static void filter16_3x3(uint8_t *dstp, int width, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, @@ -604,6 +701,10 @@ static int config_input(AVFilterLink *inlink) if (s->depth > 8) for (p = 0; p < s->nb_planes; p++) s->filter[p] = filter16_sobel; + } else if (!strcmp(ctx->filter->name, "kirsch")) { + if (s->depth > 8) + for (p = 0; p < s->nb_planes; p++) + s->filter[p] = filter16_kirsch; } return 0; @@ -744,6 +845,17 @@ static av_cold int init(AVFilterContext *ctx) s->rdiv[i] = s->scale; s->bias[i] = s->delta; } + } else if (!strcmp(ctx->filter->name, "kirsch")) { + for (i = 0; i < 4; i++) { + if ((1 << i) & s->planes) + s->filter[i] = filter_kirsch; + else + s->copy[i] = 1; + s->size[i] = 3; + s->setup[i] = setup_3x3; + s->rdiv[i] = s->scale; + s->bias[i] = s->delta; + } } return 0; @@ -864,4 +976,25 @@ AVFilter ff_vf_roberts = { }; #endif /* CONFIG_ROBERTS_FILTER */ + +#if CONFIG_KIRSCH_FILTER + +#define kirsch_options prewitt_roberts_sobel_options +AVFILTER_DEFINE_CLASS(kirsch); + +AVFilter ff_vf_kirsch = { + .name = "kirsch", + .description = NULL_IF_CONFIG_SMALL("Apply kirsch operator."), + .priv_size = sizeof(ConvolutionContext), + .priv_class = &kirsch_class, + .init = init, + .query_formats = query_formats, + .inputs = convolution_inputs, + .outputs = convolution_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, +}; + +#endif /* CONFIG_KIRSCH_FILTER */ + #endif /* CONFIG_PREWITT_FILTER || CONFIG_ROBERTS_FILTER || CONFIG_SOBEL_FILTER */ -- 2.17.1 _______________________________________________ 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".