Ich habe mich in der letzten Zeit, wie einige von euch evtl.
schon auf forum.doom9.org mitbekommen haben, mit einer neuen
Methode beschäftigt, um Videos zu deinterlacen.
Zur Vorgeschichte:
Ich bastle hier seit einiger Zeit mit Videos rum,
die blended-fields haben, also Videos die eine Normwandlung
oder andere Framratenkonvertierungen durchlaufen haben.
Bevor man diese Videos behandeln kann, muss man sie auf
Fullframerate deinterlacen. Am einfachsten ginge das mit
Sicherheit mit:
- bob() , das wuerde aber ein unsaegliches flimmern ins video bringen
- dgbob(order=1), aber das bringt ganz unschoene Treppchen ins Video
- kernelbob(5), verbessert die Treppchenproblematik und verringert flimmern
tun, alle sind aber alles andere als Optimal.
Mein Script sucht nach dem passenden Nachbarhalbbild, bevor es
ueberhaupt anfaengt zu deinterlacen, dadurch werden wirklich
nur die Bildbereiche deinterlaced, die sich wirklich veraendern.
Dadurch wird mein deinterlacer zu einer Art Telecide fuer Fullframerate.
Desweitern benutze ich zur interpolation der intrlacedten Bildbereiche
eine Mischung aus kernel-deinterlacing und tomsmocomp-deinterlacing,
das vereint die Vorteile von kerneldeint (erhoehte aufloesung, weniger flicker)
und tomsmocomp (saubere Kanten, weniger Treppcheneffekte).
Das Script:
[size=8]# Test-Mask-Deinterlacer (for Restore24)function Tomsbobsoft(clip c){ input=c.separatefields.tomsmocomp(1,-1,1) a = getparity(input) ? input.selectodd : input.selecteven b = getparity(input) ? input.selecteven : input.selectodd a=stackvertical(a.crop(0,0,0,1-a.height),a.crop(0,0,0,-1)) output = getparity(input) ? interleave(b,a) : interleave(a,b) output.assumeframebased}# Pre-Deinterlacer for Bobmatcher# can also be used as standalone-bobber# Kernelbob, using kernel-interpolation for achieving# a higher resolution at slow-, and nonmoving locationsfunction kernelbob(clip a, int th){ ord = getparity(a) ? 1 : 0 f=a.kerneldeint(order=ord, sharp=true, twoway=true, threshold=th) e=a.separatefields.trim(1,0).weave.kerneldeint(order=1-ord, sharp=true, twoway=true, threshold=th) interleave(f,e).assumeframebased}# TMCbob, uses tomsmocomp-interpolation for getting # diagonal lines with reduced stairsteppingfunction TMCbob(clip c){ ord = getparity(c) ? 1 : 0 c = c.SeparateFields.TomsMoComp(1,-1,0) c = stackvertical(c.crop(0,0,0,1-c.height),c,c.crop(0,c.height-1,0,0)) evn = c.SelectEven odd = c.SelectOdd evn = (ord == 0) ? evn : evn.crop(0,1,0,0).addborders(0,0,0,1) odd = (ord == 1) ? odd : odd.crop(0,1,0,0).addborders(0,0,0,1) interleave(evn,odd).crop(0,0,0,-2).assumeframebased()}# Hehe, the TV-Simulator:function TVdeint(clip clip, float kell){ clip=clip.addborders(0,4,0,4) input=clip.converttoyuy2().separatefields() blank=blankclip(selecteven(input)) even=interleave(selecteven(input),blank).weave() odd =interleave(selectodd(input) ,blank).weave() output=interleave(even,odd) kell = (kell < 0 ) || (kell > 1) ? 0 : kell (kell == 0) ? output : output.blur(0,kell).levels(0,1,255-int(128*kell),0,255) crop(0,4,0,-4)}# And finally: the bobmatcherfunction bobmatcher(clip fg, int "md", int "deintth", bool "showmask", bool "showmatch", bool "domatch",float "matchth", int "bobmethod"){# add borders to prevent the border-bug of motionmask fg.AddBorders(8,0,8,0) x1=last .converttoyuy2(interlaced=true)# set vars md = default(md,3) deintth = default(deintth,3)# maskedtmc = default(maskedtmc,true) matchth = default(matchth, 0.3) showmask = default(showmask,false) showmatch = default(showmatch,false) domatch = default(domatch,true) bobmethod = default(bobmethod,128)# create bobbing motionmask evn = x1.motionmask(md,deintth) odd = x1.doubleweave.selectodd.motionmask(md,deintth) mask = interleave(evn,odd)# create bobbed clip# bobmethod = 0 only uses kernelbob for getting the interpolated data# bobmethod = 255 only uses TMCbob# bobmethod = 1..254 uses a weighted mix of kernelbob and TMCbob for getting # the interpolated data, 128 creates a 1:1-blend (default) bobx = (bobmethod == 0 ) ? x1.kernelbob(5) : \ (bobmethod == 255) ? x1.tmcbob() : \ layer(x1.kernelbob(5),x1.tmcbob(),"add",level=bobmethod) bobx = showmask ? bobx.coloryuv(gain_v=-48) : bobx# create doubleweaved clip douw = x1.doubleweave douw = showmask ? douw.coloryuv(gain_u=48) : douw# calculate smartbobbed streams:# using previous field to get the interpolation of the current fieldglobal out1 = maskedmix(douw,bobx.trim(1,0),mask)# using next field to get the interpolation of the current fieldglobal out2 = maskedmix(douw,bobx,mask).trim(1,0)# setup mask for matchingglobal mask1 = mask.converttoyv12global mask2 = mask1.trim(1,0)# if masks are to similar (No Matching), blend both bobbed streams together for best outputglobal outnomatch = overlay(out2,out1,opacity=0.5,mode="blend")# create debug messagesglobal outnomatch = showmatch ? \outnomatch.subtitle("Using Both Fields - No Matching") : outnomatchglobal out1 = showmatch ? out1.subtitle("Using Previous Field") : out1global out2 = showmatch ? out2.subtitle("Using Next Field") : out2# do the matchingglobal outmatch = domatch ? ConditionalFilter(out1, out2, "averageluma(mask1)", \ "<", "averageluma(mask2)") : outnomatch# disable matching, if lumadifference between the prev-mask and the next-mask is smaller than p*100 percentglobal p = matchth o6 = ScriptClip(blankclip(out1), "outx") o8 = FrameEvaluate(o6, "global outx = ((AL1*(1+p) > AL2) && (AL2 > AL1*(1-p))) ? outnomatch : outmatch") o9 = Frameevaluate(o8,"global AL1 = averageluma(mask1)") out= Frameevaluate(o9,"global AL2 = averageluma(mask2)")# do some final things to get the output in sync with other bobbers out = bobx.trim(0,-3) + out.assumeframebased().trim(2,0) out.Crop(8,0,-8,0)}[/size]
Ihr solltet die richtige Fieldorder vor dem Deinterlacen festlegen!
Dazu reicht es, entweder AssumeTFF oder AssumeBFF
direkt nach dem Laden des Videos benutzen.
Die (optionalen) Parameter:
md Bestimmt den Modus, welcher der die Interlacing-Maske erstellt:
md = 1 : frame-differencing
md = 2 : field-differencing
md = 3 : frame & field-differencing (default)
deintth bestimmt den Interlacing Schwellwert
kleinere Werte deinterlacen mehr, fuehren aber auch zu staerkerem flimmern
groszere Werte deinterlacen weniger, hinterlassen aber moeglicherweise Kaemme
default = 3
matchth stellt den schwellwert fuer das ausschalten des automatischen
Matching der Halbbilder ein, damit echte video-sequenzen nicht durch
wildes hin-und-herspringen des Field-Matchers leiden
(default=0.3)
groeszere Werte geben mehr stabilietaet in video-szenen, verhindern aber
moeglicherweise das matching bei blended-szenen.
domatch wenn man diesen Parameter auf false setzt, wird das
Matching ausgeschaltet (normalerweise unnoetig) (default=true)
showmask wenn auf true gesetzt, zeigt der bobmatcher die
deinterlaced-bereiche an:
blaeulich = das Video bleibt unangetastet
gruenlich = das Video wird deinterlaced
(default = false)
showmatch Zeigt als Texteinblendung an, welches Halbbild
zum Deinterlacing herangezogen wird. Die Anzeigemoeglichkeiten sind:
- Using Next Field
- Using Previous Field
- Using Both Fields
(default=false)
bobmethod bestimmt, auf welche weise die interpolierten Bilddaten
erzeugt werden:
bobmethod = 0 benutzt nur den puren Kerneldeint
bobmethod = 255 benutzt nur tomsmocomp
bobmethod = 1..254 erzeugt eine gewichtete Mischung aus kerneldeint und tomsmocomp
128 ergibt einen 50:50 - Mix (default)
Beispiel