Log in

View Full Version : Modified QMF


defunkt
27th January 2005, 02:14
If my understanding of XVID is correct one thing it will benefit from is a steady stream of consistant information, allowing it to reuse blocks from other frames particularly I-Frames on scene changes.

In which case, one problem with QMF is that it evaluates the first frame of a new scene (presumably an I-Frame) as high motion, which given its intended use will be a frame with less detail than a low motion frame even when the scene that follows is low motion. So I've messed about with the original script to make it detect scene changes (I find a threshold of 24 pretty accurate) and then treat that frame as it would the frame that follows.

I also added another level of motion but think that this is probably fairly gratuitous and unneccesary.

Thoughts?

function Motion() {
global motion_level = 0
global motion_level = (diff > threshold_zm) ? 1 : motion_level
global motion_level = (diff > threshold_lm) ? 2 : motion_level
global motion_level = (diff > threshold_hm) ? 3 : motion_level
global motion_level = (diff > threshold_sc) ? 4 : motion_level
}

function Change() {
global motion_level = (next > threshold_zm && motion_level > 3) ? 5 : motion_level
global motion_level = (next > threshold_lm && motion_level > 3) ? 6 : motion_level
global motion_level = (next > threshold_hm && motion_level > 3) ? 7 : motion_level
}

function QMF(clip c,
float "threshold_zm",
float "threshold_lm",
float "threshold_hm",
float "threshold_sc",
bool "debug") {
global threshold_zm = default(threshold_zm, 3.0)
global threshold_lm = default(threshold_lm, 6.0)
global threshold_hm = default(threshold_hm, 12.0)
global threshold_sc = default(threshold_sc, 24.0)
global motion_level = 0
global clip = c
c = ConditionalFilter(c, Filter_Motion_Nil(c), c, "motion_level", "=", "0")
c = ConditionalFilter(c, Filter_Motion_Min(c), c, "motion_level", "=", "1")
c = ConditionalFilter(c, Filter_Motion_Mid(c), c, "motion_level", "=", "2")
c = ConditionalFilter(c, Filter_Motion_Max(c), c, "motion_level", "=", "3")
c = ConditionalFilter(c, Filter_Motion_Nil(c), c, "motion_level", "=", "4")
c = ConditionalFilter(c, Filter_Motion_Min(c), c, "motion_level", "=", "5")
c = ConditionalFilter(c, Filter_Motion_Mid(c), c, "motion_level", "=", "6")
c = ConditionalFilter(c, Filter_Motion_Max(c), c, "motion_level", "=", "7")
c = (default(debug, false)) == true ? ScriptClip(c, "Debug()") : c
c = FrameEvaluate(c, "Change()")
c = FrameEvaluate(c, "global next =
(0.50 * YDifferenceToNext(clip)) +
(0.25 * UDifferenceToNext(clip)) +
(0.25 * VDifferenceToNext(clip))")
c = FrameEvaluate(c, "Motion()")
c = FrameEvaluate(c, "global diff =
(0.50 * YDifferenceFromPrevious(clip)) +
(0.25 * UDifferenceFromPrevious(clip)) +
(0.25 * VDifferenceFromPrevious(clip))")
return c
}

function Debug(clip c) {
c = Subtitle(c, "Motion Evaluation: " + string(diff),
x=25, y=150, font="courier new", size=24)
c = (motion_level == 0) ? Subtitle(c, "Zero Motion Frame",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 1) ? Subtitle(c, "Low Motion Frame",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 2) ? Subtitle(c, "Medium Motion Frame",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 3) ? Subtitle(c, "High Motion Frame",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 4) ? Subtitle(c, "Scene Change (Zero)",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 5) ? Subtitle(c, "Scene Change (Low)",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 6) ? Subtitle(c, "Scene Change (Medium)",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
c = (motion_level == 7) ? Subtitle(c, "Scene Change (High)",
x=25, y=200, font="courier new", size=32, text_color=$FFFFFF) : c
return c
}

Dreassica
17th July 2005, 19:50
Post an example for usage. I May be missing something obvious, but I can't get this script to load.

Schlumpf
18th July 2005, 17:29
Is that modification based on the latest Qmf 1.5 b1 ?
'Cause that was apparently the latest released version but all the downloadlinks in the old threads are down and I couldn't find a mirror via Google, that's why I can't compare.

Dreassica
18th July 2005, 17:39
Here, attached qmf 1.5b1. I tried comparing screipts to see if i could derive proper usage from modified one. But I'm not good at that kind of scripting.

defunkt
18th July 2005, 20:45
The script as posted is only a fragment, it was also line broken on the longer lines (so as not to make the post too wide). You can grap a more complete implementation here (http://www.ionwerks.net/defunkt/ModQMF.avs). Have enabled debug mode QMF(..., debug=true) so you can see what decisions the script is making, runs much faster without this. The functions:

Filter_Motion_Nil(clip base)
Filter_Motion_Min(clip base)
Filter_Motion_Mid(clip base)
Filter_Motion_Max(clip base)

...presently do nothing but return the clip they are passed. Use these to perform your own processing based on the frame type.

Hope this helps.

Dreassica
18th July 2005, 22:04
Thanks, got it working. The scenechanges no longer look blurry compared to frames after it in low motion scenes. It does seem to be more switch-happy during scenes itself though, compared to original qmf. Especially apparent when theres sudden motion in relative quiet scenes. Most likely it's a matter of further tweaking.

defunkt
19th July 2005, 07:36
Keep in mind that I added a fourth level of motion separation which on reflection I think was probably unnecessary. As you say it's very twitchy between nil/low motion - the two could (should?) probably be treated as one.