Log in

View Full Version : New bobbing deinterlacer (especially for blended clips)


scharfis_brain
24th February 2004, 11:25
Everytime i deinterlaced artificial interlaced progressive streams
(the long form of blended streams), I recognized, that every bobber
out there is not able to handle the phase-shift in the video.
This means, that false-phased parts of the video are always getting
deinterlaced, thus reducing image quality and resolution.

My bobber is something like a (very) simple telecide. But in
comparision to telecide, it will return a fullframerate clip that
provides a higher quality due to the internal field-matching

here is the script:
# 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 locations

function 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 stairstepping

function 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 bobmatcher

function 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 field

global out1 = maskedmix(douw,bobx.trim(1,0),mask)

# using next field to get the interpolation of the current field

global out2 = maskedmix(douw,bobx,mask).trim(1,0)

# setup mask for matching

global mask1 = mask.converttoyv12
global mask2 = mask1.trim(1,0)

# if masks are to similar (No Matching), blend both bobbed streams together for best output

global outnomatch = overlay(out2,out1,opacity=0.5,mode="blend")

# create debug messages

global outnomatch = showmatch ?
\outnomatch.subtitle("Using Both Fields - No Matching") : outnomatch
global out1 = showmatch ? out1.subtitle("Using Previous Field") : out1
global out2 = showmatch ? out2.subtitle("Using Next Field") : out2

# do the matching

global 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 percent

global 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)
}

please be sure to have set up the fieldorder right before calling bobmatcher. assumetff or assumebff are okay...

Okay, lets get us to the parameters:

md sets the mode, which creates the interlacing-mask:
md = 1 : frame-differencing
md = 2 : field-differencing
md = 3 : frame & field-differencing (default)


deintth sets the interlacing threshold.
lower values are making it moresensitive for motion and noise
default = 3


matchth sets the threshold to prevent the deinterlacer from
irrgeular field-jumping in pure video-scenes (default=0.3)
higher values gives more stability in video, but lesser fieldmatching
in telecined parts.

domatch disables matching, if set to false (default=true)

showmask if true, it makes interpolated areas visible (default=false)
blueish = video is passed through as it is
greenish = video gets deinterlaced

showmatch if true it shows, which field is used to match on
the current one (default=false)

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
bobmethod = 128 is default

example:

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("wall.d2v",cpu=4,iPP=true).crop(0,76,0,-76)

bobmatcher()

avih
24th February 2004, 11:32
i love your avatar ;)

scharfis_brain
25th February 2004, 18:28
Did nobody tested this thingie?


Okay, but I did :)

I found some smaller issues that I removed with this version:

see above

It removes a color-error of sangnom, when TFF-Video is used and makes matching optional.

by now I am searching for a method to disable the matching in true interlaced parts of a video (real 50fps or 60fps)
real video can be determined, if both interlacing masks have nearly the same averageluma.

the condition to match or not to matchis like this:

if ((AVGluma(mask1)*1.1 > AVGluma(mask2)) && (AVGluma(mask2) > AVGluma(mask1)*0.9)) then return outa else return matched_out


btw. this deinterlacer would be quite nice as preprocessor for hybrid clips 480line/60i to 720line/60p upconversion.

in telecined parts of a Video it will return non-deinterlaced FullFrames, even for phase-shifted material.

echooff
25th February 2004, 18:36
I noticed you are very active with avisynth code creation. Do you maintain a homepage for just your code?

scharfis_brain
25th February 2004, 19:40
I have a site, but it is very outdated.

http://home.arcor.de/scharfis_brain/

the only new thing is a German articel about PAL-Movie interlacing:
http://home.arcor.de/scharfis_brain/ExotischesInterlacing/

I think I should update this site with some of my scripts...

but this lazyness... :rolleyes:

back to my problem: can anybody help me?
I do not really get behind AVISynths conditional Filtering...

Bogalvator
26th February 2004, 03:47
I tried to test your script scharfis, but I'm obviously being stupid:

First it tells me MotionMask needs YV12. Even if I get round this by adding by changing

evn =x1.motionmask(md,th)

to

evn =x1.converttoyv12(interlaced=true).motionmask(md,th)
\.converttoyuy2(interlaced=true)

(and similar for odd = etc), it then says maskedmix is not a function, so I'm obviously missing a filter that is required.

I'm using AviSynth 2.5.5 Alpha + MaskTools 1.4.9 in the plugins directory

scharfis_brain
26th February 2004, 03:47
okay,next try.

updated script above.

EDIT: @Bogalvator:

you have to use the old mpeg2dec.dll...

load it after masktools and before mpeg2dec3

scharfis_brain
28th February 2004, 21:47
hopfully last update. see above

