View Single Post
Old 16th November 2012, 19:21   #10  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
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.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 17th November 2012 at 17:35.
StainlessS is offline   Reply With Quote