[FFmpeg-devel] [PATCH v2 1/2] lavfi/edge_common: Add 16bit versions of gaussian_blur and sobel
Thilo Borgmann
thilo.borgmann at mail.de
Mon Jul 11 11:53:20 EEST 2022
Hi,
1/2 adds 16 bit versions of ff_gaussian_blur and ff_sobel.
2/2 adds new mode to cropdetect.
Thanks,
Thilo
-------------- next part --------------
From fc8c179e2de4dee3d32d2e02684f3e3215af63c6 Mon Sep 17 00:00:00 2001
From: Thilo Borgmann <thilo.borgmann at mail.de>
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)
More information about the ffmpeg-devel
mailing list