Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Usage

Reply
 
Thread Tools Search this Thread Display Modes
Old 23rd April 2012, 00:10   #1  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,995
MatchFrames/LocateFrames v1.06

MatchFrames, intended for matched frames extraction,
LocateFrames, intended to be usable by other scripts to identify matches.

MatchFrames()

Find And return frames in c clip that are best matched to frames in f clip.

Below a mod of Gavino's FindFrame, Advantages:-

Deals with a clip of frames to find rather than a single frame.
Can find exact/best match or 1st match below or equal to a threshold (rather than last frame if <= Thresh not found).
Extra Paranoia setting continues searching subsequent frames for a better match once thresh is broken.
Float Threshold.
Can show StackHorizontal required 'find' frame alongside source clip 'found' frames.
Can output a command file consisting of frame numbers found.
Command file can be used with FrameSelect() Plugin to select all found frames (useful if viewing StackHorizontal frames without 2nd SLOW run for extraction).

Originally prompted by this thread:
http://forum.doom9.org/showthread.php?t=164662

Code:
v1.02 
  Outputs LogFile
  Can cut down on search times if clip f is known to be time ordered (in c).
v1.03
  Added "(Thresh2)" Indicator to log.
v1.04
 Added Args, "Start", "Stop", "XP".
v1.05
 Added Args, "Chroma", "ChromaWeight", "Title", Added Debug Mode.
v1.06
 Debug mode now holds TotalDiff as two floats providing greater precision.
Code:
############################################################################
# MatchFrames v1.06, by StainlessS:
#
# Find And return frames in c clip that are best matched to frames in f clip.
# Requires YV12, as uses LumaDifference(). Null Audio returned.
# ##################################
# Based on FindFrame() (c) Gavino. http://forum.doom9.org/showthread.php?p=1569622#post1569622
# Required: GScript    (c) Gavino: http://forum.doom9.org/showthread.php?t=147846
# ##################################
#
# MatchFrames(clip c,clip f,bool "Show",float "Thresh",float "Thresh2",string "FileName",string "LogFile", \
#               int "Start",int "Stop",bool "XP",Bool "Chroma",Float "ChromaWeight",string "Title")
#
# Args:
#
# c       = clip, Source clip.
# f       = clip, Consisting of frames that you wish to find in the c clip.
# Show    = bool[true], True returns both find and found frames using StackHorizontal. NOTE, hires clips, may cause problems in eg VDUB
#                if StackHorizontal width goes over some VD imposed limit.
# Thresh  = float[0.0 == Search for 1st exact match or best possible if no exact match found]. Threshold for declaring match (diff <= Thresh).
# Thresh2 = float[0.0 == NOT time ordered]. Both a 'time ordered' indicator and a threshold.
#           If (Thresh < Thresh2) Then clip f is taken as time ordered (in c), ie frames in both f and c clips are temporally ordered.
#           If f clip is known to be time ordered (in c), this arg can significantly cut down on the time taken to search for frames.
#
#           Assuming time ordered f clip (Thresh < Thresh2),
#
#               If a match found where diff of find to found frame <= Thresh,
#                    Next frame search will start from found frame + 1.
#               Else if diff of find to Full Scan BEST found frame < Thresh2
#                    Next frame search will start from BEST found frame + 1.
#               Else
#                    Next frame search will start from current start position.
#               End if                    
#               *** Where above 'Full Scan' means scan from current start postion to the last valid search frame.
#                
# FileName= string["MatchFramesCmd.txt"], Output Frames command file.
#             Can use FrameSelect() Plugin to select frames using MatchFramesCmd.txt Command file.
#             FrameSelect() Plugin can be found here:- http://forum.doom9.org/showthread.php?t=164497
#             Can monitor the MatchFramesCmd.txt file during scanning to view progress (ie view in notepad, [Read-Only viewer maybe safer]).
#
# LogFile = string["MatchFrames.Log"], Output Log file. Can monitor as for command file.
#             The Logfile might produce an output line like that below:
#
#             "0]=[1100] Diff=0.239 (T1:XP) S=1000 E =1101 XPCNT=5"
#
#             Where eg 0] is find frame number, [1100] is found frame, 
#             Diff is the Difference (Luma + optional Chroma) between find and found frames.
#             S and E are the search start and end positions that were searched for that frame.
#             The "(T1:XP)" stuff presents just a little info about the search:
#              "(BM:  )" Best Match, where no frame was found with a Diff <= Thresh, the returned frame was best match found in search area.
#              "(BM:T2)" Same as "(BM:  )" but was an Ordered search & because Diff<Thresh2, then next frame search will start at Best Match+1.
#              "(T1:  )" Means that the found frame had a Diff <= Thresh.
#              "(T1:XP)" Same as "(T1:  )" but Xtra Paranoia (XP) successfully found a better matching frame following the one that
#              initially broke thresh. If this flag is shown, you will also see "XPCNT" which will tell how many successive better frames 
#              were found after the initial frame that broke Thresh.
#
# Start   = int[0, == First frame of clip], Start frame to search from (eg Skip introduction).
# Stop    = int[0, == Last frame of clip + 1], Frame prior to which, c clip is searched (Exclusive). (eg Skip end credits).
# XP      = bool[true == Extra Paranoid] Main purpose of XP is so that you can use Thresh > 0.0 even if you dont fully trust a non best search.
#               If diff of find to found frame <= Thresh, then search would normally stop at that frame, but when
#               XP is true (Default), it will continue to search so long as subsequent frames provide a better match. Will usually result
#               in 1 extra frame being compared (providing that your Thresh is not too high).
#               If Thresh is set to 0.0 (default) then will only stop search on EXACT match, and so is likely to do a full search
#               (unless exact frame exists). XP allows you to settle for a close match by setting thresh a little above 0.0, and when a close
#               match is found, it will continue to edge forward 1 frame at a time until matches cease to be better.
#               If exact match was found, ie diff == 0.0 then will not scan extra frames (no better match possible).
#
# Chroma   = bool[false==Luma diff Only], If true then also uses chroma difference as per ChromaWeight.
# ChromaWeight=float[1.0/3.0 ie 0.33333], default for now, may change. If Chroma==true then LumaWeight = 1.0-ChromaWeight.
#               If Chroma==false then ChromaWeight is ignored and only luma difference is used.
# Title    = string[""== none], Allows you to place a string of text in the Log and Command file headers, eg "Hires Test#2" or whatever.
# ##################################
# DEBUG MODE: If the f FrameCount and c[START,STOP] FrameCount (ie STOP-START) are same AND Thresh < Thresh2 (ie Ordered), then the script is put
# into DEBUG mode. This would be easiest achieved when START and STOP are at their default 0 values meaning 'All of c clip' and lengths of
# f and c are same.
# In Debug Mode, there is no searching for best match, log is produced with difference between all corresponding frames
# and in the footer of the log, it will show Average Diff, Min Diff, and Max Diff for the entire frame set.
# In DEBUG mode, the command file is cleared, prints header only.
# ##################################
# 
# Will take some time to show results, it is not a bug if it seems to hang, it is WORKING HARD.
#
############################################################################
#
Suggested settings, Thresh=1.0, (if ordered clips then Thresh2=Thresh+0.1) but of course depends on f clip quality.
And always leave XP default.
If you have a lot of frames to find, might like to do a dummy run on only the first find frame and note what the difference
is, then repeat full scan with eg Thresh = Diff *1.25 (maybe 1.5) and Thresh2 = Thresh + 0.1 (assuming ordered clips).

As Script overflowed D9 16kb limit, have had to move posts around and the current script is in next post.

For Sister script LocateFrames(), see here:- http://forum.doom9.org/showthread.ph...61#post1600961

MatchFrames & LocateFrames in single zip, also available via MediaFire in Sig.
__________________
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; 18th November 2012 at 18:49. Reason: Update
StainlessS is offline   Reply With Quote
Old 23rd April 2012, 05:59   #2  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,995
MatchFrames() v1.06 current script.

