Log in

View Full Version : ConditionalFilter chooses not to work properly sometimes?


nonoitall
8th May 2008, 08:02
Wherever there's a weird problem to be found, I seem to stumble upon it. I've written a fairly complicated and slow but theoretically effective script for cleaning up bad splices in my clip. It replaces bad frames at the scene end with the previous frame if the previous frame is similar to the bad frame. Likewise it replaces bad frames at the scene start with the next frame if the next frame is similar to the bad frame.

# Next frame
next = clip.Trim(1, 0)

# Previous frame
prev = clip.Trim(0, -1) + clip

# Difference where gray is no difference and above or below that is the luma
# difference divided by 2
diffGray = clip.mt_lutxy(prev, "x y - 2 / 128 +", u=-128, v=-128)

# Absolute difference where black is no difference and above that is the luma
# difference
diffAbs = clip.mt_lutxy(prev, "x y - abs", u=-128, v=-128)

# A white clip (this represents true)
white = clip.BlankClip(width=16, height=16, pixel_type="YV12", color=$ffffff)

# A black clip (this represents false)
black = clip.BlankClip(width=16, height=16, pixel_type="YV12", color=$000000)

# This detects what could potentially be a bad end of a scene and returns a
# white frame for bad frames and a black frame for good frames
badEnd = diffGray.ConditionalFilter(white, black, \
"Crop(0, 0, 0, -8).AverageLuma() - Crop(0, 472, 0, 0).AverageLuma()", \
">", "20", false)

# This detects the end of a scene, returning white for scene ends, black
# otherwise
sceneEnd = diffAbs.ConditionalFilter(white, black, "AverageLuma()", \
">", "45", false).Trim(1, 0)

# This 'AND's the scene end and the bad end together, returning a white
# frame for bad scene ends and a black frame otherwise
badSceneEnd = sceneEnd.ConditionalFilter(badEnd, black, "AverageLuma()", \
">", "128", false)

# In this clip we can assume that all bad scene ends are followed by bad
# scene beginnings
badSceneBegin = black.Trim(0, -1) + badSceneEnd

# This detects whether this frame has noteworthy differences from the next
# frame and returns black if it does, white if it doesn't
safeBegin = diffAbs.ConditionalFilter(white, black, "AverageLuma()", \
"<", "2.5", false).Trim(1, 0)

# This detects whether this frame has noteworthy differences from the previous
# frame and returns black if it does, white if it doesn't
safeEnd = diffAbs.Crop(0, 0, 0, -120).ConditionalFilter(white, black, \
"AverageLuma()", "<", "2.6", false)

# The point of those two 'safe' clips is that even if a frame is bad, I don't want
# to throw it away if it has a lot of unique information in it

# This 'AND's safe begin and bad scene begin together, returning white if this is
# a bad scene beginning that is similar to the next frame, black otherwise
replaceBegin = safeBegin.ConditionalFilter(badSceneBegin, black, \
"AverageLuma()", ">", "128", false)

# This 'AND's safe end and bad scene end together, returning white if this is a
# bad scene ending that is similar to the previous frame, black otherwise
replaceEnd = safeEnd.ConditionalFilter(badSceneEnd, black, "AverageLuma()", \
">", "128", false)

# This replaces the current frame with the next frame when a safe-to-change
# bad scene beginning is detected
fixed1 = replaceBegin.ConditionalFilter(next, denoised, "AverageLuma()", \
">", "128", true)

# This replaces the current frame with the previous frame when a safe-to-change
# bad scene ending is detected
fixed2 = replaceEnd.ConditionalFilter(prev, fixed1, "AverageLuma()", ">", \
"128", true)
I've already tuned all of the numbers to my source material and they are accurate enough. Sometimes, though, frames that should be replaced don't get replaced. For example, let's say frame #1000 is white in badEnd, sceneEnd and safeEnd. Logically, 'AND'ing together badEnd and sceneEnd should produce white in badSceneEnd, and 'AND'ing that with safeEnd should produce white in replaceEnd. But, for some bizarre reason, frame #1000 ends up being black in badSceneEnd and replaceEnd.

This only happens on some frames - on other frames it will work the way it's supposed to. Is there some special way I have to use ConditionalFilter to make it work properly or is this a bug?

gzarkadas
10th May 2008, 12:31
It is more probable, since you are chaining many conditional filters and you also shift +/- 1 frame the base clip in some of them to just not getting the frame that you expected (which is a bug in your logic and not in the filter).

But neither this or the other alternative can be decided by your script, because it is incomplete. If you want others to track it down you should post a complete script and a short fragment of your input that together reproduce the error.

If this is difficult for any reason, you can try debug the frame sequence by putting calls to WriteFile between your conditional filters, such as:

safeEnd = diffAbs.Crop(0, 0, 0, -120).ConditionalFilter(white, black, \
"AverageLuma()", "<", "2.6", false).WriteFile("__script__.log", "current_frame")

and then step a few frames in a part of the clip that shows this error. Inspect the log to observe the frame sequence.

It will help if in each call to WriteFile you place a unique id, as for example:

# at the top of the script
tab = chr(9)
idprefix = "call_id:"
...
# at the point of call
id = <whatever>
...WriteFile("__script__.log", "current_frame", "tab", "idprefix", "id")

nonoitall
10th May 2008, 21:53
Well that was weird. I plugged in WriteFile just about everywhere to figure out what the heck was going on and for some reason my threshold was off on the check for bad frames. (The problem frame had a value of ~18 which was a little below my 20 threshold.)

I could have sworn that threshold worked on that frame when I checked it multiple times the other day, but perhaps I'm just going a little nutty. Anyway, now it works and I have you and your suggestion to thank for it!

:thanks: