HighQuality-Deinterlacing, die Zweite

  • 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:

    Code
    [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

    Code
    loadplugin("C:\x\kerneldeint140.dll")
    loadplugin("C:\x\tomsmocomp.dll")
    loadplugin("C:\x\mpeg2dec.dll") #must be loaded before mpeg2dec3!
    loadplugin("C:\x\mpeg2dec3.dll")
    mpeg2source("video.d2v",cpu=4,iPP=true).crop(0,76,0,-76)
    bobmatcher()
  • Hi Scharfi,

    hat sich eigentlich noch was im Bereich "Restore 24" getan, dort hast du ja auch ein Tweak in Doom9..org veröffentlicht, wo du 2 parameter eingebaut hast, welche eben auf deinen Bobmatcher etc. zugreifen.

    Ich hatte mal gestern einen neuen Test mit Rest.24 gemacht ... "StarTrek Vojager", aber irgendwie sind noch doppelte Frames drin, Bild bleibt also ab und zu 2 Frames lang stehen.

  • der bobmatcher ist nicht zwingend fuer restore24, er erhoeht nur die maxmial erreichbare qualitaet ein wenig.

    zum testen der erkennungsleistung sollte ein
    restore24(tomsbobspecial(),kernelbob(5))
    vollkommen ausreichen.

    zum finalen rendern sollte man dann
    kernelbob(5) durch bobmatcher() ersetzen.

    am restore24-kern habe ich garnichts geaendert, die erkennungsleistung ist dieselbe, wie die unmodifizierte Version. ich habe lediglich die deinterlacer fuer TFF und BFF aufbereitet.

    aber doppelte oder uebersprungene frames sind bei restore24 an der tagesordnung, wenn die entsprechende szene nichts zu erkennen hergibt.

    du koenntest allenfalls versuchen, im restore24-script die verkleinerung der edgemask mit bicubicresize verhindern, dadurch gibts mehr maske zu verarbeiten, aber auch mehr speicherverbrauch

  • kurzfassung:
    + sauschnell!
    - braucht unbedingt interlaced VY12 als input (nuetzt nur, wenn man schon YV12 vorzuliegen hat, sonst sinnlos)
    - schlechte, bzw. garkeine interpolation der Zeilen -> treppchenbildung
    (die interpolationsqualitaet gleicht der von dgbob)
    - schlechtes Thresholding, im bob-modus flimmerts gewaltig, und wenn man die thresholds erhoeht, geht das flimmern nur wenig zurueck, es treten aber vermehrt übriggebliebene Kaemme auf.

    Ligh: was fandest Du an diesen Deinterlacer denn so toll, ausser dass er so schnell ist?
    ich finde, dass man dann fast lieber zum normalen bob() greifen sollte.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!