Code:
Function MatchFrames(clip c,clip f,bool "Show",float "Thresh",float "Thresh2",string "FileName",string "LogFile", \
        int "Start",int "Stop",bool "XP", Bool "Chroma",Float "ChromaWeight",string "Title") {
    ver         = "v1.06 - 18 May 2012"                 # Version Number
    Show        = Default(Show,true)                    # Defaults true = show StackHorizontal find & found frames
    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.
    FileName    = Default(FileName,"MatchFramesCmd.txt")# "" to switch OFF Frames output command file.
    LogFile     = Default(LogFile,"MatchFrames.Log")    # "" to switch OFF Logfile.
    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).    
    Title       = Default(Title,"")                     # Shown in log and command file, Default "".
    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(),"MatchFrames:- Requires YV12 clips")
    Assert(c.Width==f.Width,"MatchFrames:- Clip Width mismatch")
    Assert(c.Height==f.Height,"MatchFrames:- Clip Height mismatch")
    Assert(cfrms>0,"MatchFrames:- Invalid Start>=Stop")
    Assert(Thresh>=0.0,"MatchFrames:- Invalid Thresh")              
    Assert(f.Framecount<=cfrms,"MatchFrames:- f Frames > c[START,STOP] Frames")
    Assert(ChromaWeight>=0.0&&ChromaWeight<=1.0,"MatchFrames:- ChromaWeight Range 0.0->1.0")
    DBug = (cfrms==f.FrameCount && Thresh < Thresh2)    # Debugging Mode ?
    Thresh  = (DBug) ? 255.0 : Thresh                   # If DBug, Ensure everything breaks Thresh.
    Thresh2 = (DBug) ? 255.1 : Thresh2                  # If DBug, Maintain Ordered.
    TDHi =0.0                                           # DEBUG: TotalDifference Hi  (Extra precision)
    TDLo =0.0                                           # DEBUG: TotalDifference Lo
    MinDiff  = 255.0 + 1.0                              # DEBUG: Output, max + 1
    MaxDiff  = 0.0 - 1.0                                # DEBUG: Output, min - 1    
    Ordered  = Thresh < Thresh2                         # If true then: Find frames are in time order (match(f[n]) searches from match(f[n-1])+1
    Result = 0                                          # Dummy, Will become a Clip, Dont use 'c.BlankClip(length=0)' (Maybe StackHorizontal)
    Scanned = 0                                         # Init Total Frames scanned
    EOL = Chr(10)                                       # End Of Line. (Do NOT use Carriage Return, Line Feed, Will auto add the CR)
    TLINE = "##########################################################################" + EOL
    TGEN  = "# MatchFrames " + Ver
    TCMD  = "Command File for SelectFrames Plugin." + EOL + "#" + EOL
    TLOG  = " (c) StainlessS : LogFile." + EOL + "#" + EOL
    TNAM  = (Title=="") ? "" : "# Title='" + Title + "'" + EOL + "#" + EOL      
    TSET  = "# Width=" + String(c.Width) + " : Height=" + String(c.Height) + " : Start=" + String(Start) + " : Stop=" + String(Stop) + EOL+"#"+EOL
    TSET2 = "# Thresh="+String(Thresh,"%.3f")+" : Thresh2="+String(Thresh2,"%.3f")+" : XP="+String(XP)
    TSET3 = ((Chroma)?" : ChromaWeight="+String(ChromaWeight,"%.3f"):"") + EOL + "#" + EOL
    TSET4 = ((DBug) ? "# DEBUG MODE" + EOL:"") + "#" + EOL
    c=(FileName=="")? c : c.WriteFileStart(FileName,"""TLINE+"#"+EOL+TGEN+" : "+TCMD+TNAM+TSET+TSET2+TSET3+TSET4+TLINE""")
    c=(LogFile=="") ? c : c.WriteFileStart(LogFile, """TLINE+"#"+EOL+TGEN      +TLOG+TNAM+TSET+TSET2+TSET3+TSET4+TLINE""")
    FileName= (DBug) ? "" : FileName                # No Command file frame numbers if DBug Mode, HEADER ONLY (ie Wipe command file).
    TimeStart = Time("%#c") # Used "%#c" LONG FORMAT time as "%c" shows eg "04/27/12" instead of correct 27/04/12 in UK.  
    GScript("""   # !!! WARNING !!!, Moving GScript before 1st WriteFileStart causes script error on 1st WriteFileStart line (Dont know why).
    Lw = (Chroma) ? 1.0 - ChromaWeight: 1.0
    Cw = ChromaWeight / 2.0                         # Half for each chroma channel
    dS=""                                           # A Spare Debug String (NOT USED).
    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 =" S=" + String(s,"%-4.0f")              # Start offset this time, as string (at least 4 digits)
        mS=" (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,"MatchFrames:- Internal Error, s > e")  # Oops.
        xS=""                                       # 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 ?
                    if(DBug) {                      # DEBUG
                        MinDiff = (CurrDiff<MinDiff)?CurrDiff:MinDiff
                        MaxDiff = (CurrDiff>MaxDiff)?CurrDiff:MaxDiff     
                        TDLo = TDLo + CurrDiff
                        TDHi = TDHi + floor(TDLo / 256.0)  # Hi part, Extra Precision
                        TDLo = frac(TDLo / 256.0) * 256.0  # Lo part, Extra Precision
                        # ANY DEBUGGING STUFF YOU MIGHT WANT TO APPEND TO LOG FILE LINE.
                        # dS = "  DBUG: Abs(AverageLuma(f)-AverageLuma(c)) = " + String(Abs(AverageLuma(ff)-AverageLuma(c)),"%.3f")                
                    }
                    e=BestSoFar                     # Where we've scanned to so far
                    mS=" (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=" (T1:XP)"               # Found satisfactory frame, (Flag Thresh, and Xtra Paranoid found better frame)
                            xS=" XPCNT=" + String(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 = " (BM:T2)"                            # For Log, Time ordered, (Flag, Best Match and Thresh2)
            Start = BestSoFar + 1                      # Next time start from BEST MATCH found + 1.
        }
        Scanned = Scanned + e - s + 1
        Text = String(ix) + "]=[" + String(BestSoFar) + "] Diff=" + String(BestSoFarDiff,"%.3f") + mS + sS + " E =" + String(e,"%-4.0f") + xS + dS
        FindFrame=ff.Trim(BestSoFar,-1).SubTitle(Text)
        wrClip=(FileName=="") ? c : c.WriteFileStart(FileName,"BestSoFar",Append=true)        # Command file
        wrClip=(LogFile=="")  ? wrClip : wrClip.WriteFileStart(LogFile,"Text",Append=true)    # Log
        wrClip=wrClip.Trim(BestSoFar,-1)                                # Only matched frame. (limit writefile to 1 frame only)
        GotFrame=(Show)?StackHorizontal(FindFrame,wrClip):wrClip        # Either will output Cmd/log if required.
        Result = (IsClip(Result)) ? Result ++ GotFrame : GotFrame       # Append to 'result clip so far'.
    }        
    """) # End Of GScript
    TimeEnd = Time("%#c")
    Result=(LogFile=="")?Result:Result.WriteFileStart(LogFile,""" EOL+TLINE+EOL+"Start Time = "+TimeStart+EOL+"End   Time = "+TimeEnd+EOL """, \
        Append=True)
    Result=(LogFile=="")?Result:Result.WriteFileStart(LogFile,""" "Total Frames Scanned = "+String(Scanned)+EOL """,Append=True)
    Result=(!DBug||LogFile=="")?Result:Result.WriteFileStart(LogFile,""" "DEBUG: AveDiff="+String((TDHi / cfrms * 256.0) + (TDLo / cfrms),"%.3f")+ \
            " : MinDiff="+ String(MinDiff,"%.3f")+" : MaxDiff="+String(MaxDiff,"%.3f") + " : [L="+String(Lw,"%.3f") + \
            " : (U+V)="+ String(Cw*2,"%.3f")+"]" + EOL """,Append=True)
    return Result.KillAudio()                           # Audio not sensible.
}
__________________
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; 18th May 2012 at 00:19.
StainlessS is offline   Reply With Quote
Old 25th April 2012, 09:49   #3  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,995
Here is the Basic Test Code with XP setting turned OFF and Thresh=Default 0.0 (Best possible match)

Code:
Test=Avisource("D:\avs\avi\TESTVID.avi").ConvertToYV12()     # For LumaDifference

MCOUNT=600                      # Size of sample taken from full Test clip.
MSTART=1000                     # Start position in Full Test clip of Sample.
MSTOP =MSTART+MCOUNT            # Stop position in full test clip.
Test.Trim(MSTART,-MCOUNT)       # Last = 600 Frames from MSTART to MSTART+MSTOP-1

