Log in

View Full Version : A new attempt at good deblending


actionman133
20th December 2005, 15:36
Hi,

Of course no one would remember that a long time ago, I attempted to create a deblend function for correcting films that underwent telecine and then had the fields blurred together.

I wasn't very successful then, but just tonight I'm trying a slightly different approach but I am stuck on how to use FrameEvaluate... the help guide might as well be inverted chinese algebra, because it makes me go crosseyed (rest of the guide is good, though).

Here is the test script to set up the detection process.

Function DeBlend (clip Last) {

a = Subtract (Last, Trim (1, 0).Levels (0, 1, 255, 128, 255, False)).Levels (0, 1, 127, 0, 255, False).Trim (1, 0)
b = Subtract (Levels (0, 1, 255, 0, 127, False), Trim (1, 0)).Levels (0, 1, 127, 255, 0, False).DuplicateFrame (0)

StackVertical (Last, a, b)

}

The result of this test is the original clip displayed on top, with two deblended frames beneath them. Those two deblended frames should be identical when the first blended frame in the pattern appears in the original clip.

That's worked fine for me so far. Where FrameEvaluate () comes in and messes me up is how to have the function work out whether to deblend or not. Here is the script I more or less came up with (I know the syntax is WAAAY out)...

Function DeBlend (clip Last) {

# Perform Deblends for the comparison test
a = Subtract (Last, Trim (1, 0).Levels (0, 1, 255, 128, 255, False)).Levels (0, 1, 127, 0, 255, False).Trim (1, 0)
b = Subtract (Levels (0, 1, 255, 0, 127, False), Trim (1, 0)).Levels (0, 1, 127, 255, 0, False).DuplicateFrame (0)

# Get difference between two tests
Global Test = Subtract (a, b)

# Get difference for each pair of frames in a 5 frame set
ab = FrameEvaluate ("YPlaneMinMaxDifference (Test.SelectEvery (5, 0))")
bc = FrameEvaluate ("YPlaneMinMaxDifference (Test.SelectEvery (5, 1))")
cd = FrameEvaluate ("YPlaneMinMaxDifference (Test.SelectEvery (5, 2))")
de = FrameEvaluate ("YPlaneMinMaxDifference (Test.SelectEvery (5, 3))")
ea = FrameEvaluate ("YPlaneMinMaxDifference (Test.SelectEvery (5, 4))")

# Find the frame which had the lowest difference in the two tests
Dupe = (ab > bc) ? "bc" : "ab"
Dupe = (Eval (Dupe) > cd) ? "cd" : Dupe
Dupe = (Eval (Dupe) > de) ? "de" : Dupe
Dupe = (Eval (Dupe) > ea) ? "ea" : Dupe

# Use SelectEvery to delete Dupe... not yet implemented

}

The FrameEvaluate () section is supposed to calculate the difference between the two deblend tests (a & b). The Dupe variable tests to find out which of these frames produced the smallest difference in those tests. The SelectEvery () piece will then remove the blended frames and replace them with a single deblended frame.

Now, for those who made it this far.... :o ... how do I properly implement FrameEvaluate () to retrieve the comparitive differences between a and b?

Thanks. :stupid:

Didée
20th December 2005, 16:10
Without checking anything, just putting the "conditionalities" in order: (hopefully)

