Mug Funky
1st October 2005, 04:03
hey all.
as some of you might know, i'm continually trying to figure out how to get a perfect hybrid NTSC to PAL conversion going in avisynth. i also tend to go all "head a splode" whenever i try to sit down and figure it out.
well, as a start, i've written an IVTC function using only masktools and avs internal functions.
because of how i plan to treat interlaced NTSC in future, this function outputs doubled frame rate (47.952 fps), but hasn't mismatched a field yet on the 1 clip i tested it on.
it's pretty slow, as it checks for the ideal decimation pattern per frame rather than per cycle, or ideally whenever a pattern break is encountered. i'm sure someone with a less linear brain could make this a whole lot faster :) (scharfi or didee come to mind... i'm too lazy at the moment, but once my current project-from-hell is over with i'll have some more thinking time).
here's the very-messy-but-works-as-proof-of-concept script:
function blindmatch (clip c,float "thresh")
{
global thresh=default(thresh,0.00001)
c=c.doubleweave()
global c = c
d=c.horizontalreduceby2()
global swapped = c.doubleweave().selectodd()
global cmetric = d.yv12convolution(horizontal="1",vertical="-1 2 -1")
global smetric = d.doubleweave().selectodd().yv12convolution(horizontal="1",vertical="-1 2 -1")
global e= scriptclip(c,"cmetric.averageluma > smetric.averageluma? swapped : c")
global metric4 = yv12lutxy(e.selectevery(5,2,2,2,2),e.selectevery(5,4,4,4,4),yexpr="x y - abs")
global metric3 = yv12lutxy(e.selectevery(5,1,1,1,1),e.selectevery(5,3,3,3,3),yexpr="x y - abs")
global metric2 = yv12lutxy(e.selectevery(5,0,0,0,0),e.selectevery(5,2,2,2,2),yexpr="x y - abs")
global metric1 = yv12lutxy(e.selectevery(5,4,4,4,4),e.selectevery(5,1,1,1,1),yexpr="x y - abs")
global metric0 = yv12lutxy(e.selectevery(5,3,3,3,3),e.selectevery(5,0,0,0,0),yexpr="x y - abs")
scriptclip(e.selectevery(5,0,1,2,4),"metric4.averageluma() < thresh ? e.selectevery(5,0,1,2,3)" +
\" : metric3.averageluma() < thresh ? e.selectevery(5,0,1,2,4)" +
\" : metric2.averageluma() < thresh ? e.selectevery(5,0,1,3,4)" +
\" : metric1.averageluma() < thresh ? e.selectevery(5,0,2,3,4)" +
\" : e.selectevery(5,1,2,3,4)")
}
hope someone finds a use for it.
defaults will be fine for anything you care to test it on - it's only meant for pure film 3:2 stuff for now, as the metrics don't work without one and i imagine it'll throw an error on interlaced or field-blended video (as no pair of fields will be under the threshold).
to use it as a regular (but very slow and no better than telecide) IVTC+decimate, just whack a selecteven after it.
[edit]
oh, that's a surprise - it doesn't crash on pure interlaced material... looking back it makes sense. it'll just return combs :)
as some of you might know, i'm continually trying to figure out how to get a perfect hybrid NTSC to PAL conversion going in avisynth. i also tend to go all "head a splode" whenever i try to sit down and figure it out.
well, as a start, i've written an IVTC function using only masktools and avs internal functions.
because of how i plan to treat interlaced NTSC in future, this function outputs doubled frame rate (47.952 fps), but hasn't mismatched a field yet on the 1 clip i tested it on.
it's pretty slow, as it checks for the ideal decimation pattern per frame rather than per cycle, or ideally whenever a pattern break is encountered. i'm sure someone with a less linear brain could make this a whole lot faster :) (scharfi or didee come to mind... i'm too lazy at the moment, but once my current project-from-hell is over with i'll have some more thinking time).
here's the very-messy-but-works-as-proof-of-concept script:
function blindmatch (clip c,float "thresh")
{
global thresh=default(thresh,0.00001)
c=c.doubleweave()
global c = c
d=c.horizontalreduceby2()
global swapped = c.doubleweave().selectodd()
global cmetric = d.yv12convolution(horizontal="1",vertical="-1 2 -1")
global smetric = d.doubleweave().selectodd().yv12convolution(horizontal="1",vertical="-1 2 -1")
global e= scriptclip(c,"cmetric.averageluma > smetric.averageluma? swapped : c")
global metric4 = yv12lutxy(e.selectevery(5,2,2,2,2),e.selectevery(5,4,4,4,4),yexpr="x y - abs")
global metric3 = yv12lutxy(e.selectevery(5,1,1,1,1),e.selectevery(5,3,3,3,3),yexpr="x y - abs")
global metric2 = yv12lutxy(e.selectevery(5,0,0,0,0),e.selectevery(5,2,2,2,2),yexpr="x y - abs")
global metric1 = yv12lutxy(e.selectevery(5,4,4,4,4),e.selectevery(5,1,1,1,1),yexpr="x y - abs")
global metric0 = yv12lutxy(e.selectevery(5,3,3,3,3),e.selectevery(5,0,0,0,0),yexpr="x y - abs")
scriptclip(e.selectevery(5,0,1,2,4),"metric4.averageluma() < thresh ? e.selectevery(5,0,1,2,3)" +
\" : metric3.averageluma() < thresh ? e.selectevery(5,0,1,2,4)" +
\" : metric2.averageluma() < thresh ? e.selectevery(5,0,1,3,4)" +
\" : metric1.averageluma() < thresh ? e.selectevery(5,0,2,3,4)" +
\" : e.selectevery(5,1,2,3,4)")
}
hope someone finds a use for it.
defaults will be fine for anything you care to test it on - it's only meant for pure film 3:2 stuff for now, as the metrics don't work without one and i imagine it'll throw an error on interlaced or field-blended video (as no pair of fields will be under the threshold).
to use it as a regular (but very slow and no better than telecide) IVTC+decimate, just whack a selecteven after it.
[edit]
oh, that's a surprise - it doesn't crash on pure interlaced material... looking back it makes sense. it'll just return combs :)