You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	lavfi/edge_common: Templatify ff_gaussian_blur and ff_sobel
This commit is contained in:
		| @@ -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 */ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user