Function DeBlend (clip clp) {

global ab = 0.0
global bc = 0.0
global cd = 0.0
global de = 0.0
global ea = 0.0

# Perform Deblends for the comparison test
a = Subtract (clp, clp.Trim (1, 0).Levels (0, 1, 255, 128, 255, False)).Levels (0, 1, 127, 0, 255, False).Trim (1, 0)
b = Subtract (clp.Levels (0, 1, 255, 0, 127, False), clp.Trim (1, 0)).Levels (0, 1, 127, 255, 0, False).DuplicateFrame (0)

# Get difference between two tests
Global Test = Subtract (a, b)

# Get difference for each pair of frames in a 5 frame set
FrameEvaluate(clp, "global ab = YPlaneMinMaxDifference (Test.SelectEvery (5, 0))")
FrameEvaluate(clp, "global bc = YPlaneMinMaxDifference (Test.SelectEvery (5, 1))")
FrameEvaluate(clp, "global cd = YPlaneMinMaxDifference (Test.SelectEvery (5, 2))")
FrameEvaluate(clp, "global de = YPlaneMinMaxDifference (Test.SelectEvery (5, 3))")
FrameEvaluate(clp, "global ea = YPlaneMinMaxDifference (Test.SelectEvery (5, 4))")

# Find the frame which had the lowest difference in the two tests
Dupe = (ab > bc) ? "bc" : "ab"
Dupe = (Eval (Dupe) > cd) ? "cd" : Dupe
Dupe = (Eval (Dupe) > de) ? "de" : Dupe
Dupe = (Eval (Dupe) > ea) ? "ea" : Dupe

# Use SelectEvery to delete Dupe... not yet implemented

} edit: FrameEvaluate needs a clip argument, too ...

Notes:

- PLEASE don't you use "Last" as name for a variable or function argument.
- you still need to do something with "Dupe"
- except for rare cases, you won't have much fun with a SelectEvery-decimation ...

actionman133
20th December 2005, 16:30
Thanks, the script is running now, except it's not working properly. The Framevaluate seems to not work as all the values are returned as 0.000000.

It's as if it's reading the original global declarations, and ignoring FrameEvaluate completely...

Any ideas?

EDIT: Just read your notes at the bottom (kinda skimmed past them, earlier... sorry). Why shouldn't I use Last as my variable? I find it makes my scripts cleaner to read...

Dupe will identify the first blended frame. I then use 5 conditional statements (one for each possible location of the blended frame in a 5 frame set), where each one will use Interleave () and SelectEvery () to keep the 3 good frames, and insert the unblended frame.

foxyshadis
20th December 2005, 16:47
Didée forgot, but all your access to the variables must be inside a FrameEvaluate or ScriptClip. Eval won't work; in this case:

frameevaluate(clp,"global Dupe = min(ab,bc,cd,de,ea)")
which must be above the frameevaluates.

I'm using the MinMax (http://www.avisynth.org/stickboy/) plugin, much easier than redoing the 5-way minimum in script.

All that said, MOmonster and I already wrote a function (http://forum.doom9.org/showthread.php?t=101477) that accurately unblends double-blended telecine, my old one actually used the same philosophy (local minimum in unblended difference) but MOmonster's extends it considerably.

Now if you have triple-blended video, or different blend-weights, that's a different and rather more evil beast.

Last is a bad idea because it's a predefined variable: The last function result that isn't explicitly assigned to a variable.

Edit: I see, a straight min isn't quite what you needed, you wanted the index. Well, you could either use a lot of nested () > ? :, or find a plugin, I'd help but I have to leave. ^^;;

Didée
20th December 2005, 16:54
Thanks, the script is running now, except it's not working properly. The Framevaluate seems to not work as all the values are returned as 0.000000.
Ah, of course. You have to put all of those "Dupe" evaluations into conditional environment, too. If these are outside like they're now, they only hold the startup values from the time of script loading ...

# Find the frame which had the lowest difference in the two tests
x99 = FrameEvaluate(clp, """Dupe = (Eval (Dupe) > ea) ? "ea" : Dupe""")
x03 = FrameEvaluate(x99, """Dupe = (Eval (Dupe) > de) ? "de" : Dupe""")
x02 = FrameEvaluate(x03, """Dupe = (Eval (Dupe) > cd) ? "cd" : Dupe""")
x01 = FrameEvaluate(x02, """Dupe = (ab > bc) ? "bc" : "ab" """)
Plus you have to make "Dupe" a global, too.

Still, you need to actually do something with the result for "Dupe" ... and you have to do it in the conditional environment. :)


/*participating in the "edit" mess*/

Oh, Evaluate doesn't work in Conditional Env.? Didn't know ... in fact I never have tried that.