# Manufacture 5 frame FindClip, NOTE middle frame exact, others blurred to some degree.
Q=trim(100,-1).Blur(0.1) + trim(200,-1).Blur(1.58).Blur(1.58)  + Trim(300,-1) + trim(400,-1).Blur(0.3) + Trim(500,-1).Blur(1.0)

MatchFrames(Test,Q,start=MSTART,stop=MSTOP,XP=false)
And the Log File:

Code:
##########################################################################
#
# MatchFrames v1.04 - 25 Apr 2012 (c) StainlessS : LogFile.
#
# Thresh=0.000 : Thresh2=0.000 : XP=false : Start=1000 : Stop=1600
#
##########################################################################

0]=[1100] Diff=0.239 (BM:  ) S=1000 E =1599
1]=[1200] Diff=1.261 (BM:  ) S=1000 E =1599
2]=[1300] Diff=0.000 (T1:  ) S=1000 E =1300
3]=[1400] Diff=0.083 (BM:  ) S=1000 E =1599
4]=[1500] Diff=0.098 (BM:  ) S=1000 E =1599

##########################################################################

Total Frames Scanned = 2701
Note that it scanned all the way to the end except where the exact match was found.

Code:
MatchFrames(Test,Q,Thresh=0.5,Start=MSTART,Stop=MEND,XP=false)

##########################################################################
#
# Thresh=0.500 : Thresh2=0.000 : XP=false : Start=1000 : Stop=1600
#
##########################################################################

0]=[1100] Diff=0.239 (T1:  ) S=1000 E =1100
1]=[1200] Diff=1.261 (BM:  ) S=1000 E =1599
2]=[1300] Diff=0.000 (T1:  ) S=1000 E =1300
3]=[1400] Diff=0.083 (T1:  ) S=1000 E =1400
4]=[1500] Diff=0.098 (T1:  ) S=1000 E =1500

##########################################################################

Total Frames Scanned = 1904
A Thresh 0f 0.5 identified all but one frame which was scanned to the end.

Code:
MatchFrames(Test,Q,Thresh=0.5,Thresh2=0.6,Start=MSTART,Stop=MSTOP,XP=false)

##########################################################################
#
# Thresh=0.500 : Thresh2=0.600 : XP=false : Start=1000 : Stop=1600
#
##########################################################################

0]=[1100] Diff=0.239 (T1:  ) S=1000 E =1100
1]=[1200] Diff=1.261 (BM:  ) S=1101 E =1596
2]=[1300] Diff=0.000 (T1:  ) S=1101 E =1300
3]=[1400] Diff=0.083 (T1:  ) S=1301 E =1400
4]=[1500] Diff=0.098 (T1:  ) S=1401 E =1500

##########################################################################

Total Frames Scanned = 997
Ordered scans fewer frames.

Code:
MatchFrames(Test,Q,Thresh=1.5,Thresh2=1.6,Start=MSTART,Stop=MSTOP,XP=true)

##########################################################################
#
# Thresh=1.500 : Thresh2=1.600 : XP=true : Start=1000 : Stop=1600
#
##########################################################################

0]=[1100] Diff=0.239 (T1:XP) S=1000 E =1101 XPCNT=5
1]=[1200] Diff=1.261 (T1:  ) S=1101 E =1201
2]=[1300] Diff=0.000 (T1:  ) S=1201 E =1300
3]=[1400] Diff=0.083 (T1:XP) S=1301 E =1401 XPCNT=1
4]=[1500] Diff=0.098 (T1:XP) S=1401 E =1501 XPCNT=1

##########################################################################

