FFmpeg
Classes | Macros | Typedefs | Functions | Variables
vf_removelogo.c File Reference

Advanced blur-based logo removing filter. More...

#include "libavutil/imgutils.h"
#include "libavutil/opt.h"
#include "avfilter.h"
#include "formats.h"
#include "internal.h"
#include "video.h"
#include "bbox.h"
#include "lavfutils.h"
#include "lswsutils.h"

Classes

struct  RemovelogoContext
 This code implements a filter to remove annoying TV logos and other annoying images placed onto a video stream. More...
 

Macros

#define OFFSET(x)   offsetof(RemovelogoContext, x)
 
#define FLAGS   AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
 
#define apply_mask_fudge_factor(x)   (((x) >> 2) + (x))
 Choose a slightly larger mask size to improve performance. More...
 
#define SHOW_LOGO_INFO(mask_type)
 

Typedefs

typedef struct RemovelogoContext RemovelogoContext
 This code implements a filter to remove annoying TV logos and other annoying images placed onto a video stream. More...
 

Functions

 AVFILTER_DEFINE_CLASS (removelogo)
 

Variables

AVFilter ff_vf_removelogo
 

Detailed Description

Advanced blur-based logo removing filter.

This filter loads an image mask file showing where a logo is and uses a blur transform to remove the logo.

Based on the libmpcodecs remove-logo filter by Robert Edele.

Macro Definition Documentation

§ apply_mask_fudge_factor

#define apply_mask_fudge_factor (   x)    (((x) >> 2) + (x))

Choose a slightly larger mask size to improve performance.

This function maps the absolute minimum mask size needed to the mask size we'll actually use. f(x) = x (the smallest that will work) will produce the sharpest results, but will be quite jittery. f(x) = 1.25x (what I'm using) is a good tradeoff in my opinion. This will calculate only at init-time, so you can put a long expression here without effecting performance.

§ SHOW_LOGO_INFO

#define SHOW_LOGO_INFO (   mask_type)
Value:
av_log(ctx, AV_LOG_VERBOSE, #mask_type " x1:%d x2:%d y1:%d y2:%d max_mask_size:%d\n", \
s->mask_type##_mask_bbox.x1, s->mask_type##_mask_bbox.x2, \
s->mask_type##_mask_bbox.y1, s->mask_type##_mask_bbox.y2, \
mask_type##_max_mask_size);
void av_log(void *avcl, int level, const char *fmt,...) av_printf_format(3
Send the specified message to the log if the level is less than or equal to the current av_log_level...
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192

Typedef Documentation

§ RemovelogoContext

This code implements a filter to remove annoying TV logos and other annoying images placed onto a video stream.

It works by filling in the pixels that comprise the logo with neighboring pixels. The transform is very loosely based on a gaussian blur, but it is different enough to merit its own paragraph later on. It is a major improvement on the old delogo filter as it both uses a better blurring algorithm and uses a bitmap to use an arbitrary and generally much tighter fitting shape than a rectangle.

The logo removal algorithm has two key points. The first is that it distinguishes between pixels in the logo and those not in the logo by using the passed-in bitmap. Pixels not in the logo are copied over directly without being modified and they also serve as source pixels for the logo fill-in. Pixels inside the logo have the mask applied.

At init-time the bitmap is reprocessed internally, and the distance to the nearest edge of the logo (Manhattan distance), along with a little extra to remove rough edges, is stored in each pixel. This is done using an in-place erosion algorithm, and incrementing each pixel that survives any given erosion. Once every pixel is eroded, the maximum value is recorded, and a set of masks from size 0 to this size are generaged. The masks are circular binary masks, where each pixel within a radius N (where N is the size of the mask) is a 1, and all other pixels are a 0. Although a gaussian mask would be more mathematically accurate, a binary mask works better in practice because we generally do not use the central pixels in the mask (because they are in the logo region), and thus a gaussian mask will cause too little blur and thus a very unstable image.

The mask is applied in a special way. Namely, only pixels in the mask that line up to pixels outside the logo are used. The dynamic mask size means that the mask is just big enough so that the edges touch pixels outside the logo, so the blurring is kept to a minimum and at least the first boundary condition is met (that the image function itself is continuous), even if the second boundary condition (that the derivative of the image function is continuous) is not met. A masking algorithm that does preserve the second boundary coundition (perhaps something based on a highly-modified bi-cubic algorithm) should offer even better results on paper, but the noise in a typical TV signal should make anything based on derivatives hopelessly noisy.

Variable Documentation

§ ff_vf_removelogo

AVFilter ff_vf_removelogo
Initial value:
= {
.name = "removelogo",
.description = NULL_IF_CONFIG_SMALL("Remove a TV logo based on a mask image."),
.priv_size = sizeof(RemovelogoContext),
.init = init,
.uninit = uninit,
.query_formats = query_formats,
.inputs = removelogo_inputs,
.outputs = removelogo_outputs,
.priv_class = &removelogo_class,
}
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
Some filters support a generic "enable" expression option that can be used to enable or disable a fil...
Definition: avfilter.h:125
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
struct RemovelogoContext RemovelogoContext
This code implements a filter to remove annoying TV logos and other annoying images placed onto a vid...