actionman133
1st January 2006, 14:28
Update!

I've worked on this filter some more and it's almost complete. It works beautifully for about the first 600 frames of my test clip, then starts mishapping. I know it's not the video fooling my script because if I trim into the clip a little, previously mismatched frames are suddenly deblended correctly. The script and my test clip are online at this page:

http://actionman133.isa-geek.net:8080/blended.html

Here is the script: (I know Didee said I shouldn't use LAST, but honestly, I can't read or write a script without using it... sorry)


AVISource ("Blended.avi")
DeBlend ()

Function DeBlend (clip Last, bool "Debug") {

# Declarations
Debug = Default (Debug, False)
Global Original = Last

# Test each frame for deblending matches.
Global a = Subtract (Last, Trim (1, 0).Levels (0, 1, 255, 128, 255, False)).Levels (0, 1, 127, 0, 255, False).Trim (1, 0)
Global b = Subtract (Levels (0, 1, 255, 0, 127, False), Trim (1, 0)).Levels (0, 1, 127, 255, 0, False).DuplicateFrame (0)
Global Unblended = Merge (a, b) # Use this as higher quality replacement in final clip
Global Diff = Subtract (a, b)


# Perform Deblending on best matches, also decimates 5 frames to 4
ScriptClip (Original, """\
(Dupe == "ab") ? Interleave (Unblended.SelectEvery (5, 0), Original.SelectEvery (5, 2), Original.SelectEvery (5, 3), Original.SelectEvery (5, 4)) : \
(Dupe == "bc") ? Interleave (Original.SelectEvery (5, 0), Unblended.SelectEvery (5, 1), Original.SelectEvery (5, 3), Original.SelectEvery (5, 4)) : \
(Dupe == "cd") ? Interleave (Original.SelectEvery (5, 0), Original.SelectEvery (5, 1), Unblended.SelectEvery (5, 2), Original.SelectEvery (5, 4)) : \
(Dupe == "de") ? Interleave (Original.SelectEvery (5, 0), Original.SelectEvery (5, 1), Original.SelectEvery (5, 2), Unblended.SelectEvery (5, 3)) : \
(Dupe == "ea") ? Interleave (Original.SelectEvery (5, 0), Original.SelectEvery (5, 1), Original.SelectEvery (5, 2), Original.SelectEvery (5, 3)) : \
Last""").\
AssumeFPS (Original.Framerate () * 0.8, False).Trim (0, Round ((Original.Framecount () + 1) * 0.8) - 1)


# Find frame with least difference between a & b in every 5 frames
FrameEvaluate ("""Dupe = (Eval (Dupe) < ea) ? Dupe : "ea" """)
FrameEvaluate ("""Dupe = (Eval (Dupe) < de) ? Dupe : "de" """)
FrameEvaluate ("""Dupe = (Eval (Dupe) < cd) ? Dupe : "cd" """)
FrameEvaluate ("""Dupe = (ab < bc) ? "ab" : "bc" """)


# Find differences between a & b for each frame
FrameEvaluate ("ea = YPlaneMinMaxDifference (Diff.SelectEvery (5, 4))")
FrameEvaluate ("de = YPlaneMinMaxDifference (Diff.SelectEvery (5, 3))")
FrameEvaluate ("cd = YPlaneMinMaxDifference (Diff.SelectEvery (5, 2))")
FrameEvaluate ("bc = YPlaneMinMaxDifference (Diff.SelectEvery (5, 1))")
FrameEvaluate ("ab = YPlaneMinMaxDifference (Diff.SelectEvery (5, 0))")


# Create Debugging clip
Global Match = "% Similar"
Top = StackHorizontal (Original, ScriptClip (Diff, "Subtitle (String (Round ((255 - YPlaneMinMaxDifference ()) / 2.55)) + Match)"))
Bottom = StackHorizontal (a, b)
Info = StackVertical (Top, Bottom)

Return (Debug == True) ? Info : Last

}