Log in

View Full Version : restore telecined FILM, that has been blend deinterlaced


scharfis_brain
8th May 2004, 14:53
This function is able to automatically restore 24 fps out of a 30fps blended video,
that originally was interlaced telecined FILM.

the function:

function undoblendedtc(clip input)
{
# prepare clips
a=loop(input).trim(0,5)+input
b=a.trim(1,0)
c=a.trim(2,0)
global d=a.trim(3,0)
e=a.trim(4,0)

half=127
half1=128

# recreate the deblended frame out of 4 frames doing some subtractions
c2=subtract(d,e.levels(0,1,255,half,255)).levels(0,1,half,0,255)
c1=subtract(c,b.levels(0,1,255,half,255)).levels(0,1,half,0,255)
global cr=layer(c2,c1,"fast").subtitle("c").levels(1,1,255,0,249)

# create testclips to identify the blends
dc0=subtract(layer(e,c2,"fast"),d)
dc1=dc0.levels(0,1,half1,255,0)
dc2=dc0.levels(half1+1,3,255,0,255)
global dc=layer(dc1,dc2,"fast").converttoyv12()

cc0=subtract(layer(b,c1,"fast"),c)
cc1=cc0.levels(0,1,half1,255,0)
cc2=cc0.levels(half1+1,3,255,0,255)
global cc=layer(cc1,cc2,"fast").converttoyv12()


#conditionalfilter(cc,cr,d,"averageluma()","<","31.3")
#conditionalfilter(dc.trim(1,0),cr.trim(1,0),d,"averageluma()","<","31.3")

# replace the blended frames with the deblended ones
c10 = ScriptClip(c, "t")
c20 = FrameEvaluate(c10, "t=blendcc ? cr : t")
c30 = FrameEvaluate(c20, "t=blenddc ? cr.trim(1,0) : d")
c40 = FrameEvaluate(c30, "blenddc = (ALdc2 < ALdc1) && (ALdc2 < ALdc3) && (ALdc2 < ALdc0) && (ALdc2 < ALdc4) ")
c50 = FrameEvaluate(c40, "")
c51 = FrameEvaluate(c50, "blendcc = (ALcc2 < ALcc1) && (ALcc2 < ALcc3) && (ALcc2 < ALcc0) && (ALcc2 < ALcc4) ")
c52 = FrameEvaluate(c51, "")
c53 = FrameEvaluate(c52, "ALdc4=averageluma(dc.duplicateframe(0))")
c54 = FrameEvaluate(c53, "ALdc3=averageluma(dc)")
c55 = FrameEvaluate(c54, "ALdc1=averageluma(dc.trim(2,0))")
c56 = FrameEvaluate(c55, "ALdc0=averageluma(dc.trim(3,0))")
c57 = FrameEvaluate(c56, "ALdc2=averageluma(dc.trim(1,0))")
c58 = FrameEvaluate(c57, "")
c59 = FrameEvaluate(c58, "ALcc4=averageluma(cc.duplicateframe(0).duplicateframe(0))")
c60 = FrameEvaluate(c59, "ALcc3=averageluma(cc.duplicateframe(0))")
c70 = FrameEvaluate(c60, "ALcc1=averageluma(cc.trim(1,0))")
c80 = FrameEvaluate(c70, "ALcc0=averageluma(cc.trim(2,0))")
c90 = FrameEvaluate(c80, "ALcc2=averageluma(cc)")

c90.trim(2,0)

# diags
#d=d.converttoyv12()
#cr=cr.converttoyv12()
#f=stackvertical(d,cr,cc)
#g=stackvertical(d,cr.trim(1,0),dc.trim(1,0))
#stackhorizontal(g,f)
}




how the function works:

the input video almost looks like this:


FilmFrame: A B BC CD D E F FG GH H
Framenumber: a b c d e f g h i j



let's recreate FILMframe C:

at first recreate the part of C in frame d
C1 = 2*(d-e/2)

then recreate the part of C in frame c
C2 = 2*(c-b/2)

finally mix C1 & C2 to reduce noise and compression artifacts:
C = (C1+C2)/2


then we will try to do some blend-detection.
my first tries always were based using and edgemask to detect the blends, but this was
unreliable in low motion and som special cases.

now I recreate a blended frame out of the previously deblended frame:

this means d must equal to a blend of C2 (the part of C in frame c) and e [ ((C2+e)/2) ]
also c must equal to a blend of C1 (the part of C in frame d) and b [ ((C1+b)/2) ]

this means the following condition must fit:

(d == (C2+e)/2) ? C : d
(c == (C1+b)/2) ? C : c

but because were dealing not with numbers, we have to do more comparision:

I am building a difference map between d and ((C2+e)/2) and then do this comparision:

the luma of the current differencemap has to be smaller than the luma of its two previous frames
AND its two following frames.

If this condition is fit, the actual frame is a blend and gets replaced with C

the same is done using a difference map between c and ((C1+b)/2)

the output of the function will then look like this:


FilmFrame: A B C C D E F G G H
Framenumber: a b c d e f g h i j


finally you habe to apply decimate(5) after undoblendedtc() to get a smooth output.

Some limitations are present with the current method:

- on hybrid video, ie. music clips the methode wouldn't work fine
- on telecined film with LOTS of offset changes that function will leave blended frames on that offset changes
- flashes etc. aren't properly recognized making the output going crazy.

Mug Funky
8th May 2004, 16:47
argh! i'd like to try this out, but don't have any appropriate sources...

i suppose i could slow a PAL film down, telecine it and blend it back to PAL...

i suppose this doesn't work on hybrids? i find that deblending is only needed on hybrids in my situation - if i came across a DVD with blended NTSC film on it, i'd take it back :)

hmm... come to think of it, i think there's film bits in my NTSC copy of beethoven's 5th. i might take a look. (don't ask why there's an NTSC version for sale in r4, especially one that's quite obviously converted from PAL! this was early days of DVD. 1999 i think.)

[edit]
ah. i just read the part about hybrids on your post... nm

scharfis_brain
8th May 2004, 17:07
ah, figured out the hybrid thing, but have no ideas how to script it.


on a hybrid, always scenechanges are offset changes, too.

this means the current approach will leave blended or false recreated C-Frames in the output.

this is, because the current check for blends uses, 2 future and 2 past frames.

I think, the only solution to fix that may be, checking for a scene change.
If a scene change get detected, the blend detection has to be made using edgemasks (not reliable, too because the amount of edges changes on a scenechange, too)

btw. I have na real material, too.
It was just the ideain my head.


I either take a progressive film, telecine it to 60i and then do a blend-deinterlacing.
or I take an NTSC-music video and do ablend deinterlacing.