Total Frames Scanned = 505
Using Ordered and XP, fewest scans of all and ALL frames correctly identified.
This test was a little contrived (1st guess) to force the Xtra Paranoia setting to work but
shows that even with a quite high threshold setting, the correct frames were
identified and number of frames scanned is reduced fairly significantly.
The XPCNT=5 line shows that the first find frame was incorrectly identified by
the Thresh setting, but the XtraParanoia setting scanned 5 further frames,
all of which were identified as giving a better match, and the eventually returned
frame was correct. Also NOTE, just before XPCNT=5, you see that the E (end frame)
scanned is one past the returned frame, ie it failed to give a better match.
__________________
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; 25th May 2012 at 23:23.
StainlessS is offline   Reply With Quote
Old 26th April 2012, 21:13   #4  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,862
That's really nice - good job!
It's almost what I need. It could be more flexible with just a few changes in logic.
My problem, which is particularly irksome, is I have a set of frames which are actually the same except for a) extreme noise and b) dupes in each that puts them out of sync eventually.
The problem is that due to a) there is no dupe finder or even frame matching possible, however there is frame *un*matching; when the camera is panning say the change is large enough to reliably detect.
So what I need is an ordered sort of unmatching frames. Let me be more clear with an example:
[code]
A B Match?
1 1 yes
2 1 yes (falsely because of low motion)
3 3 yes
4 5 yes (falsely, also we're out of sync now)
5 6 no (noticed beause there's camera pan now)
6 7 no
.......
31 32 yes (pan is finished, false matching again)
I know that 4-30 don't match, but I'd like to know that a shift of 1 matches this string for n frames better than another offset. So I guess a multiframe match is more robust. At some point I'd know I was in sync from n1 to n2 and out of sync from n3 to n4, and the loss was somewhere in n2-n3, which I'd have to check by hand.
I believe I explained this before and Gavino provided an answer but I didn't get back to it, to explain that I required a more robust solution.
So Id like to say, for a sync shift of up to n frames, do an ordfered search for each offset until you've eliminated an offset by virtue of it definitely mismatching for m frames. For n>=2 you could end up with two theories which aren't eliminated; then log the result with a confidence. But over enough video you hould always find areas with definite mismatch
I probably have to think about this more.

Bear in mind that when I say matching here, the tolerance is at a really high level because of all the noise.
One more thing, I'd like to see the matching function just separated out in code to return a value between two single frames, then I can put other matching functinos in there. I'd have to test some, but I like correlation because I can prove that mathematically it will match even different brightness or contrast, but not match really different pixels. That's good for my case.

Last edited by jmac698; 26th April 2012 at 21:26.
jmac698 is offline   Reply With Quote
Old 27th April 2012, 11:26   #5  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,995
Hi Jmac,

Cant look at it just now, I've really got to get some sleep (10:27 am right now), but can you seek out the
Gavino answer thread/post, I'll take a peek later.
Been up all night on a mod to the script, Added args:- bool "Chroma",Float "ChromaWeight",string "Title".
Also added a Debug mode (When c.FrameCount == f.FrameCount), all that it does is scan through the
clips logging difference between similar position frames with no searching, at the end of the log, it will
also print out the clip Average Difference, Minimum Difference and Maximum Difference.
Also, I now think that it may be better to downsize any eg hirez clip to the same size as a smaller
clip as the Clip average difference seem to be lower when doing that, I guess that upscaling a low
rez compressed clip would also play games with the already existing compression artefacts,
better to downscale, possibly quicker too. Anyway, that was the reason for implementing the
Debug mode, and also so I can experiment with eg Luma only Average Difference and also
Chroma Only Average difference. I think I've seen elsewhere, that weighting Chroma along with
Luma, Chroma is given a combined weight of 0.5 (U+V), maybe I'm wrong on that, and its actually
0.25 combined. Anyways been doing a couple of tests and got these results (for the same f and c clips):

Test 1: Upscale Lowres f clip
DEBUG: Average Diff = 3.408322 : MinDiff=1.437595 : MaxDiff=4.771824 # Lumaweight = 1.0 (Luma Only)
DEBUG: Average Diff = 0.706108 : MinDiff=0.075863 : MaxDiff=2.565223 # Chromaweight = 1.0 (Chroma Only)

Test 2: Downscale Hires c clip
DEBUG: Average Diff = 1.099017 : MinDiff=0.162313 : MaxDiff=5.715830 # Lumaweight = 1.0 (Luma Only)
DEBUG: Average Diff = 0.587522 : MinDiff=0.079203 : MaxDiff=2.198153 # Chromaweight = 1.0 (Chroma Only)

Note, when downscaling (This clip pair):
The ave diff of both luma & chroma goes down.
The min diff luma goes down & chroma goes up.
The max diff luma goes up & chroma goes down.

Dont know if anything sensible can be deduced from that, need more samples.

I'm tempted to do something like this:

ChromaWeight = ChromaAveDiff / (LumaAveDiff+ChromaAveDiff)

0.706108 / (3.408322 + 0.706108) = 0.171617453 # Upscale

0.587522 / (1.099017 + 0.587522) = 0.348359569 # Downscale

ie for

Upscale maybe suggests ChromaWeight = ~0.17 and LumaWeight= 1.0 - 0.17 == 0.83

Downscale maybe suggests ChromaWeight = ~0.35 and LumaWeight= 1.0 - 0.35 == 0.65

Could a generally good ChromaWeight be deduced from a greater sample set or is the above,
total twaddle? (Compression has got to mangle chroma to a greater extent than luma).

Any thoughts ?

EDIT: All resizing up/down using BilinearResize.
EDIT: Above clip pair, the hirez source was 1920x1080, Lowrez resize/compressed to 352x288 MPG Low bitRate (0.2 bits per pixel).
EDIT: Aspect ratio was not taken into account (352x288), lowest rez I felt comfortable converting to.
__________________
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; 25th May 2012 at 23:35.
StainlessS is offline   Reply With Quote
Old 28th April 2012, 00:14   #6  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,995
Jmac, if you want to try the current beta, probably about complete, maybe just a little playing with format
and set a preliminary ChromaWeight default to 0.333.

Any body else want to try it, and any results/conclusions would be good, otherwise, may keep this chromaweight of 0.333 (What I 'feel' is about right).

EDIT: I think I'm correct about most filters using a weighting of about 0.5 for combined chroma, dont myself think
this is a good measure, luma commonly fills it's full dynamic range, whereas chroma huddles about the middle,
as chroma habitually occupies considerably less dynamic range, it should count for less in any kind of weighting, even
if combining two chroma channels. If the dynmic range of chroma is somewhat reduced, then the difference between
two identical frames where one has been reduced/compressed has got to be likewise reduced and of lesser importance
as a measure. Think about 33% might be a better guestimate.

See here: (Will be deleted when new non beta published)

EDIT: Link Removed.
__________________
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; 27th May 2012 at 11:44.
StainlessS is offline   Reply With Quote
Old 12th May 2012, 17:58   #7  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,995
New version v1.05, see 1st & 2nd posts.
__________________
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 ???
StainlessS is offline   Reply With Quote
Old 18th May 2012, 00:21   #8  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,995
New version v1.06, see 1st & 2nd posts.
__________________
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 ???
StainlessS is offline   Reply With Quote
Old 27th May 2012, 11:44   #9  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,995
Quote:
Originally Posted by StainlessS View Post
may keep this chromaweight of 0.333 (What I 'feel' is about right).

EDIT: I think I'm correct about most filters using a weighting of about 0.5 for combined chroma, dont myself think
this is a good measure, luma commonly fills it's full dynamic range, whereas chroma huddles about the middle,
as chroma habitually occupies considerably less dynamic range, it should count for less in any kind of weighting, even
if combining two chroma channels. If the dynmic range of chroma is somewhat reduced, then the difference between
two identical frames where one has been downsized/compressed has got to be likewise reduced and of lesser importance
as a measure. Think about 33% might be a better guestimate.
Seems the reason that combined chroma normally counts for 0.5 total weight can be found here:
http://forum.doom9.org/showthread.ph...032#post640032
And as already stated, chroma tends to huddle around the centre so should probably be of lesser weight.
__________________
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; 28th May 2012 at 01:41.
StainlessS is offline   Reply With Quote
Old 16th November 2012, 19:21   #10  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,995
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
Old 16th November 2012, 19:25   #11  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,995
Test snippet for LocateFrames() in previous post.

Code:
#Import("LocateFrames.avs")
VIDOEOFILE="D:\AVS\AVI\PAL-P_169_P-AeonFlux.d2v"
Test=MPEG2Source(VIDOEOFILE).Trim(0,2999)

MCOUNT=600                      # Size of sample taken from full Test clip.
MSTART=1000                     # Start position in Full Test clip of Sample.
MSTOP =MSTART+MCOUNT            # Stop position in full test clip.
Test.Trim(MSTART,-MCOUNT)       # Last = 600 Frames from MSTART to MSTART+MSTOP-1

# Manufacture 5 frame FindClip, NOTE middle frame exact, others blurred to some degree.
Q=trim(100,-1).Blur(0.1) + trim(200,-1).Blur(1.58).Blur(1.58)  + Trim(300,-1) + trim(400,-1).Blur(0.3) + Trim(500,-1).Blur(1.0)

Results=LocateFrames(Test,Q,start=MSTART,stop=MSTOP)
#Results=LocateFrames(Test,Q,Thresh=1.5,Thresh2=1.6,Start=MSTART,Stop=MSTOP) # Alternative Ordered search

RT_Debug(Results)   # Send combined results to debugview
RT_Debug(" ")       # Line separator

GScript("""
    N = RT_TxtQueryLines(Results)       # Same as number of frames in find f clip.
    for(i=0,N-1) {
        s=RT_TxtGetLine(Results,Line=i) # Get individual result string
        Eval(s)                         # Set variables for this find frame
        RT_Debug("Found frame",String(LF_FOUND),"for find frame",String(LF_FIND),"Had a diff of",String(LF_DIFF))
    }
""")

Return Test # Dummy return avoid ThrowError
Results from DebugView

Code:
00000002	25.34745216	[3680] RT_Debug: LF_FOUND=1100 LF_FIND=0 LF_DIFF=0.006134 LF_START=1000 LF_END=1599 LF_XPCNT=0 LF_MATCH=0	
00000003	25.34751892	[3680] RT_Debug: LF_FOUND=1200 LF_FIND=1 LF_DIFF=0.482239 LF_START=1000 LF_END=1599 LF_XPCNT=0 LF_MATCH=0	
00000004	25.34756088	[3680] RT_Debug: LF_FOUND=1300 LF_FIND=2 LF_DIFF=0.000000 LF_START=1000 LF_END=1300 LF_XPCNT=0 LF_MATCH=2	
00000005	25.34760475	[3680] RT_Debug: LF_FOUND=1400 LF_FIND=3 LF_DIFF=0.038260 LF_START=1000 LF_END=1599 LF_XPCNT=0 LF_MATCH=0	
00000006	25.34764290	[3680] RT_Debug: LF_FOUND=1500 LF_FIND=4 LF_DIFF=0.928930 LF_START=1000 LF_END=1599 LF_XPCNT=0 LF_MATCH=0	
00000007	25.34771919	[3680] RT_Debug: 	
00000008	25.35038757	[3680] RT_Debug: Found frame 1100 for find frame 0 Had a diff of 0.006134	
00000009	25.35267448	[3680] RT_Debug: Found frame 1200 for find frame 1 Had a diff of 0.482239	
00000010	25.35495567	[3680] RT_Debug: Found frame 1300 for find frame 2 Had a diff of 0.000000	
00000011	25.35724068	[3680] RT_Debug: Found frame 1400 for find frame 3 Had a diff of 0.038260	
00000012	25.35950851	[3680] RT_Debug: Found frame 1500 for find frame 4 Had a diff of 0.928930
__________________
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; 16th November 2012 at 21:58.
StainlessS is offline   Reply With Quote
Old 17th November 2012, 18:37   #12  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,995
Modified LocateFrames version from v0.0 to v1.06 to sync with MatchFrames (logic is same).
Uploaded zip to Mediafire (in sig) containing both MatchFrames and LocateFrames scripts.
EDIT: LocateFrames() Intro is extended with full args spec in zip (similar to MatchFrames spec).
__________________
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; 18th November 2012 at 17:15.
StainlessS is offline   Reply With Quote
Old 21st November 2012, 11:37   #13  |  Link
Brad555
Registered User
 
Join Date: Nov 2012
Posts: 1
Good job, Thanks to post here Code..

Last edited by Brad555; 24th December 2012 at 12:51.
Brad555 is offline   Reply With Quote
Old 29th April 2015, 21:57   #14  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,995
Both scripts have had several updates (In RT_Stats zip) which have not been posted here (mainly due to D9 post size restriction).

Matchframes.avs Part 1 of 2
Code:
############################################################################
# MatchFrames v1.10, by StainlessS:
#
# Find And return frames in c clip that are best matched to frames in f clip.
# v1.10 Planar, YUY2, RGB24/32. Previously YV12 only.
# Null Audio returned.
# ##################################
# Based on FindFrame() (c) Gavino.     http://forum.doom9.org/showthread.php?p=1569622#post1569622
# Required: GScript    (c) Gavino:     http://forum.doom9.org/showthread.php?t=147846
# Required: RT_Stats (c) StainlessS:   http://forum.doom9.org/showthread.php?p=1584313
# Recommended FrameSel (c) StainlessS: http://forum.doom9.org/showthread.php?t=167971
# Recommended DebugView utility to view and capture output: http://technet.microsoft.com/en-gb/sysinternals/bb545027
# MatchFrames  THREAD:                 http://forum.doom9.org/showthread.php?t=164766
# LocateFrames POST:                   http://forum.doom9.org/showthread.php?p=1600961#post1600961
# ##################################
#
# MatchFrames(clip c,clip f,bool "Show",float "Thresh",float "Thresh2",string "FileName",string "LogFile", \
#               int "Start",int "Stop",bool "XP",Bool "Chroma",Float "ChromaWeight",string "Title",bool "debug")
#
# Args:
#
# c       = clip, Source clip.
# f       = clip, Consisting of frames that you wish to find in the c clip.
# Show    = bool[true], True returns both find and found frames using StackHorizontal. NOTE, hires clips, may cause problems in eg VDUB
#                if StackHorizontal width goes over some VD imposed limit.
# Thresh  = float[0.0 == Search for 1st exact match or best possible if no exact match found]. Threshold for declaring match (diff <= Thresh).
#           Range 0.0 -> 255.0.
# Thresh2 = float[0.0 == NOT time ordered]. Both a 'time ordered' indicator and a threshold.
#           If (Thresh < Thresh2) Then clip f is taken as time ordered (in c), ie frames in both f and c clips are temporally ordered.
#           If f clip is known to be time ordered (in c), this arg can significantly cut down on the time taken to search for frames.
#
#           Assuming time ordered f clip (Thresh < Thresh2),
#
#               If a match found where diff of find to found frame <= Thresh,
#                    Next frame search will start from found frame + 1.
#               Else if diff of find to Full Scan BEST found frame < Thresh2
#                    Next frame search will start from BEST found frame + 1.
#               Else
#                    Next frame search will start from current start position.
#               End if
#               *** Where above 'Full Scan' means scan from current start postion to the last valid search frame.
#
# FileName= string["MatchFramesCmd.txt"], Output Frames command file.
#             Can use FrameSel() Plugin to select frames using MatchFramesCmd.txt Command file.
#             FrameSel() Plugin can be found here:- http://forum.doom9.org/showthread.php?t=167971
#             Can monitor the MatchFramesCmd.txt file during scanning to view progress (ie view in notepad, [Read-Only viewer maybe safer]).
#
# LogFile = string["MatchFrames.Log"], Output Log file. Can monitor as for command file.
#             The Logfile might produce an output line like that below:
#
#             "0]=[1100] Diff=0.239 (T1:XP) S=1000 E =1101 XPCNT=5"
#
#             Where eg 0] is find frame number, [1100] is found frame,
#             Diff is the Difference (Luma + optional Chroma) between find and found frames.
#             S and E are the search start and end positions that were searched for that frame.
#             The "(T1:XP)" stuff presents just a little info about the search:
#              "(BM:  )" Best Match, where no frame was found with a Diff <= Thresh, the returned frame was best match found in search area.
#              "(BM:T2)" Same as "(BM:  )" but was an Ordered search & because Diff<Thresh2, then next frame search will start at Best Match+1.
#              "(T1:  )" Means that the found frame had a Diff <= Thresh.
#              "(T1:XP)" Same as "(T1:  )" but Xtra Paranoia (XP) successfully found a better matching frame following the one that
#              initially broke thresh. If this flag is shown, you will also see "XPCNT" which will tell how many successive better frames
#              were found after the initial frame that broke Thresh.
#             v1.10, See Debug arg below to view real time output in DebugView window without slight risk involved reading open log file.
#
# Start   = int[0, == First frame of clip], Start frame to search from (eg Skip introduction).
# Stop    = int[0, == Last frame of clip + 1], Frame prior to which, c clip is searched (Exclusive). (eg Skip end credits).
# XP      = bool[true == Extra Paranoid] Main purpose of XP is so that you can use Thresh > 0.0 even if you dont fully trust a non best search.
#               If diff of find to found frame <= Thresh, then search would normally stop at that frame, but when
#               XP is true (Default), it will continue to search so long as subsequent frames provide a better match. Will usually result
#               in 1 extra frame being compared (providing that your Thresh is not too high).
#               If Thresh is set to 0.0 (default) then will only stop search on EXACT match, and so is likely to do a full search
#               (unless exact frame exists). XP allows you to settle for a close match by setting thresh a little above 0.0, and when a close
#               match is found, it will continue to edge forward 1 frame at a time until matches cease to be better.
#               If exact match was found, ie diff == 0.0 then will not scan extra frames (no better match possible).
#
# Chroma   = bool[false==Luma diff Only], If true then also uses chroma difference as per ChromaWeight.
# ChromaWeight=float[1.0/3.0 ie 0.33333]. If Chroma==true then LumaWeight = 1.0-ChromaWeight.
#               If Chroma==false then ChromaWeight is ignored and only luma difference is used.
#               v1.10, Chroma and ChromaWeight are for YUV only, not used for Y8 or RGB, no real advantage to using Luma only.
# Title    = string[""== none], Allows you to place a string of text in the Log and Command file headers, eg "Hires Test#2" or whatever.
# Debug    = bool[True == Debug info sent to debugview], True, send logging info to DebugView window (google DebugView),
#            allows monitoring of progress without the slightly risky method of reading the open LogFile. New v1.10.
#            Default True as cannot change your mind in middle of long search, does not have significant overhead in producing debug log.
#            False, switch real time debug logging off.
#            This setting has nothing whatever to do with below pre v1.10 DEBUG MODE, see below.
# ##################################
# DEBUG MODE: If the f FrameCount and c[START,STOP] FrameCount (ie STOP-START) are same AND Thresh < Thresh2 (ie Ordered), then the script is put
# into DEBUG MODE. This would be easiest achieved when START and STOP are at their default 0 values meaning 'All of c clip' and lengths of
# f and c are same.
# In Debug Mode, there is no searching for best match, log is produced with difference between all corresponding frames
# and in the footer of the log, it will show Average Diff, Min Diff, and Max Diff for the entire frame set.
# In DEBUG MODE, the command file is cleared, prints header only.
# ##################################
#
# Will take some time to show results, it is not a bug if it seems to hang, it is WORKING HARD.
#
############################################################################
#
__________________
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; 31st May 2015 at 15:12.
StainlessS is offline   Reply With Quote
Old 29th April 2015, 21:58   #15  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,995
Matchframes.avs Part 2 of 2
Code:
Function MatchFrames(clip c,clip f,bool "Show",float "Thresh",float "Thresh2",string "FileName",string "LogFile", \
        int "Start",int "Stop",bool "XP", Bool "Chroma",Float "ChromaWeight",string "Title",bool "Debug") {
    ver         = "v1.10 - 25 June 2014"                # Version Number
    myName      ="MatchFrames: "
    c = c.Killaudio()   f = f.Killaudio()               # Audio return not sensible.
    Show        = Default(Show,true)                    # Defaults true = show StackHorizontal find & found frames
    Thresh      = Float(Default(Thresh, 0.0))           # Threshold for declaring match, Default==0.0 to search for best possible match.
    Thresh2     = Float(Default(Thresh2,0.0))           # Threshold2 Default==0.0, find clip f, not time ordered.
    FileName    = Default(FileName,"MatchFramesCmd.txt")# "" to switch OFF Frames output command file.
    LogFile     = Default(LogFile,"MatchFrames.Log")    # "" to switch OFF Logfile.
    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,True)                  # Default Luma + Chroma.
    ChromaWeight= Float(Default(ChromaWeight,1.0/3.0))  # Default, 33% of Total Difference (Combined U and V).
    Title       = Default(Title,"")                     # Shown in log and command file, Default "".
    Debug       = Default(Debug,True)                   # Default no debug logging to DebugView
    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.Width==f.Width,myName+"- Clip Width mismatch")
    Assert(c.Height==f.Height,myName+"- Clip Height mismatch")
    Assert(RT_VarIsSame(c,f),myName+"- ColorSpace Mismatch")    # Same colorspace ?
    Assert(cfrms>0,myName+"- Invalid Start>=Stop")
    Assert(Thresh>=0.0,myName+"- Invalid Thresh")
    Assert(f.Framecount<=cfrms,myName+"- f Frames > c[START,STOP] Frames")
    Assert(ChromaWeight>=0.0&&ChromaWeight<=1.0,myName+"- ChromaWeight Range 0.0->1.0")
    DBug = (cfrms==f.FrameCount && Thresh < Thresh2)    # Debugging Mode ?
    Thresh  = (DBug) ? 255.0 : Thresh                   # If DBug, Ensure everything breaks Thresh.
    Thresh2 = (DBug) ? 255.1 : Thresh2                  # If DBug, Maintain Ordered.
    TDHi =0.0                                           # DEBUG: TotalDifference Hi  (Extra precision)
    TDLo =0.0                                           # DEBUG: TotalDifference Lo
    MinDiff  = 255.0 + 1.0                              # DEBUG: Output, max + 1
    MaxDiff  = 0.0 - 1.0                                # DEBUG: Output, min - 1
    Ordered  = Thresh < Thresh2                         # If true then: Find frames are in time order (match(f[n]) searches from match(f[n-1])+1
    Result = 0                                          # Dummy, Will become a Clip, Dont use 'c.BlankClip(length=0)' (Maybe StackHorizontal)
    Scanned = 0                                         # Init Total Frames scanned
    EOL = Chr(10)                                       # End Of Line. (Do NOT use Carriage Return, Line Feed, Will auto add the CR)
    TLINE = "##########################################################################" + EOL
    TGEN  = "# MatchFrames " + Ver
    TCMD  = "Command File for FrameSel() Plugin." + EOL + "#" + EOL
    TLOG  = " (c) StainlessS : LogFile." + EOL + "#" + EOL
    TNAM  = (Title=="") ? "" : "# Title='" + Title + "'" + EOL + "#" + EOL
    TSET  = "# Width=" + String(c.Width) + " : Height=" + String(c.Height) + " : Start=" + String(Start) + " : Stop=" + String(Stop)
            \ + ((ORDERED && !DBug) ? " : ORDERED" : "") + EOL+"#"+EOL
    TSET2 = "# Thresh="+String(Thresh,"%.3f")+" : Thresh2="+String(Thresh2,"%.3f")+" : XP="+String(XP)
    TSET3 = ((Chroma)?" : ChromaWeight="+String(ChromaWeight,"%.3f"):"") + EOL + "#" + EOL
    TSET4 = ((DBug) ? "# DEBUG MODE" + EOL:"") + "#" + EOL
    LogT = RT_String("%s#\n%s%s%s%s%s%s%s%s",TLINE,TGEN,TLOG,TNAM,TSET,TSET2,TSET3,TSET4,TLINE)
    (Debug) ? RT_DebugF("%s",LogT,name=myName)  : NOP           # DebugView
    (LogFile !="") ? RT_WriteFile(LogFile, "%s",LogT)   : NOP
    (FileName!="") ? RT_WriteFile(FileName,"%s#\n%s : %s%s%s%s%s%s%s",TLINE,TGEN,TCMD,TNAM,TSET,TSET2,TSET3,TSET4,TLINE) : NOP
    FileName= (DBug) ? "" : FileName                # No Command file frame numbers if DBug Mode, HEADER ONLY (ie Wipe command file).
    TimeStart = RT_LocalTimeString(file=false)      # Format "YYYY-MM-DD HH:MM:SS.mmm"
    Start_Secs = RT_TimerHP()
    GScript("""
    for(ix = 0, f.Framecount-1) {                   # Iterate through find frames clip.
        s = Start                                   # Init Start search position
        BestSoFar       = s                         # Search start position
        BestSoFarDiff   = 255.0 + 1.0               # Maximum Possible + 1
        sS =" S=" + String(s,"%-4.0f")              # Start offset this time, as string (at least 4 digits)
        mS=" (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,myName+"- Internal Error, s > e")  # Oops.
        xS=""                                       # Prep XP skip Count string
        for(n=s, eterm) {                           # Search c clip(s to eterm) or until satisfactory match found. (eterm evaluated on entry only)
            # Difference to current find frame.
            CurrDiff=RT_FrameDifference(c,f,n=n,n2=ix,ChromaWeight=ChromaWeight)
            if(CurrDiff < BestSoFarDiff) {                      # Better match than found so far ?
                BestSoFar       = n                             # Remember frame number
                BestSoFarDiff   = CurrDiff                      # Remember difference
                if(BestSoFarDiff <= thresh) {                   # Good enough to satisfy user requirement ?
                    if(DBug) {                                  # DEBUG
                        MinDiff = Min(CurrDiff,MinDiff)
                        MaxDiff = Max(CurrDiff,MaxDiff)
                        TDLo = TDLo + CurrDiff
                        TDHi = TDHi + floor(TDLo / 256.0)       # Hi part, Extra Precision
                        TDLo = frac(TDLo / 256.0) * 256.0       # Lo part, Extra Precision
                    }
                    e=BestSoFar                                 # Where we've scanned to so far
                    mS=" (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(n=BestSoFar+1,eterm) {
                            CurrDiff=RT_FrameDifference(c,f,n=n,n2=ix,ChromaWeight=ChromaWeight)
                            e=n                                 # We scanned more frames past original BestSoFar
                            if(CurrDiff < BestSoFarDiff) {      # Better match ?
                                BestSoFar    = n                # Remember frame number
                                BestSoFarDiff= CurrDiff         # Remember difference
                            } else {
                                n = eterm+1                     # Force Exit with n == eterm + 2 (normally exit @ eterm+1)
                            }
                        }
                        if(BestSoFar != tmp) {
                            mS=" (T1:XP)"                       # Found satisfactory frame, (Flag Thresh, and Xtra Paranoid found better frame)
                            xS=" XPCNT=" + String(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
                    n = eterm + 1                               # Force Exit with current_frame == eterm + 2 (normally exit @ eterm + 1)
                }
            }
        }
        if(Ordered && n == eterm+1 && BestSoFarDiff < Thresh2) {
            mS = " (BM:T2)"                                     # For Log, Time ordered, (Flag, Best Match and Thresh2)
            Start = BestSoFar + 1                               # Next time start from BEST MATCH found + 1.
        }
        Scanned = Scanned + e - s + 1
        Text = RT_String("%4d]=[%6d] Diff=%7.3f%s%s E =%-4.0f%s",ix,BestSoFar,BestSoFarDiff,ms,sS,e,xS)
        (Debug) ? RT_DebugF("%s",Text,name=myName) : NOP                                            # DebugView
        (LogFile!="")  ? RT_WriteFile(LogFile,"%s",Text,Append=true) : NOP              # Log file
        (FileName!="") ? RT_WriteFile(FileName,"%d",BestSoFar,Append=true) : NOP        # Command file
        FindFrame =f.Trim(ix,-1).SubTitle(Text)
        wrClip    =c.Trim(BestSoFar,-1)
        GotFrame=(Show) ? StackHorizontal(FindFrame,wrClip) : wrClip
        Result = (IsClip(Result)) ? Result ++ GotFrame : GotFrame                       # Append to 'result clip so far'.
    }
    """) # End Of GScript
    TimeEnd = RT_LocalTimeString(file=false)
    Tim = RT_TimerHP - Start_Secs
    Text = RT_String("\n%s\nStart Time = %s\nEnd   Time = %s\nTotal Time = %.3f Secs (%.3f Mins)\n",TLINE,TimeStart,TimeEnd,Tim,Tim/60.0)
    Text2 = RT_String("Total Frames Searched =%6d (%7.3f FPS : %10.6f SPF)",Scanned,Scanned/Tim,Tim/Scanned)
    Text3 = RT_String("Find Frames Located   =%6d (%7.3f FPS : %10.6f SPF)",f.FrameCount,f.FrameCount/Tim,Tim/f.FrameCount)
    (Debug) ? RT_DebugF("%s\n%s\n%s",Text,Text2,Text3,name=myName) : NOP
    (LogFile!="") ? RT_WriteFile(LogFile,"%s\n%s\n%s",Text,Text2,Text3,Append=True) : NOP
    Text4 = RT_String("DEBUG: AveDiff=%.3f : MinDiff=%.3f : MaxDiff=%.3f : [L=%.3f : (U+V)=%.3f]\n",
        \ (TDHi / cfrms * 256.0) + (TDLo / cfrms),MinDiff,MaxDiff,1.0-ChromaWeight,ChromaWeight)
    (DBug&&Debug)       ? RT_DebugF("%s",Text4,name=myName)             : NOP
    (DBug&&LogFile!="") ? RT_WriteFile(LogFile,"%s",Text4,Append=True)  : NOP
    Return Result.AssumeFPS(1.0)
}
__________________
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 ???
StainlessS is offline   Reply With Quote
Old 29th April 2015, 22:01   #16  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,995
LocateFrame.avs Part 1 of 2 (DBase usage added)
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",String "DB") {
#
# LocateFrames() v1.10 by StainlessS:
# Find frames in c clip that are best matched to frames in f clip.
# v1.10 Planar, YUY2, RGB24/32. Previously YV12 only.
#
# Returns either a result string (old method) or if given a string DB arg, creates RT_Stats DB DataBase file, and returns number of records, Int.
#
# ##################################
# Based on FindFrame() (c) Gavino.     http://forum.doom9.org/showthread.php?p=1569622#post1569622
# Required: GScript    (c) Gavino:     http://forum.doom9.org/showthread.php?t=147846
# Required: RT_Stats (c) StainlessS:   http://forum.doom9.org/showthread.php?p=1584313
# Recommended FrameSel (c) StainlessS: http://forum.doom9.org/showthread.php?t=167971
# Recommended DebugView utility to view and capture output: http://technet.microsoft.com/en-gb/sysinternals/bb545027
# MatchFrames  THREAD:                 http://forum.doom9.org/showthread.php?t=164766
# LocateFrames POST:                   http://forum.doom9.org/showthread.php?p=1600961#post1600961
# ##################################
# Args:
#
# c       = clip, Source clip.
# f       = clip, Consisting of frames that you wish to find in the c clip.
# Thresh  = float[0.0 == Search for 1st exact match or best possible if no exact match found]. Threshold for declaring match (diff <= Thresh).
#           Range 0.0 -> 255.0.
# Thresh2 = float[0.0 == NOT time ordered]. Both a 'time ordered' indicator and a threshold.
#           If (Thresh < Thresh2) Then clip f is taken as time ordered (in c), ie frames in both f and c clips are temporally ordered.
#           If f clip is known to be time ordered (in c), this arg can significantly cut down on the time taken to search for frames.
#
#           Assuming time ordered f clip (Thresh < Thresh2),
#
#               If a match found where diff of find to found frame <= Thresh,
#                    Next frame search will start from found frame + 1.
#               Else if diff of find to Full Scan BEST found frame < Thresh2
#                    Next frame search will start from BEST found frame + 1.
#               Else
#                    Next frame search will start from current start position.
#               End if
#               *** Where above 'Full Scan' means scan from current start postion to the last valid search frame.
#
# Start   = int[0, == First frame of clip], Start frame to search from (eg Skip introduction).
# Stop    = int[0, == Last frame of clip + 1], Frame prior to which, c clip is searched (Exclusive). (eg Skip end credits).
# XP      = bool[true == Extra Paranoid] Main purpose of XP is so that you can use Thresh > 0.0 even if you dont fully trust a non best search.
#               If diff of find to found frame <= Thresh, then search would normally stop at that frame, but when
#               XP is true (Default), it will continue to search so long as subsequent frames provide a better match. Will usually result
#               in 1 extra frame being compared (providing that your Thresh is not too high).
#               If Thresh is set to 0.0 (default) then will only stop search on EXACT match, and so is likely to do a full search
#               (unless exact frame exists). XP allows you to settle for a close match by setting thresh a little above 0.0, and when a close
#               match is found, it will continue to edge forward 1 frame at a time until matches cease to be better.
#               If exact match was found, ie diff == 0.0 then will not scan extra frames (no better match possible).
#
# Chroma   = bool[false==Luma diff Only], If true then also uses chroma difference as per ChromaWeight.
# ChromaWeight=float[1.0/3.0 ie 0.33333]. If Chroma==true then LumaWeight = 1.0-ChromaWeight.
#               If Chroma==false then ChromaWeight is ignored and only luma difference is used.
#               v1.10, Now Planar, YUY2, RGB (was YV12 only), Chroma and ChromaWeight are for YUV only, not used for Y8 or RGB,
#               no real advantage to using Luma only.
# Prefix   = string("LF_"). Prefix prepended to variable names in returned string. (NOT USED if DBase mode, see below DB arg)
# Debug    = bool[True == Debug info sent to debugview], True, send logging info to DebugView window (google DebugView),
#            allows monitoring of progress.
#            v1.10, Default True as cannot change your mind in middle of long search, does not have significant overhead in producing debug log.
#            False, switch real time debug logging off.
#
# DB       = string["" == Do Not Use DataBase]. Default "" as old version, where results returned in String as described below.
#            v1.10, Otherwise, if DB != "" eg "LocateFrames.DB", then will create an RT_Stats DBase file using supplied DB as the filename,
#            where results are stored in the Dbase and will return an Int, ie the number of frames in find f clip, which is also the
#            number of records stored in the DB File. DB file created with typestring "iifiiii", in other words 7 fields per record.
#            First two fields are Type Int, next 1 field of Type Float, then 4 fields of Type Int.
#              Field 0 : Type Int   : LF_FOUND      Index of found clip frame
#              Field 1 : Type Int   : LF_FIND       Index of find clip frame
#              Field 2 : Type Float : LF_DIFF       FrameDifference() between find and found
#              Field 3 : Type Int   : LF_START      Start frame searched
#              Field 4 : Type Int   : LF_END        End frame searched
#              Field 5 : Type Int   : LF_XPCNT      Count of extra frames advanced due to eXtra Paranoia setting, See above XP.
#              Field 6 : Type Int   : LF_MATCH      Kind of match found.  # As for MatchFrames(), 0="BM", 1="(BM:T2)", 2="(T1:  )", 3="(T1:XP)"
#              See below for explanation of field contents, and RT_Stats for usage of RT_DBaseGetField(String Filename,Int Record,Int Field).
# ##################################
#
# Returns newline [Chr(10)] separated list of results as a multiline String, OR results stored in DB Database File, where it returns
#  the number of records in the DB file (ie frames in Findclip f).
#
#  STRING RESULT:-
#   Results string for a single frame find clip using default "LF_" prefix, 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 = FrameDifference() between find and found (range 0.0 -> 255.0)
#     LF_START= Start frame searched
#     LF_END  = End frame searched
#     LF_XPCNT= Count of extra frames advanced due to eXtra Paranoia setting, See above XP.
#     LF_MATCH= Kind of match found.  # As for MatchFrames(), 0="BM", 1="(BM:T2)", 2="(T1:  )", 3="(T1:XP)"
#
#           0= Best Match, where no frame was found with a Diff <= Thresh, the returned frame was best match found in search area.
#           1= Same as 0 but was an Ordered search & because Diff<Thresh2, then next frame search will start at Best Match+1.
#           2= Means that the found frame had a Diff <= Thresh.
#           3= Same as 2 but Xtra Paranoia (XP) successfully found a better matching frame following the one that
#              initially broke thresh. "XPCNT" will tell how many successive better frames were found after the initial
#              frame that broke Thresh.
#
#   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.
#
#   Brief example usage:
#
#    GScript("""
#       myName="StringResultScript:"
#       SearchClip=avisource("D:\avs\xmen2.avi").trim(4000,-1000)                                   # 1000 frame SearchClip
#       FindClip=SearchClip.SelectEvery(100,0).Blur(1.58)                                           # 10 frame FindClip, Make a bit Different
#       Results=LocateFrames(searchclip,findclip)
#       n = RT_TxtQueryLines(Results)                                                               # Same as number of frames in findclip.
#       Result = 0                                                                                  # Will become clip
#       for(i=0,n-1) {
#           s=RT_TxtGetLine(Results,Line=i)                                                         # Get individual result string
#           Eval(s)                                                                                 # Set variables for this find frame
#           RT_DebugF("Found frame %d for find frame %d Had a diff of %f",LF_FOUND,LF_FIND,LF_DIFF,name=myName)
#           Lft=FindClip.Trim(LF_FIND,-1).RT_SubTitle("%d DIFF=%f",LF_FIND,LF_DIFF)                 # Find Frame
#           Rgt=SearchClip.Trim(LF_FOUND,-1).RT_SubTitle("%d",LF_FOUND)                             # Found Frame
#           Stak = StackHorizontal(Lft,Rgt)
#           Result = (Result.IsClip) ? Result ++ Stak : Stak                                        # Append to clip so far
#       }
#       Return Result.AssumeFPS(1.0)
#    """)
#    Return Last
# ##################################
#
# DBASE RESULT:- (actual result is Int, number of records in created DB, ie frames in FindClip)
#
#    SearchClip=avisource("D:\avs\xmen2.avi").trim(4000,-1000)                                      # 1000 frame SearchClip
#    FindClip=SearchClip.SelectEvery(100,0).Blur(1.58)                                              # 10 frame FindClip, Make a bit Different
#    DEBUG=True
#    myName="DB_Script: "
#    DB="~MyDbase_" + RT_LocalTimeString(File=True)+".DB"                                           # Unique Temporary DBase filename
#    Records = LocateFrames(SearchClip,FindClip,debug=DEBUG,db=DB)                                  # Same as number of frames in FindClip.
#    RT_DebugF("I got %d Records",Records,name=myName)                                              # Send to DebugView
#    Result = 0                                                                                     # Will later be a clip
#    GScript("""
#        for(i=0,Records-1) {
#            FoundIx = RT_DBaseGetField(DB,i,0)                                                      # Frame we found (Int)
#            FindIx  = RT_DBaseGetField(DB,i,1)                                                      # Frame that we had to find (Int)
#            Diff    = RT_DBaseGetField(DB,i,2)                                                      # FrameDifference (Float)
#            RT_DebugF("%d ] Found frame %d with Difference of %f",FindIx,FoundIx,Diff,name=myName)
#            Lft=FindClip.Trim(FindIx,-1).RT_SubTitle("%d DIFF=%f",FindIx,Diff)                      # Find Frame
#            Rgt=SearchClip.Trim(FoundIx,-1).RT_SubTitle("%d",FoundIx)                               # Found Frame
#            Stak = StackHorizontal(Lft,Rgt)
#            Result = (Result.IsClip) ? Result ++ Stak : Stak                                        # Append to clip so far
#        }
#        RT_FileDelete(DB)                                                                           # Delete temp DB file
#    """)
#    Return Result.AssumeFPS(1.0)
#
# ##################################
__________________
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 ???
StainlessS is offline   Reply With Quote
Old 29th April 2015, 22:01   #17  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,995
Post 4 of 4.

