mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-26 19:01:44 +02:00
lavfi/edge_common: Templatify ff_gaussian_blur and ff_sobel
This commit is contained in:
parent
1001bdc504
commit
cf1f574431
@ -46,33 +46,13 @@ static int get_rounded_direction(int gx, int gy)
|
||||
return DIRECTION_VERTICAL;
|
||||
}
|
||||
|
||||
// Simple sobel operator to get rounded gradients
|
||||
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)
|
||||
{
|
||||
int i, j;
|
||||
#undef DEPTH
|
||||
#define DEPTH 8
|
||||
#include "edge_template.c"
|
||||
|
||||
for (j = 1; j < h - 1; j++) {
|
||||
dst += dst_linesize;
|
||||
dir += dir_linesize;
|
||||
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];
|
||||
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];
|
||||
|
||||
dst[i] = FFABS(gx) + FFABS(gy);
|
||||
dir[i] = get_rounded_direction(gx, gy);
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef DEPTH
|
||||
#define DEPTH 16
|
||||
#include "edge_template.c"
|
||||
|
||||
// Filters rounded gradients to drop all non-maxima
|
||||
// Expects gradients generated by ff_sobel()
|
||||
@ -137,45 +117,3 @@ void ff_double_threshold(int low, int high, int w, int h,
|
||||
src += src_linesize;
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
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];
|
||||
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[i ];
|
||||
dst[i + 1] = src[i + 1];
|
||||
|
||||
dst += dst_linesize;
|
||||
src += src_linesize;
|
||||
}
|
||||
memcpy(dst, src, w); dst += dst_linesize; src += src_linesize;
|
||||
memcpy(dst, src, w);
|
||||
}
|
||||
|
@ -48,10 +48,14 @@ enum AVRoundedDirection {
|
||||
* @param src data pointers to source image
|
||||
* @param src_linesize linesizes for the source image
|
||||
*/
|
||||
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);
|
||||
#define PROTO_SOBEL(depth) \
|
||||
void ff_sobel_##depth(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);
|
||||
|
||||
PROTO_SOBEL(8)
|
||||
PROTO_SOBEL(16)
|
||||
|
||||
/**
|
||||
* Filters rounded gradients to drop all non-maxima pixels in the magnitude image
|
||||
@ -100,8 +104,12 @@ void ff_double_threshold(int low, int high, int w, int h,
|
||||
* @param src data pointers to source image
|
||||
* @param src_linesize linesizes for the source image
|
||||
*/
|
||||
void ff_gaussian_blur(int w, int h,
|
||||
uint8_t *dst, int dst_linesize,
|
||||
const uint8_t *src, int src_linesize);
|
||||
#define PROTO_GAUSSIAN_BLUR(depth) \
|
||||
void ff_gaussian_blur_##depth(int w, int h, \
|
||||
uint8_t *dst, int dst_linesize, \
|
||||
const uint8_t *src, int src_linesize, int src_stride);
|
||||
|
||||
PROTO_GAUSSIAN_BLUR(8)
|
||||
PROTO_GAUSSIAN_BLUR(16)
|
||||
|
||||
#endif
|
||||
|
118
libavfilter/edge_template.c
Normal file
118
libavfilter/edge_template.c
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Thilo Borgmann <thilo.borgmann _at_ mail.de>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*/
|
||||
|
||||
#include "libavutil/avassert.h"
|
||||
#include "avfilter.h"
|
||||
#include "formats.h"
|
||||
#include "internal.h"
|
||||
#include "video.h"
|
||||
|
||||
#undef pixel
|
||||
#if DEPTH == 8
|
||||
#define pixel uint8_t
|
||||
#else
|
||||
#define pixel uint16_t
|
||||
#endif
|
||||
|
||||
#undef fn
|
||||
#undef fn2
|
||||
#undef fn3
|
||||
#define fn3(a,b) ff_##a##_##b
|
||||
#define fn2(a,b) fn3(a,b)
|
||||
#define fn(a) fn2(a, DEPTH)
|
||||
|
||||
void fn(sobel)(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)
|
||||
{
|
||||
pixel *srcp = (pixel *)src;
|
||||
|
||||
src_stride /= sizeof(pixel);
|
||||
src_linesize /= sizeof(pixel);
|
||||
dst_linesize /= sizeof(pixel);
|
||||
|
||||
for (int j = 1; j < h - 1; j++) {
|
||||
dst += dst_linesize;
|
||||
dir += dir_linesize;
|
||||
srcp += src_linesize;
|
||||
for (int i = 1; i < w - 1; i++) {
|
||||
const int gx =
|
||||
-1*srcp[-src_linesize + (i-1)*src_stride] + 1*srcp[-src_linesize + (i+1)*src_stride]
|
||||
-2*srcp[ (i-1)*src_stride] + 2*srcp[ (i+1)*src_stride]
|
||||
-1*srcp[ src_linesize + (i-1)*src_stride] + 1*srcp[ src_linesize + (i+1)*src_stride];
|
||||
const int gy =
|
||||
-1*srcp[-src_linesize + (i-1)*src_stride] + 1*srcp[ src_linesize + (i-1)*src_stride]
|
||||
-2*srcp[-src_linesize + (i )*src_stride] + 2*srcp[ src_linesize + (i )*src_stride]
|
||||
-1*srcp[-src_linesize + (i+1)*src_stride] + 1*srcp[ src_linesize + (i+1)*src_stride];
|
||||
|
||||
dst[i] = FFABS(gx) + FFABS(gy);
|
||||
dir[i] = get_rounded_direction(gx, gy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fn(gaussian_blur)(int w, int h,
|
||||
uint8_t *dst, int dst_linesize,
|
||||
const uint8_t *src, int src_linesize, int src_stride)
|
||||
{
|
||||
pixel *srcp = (pixel *)src;
|
||||
pixel *dstp = (pixel *)dst;
|
||||
|
||||
src_stride /= sizeof(pixel);
|
||||
src_linesize /= sizeof(pixel);
|
||||
dst_linesize /= sizeof(pixel);
|
||||
|
||||
memcpy(dstp, srcp, w*sizeof(pixel)); dstp += dst_linesize; srcp += src_linesize;
|
||||
memcpy(dstp, srcp, w*sizeof(pixel)); dstp += dst_linesize; srcp += src_linesize;
|
||||
for (int j = 2; j < h - 2; j++) {
|
||||
dstp[0] = srcp[(0)*src_stride];
|
||||
dstp[1] = srcp[(1)*src_stride];
|
||||
for (int i = 2; i < w - 2; i++) {
|
||||
/* Gaussian mask of size 5x5 with sigma = 1.4 */
|
||||
dstp[i] = ((srcp[-2*src_linesize + (i-2)*src_stride] + srcp[2*src_linesize + (i-2)*src_stride]) * 2
|
||||
+ (srcp[-2*src_linesize + (i-1)*src_stride] + srcp[2*src_linesize + (i-1)*src_stride]) * 4
|
||||
+ (srcp[-2*src_linesize + (i )*src_stride] + srcp[2*src_linesize + (i )*src_stride]) * 5
|
||||
+ (srcp[-2*src_linesize + (i+1)*src_stride] + srcp[2*src_linesize + (i+1)*src_stride]) * 4
|
||||
+ (srcp[-2*src_linesize + (i+2)*src_stride] + srcp[2*src_linesize + (i+2)*src_stride]) * 2
|
||||
|
||||
+ (srcp[ -src_linesize + (i-2)*src_stride] + srcp[ src_linesize + (i-2)*src_stride]) * 4
|
||||
+ (srcp[ -src_linesize + (i-1)*src_stride] + srcp[ src_linesize + (i-1)*src_stride]) * 9
|
||||
+ (srcp[ -src_linesize + (i )*src_stride] + srcp[ src_linesize + (i )*src_stride]) * 12
|
||||
+ (srcp[ -src_linesize + (i+1)*src_stride] + srcp[ src_linesize + (i+1)*src_stride]) * 9
|
||||
+ (srcp[ -src_linesize + (i+2)*src_stride] + srcp[ src_linesize + (i+2)*src_stride]) * 4
|
||||
|
||||
+ srcp[(i-2)*src_stride] * 5
|
||||
+ srcp[(i-1)*src_stride] * 12
|
||||
+ srcp[(i )*src_stride] * 15
|
||||
+ srcp[(i+1)*src_stride] * 12
|
||||
+ srcp[(i+2)*src_stride] * 5) / 159;
|
||||
}
|
||||
dstp[w - 2] = srcp[(w - 2)*src_stride];
|
||||
dstp[w - 1] = srcp[(w - 1)*src_stride];
|
||||
|
||||
dstp += dst_linesize;
|
||||
srcp += src_linesize;
|
||||
}
|
||||
memcpy(dstp, srcp, w*sizeof(pixel)); dstp += dst_linesize; srcp += src_linesize;
|
||||
memcpy(dstp, srcp, w*sizeof(pixel));
|
||||
}
|
@ -283,12 +283,12 @@ static int blurdetect_filter_frame(AVFilterLink *inlink, AVFrame *in)
|
||||
nplanes++;
|
||||
|
||||
// gaussian filter to reduce noise
|
||||
ff_gaussian_blur(w, h,
|
||||
filterbuf, w,
|
||||
in->data[plane], in->linesize[plane]);
|
||||
ff_gaussian_blur_8(w, h,
|
||||
filterbuf, w,
|
||||
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_8(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
|
||||
|
@ -191,15 +191,15 @@ 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]);
|
||||
ff_gaussian_blur_8(width, height,
|
||||
tmpbuf, width,
|
||||
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);
|
||||
ff_sobel_8(width, height,
|
||||
gradients, width,
|
||||
directions,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 */
|
||||
|
Loading…
Reference in New Issue
Block a user