Log in

View Full Version : Script master help needed: ConditionalFreeze()


frankio
18th February 2004, 00:46
This script is driving me crazy...

I was experimenting a dumb way to remove interlace artifacts from my Simpsons captures...
Basically I want to:

1) get 2 frames at a time from the clip (a couple)
2) for each calculate luma difference between top and bottom field (let them diff1 and diff2)
3) (diff1-diff2 > threshold) ? freeze the one whose diff is smallest onto the other one : nop()
4) go on till end of clip

This is my script (not working!):

function fmin(float f1, float f2) {
return (f1<f2) ? 0 : 1
}

src = mpeg2source("C:\cap\Simpson\palooza.d2v",cpu2="xxooxo").trim(50,31699).ChromaShift(C=-2).trim(17578,18999)

clp = src.SeparateFields()

evcl = clp.SelectEvery(4,0,1)
global tf_evcl = evcl.SelectEven()
global bf_evcl = evcl.SelectOdd()

odcl = clp.SelectEvery(4,2,3)
global tf_odcl = odcl.SelectEven()
global bf_odcl = odcl.SelectOdd()

ScriptClip(src,"abs(LumaDifference(tf_evcl,bf_evcl) - LumaDifference(tf_odcl,bf_odcl)) > 1 ? \
FreezeFrame(current_frame,current_frame+1,current_frame + \
fmin(LumaDifference(tf_evcl,bf_evcl),LumaDifference(tf_odcl,bf_odcl))) : nop()")
return src

N.B. ScriptClip was the only function that let me use current_frame...
Help is very appreciated, I've spent many hours with no luck and I don't want to give up.
TIA

frankio
19th February 2004, 14:28
I've cleaned up a bit my script and I gave up using current_frame (replaced with Interleave()) but still _not working_

function getClean(clip c) {

global e = c.SelectEven()
global et = e.SeparateFields().SelectEven()
global eb = e.SeparateFields().SelectOdd()

global o = c.SelectOdd()
global ot = o.SeparateFields().SelectEven()
global ob = o.SeparateFields().SelectOdd()

c = FrameEvaluate(c, "global od = LumaDifference(ot,ob)")
c = FrameEvaluate(c, "global ed = LumaDifference(et,eb)")

return c
}


mpeg2source("C:\cap\Simpson\palooza.d2v",cpu2="xxooxo")
trim(50,31699)
ChromaShift(C=-2)
trim(17578,18999)

AssumeTFF()
getClean()

a = (abs(ed - od) > 1) ? ((ed > od) ? e : o) : e
b = (abs(ed - od) > 1) ? ((ed > od) ? e : o) : o

Interleave(a,b)


:confused: why globals like ed and od aren't available outside getClean() :confused:
Anyone helping to find a solution??
I just want to copy clean frames over interlaced ones upon a condition... maybe I wasn't clear enough and I'm quite confident it can be done in avisynth!!
Hopefully waiting...

scharfis_brain
19th February 2004, 14:46
a = (abs(ed - od) > 1) ? ((ed > od) ? e : o) : e
b = (abs(ed - od) > 1) ? ((ed > od) ? e : o) : o

you cannot compare clips or their contents with the = (xxx) ? x : y - construct.

use conditionalfilter instead.

frankio
19th February 2004, 15:00
From AviSynth docs:


Runtime Functions

These are the internal functions which are evaluated every frame.
...
These return a float value between 0 and 255 of the absolute difference between two planes (require YV12, ISSE):
RGBDifference(clip1, clip2)
LumaDifference(clip1, clip2)
...


I've thought LumaDifference returns a float and not a clip.
However I've tried several times using conditionalfilter with no success.

Wilbert
19th February 2004, 15:14
Yes, it returns a float.

You have to put this:

a = (abs(ed - od) > 1) ? ((ed > od) ? e : o) : e
b = (abs(ed - od) > 1) ? ((ed > od) ? e : o) : o

Interleave(a,b)

in ConditionalFilter somehow (thus also in the getClean function).

In don't see 1-2-3 how to make it work, but it should be possible.

frankio
19th February 2004, 16:07
I tried:

function getClean(clip c) {

global e = c.SelectEven()
global et = e.SeparateFields().SelectEven()
global eb = e.SeparateFields().SelectOdd()

global o = c.SelectOdd()
global ot = o.SeparateFields().SelectEven()
global ob = o.SeparateFields().SelectOdd()

c = ConditionalFilter(c,doClean(c),c,"abs(ed - od)","morethan","1")
c = FrameEvaluate(c, "global od = LumaDifference(ot,ob)",true)
c = FrameEvaluate(c, "global ed = LumaDifference(et,eb)",true)

return c
}

function doClean(clip c) {

a = (ed > od) ? e : o
b = (ed > od) ? e : o

return Interleave(a,b)
}


and I get: "Avisynth open failure: I don't know what "od" means"

Some wise guy could explain me how is global variables scope treated in Avisynth? (before I start digging in avisynth source)
Or am I coerced to write a plugin? (never did before)
Anyhow thanks scharfis and wilbert

Wilbert
19th February 2004, 16:26
You should initialize them first. Try something like

function getClean(clip c) {

global e = c.SelectEven()
global et = e.SeparateFields().SelectEven()
global eb = e.SeparateFields().SelectOdd()

global o = c.SelectOdd()
global ot = o.SeparateFields().SelectEven()
global ob = o.SeparateFields().SelectOdd()

global ed = 0
global od = 0

c = ConditionalFilter(c,doClean(c),c,"abs(ed - od)","morethan","1")
c = FrameEvaluate(c, "global od = LumaDifference(ot,ob)",true)
c = FrameEvaluate(c, "global ed = LumaDifference(et,eb)",true)

return c
}

function doClean(clip c) {

a = (ed > od) ? e : o
b = (ed > od) ? e : o

return Interleave(a,b)
}

frankio
19th February 2004, 23:33
:thanks: Wilbert, it worked. But...
there's a flaw in my script: if I set show=true in

c = ConditionalFilter(c,doClean(c),c,"abs(ed - od)","morethan","1",true)

I can see values in the center column

Frame__ed/od____shown__wanted
0______3.306_____.881____.881
1______2.424____1.765____.881
2______4.757____2.935___1.765
3______2.992____6.576___1.765
4______5.774____7.683___2.935
...

but I would like to see values on the right column;
values on the left come from this script:

t = src.SeparateFields().SelectEven()
b = src.SeparateFields().SelectOdd()

return ScriptClip(src,"Subtitle(src,string(LumaDifference(t,b)))")


I'll try to make it clearer:
whenever a frame is copied over the next one (or the previous one) the script had to skip 1 frame.
:scratching my head:
Suggestions are welcomed.

a sidenote:
if I use operator "morethan" instead of ">" VDM gives me an error:
"ConditionalFilter: Evaluator could not be recognized!"
and Evaluate result is alway TRUE.
Aren't they supposed to have the same behaviour?