LocateFrame.avs Part 2 of 2

Code:
    myName      = "LocateFrames: "
    ver         = "v1.10 - 25 June 2014"                # Version Number
    Assert(RT_FunctionExist("GScript"),myName+"Essential GScript plugin installed, http://forum.doom9.org/showthread.php?t=147846")
    c = c.Killaudio()   f = f.Killaudio()               # Audio not needed.
    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,True)                   # v1.10, changed True
    DB          = Default(DB,"")                        # DBase not default
    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.Width==f.Width,myName+"- Clip Width mismatch")
    Assert(c.Height==f.Height,myName+"- Clip Height mismatch")
    Assert(RT_VarIsSame(c,f),myName+"- ColorSpace Mismatch")    # Same colorspace ?
    Assert(cfrms>0,myName+"- Invalid Start>=Stop")
    Assert(Thresh>=0.0,myName+"- Invalid Thresh")
    Assert(f.Framecount<=cfrms,myName+"- f Frames > c[START,STOP] Frames")
    Assert(ChromaWeight>=0.0&&ChromaWeight<=1.0,myName+"- ChromaWeight Range 0.0->1.0")
    MODE = (DB!="")
    Ordered  = Thresh < Thresh2                         # If true then: Find frames are in time order (match(f[n]) searches from match(f[n-1])+1
    FMT="%sFOUND=%-6d %sFIND=%-6d %sDIFF=%f %sSTART=%d %sEND=%-6d %sXPCNT=%-3d %sMATCH=%d"
    Result = ""
    GScript("""
        (DEBUG) ? RT_DebugF("\n%s %s (%s Mode)\n",myName, Ver,(!MODE)? "STRING" : "DBASE",name=myName) : NOP
        if(MODE) {RT_DBaseAlloc(DB,0,"iifiiii")}
        for (ix = 0, f.Framecount-1) {                  # Iterate through find frames clip.
            s = Start                                   # Init Start search position
            BestSoFar       = s                         # Search start position
            BestSoFarDiff   = 255.0 + 1.0               # Maximum Possible + 1
            sS =s                                       # Start offset this time
            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,myName+"- Internal Error, s > e")  # Oops.
            xpCnt=0                                     # Prep XP skip Count string
            for(n=s, eterm) {               # Search c clip(s to eterm) or until satisfactory match found. (eterm evaluated on entry only)
                # Difference to current find frame.
                CurrDiff=RT_FrameDifference(c,f,n=n,n2=ix,ChromaWeight=ChromaWeight)
                if(CurrDiff < BestSoFarDiff) {          # Better match than found so far ?
                    BestSoFar       = n                 # 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(n=BestSoFar+1,eterm) {
                                CurrDiff=RT_FrameDifference(c,f,n=n,n2=ix,ChromaWeight=ChromaWeight)
                                e=n                                 # We scanned more frames past original BestSoFar
                                if(CurrDiff < BestSoFarDiff) {      # Better match ?
                                    BestSoFar    = n                # Remember frame number
                                    BestSoFarDiff= CurrDiff         # Remember difference
                                } else {
                                    n = 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
                        n = eterm + 1                       # Force Exit with current_frame == eterm + 2 (normally exit @ eterm + 1)
                    }
                }
            }
            if(Ordered && n == 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.
            }
            if(MODE) {
                (DEBUG) ? RT_DebugF(FMT,Prefix,BestSoFar,Prefix,ix,Prefix,BestSoFarDiff,Prefix,sS,Prefix,e,Prefix,XpCnt,Prefix,mS,name=myName) : NOP
                RT_DBaseAppend(DB,BestSoFar,ix,BestSoFarDiff,sS,e,XpCnt,mS)
            } Else {
                Text = RT_String(FMT, Prefix,BestSoFar,Prefix,ix,Prefix,BestSoFarDiff,Prefix,sS,Prefix,e,Prefix,XpCnt,Prefix,mS)
                Result = RT_TxtAddStr(Result,Text)              # Avoid string concatenation bug in v2.58 and v2.6a3.
                (DEBUG) ? RT_DebugF("%s",Text,name=myName) : NOP
            }
        }
    """) # End Of GScript
    return (MODE) ? f.FrameCount : Result           # Int return for Dbase and String if not DBase
}
__________________
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 ???
StainlessS is offline   Reply With Quote
Old 29th April 2015, 23:08   #18  |  Link
creaothceann
Registered User
 
