From fc8c179e2de4dee3d32d2e02684f3e3215af63c6 Mon Sep 17 00:00:00 2001 From: Thilo Borgmann Date: Sun, 10 Jul 2022 12:40:27 +0200 Subject: [PATCH v2 1/2] lavfi/edge_common: Add 16bit versions of gaussian_blur and sobel --- libavfilter/edge_common.c | 134 ++++++++++++++++++++++++++++-------- libavfilter/edge_common.h | 14 +++- libavfilter/vf_blurdetect.c | 4 +- libavfilter/vf_edgedetect.c | 4 +- 4 files changed, 121 insertions(+), 35 deletions(-) diff --git a/libavfilter/edge_common.c b/libavfilter/edge_common.c index d72e8521cd..f0bf273b84 100644 --- a/libavfilter/edge_common.c +++ b/libavfilter/edge_common.c @@ -50,7 +50,7 @@ static int get_rounded_direction(int gx, int gy) void ff_sobel(int w, int h, uint16_t *dst, int dst_linesize, int8_t *dir, int dir_linesize, - const uint8_t *src, int src_linesize) + const uint8_t *src, int src_linesize, int src_stride) { int i, j; @@ -60,13 +60,43 @@ void ff_sobel(int w, int h, src += src_linesize; for (i = 1; i < w - 1; i++) { const int gx = - -1*src[-src_linesize + i-1] + 1*src[-src_linesize + i+1] - -2*src[ i-1] + 2*src[ i+1] - -1*src[ src_linesize + i-1] + 1*src[ src_linesize + i+1]; + -1*src[-src_linesize + (i-1)*src_stride] + 1*src[-src_linesize + (i+1)*src_stride] + -2*src[ (i-1)*src_stride] + 2*src[ (i+1)*src_stride] + -1*src[ src_linesize + (i-1)*src_stride] + 1*src[ src_linesize + (i+1)*src_stride]; const int gy = - -1*src[-src_linesize + i-1] + 1*src[ src_linesize + i-1] - -2*src[-src_linesize + i ] + 2*src[ src_linesize + i ] - -1*src[-src_linesize + i+1] + 1*src[ src_linesize + i+1]; + -1*src[-src_linesize + (i-1)*src_stride] + 1*src[ src_linesize + (i-1)*src_stride] + -2*src[-src_linesize + (i )*src_stride] + 2*src[ src_linesize + (i )*src_stride] + -1*src[-src_linesize + (i+1)*src_stride] + 1*src[ src_linesize + (i+1)*src_stride]; + + dst[i] = FFABS(gx) + FFABS(gy); + dir[i] = get_rounded_direction(gx, gy); + } + } +} + +void ff_sobel16(int w, int h, + uint16_t *dst, int dst_linesize, + int8_t *dir, int dir_linesize, + const uint8_t *src, int src_linesize, int src_stride) +{ + int i, j; + uint16_t *src16 = (uint16_t *)src; + int src16_stride = src_stride / 2; + int src16_linesize = src_linesize / 2; + + for (j = 1; j < h - 1; j++) { + dst += dst_linesize; + dir += dir_linesize; + src16 += src16_linesize; + for (i = 1; i < w - 1; i++) { + const int gx = + -1*src16[-src16_linesize + (i-1)*src16_stride] + 1*src16[-src16_linesize + (i+1)*src16_stride] + -2*src16[ (i-1)*src16_stride] + 2*src16[ (i+1)*src16_stride] + -1*src16[ src16_linesize + (i-1)*src16_stride] + 1*src16[ src16_linesize + (i+1)*src16_stride]; + const int gy = + -1*src16[-src16_linesize + (i-1)*src16_stride] + 1*src16[ src16_linesize + (i-1)*src16_stride] + -2*src16[-src16_linesize + (i )*src16_stride] + 2*src16[ src16_linesize + (i )*src16_stride] + -1*src16[-src16_linesize + (i+1)*src16_stride] + 1*src16[ src16_linesize + (i+1)*src16_stride]; dst[i] = FFABS(gx) + FFABS(gy); dir[i] = get_rounded_direction(gx, gy); @@ -141,37 +171,37 @@ void ff_double_threshold(int low, int high, int w, int h, // Applies gaussian blur, using 5x5 kernels, sigma = 1.4 void ff_gaussian_blur(int w, int h, uint8_t *dst, int dst_linesize, - const uint8_t *src, int src_linesize) + const uint8_t *src, int src_linesize, int src_stride) { int i, j; memcpy(dst, src, w); dst += dst_linesize; src += src_linesize; memcpy(dst, src, w); dst += dst_linesize; src += src_linesize; for (j = 2; j < h - 2; j++) { - dst[0] = src[0]; - dst[1] = src[1]; + dst[0] = src[(0)*src_stride]; + dst[1] = src[(1)*src_stride]; for (i = 2; i < w - 2; i++) { /* Gaussian mask of size 5x5 with sigma = 1.4 */ - dst[i] = ((src[-2*src_linesize + i-2] + src[2*src_linesize + i-2]) * 2 - + (src[-2*src_linesize + i-1] + src[2*src_linesize + i-1]) * 4 - + (src[-2*src_linesize + i ] + src[2*src_linesize + i ]) * 5 - + (src[-2*src_linesize + i+1] + src[2*src_linesize + i+1]) * 4 - + (src[-2*src_linesize + i+2] + src[2*src_linesize + i+2]) * 2 - - + (src[ -src_linesize + i-2] + src[ src_linesize + i-2]) * 4 - + (src[ -src_linesize + i-1] + src[ src_linesize + i-1]) * 9 - + (src[ -src_linesize + i ] + src[ src_linesize + i ]) * 12 - + (src[ -src_linesize + i+1] + src[ src_linesize + i+1]) * 9 - + (src[ -src_linesize + i+2] + src[ src_linesize + i+2]) * 4 - - + src[i-2] * 5 - + src[i-1] * 12 - + src[i ] * 15 - + src[i+1] * 12 - + src[i+2] * 5) / 159; + dst[i] = ((src[-2*src_linesize + (i-2)*src_stride] + src[2*src_linesize + (i-2)*src_stride]) * 2 + + (src[-2*src_linesize + (i-1)*src_stride] + src[2*src_linesize + (i-1)*src_stride]) * 4 + + (src[-2*src_linesize + (i )*src_stride] + src[2*src_linesize + (i )*src_stride]) * 5 + + (src[-2*src_linesize + (i+1)*src_stride] + src[2*src_linesize + (i+1)*src_stride]) * 4 + + (src[-2*src_linesize + (i+2)*src_stride] + src[2*src_linesize + (i+2)*src_stride]) * 2 + + + (src[ -src_linesize + (i-2)*src_stride] + src[ src_linesize + (i-2)*src_stride]) * 4 + + (src[ -src_linesize + (i-1)*src_stride] + src[ src_linesize + (i-1)*src_stride]) * 9 + + (src[ -src_linesize + (i )*src_stride] + src[ src_linesize + (i )*src_stride]) * 12 + + (src[ -src_linesize + (i+1)*src_stride] + src[ src_linesize + (i+1)*src_stride]) * 9 + + (src[ -src_linesize + (i+2)*src_stride] + src[ src_linesize + (i+2)*src_stride]) * 4 + + + src[(i-2)*src_stride] * 5 + + src[(i-1)*src_stride] * 12 + + src[(i )*src_stride] * 15 + + src[(i+1)*src_stride] * 12 + + src[(i+2)*src_stride] * 5) / 159; } - dst[i ] = src[i ]; - dst[i + 1] = src[i + 1]; + dst[i ] = src[(i )*src_stride]; + dst[i + 1] = src[(i + 1)*src_stride]; dst += dst_linesize; src += src_linesize; @@ -179,3 +209,49 @@ void ff_gaussian_blur(int w, int h, memcpy(dst, src, w); dst += dst_linesize; src += src_linesize; memcpy(dst, src, w); } + +void ff_gaussian_blur16(int w, int h, + uint8_t *dst, int dst_linesize, + const uint8_t *src, int src_linesize, int src_stride) +{ + int i, j; + uint16_t *src16 = (uint16_t *)src; + uint16_t *dst16 = (uint16_t *)dst; + int src16_stride = src_stride / 2; + int src16_linesize = src_linesize / 2; + int dst16_linesize = dst_linesize / 2; + + memcpy(dst16, src16, w*2); dst16 += dst16_linesize; src16 += src16_linesize; + memcpy(dst16, src16, w*2); dst16 += dst16_linesize; src16 += src16_linesize; + for (j = 2; j < h - 2; j++) { + dst16[0] = src16[(0)*src16_stride]; + dst16[1] = src16[(1)*src16_stride]; + for (i = 2; i < w - 2; i++) { + /* Gaussian mask of size 5x5 with sigma = 1.4 */ + dst16[i] = ((src16[-2*src16_linesize + (i-2)*src16_stride] + src16[2*src16_linesize + (i-2)*src16_stride]) * 2 + + (src16[-2*src16_linesize + (i-1)*src16_stride] + src16[2*src16_linesize + (i-1)*src16_stride]) * 4 + + (src16[-2*src16_linesize + (i )*src16_stride] + src16[2*src16_linesize + (i )*src16_stride]) * 5 + + (src16[-2*src16_linesize + (i+1)*src16_stride] + src16[2*src16_linesize + (i+1)*src16_stride]) * 4 + + (src16[-2*src16_linesize + (i+2)*src16_stride] + src16[2*src16_linesize + (i+2)*src16_stride]) * 2 + + + (src16[ -src16_linesize + (i-2)*src16_stride] + src16[ src16_linesize + (i-2)*src16_stride]) * 4 + + (src16[ -src16_linesize + (i-1)*src16_stride] + src16[ src16_linesize + (i-1)*src16_stride]) * 9 + + (src16[ -src16_linesize + (i )*src16_stride] + src16[ src16_linesize + (i )*src16_stride]) * 12 + + (src16[ -src16_linesize + (i+1)*src16_stride] + src16[ src16_linesize + (i+1)*src16_stride]) * 9 + + (src16[ -src16_linesize + (i+2)*src16_stride] + src16[ src16_linesize + (i+2)*src16_stride]) * 4 + + + src16[(i-2)*src16_stride] * 5 + + src16[(i-1)*src16_stride] * 12 + + src16[(i )*src16_stride] * 15 + + src16[(i+1)*src16_stride] * 12 + + src16[(i+2)*src16_stride] * 5) / 159; + } + dst16[i ] = src16[(i )*src16_stride]; + dst16[i + 1] = src16[(i + 1)*src16_stride]; + + dst16 += dst16_linesize; + src16 += src16_linesize; + } + memcpy(dst16, src16, w*2); dst16 += dst16_linesize; src16 += src16_linesize; + memcpy(dst16, src16, w*2); +} diff --git a/libavfilter/edge_common.h b/libavfilter/edge_common.h index 87c143f2b8..310d92a388 100644 --- a/libavfilter/edge_common.h +++ b/libavfilter/edge_common.h @@ -51,7 +51,13 @@ enum AVRoundedDirection { void ff_sobel(int w, int h, uint16_t *dst, int dst_linesize, int8_t *dir, int dir_linesize, - const uint8_t *src, int src_linesize); + const uint8_t *src, int src_linesize, int src_stride); + +void ff_sobel16(int w, int h, + uint16_t *dst, int dst_linesize, + int8_t *dir, int dir_linesize, + const uint8_t *src, int src_linesize, int src_stride); + /** * Filters rounded gradients to drop all non-maxima pixels in the magnitude image @@ -102,6 +108,10 @@ void ff_double_threshold(int low, int high, int w, int h, */ void ff_gaussian_blur(int w, int h, uint8_t *dst, int dst_linesize, - const uint8_t *src, int src_linesize); + const uint8_t *src, int src_linesize, int src_stride); + +void ff_gaussian_blur16(int w, int h, + uint8_t *dst, int dst_linesize, + const uint8_t *src, int src_linesize, int src_stride); #endif diff --git a/libavfilter/vf_blurdetect.c b/libavfilter/vf_blurdetect.c index 0e08ba96de..ed4fb29b31 100644 --- a/libavfilter/vf_blurdetect.c +++ b/libavfilter/vf_blurdetect.c @@ -285,10 +285,10 @@ static int blurdetect_filter_frame(AVFilterLink *inlink, AVFrame *in) // gaussian filter to reduce noise ff_gaussian_blur(w, h, filterbuf, w, - in->data[plane], in->linesize[plane]); + in->data[plane], in->linesize[plane], 1); // compute the 16-bits gradients and directions for the next step - ff_sobel(w, h, gradients, w, directions, w, filterbuf, w); + ff_sobel(w, h, gradients, w, directions, w, filterbuf, w, 1); // non_maximum_suppression() will actually keep & clip what's necessary and // ignore the rest, so we need a clean output buffer diff --git a/libavfilter/vf_edgedetect.c b/libavfilter/vf_edgedetect.c index 90390ceb3e..10397fb8dc 100644 --- a/libavfilter/vf_edgedetect.c +++ b/libavfilter/vf_edgedetect.c @@ -193,13 +193,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) /* gaussian filter to reduce noise */ ff_gaussian_blur(width, height, tmpbuf, width, - in->data[p], in->linesize[p]); + in->data[p], in->linesize[p], 1); /* compute the 16-bits gradients and directions for the next step */ ff_sobel(width, height, gradients, width, directions,width, - tmpbuf, width); + tmpbuf, width, 1); /* non_maximum_suppression() will actually keep & clip what's necessary and * ignore the rest, so we need a clean output buffer */ -- 2.20.1 (Apple Git-117)