things changed:

- splitted tomsbobspecial into two fuctions
- replaced chroma of tomsbobspecial with chroma of tmcbob, because tomsbobspecial tends to smear chroma in high-motion scenes
- fixed some fieldorder-issues
- added a sangnom postprocessor to reduce remaining stairstepping on deinterlaced diagonal edges (slow, blurs the image a little bit)

Didée
28th February 2004, 22:25
And me was deadly sure, that this plumb "TomsBobSpecial"-dinosaur was good for nothing but throwing CPU-cycles down the drain ...

:eek:

Seems there was a grain of good idea between all those bugs :D

- Didée

scharfis_brain
28th February 2004, 22:49
I do not really step behind your tomsbobspecial...

but do you have the energy (and time) to prevent it from making those dotty effects (undot() seems to help here a little bit) on hard borders in fast moving scenes?

With bobmatcher and restore24 I was able to convert a fieldblended-video without any big deinterlacing-side-effects like stairstepping or remained combing.
Kernelbob or DGbob in comparision looked like :rolleyes: :eek: but they did their job much faster (who wonders)

scharfis_brain
29th February 2004, 18:50
oh-oh...next update

tested this thingie on some other clips with very poor results.

so I decided to replace the TMC with kernelbob.
this also speeded up the thing.

Script above

Yuri
2nd March 2004, 20:47
What could be possibly wrong with my script if I get the message that there is no function "Overlay"? Please.

scharfis_brain
2nd March 2004, 21:36
You're not using the actual version of ABISynth

Okay, I've changed my script to be usable with older AVISynth-Versions.

I've replaced overlay(out2,out1,...) with the old common layer - function

Now it should work with every AVISynth 2.5x

Mug Funky
3rd March 2004, 17:25
interesting. had a read through it, but haven't tested yet (it'll make my music go all clicky-clicky in foobar, and i like this CD).

is the generalconvolution step in the processor necessary? i've had good enough results with blur(0,1), and much faster without the colourspace conversion (although sh0dan is usually 1 step ahead of us with features in avisynth, generalconvolution remains RGB only, more's the pity).

could you upload the overlay version somewheres? it's soooo much faster.

if this works well it'll be JUST what i need. thanks for this (complicated) effort.

scharfis_brain
3rd March 2004, 20:50
the postprocessor needs the convo, because it shifts the image by 1/2 Pixel to maintain the correct image position

btw. this postprocessor doesn't seem to be that effetive regarding speeed am image quality :(

Yuri
3rd March 2004, 21:17
scharfis_brain,
thank you a lot! This IS very kind of you!

scharfis_brain
6th March 2004, 22:41
made some minor changes:

cutted out the postprocesser, it was nearly useless and wasted a lot of CPU-time

reintroduced TMCbob for interpolation

included a weighted mix of kernelinterpolation and tomsmocompinterpolation
to get the best of both ones.
bobmethod = 0 returns only a kernelbobbed interpolation with lesser flickering and higher resolution, but a lot of stairstepping in high-motion-areas

bobmethod = 255 returns the tomsbobbed interpolation only with extremely reduced stairstepping, but at the cost of some resolution and flickering of heigh detailed areas

values between 1 and 254 returns a weighted blend of both ones.
128 is a 50:50 blend and default

Mug Funky
9th March 2004, 07:02
this works wonders on my anime, but i'm noticing what looks to be blocking artefacts on some moving areas...?

i have no idea what in the script would be causing this though.

scharfis_brain
9th March 2004, 07:08
very easy to explain:
Its the interlacing-mask!

use showmask=true , like I described above and You'll see that.

I know about this Issue, But cant Do anything against this for now.

I just need some other method/plugin to build a reliable combmask, like kerneldeint or dgbob uses.

Can someone do a 'hack' into one of both, for only putting out the mask insteat of a deinterlaced picture?

Mug Funky
9th March 2004, 08:28
ah yes, interlace masks are a PITA. i'm trying to find a good (automated) way to create them, but it's not easy to distinguish between combs and high-frequency details.

believe me, when i find a comb masking technique that works (nearly) flawlessly, it'll be up here ASAP

Guest
6th April 2004, 06:11
Originally posted by Mug Funky
it's not easy to distinguish between combs and high-frequency details This man gets it. Tell me about it. :(

Audionut
14th September 2004, 07:30
I get the error.

I don't know what "mask 1" means
bobmather.avs, line 109

scharfis_brain
14th September 2004, 15:23
uh, this bobmather is fairly old and should not be used anymore.

better use intellibob() or tdeint() http://forum.doom9.org/showthread.php?s=&threadid=82264 for deinterlacing