Join Date: Jul 2010
Location: Germany
Posts: 360
You can always post it on pastebin. (it even has an Avisynth color scheme)
creaothceann is offline   Reply With Quote
Old 29th April 2015, 23:37   #19  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,995
Good to know, thanks very much
__________________
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 ???
StainlessS is offline   Reply With Quote
Old 26th October 2016, 02:06   #20  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,995
MatchFrames.avs + LocateFrames.avs v1.13, Requires RT_Stats v2.00 Beta 2. http://forum.doom9.org/showthread.ph...28#post1782028

For MatchFrames zip (~15KB) see MediaFire in sig. (there will be two versions).


Here on PasteBin
MatchFrames:- http://pastebin.com/1TGKg3nw
LocateFrames:- http://pastebin.com/kBX4RCPY

Added X,Y,W,H coords (avoid logos), also new PD mode (Pearsons distance based on LumaCorrelation, less affected by changes in brightness).

EDIT: Seems to be formatted a bit too wide for Pastebin.

EDIT: Note, also added DBASE mode to LocateFrames, some time ago (old version supplied in RT_Stats). DBase mode returns results
for LocateFrames in DBase, instead of via a multiline string.
__________________
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; 26th October 2016 at 02:11.
StainlessS is offline   Reply With Quote
Reply

Tags
find, findframe, frame, search

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 17:42.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2018, vBulletin Solutions Inc.