PDA

View Full Version : Does avisynth allow relative frame referencing


biskits
29th November 2007, 23:50
Hello

I'm looking to use an avisynth script to automatically remove certain frames from a video which are characterised by being different and brighter than their immediate neighbors, i.e given a sequence of frames a/b/c if the difference between a and b is greater than between a and c and b is brighter than a then delete b and replace it with a duplicate of c. The runtime function YDifferenceToNext() lets me compare a and b but I cant work out how to compare a and c, as referencing a frame with trim() seems to require absolute trim numbers rather than relative to current frame. Am I wrong or is there an alternative?

Thanks

stickboy
30th November 2007, 00:23
Relative frame numbers don't really make sense, because outside of ScriptClip/FrameEvaluate/et al., the notion of a "current frame number" doesn't make much sense.

http://forum.doom9.org/showthread.php?t=132109

IanB
30th November 2007, 00:36
Use SelectEven().YDifferenceToNext() interleaved with SelectOdd().YDifferenceToNext() to do the 2 apart comparisons.

:script: if you need more hints.

biskits
30th November 2007, 00:51
Ah-ha - thanks for that. I'll experiment with building my script as that's the best way to learn and repost if I get stuck. Basically it's to remove strobe flashes from a video to make it more comfortable for viewing by a relative with photosensitive epilepsy, rather than doing it manually. I don't mind if it's not perfect if it gets rid of most of the flashes.

Dark Shikari
30th November 2007, 00:58
Ah-ha - thanks for that. I'll experiment with building my script as that's the best way to learn and repost if I get stuck. Basically it's to remove strobe flashes from a video to make it more comfortable for viewing by a relative with photosensitive epilepsy, rather than doing it manually. I don't mind if it's not perfect if it gets rid of most of the flashes.You could try equalizing the brightness of all frames, or frames within a certain window.

biskits
30th November 2007, 01:09
Interesting - I could use that technique where the strobe light is indirect, although I would still need the original approach when the strobe is directly visible (a big white blob in the frames). Could end up being a complicated script, but that's fun in itself

Didée
30th November 2007, 02:04
An easy proposal for starting up:
source = last
clipped = source.Clense(reduceflicker=false)
diff = mt_MakeDiff(source,clipped)
replace = mt_Average(SelectEvery(1,-1),SelectEvery(1,1),U=3,V=3)
ConditionalFilter(diff,source,replace,"AverageLuma()","<","128-8")
where the "8" in the last line (in "128-8") is the sensitivity threshold that could be changed.

Thinking further, one could make a difficult quest out of this. The above should suffice for strobes where all of the frame (or bigger parts of it) is lit by strobing. But what is with ...

... flashing objects (e.g. a crowd of photographers)? This moves into the range of the good old "spot removal" problem.

... strobing effects that last for two frames, not only one?

Dark Shikari
30th November 2007, 02:05
An easy proposal for starting up:
source = last
clipped = source.Clense(reduceflicker=false)
diff = mt_MakeDiff(source,clipped)
replace = mt_Average(SelectEvery(1,-1),SelectEvery(1,1),U=3,V=3)
ConditionalFilter(diff,source,replace,"AverageLuma()","<","128-8")
where the "8" in the last line (in "128-8") is the sensitivity threshold that could be changed.

Thinking further, one could make a difficult quest out of this. The above should suffice for strobes where all of the frame (or bigger parts of it) is lit by strobing. But what is with ...

... flashing objects (e.g. a crowd of photographers)? This moves into the range of the good old "spot removal" problem.

... strobing effects that last for two frames, not only one?How about a filter that temporal-blurs pixels based on their brightness? Higher brightness = higher temporal blur.

Didée
30th November 2007, 02:19
Wouldn't be very difficult to do, yep. The question is, how much overall destruction one is willing to trade for strobe removal.

biskits
1st December 2007, 02:46
This is the script I came up with. It works fine but its very clunky compared with the script that Didee suggested, I'll need to learn about the filters before I understand it.

global current = DirectShowSource("infile.avi")

global d1 = 0
global d2 = 0
global b1 = 0
global b2 = 0
# global repl = 0 # debug

# thresholds to indicate level of difference required
global t1 = 2 # difference ratio
global t2 = 1.5 # brightness ratio

# create a clip to select every forward frame
global forward = current.SelectEvery(1,1)

# create a clip to select every backward frame
global backward = current.SelectEvery(1,-1)

# create a clip that replaces current frame with next frame
global replace = current.trim(1,0)

return removeFlash()


function removeFlash {

# debug
# cs = ScriptClip(current, """subtitle(string(current_frame)+" ) "+String(d1)+ " : "+String(d2)+ " / "+String(b1)+ " : "+String(b2)+ " > "+String(repl) )""")
# c0 = FrameEvaluate(cs, "global repl = ((d1 > (d2*t1)) && (b1 > (b2*t2))) ? 1 : 0")

# determine if current frame is a strobe (more different and brighter) using evaluations below, if so replace it
c0 = ScriptClip(current, "((d1 > (d2*t1)) && (b1 > (b2*t2))) ? replace : current")

# compare current with previous
c1 = FrameEvaluate(c0, "global d1 = current.LumaDifference(backward)")

# compare next with previous
c2= FrameEvaluate(c1, "global d2 = forward.LumaDifference(backward)")

# get brightness of previous
c3 = FrameEvaluate(c2, "global b1 = current.AverageLuma()")

# get brightness of current
c4 = FrameEvaluate(c3, "global b2 = backward.AverageLuma()")

return c4
}