Log in

View Full Version : DualDelogo.avsi — automatic switching between alternating logos


shurik_pronkin
3rd April 2026, 07:47
DualDelogo.avsi — automatic switching between alternating logos

Sharing a helper function for a common scenario with old TV recordings: two (or more) logos alternate in blocks — e.g. channel logo for a minute, then production company logo for a minute, then back. Each needs its own InpaintDelogo mask, and you don't want to manually Trim() hundreds of segments.

DualDelogo detects which logo is present on each frame using RT_LumaCorrelation between the current frame and reference images, then applies the matching InpaintDelogo — or passes the frame through untouched if no logo is detected.

How it works:

1. You provide two clean masks (for InpaintDelogo) and two reference frames (BMP screenshots where each logo is visible).
2. On each frame, the function compares a detection region with both references using RT_LumaCorrelation.
3. Higher correlation → that logo is present → apply corresponding delogo.
4. If both correlations are below threshold → no logo → pass original frame.

The correlation-based approach is robust to varying scene content behind the logo because the logo text pattern contributes a consistent correlation signature regardless of background.

Requirements:
InpaintDelogo 3.7, RT_Stats, GRunT (all standard InpaintDelogo dependencies).

Minimal usage:

Import("DualDelogo.avsi")
LWLibavVideoSource("D:\film.mkv")
DualDelogo("logo1_clean.bmp", "logo2_clean.bmp", Loc="928,52,-0,-818")


Step-by-step:

1. Prepare clean masks for each logo (white-filled logo text on original frame background).

2. Run with Diag=true to see correlation values and tune the no-logo threshold:

Import("DualDelogo.avsi")
LWLibavVideoSource("D:\film.mkv")
DualDelogo("logo1_clean.bmp", "logo2_clean.bmp", \
Loc="928,52,-0,-818", Diag=true)

This shows c1, c2, max and detection result on every frame as OSD overlay.

3. Scroll through the film. On frames without any logo, note the max value. Set no_logo_th slightly above it:

DualDelogo("logo1_clean.bmp", "logo2_clean.bmp", \
Loc="928,52,-0,-818", no_logo_th=0.25)


Full parameter list:

DualDelogo(clip src, string mask1, string mask2,
string "Loc", # shared Loc covering both logos
string "ref1", string "ref2", # reference frames (default: mask1/mask2)
int "det_x", int "det_y", # detection region (default: 1150, 110)
int "det_w", int "det_h", # (default: 260, 100)
float "no_logo_th", # no-logo threshold (default: 0.30)
string "Mode1", string "Mode2", # InpaintDelogo Mode per logo (default: "Inpaint")
int "Analyze1", int "Analyze2", # if >0, use Analyze instead of Automask (default: 0)
bool "Diag") # OSD diagnostics (default: false)


Notes:

Loc must cover both logos with padding. Use the union of their bounding boxes + 40px.
ref1/ref2 default to the mask files themselves. Separate reference BMP files can give better detection if the clean masks have too much white fill.
det_x/y/w/h should be set to the area where the logos visually differ. Defaults work for upper-right corner logos. Adjust for your layout.
Detection is per-frame with zero state — no temporal smoothing. Since logos switch in blocks (not frame-by-frame), occasional single-frame misdetections at scene boundaries are invisible in playback.
Performance: AviSynth evaluates lazily, so only the chosen delogo branch is computed per frame. RT_LumaCorrelation on a 260×100 region adds negligible overhead.
For mixed modes (e.g. one logo opaque, another semi-transparent): Mode1="Inpaint", Mode2="both", Analyze2=3.


The function:

function DualDelogo(clip src, string mask1, string mask2, \
string "Loc", \
string "ref1", string "ref2", \
int "det_x", int "det_y", int "det_w", int "det_h", \
float "no_logo_th", \
string "Mode1", string "Mode2", \
int "Analyze1", int "Analyze2", \
bool "Diag")
{
Loc = default(Loc, "928,52,-0,-818")
ref1 = default(ref1, mask1)
ref2 = default(ref2, mask2)
det_x = default(det_x, 1150)
det_y = default(det_y, 110)
det_w = default(det_w, 260)
det_h = default(det_h, 100)
no_logo_th = default(no_logo_th, 0.30)
Mode1 = default(Mode1, "Inpaint")
Mode2 = default(Mode2, "Inpaint")
Analyze1 = default(Analyze1, 0)
Analyze2 = default(Analyze2, 0)
Diag = default(Diag, false)

r1 = ImageSource(ref1, end=0).ConvertToYV12(matrix="Rec709")
r2 = ImageSource(ref2, end=0).ConvertToYV12(matrix="Rec709")

d1 = (Analyze1 > 0) \
? src.InpaintDelogo(mask1, Loc=Loc, Analyze=Analyze1, Mode=Mode1) \
: src.InpaintDelogo(mask1, Loc=Loc, Automask=0, aMix=0, Mode=Mode1)

d2 = (Analyze2 > 0) \
? src.InpaintDelogo(mask2, Loc=Loc, Analyze=Analyze2, Mode=Mode2) \
: src.InpaintDelogo(mask2, Loc=Loc, Automask=0, aMix=0, Mode=Mode2)

return (Diag) \
? src.ScriptClip(function [r1, r2, det_x, det_y, det_w, det_h, no_logo_th] () {
c1 = RT_LumaCorrelation(r1, n2=0, x=det_x, y=det_y, w=det_w, h=det_h)
c2 = RT_LumaCorrelation(r2, n2=0, x=det_x, y=det_y, w=det_w, h=det_h)
mx = (c1 > c2) ? c1 : c2
tag = (mx < no_logo_th) ? "NO LOGO" : (c1 > c2) ? "LOGO 1" : "LOGO 2"
Subtitle("c1=" + String(c1,"%.3f") + " c2=" + String(c2,"%.3f") + \
" max=" + String(mx,"%.3f") + " th=" + String(no_logo_th,"%.2f") + \
"\n" + tag, lsp=0, size=28, text_color=$00FF88)
}) \
: src.ScriptClip(function [d1, d2, src, r1, r2, det_x, det_y, det_w, det_h, no_logo_th] () {
c1 = RT_LumaCorrelation(r1, n2=0, x=det_x, y=det_y, w=det_w, h=det_h)
c2 = RT_LumaCorrelation(r2, n2=0, x=det_x, y=det_y, w=det_w, h=det_h)
mx = (c1 > c2) ? c1 : c2
return (mx < no_logo_th) ? src : (c1 > c2) ? d1 : d2
})
}


Feedback welcome. If there's interest I can extend this to N logos (array-based) and add optional temporal smoothing.

StainlessS
3rd April 2026, 15:00
Sounds handy :)

Maybe you'de like to also post link to this thread in New Plugins and Utilities thread:-
https://forum.doom9.org/showthread.php?t=84481&page=19

johnmeyer
3rd April 2026, 16:27
Wow, that is an exceedingly cool function. I used to do restoration for collectors, back before everything was available on YouTube, and this would have been very handy.

VoodooFX
6th April 2026, 13:00
Thanks for the script.
I never encountered such alternating logos.

if >0, use Analyze instead of Automask (default: 0)

Analyze/Automask are completely different things, it makes same sense as - "use Blur instead of Normalize audio".

PS:
I've added a link to this in the main InpaintDelogo post.