HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
LocateFrames(), Sister script to MatchFrames().
Code:
Function LocateFrames(clip c,clip f,float "Thresh",float "Thresh2",int "Start",int "Stop",bool "XP", Bool "Chroma", \
Float "ChromaWeight",String "Prefix",bool "Debug") {
# LocateFrames() v1.06 by StainlessS:
# THREAD: http://forum.doom9.org/showthread.php?t=164766
# POST: http://forum.doom9.org/showthread.php?p=1600961#post1600961
# Requires GScript & RT_Stats plugins.
# Args as per MatchFrames() script.
# Returns newline [Chr(10)] separated list of results as a multiline String.
# Results string for a single frame find clip, as in format:-
#
# "LF_FOUND=1100 LF_FIND=0 LF_DIFF=0.006134 LF_START=1000 LF_END=1599 LF_XPCNT=0 LF_MATCH=0"
#
# LF_FOUND= Index of found clip frame
# LF_FIND = Index of find clip frame
# LF_DIFF = LumaDifference between find and found
# LF_START= Start frame searched
# LF_END = End frame searched
# LF_XPCNT= As for XPCNT in MatchFrames.
# LF_MATCH= Kind of match found. # As for MatchFrames(), 0="BM", 1="(BM:T2)", 2="(T1: )", 3="(T1:XP)"
#
# Additional arg String Prefix, sets the default variable name prefix and defaults to "LF_" as in above.
# Bool Debug, default false, sends debug info to DebugView, if true.
#
# Can use RT_Stats functions eg
# RT_TxtQueryLines() to inquire lines of text in result string (same as frames in find f clip).
# RT_TxtGetLine() to extract a single result (if multiple find frames) from the combined results string.
# Can use eg "Eval(s)" to set variables where s is a single line result string.
#
# The innards of LocateFrames are much like MatchFrames, but could be more useful as implemented to use results
# programatically in other scripts.
#
# Use DebugView utility to view and capture output: http://technet.microsoft.com/en-gb/sysinternals/bb545027
#
Thresh = Default(Thresh, 0.0) # Threshold for declaring match, Default==0.0 to search for best possible match.
Thresh2 = Default(Thresh2,0.0) # Threshold2 Default==0.0, find clip f, not time ordered.
Start = Default(Start,0) # Frame to start search from.
Stop = Default(Stop,0) # Frame to stop search (0 == last frame + 1).
XP = Default(XP,true) # Extra Paranoid, dont fully trust Thresh.
Chroma = Default(Chroma,False) # Default Luma Only.
ChromaWeight= Default(ChromaWeight,1.0/3.0) # Default, 33% of Total Difference (Combined U and V).
Prefix = Default(Prefix,"LF_")
Debug = Default(Debug,False)
Start = (Start<0)?0:Start # Silent check
Stop=(Stop<=0||Stop>c.FrameCount)?c.FrameCount:Stop # Silent check
cfrms = Stop-Start # Number of frames to scan in c
ChromaWeight=(Chroma)?ChromaWeight:0.0 # If Not Needed, ignore default weight.
Assert(c.IsYV12() && f.IsYV12(),"LocateFrames:- Requires YV12 clips")
Assert(c.Width==f.Width,"LocateFrames:- Clip Width mismatch")
Assert(c.Height==f.Height,"LocateFrames:- Clip Height mismatch")
Assert(cfrms>0,"LocateFrames:- Invalid Start>=Stop")
Assert(Thresh>=0.0,"LocateFrames:- Invalid Thresh")
Assert(f.Framecount<=cfrms,"LocateFrames:- f Frames > c[START,STOP] Frames")
Assert(ChromaWeight>=0.0&&ChromaWeight<=1.0,"LocateFrames:- ChromaWeight Range 0.0->1.0")
Ordered = Thresh < Thresh2 # If true then: Find frames are in time order (match(f[n]) searches from match(f[n-1])+1
Result = ""
GScript("""
Lw = (Chroma) ? 1.0 - ChromaWeight: 1.0
Cw = ChromaWeight / 2.0 # Half for each chroma channel
for (ix = 0, f.Framecount-1) { # Iterate through find frames clip.
ff=f.Trim(ix,-1).Loop(c.FrameCount, 0, 0) # Make a clip of identical find frame, same length as clip c (dont 'Stop' Limit).
s = Start # Init Start search position
BestSoFar = s # Search start position
BestSoFarDiff = 255.0 + 1.0 # Maximum Possible + 1
sS =String(s,"%-4.0f") # Start offset this time, as string (at least 4 digits)
mS= 0 # " (BM: )", Init to 'scanned all the way' message (Flag Best Match).
eterm=(Ordered)?Stop-f.Framecount+ix:Stop-1 # Init last frame to compare for this iteration.
e=eterm # Init to 'scanned all the way'
Assert(s<=e,"LocateFrames:- Internal Error, s > e") # Oops.
xpCnt=0 # Prep XP skip Count string
for(current_frame=s, eterm) { # Search c clip(s to eterm) or until satisfactory match found. (eterm evaluated on entry only)
# Difference to current find frame.
CurrDiff=(!Chroma)?LumaDifference(c,ff):Cw*ChromaUDifference(c,ff)+Cw*ChromaVDifference(c,ff)+(Lw>0.0?Lw*LumaDifference(c,ff):0)
if(CurrDiff < BestSoFarDiff) { # Better match than found so far ?
BestSoFar = current_frame # Remember frame number
BestSoFarDiff = CurrDiff # Remember difference
if(BestSoFarDiff <= thresh) { # Good enough to satisfy user requirement ?
e=BestSoFar # Where we've scanned to so far
mS=2 # " (T1: )", Found satisfactory frame, (Flag Thresh)
if(XP && BestSoFar < eterm && BestSoFarDiff > 0.0) { # DBug will NOT enter here!, eterm condition will fail.
tmp = BestSoFar # Remember
for(current_frame=BestSoFar+1,eterm) {
CurrDiff=(!Chroma)?LumaDifference(c,ff): \
Cw*ChromaUDifference(c,ff)+Cw*ChromaVDifference(c,ff)+(Lw>0.0?Lw*LumaDifference(c,ff):0)
e=current_frame # We scanned more frames past original BestSoFar
if(CurrDiff < BestSoFarDiff) { # Better match ?
BestSoFar = current_frame # Remember frame number
BestSoFarDiff= CurrDiff # Remember difference
} else {
current_frame = eterm+1 # Force Exit with current_frame == eterm + 2 (normally exit @ eterm+1)
}
}
if(BestSoFar != tmp) {
mS=3 # " (T1:XP)", Found satisfactory frame, (Flag Thresh, and Xtra Paranoid found better frame)
XpCnt=BestSoFar-tmp # How many frames Xtra Paranoid skipped to find better match than Thresh.
}
}
Start=(Ordered)?BestSoFar+1:Start # If required, Next time search from BestSoFar + 1
current_frame = eterm + 1 # Force Exit with current_frame == eterm + 2 (normally exit @ eterm + 1)
}
}
}
if(Ordered && current_frame == eterm+1 && BestSoFarDiff < Thresh2) {
mS = 1 # " (BM:T2)", For Log, Time ordered, (Flag, Best Match and Thresh2)
Start = BestSoFar + 1 # Next time start from BEST MATCH found + 1.
}
Text = Prefix + "FOUND=" + String(BestSoFar) + " " + \
Prefix + "FIND=" + String(ix) + " " + \
Prefix + "DIFF=" + String(BestSoFarDiff) + " " + \
Prefix + "START=" + sS + " " + \
Prefix + "END=" + String(e) + " " + \
Prefix + "XPCNT=" + String(XpCnt) + " " + \
Prefix + "MATCH=" + String(mS) # 0=BM, 1=(BM:T2), 2=(T1: ), 3=(T1:XP)
Result = RT_TxtAddStr(Result,Text) # Avoid string concatenation bug in v2.58 and v2.6a3.
(DEBUG) ? RT_Debug(Text) :NOP
}
""") # End Of GScript
return Result
}
EDIT: Changed from version v0.0 to 1.06 to sync with MatchFrames() version.
Test snippet in next post.
Last edited by StainlessS; 17th November 2012 at 17:35.
|