Log in

View Full Version : Uneven strobing/banding in old TV footage


Morte66
25th January 2014, 13:30
I'm asking this more in hope than expectation...

I have a DVD of a ballet performance from Russian TV circa 1970. I think it's been blended, lost, buried in a peat bog, found, recycled as firelighters, and blended some more for DVD release. But it's the only way to see Vladimir Vasiliev dancing Spartacus.

Anyhow I bobbed it and SRestored to 25fps, which looks less bad than everything else I tried. I am left with a sort of strobing/banding effect which I think is caused by the frequency of the lights beating with the frequency of the camera. At least, it's strongest where the lighting is strongest and changes as the direction of the light changes. Here is a sample (https://dl.dropboxusercontent.com/u/80519209/Spartacus%201970.bob.srestore25.cut.mkv).

I wonder is there any sort of filter or script out there to tackle this? It looks very hard to do, but I know people wrote some pretty funky tools for getting things off video tape back in the day. Does anybody have a suggestion?

Here's a cut from the original (https://dl.dropboxusercontent.com/u/80519209/Spartacus.1970.cut.m2v) in case it helps.

martin53
25th January 2014, 15:08
I share your opinion about the cause and suggest you try Fitzick's DeFlicker plugin on the fields before you deinterlace.

*.mp4 guy
27th January 2014, 17:16
It is actually a tractable problem (http://forum.doom9.org/showthread.php?t=157353), though the solution isn't perfect.

No pictures, but this script should work pretty well, at least it does on the posted sample.
function dfir(clip c, string "kernel", int "taps", bool "gamma", int "fv", int "fh", float "kovrspl")
{
sharp1 = string(" -1 -2 -3 -4 -5 -6 -6 -7 220 -7 -6 -6 -5 -4 -3 -2 -1")

kernel_ = Default(kernel, string("1"))
kernel = string(Eval(kernel_))
taps = Default(taps, 8)
gamma = default(gamma, false)
fv = default(fv, -1)
fh = default(fh, -1)
kovrspl= default(kovrspl, 1)

in = c
out = in.Dither_convert_8_to_16
out = gamma ? out.Dither_y_gamma_to_linear : out
out = out.Dither_resize16(c.width, c.height, 0, 0, 0, 0, kernel="impulse "+string(Eval(kernel_))+"", kovrspl=kovrspl, taps=taps, fh=fh, fv=fv, center=false)
out = gamma ? out.Dither_y_linear_to_gamma : out
out = out.DitherPost

return(out)
}


#thr is strength, rad is "how big are the (whatevers)" offset is "how far apart are they" rad goes from 1 to 5, offset from 1 to 4, thr from 1 to bignumber
function DeStripe(Clip C, int "rad", int "offset", int "thr")
{

rad = Default(rad, 2)
offset = Default(offset, 0)
thr_ = Default(thr, 256)


Blurred = Rad == 1 ? C.Mt_Convolution(Horizontal=" 1 1 1 ", vertical = " 1 ", u=1, v=1) : C
Blurred = Rad == 2 ? offset == 0 ? C.Mt_Convolution(Horizontal=" 1 1 1 1 1 ", vertical = " 1 ", u=1, v=1) : C.Mt_Convolution(Horizontal=" 1 0 1 0 1 ", vertical = " 1 ", u=1, v=1) : Blurred
Blurred = Rad == 3 ? offset == 0 ? C.Mt_Convolution(Horizontal=" 1 1 1 1 1 1 1 ", vertical = " 1 ", u=1, v=1) : offset == 1 ? C.Mt_Convolution(Horizontal=" 1 1 0 1 0 1 1 ", vertical = " 1 ", u=1, v=1) : C.Mt_Convolution(Horizontal=" 1 0 0 1 0 0 1 ", vertical = " 1 ", u=1, v=1) : Blurred
Blurred = Rad == 4 ? offset == 0 ? C.Mt_Convolution(Horizontal=" 1 1 1 1 1 1 1 1 1 ", vertical = " 1 ", u=1, v=1) : offset == 1 ? C.Mt_Convolution(Horizontal=" 1 1 1 0 1 0 1 1 1 ", vertical = " 1 ", u=1, v=1) : offset == 2 ? C.Mt_Convolution(Horizontal=" 1 1 0 0 1 0 0 1 1 ", vertical = " 1 ", u=1, v=1) : C.Mt_Convolution(Horizontal=" 1 0 0 0 1 0 0 0 1 ", vertical = " 1 ", u=1, v=1) : Blurred
Blurred = Rad == 5 ? offset == 0 ? C.Mt_Convolution(Horizontal=" 1 1 1 1 1 1 1 1 1 1 1 ", vertical = " 1 ", u=1, v=1) : offset == 1 ? C.Mt_Convolution(Horizontal=" 1 1 1 1 0 1 0 1 1 1 1 ", vertical = " 1 ", u=1, v=1) : offset == 2 ? C.Mt_Convolution(Horizontal=" 1 1 1 0 0 1 0 0 1 1 1 ", vertical = " 1 ", u=1, v=1) : offset == 3 ? C.Mt_Convolution(Horizontal=" 1 1 0 0 0 1 0 0 0 1 1 ", vertical = " 1 ", u=1, v=1) : C.Mt_Convolution(Horizontal=" 1 0 0 0 0 1 0 0 0 0 1 ", vertical = " 1 ", u=1, v=1) : Blurred
Diff = Mt_Makediff(C, Blurred)

THR=string(thr_)
MedianDiff = Rad == 1 ? MT_Luts(Diff, Diff, mode="med", pixels = " 0 0 1 0 -1 0 " , expr = " X Y - X Y - X Y - abs 1 + * X Y - abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + / - 128 +", u=1,v=1) : Diff
MedianDiff = Rad == 2 ? offset == 0 ? MT_Luts(Diff, Diff, mode="med", pixels = " 0 0 1 0 -1 0 2 0 -2 0 " , expr = " X Y - X Y - X Y - abs 1 + * X Y - abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + / - 128 +", u=1,v=1) : MT_Luts(Diff, Diff, mode="med", pixels = " 0 0 2 0 -2 0 " , expr = " X Y - X Y - X Y - abs 1 + * X Y - abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + / - 128 +", u=1,v=1) : MedianDiff
MedianDiff = Rad == 3 ? offset == 0 ? MT_Luts(Diff, Diff, mode="med", pixels = " 0 0 1 0 -1 0 2 0 -2 0 3 0 -3 0 " , expr = " X Y - X Y - X Y - abs 1 + * X Y - abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + / - 128 +", u=1,v=1) : offset == 1 ? MT_Luts(Diff, Diff, mode="med", pixels = " 0 0 2 0 -2 0 3 0 -3 0 " , expr = " X Y - X Y - X Y - abs 1 + * X Y - abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + / - 128 +", u=1,v=1) : MT_Luts(Diff, Diff, mode="med", pixels = " 0 0 3 0 -3 0 " , expr = " X Y - X Y - X Y - abs 1 + * X Y - abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + / - 128 +", u=1,v=1) : MedianDiff
MedianDiff = Rad == 4 ? offset == 0 ? MT_Luts(Diff, Diff, mode="med", pixels = " 0 0 1 0 -1 0 2 0 -2 0 3 0 -3 0 4 0 -4 0 " , expr = " X Y - X Y - X Y - abs 1 + * X Y - abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + / - 128 +", u=1,v=1) : offset == 1 ? MT_Luts(Diff, Diff, mode="med", pixels = " 0 0 2 0 -2 0 3 0 -3 0 4 0 -4 0 " , expr = " X Y - X Y - X Y - abs 1 + * X Y - abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + / - 128 +", u=1,v=1) : offset == 2 ? MT_Luts(Diff, Diff, mode="med", pixels = " 0 0 3 0 -3 0 4 0 -4 0 " , expr = " X Y - X Y - X Y - abs 1 + * X Y - abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + / - 128 +", u=1,v=1) : MT_Luts(Diff, Diff, mode="med", pixels = " 0 0 4 0 -4 0 " , expr = " X Y - X Y - X Y - abs 1 + * X Y - abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + / - 128 +", u=1,v=1) : MedianDiff
MedianDiff = Rad == 5 ? offset == 0 ? MT_Luts(Diff, Diff, mode="med", pixels = " 0 0 1 0 -1 0 2 0 -2 0 3 0 -3 0 4 0 -4 0 5 0 -5 0 " , expr = " X Y - X Y - X Y - abs 1 + * X Y - abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + / - 128 +", u=1,v=1) : offset == 1 ? MT_Luts(Diff, Diff, mode="med", pixels = " 0 0 2 0 -2 0 3 0 -3 0 4 0 -4 0 5 0 -5 0 " , expr = " X Y - X Y - X Y - abs 1 + * X Y - abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + / - 128 +", u=1,v=1) : offset == 2 ? MT_Luts(Diff, Diff, mode="med", pixels = " 0 0 3 0 -3 0 4 0 -4 0 5 0 -5 0 " , expr = " X Y - X Y - X Y - abs 1 + * X Y - abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + / - 128 +", u=1,v=1) : offset == 3 ? MT_Luts(Diff, Diff, mode="med", pixels = " 0 0 4 0 -4 0 5 0 -5 0 " , expr = " X Y - X Y - X Y - abs 1 + * X Y - abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + / - 128 +", u=1,v=1) : MT_Luts(Diff, Diff, mode="med", pixels = " 0 0 5 0 -5 0 " , expr = " X Y - X Y - X Y - abs 1 + * X Y - abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + / - 128 +", u=1,v=1) : MedianDiff
ReconstructedMedian = mt_makediff(Diff, MedianDiff)
Mt_AddDiff(Blurred, ReconstructedMedian)

Return(Mergechroma(Last, C, 1))
}
#may be done before bob/srestore
assumetff()
separatefields()
greyscale()
turnleft
DeStripe(4,1,100)
DeStripe(3,0,100)
#DeStripe(5,0,16)
turnright
weave()

#must be done after bobbing
vaguedenoiser(threshold=0, chromat=0, method=4, nsteps=10, wavelet=2, wiener=true, wratio=0.5, percent=90)
hqdn3d(0.33, 0.33, 2.5, 2.5)
dfir("sharp1", fh=1)
unsharp(vary=6, strength=0.25)

Morte66
27th January 2014, 21:26
Thanks guys.

@martin53: That didn't seem to especially target the striping in particular, but it Deflicker did generally make it more agreeable.

@m4g: That's a huge (remarkable) impact on the striping in the clip I posted, but alas it seems the striping varies (in width and spacing) according to the lighting. So the script needs setting up for individual sections. I'm going to have a look and see if the lighting is just per act, i.e. 3 or 4 changes which I could handle, or it changes continually. Also, where is your "unsharp(vary=6, strength=0.25)" filter from? I presume it's an unsharp masp sharpener?

*.mp4 guy
28th January 2014, 02:54
Unsharp is part of the variable blur package. The version you want should be here (http://forum.doom9.org/showthread.php?p=1591538#post1591538).

As far as the variability of the striping is concerned, this function is very very forgiving compared to the alternatives. It's almost certainly possibly to put something together that will do pretty well on the majority of the footage, though doing so will still take a bit of work.

Morte66
5th February 2014, 08:57
Unsharp is part of the variable blur package. The version you want should be here (http://forum.doom9.org/showthread.php?p=1591538#post1591538).

As far as the variability of the striping is concerned, this function is very very forgiving compared to the alternatives. It's almost certainly possibly to put something together that will do pretty well on the majority of the footage, though doing so will still take a bit of work.

Thanks m4g, I got a decently un-stripey version out. It's a bit soft, but I think that's inevitable since most of the perceived sharpness in the original was film/video/DVD junk rather than real detail.