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
Register FAQ Calendar Today's Posts Search

Reply
 
Thread Tools Search this Thread Display Modes
Old 29th May 2014, 01:41   #281  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
RT_Stats v1.40 Beta02,

Main changes,
LumaTol change from Float to Int.
Added Exit Condition RT_LumaPixelsDifferent arg PCThresh.
Added BEST MATCH status when Function returns -1 NOT FOUND and EXIT CONDITION Flags set.
Code:
RT_QwikScanGetNear(clip DBClip,string DB,string PNDB,int StartFrame,int FindFrame,                          \
    clip "FindClip"=NULL,int "Maxdistance"=DBClip.FrameCount-1,bool "Inclusive"=True,Int "LumaTol"=0,   \
    int "Flags"=0, Float "LD"=0.0,Float "LC"=0.0,Float "FD"=0.0,int "PC"=0,int "XP"=1,                      \
    string "Prefix"="QSGN_",Float "ChromaWeight"=1.0/3.0,Int "PCThresh"=0)

    *** EXPERIMENTAL ***

    Developer function only, not for the casual scriptor.
    Function that scans a pair of database files to find a sequence of candidate frames that could match a target FindFrame.
    Returns frame number of possible matching frame, or -1 meaning NOT FOUND.
    DBClip, the clip to search, and used as arg to RT_QwikScanCreate to create DB, PrevDB and NextDB database files that hold
      "FingerPrint" and frame location data to assist in rapid location of candidate frames.
    DB, Filename of the "FingerPrint" Dbase. Created via RT_QwikScanCreate.
    PNDB, Filename of the frame locator Dbase. Created via RT_QwikScanCreate as either PrevDB or NextDB.
      Use the PrevDB if searching frames prior to StartFrame in DBClip, or the NextDB if search frames after StartFrame.
    StartFrame, frame in DBClip where searching will start, see also Inclusive.
    FindFrame, Frame number of the frame that is to be matched (in FindClip if supplied or DBClip if not supplied).
    FindClip, clip holding frame to match, defaults to DBClip if not supplied.
    MaxDistance, maximum number of frames to search, defaults DBClip.FrameCount -1, but silently limited to the maximum possible
      distance depending upon where StartFrame is and whether searching forwards or backwards. A MaxDistance of 1 will search only
      the StartFrame (if Inclusive) and the frame next to it.
    Inclusive. If true (default) then also tests StartFrame.
    LumaTol, +- Luma Tolerance (0 -> 16). Allow for mismatch in luma between DBClip and FindClip. If eg the FindClip pixels can vary
      by as much as +- 4 pixel levels, then set LumaTol to 4, the bigger this number the slower the function, but it should be still
      quite fast with most clips even up to a LumaTol of maximum 16, the bigger this number, the more frames will fit the fingerprint
      and so there will be more candidate frames to check.
    Flags, Bit flags, sets the additional Exit Conditions of the function.
        Bit 0 set eg 0x01, Sets the LumaDifference Exit Condition.
        Bit 1 set eg 0x02, Sets the LumaCorrelation Exit Condition.
        Bit 2 set eg 0x04, Sets the FrameDifference Exit Condition.
        Bit 3 set eg 0x08, Sets the PixelsDifferentCount Exit Condition.
    LD, LumaDifference Exit Condition Threshold.
    LC, LumaCorrelation Exit Condition Threshold.
    FD, FrameDifference Exit Condition Threshold.
    PC, PixelsDifferentCount Exit Condition Threshold (int). See Also PCThresh.
    XP, Sets eXtra Paranoia for EXIT Conditions.
        0=Off
        1=Continue searching while next frame is a better Exit Condition match.
        2=Continue searching while next frame is a better or equal Exit Condition match.

    Prefix, Default "QSGN_". Prefix for names of local variables returned to give status of exit conditions.
        All Below only set if Flags arg non zero.
         QSGN_Exit_Flags, bit flag, condition that was satisfied to cause exit (same as Flags arg, only 1 bit will be set).
          Below Only set if QSGN_Exit_Flags != 0 (where function returns a valid candidate frame number).
           QSGN_Exit_LD, LumaDifference for the exit frame, Only set if QSGN_Exit_Flags == 0x01.
           QSGN_Exit_LC, LumaCorrelation for the exit frame, Only set if QSGN_Exit_Flags == 0x02.
           QSGN_Exit_FD, FrameDifference for the exit frame, Only set if QSGN_Exit_Flags == 0x04.
           QSGN_Exit_PC, PixelsDifferentCount for the exit frame, Only set if QSGN_Exit_Flags == 0x08.
           QSGN_Exit_XP, Count of additional frames traversed if found to be a better match. Only set if both XP arg is non zero
         Below Only set if Function returns -1 NOT FOUND, AND QSGN_BM_Flags != 0 (QSGN_Exit_Flags will be 0 if NOT FOUND)
           QSGN_BM_LD, LumaDifference of the BEST MATCHING frame, Only set if QSGN_BM_Flags == 0x01.
           QSGN_BM_LD_Frm, LumaDifference BEST MATCHING frame, Only set if QSGN_BM_Flags == 0x01.
           QSGN_BM_LC, LumaCorrelation of the BEST MATCHING frame, Only set if QSGN_BM_Flags == 0x02.
           QSGN_BM_LC_Frm, LumaCorrelation BEST MATCHING frame, Only set if QSGN_BM_Flags == 0x02.
           QSGN_BM_FD, FrameDifference of the BEST MATCHING frame, Only set if QSGN_BM_Flags == 0x04.
           QSGN_BM_FD_Frm, FrameDifference BEST MATCHING frame, Only set if QSGN_BM_Flags == 0x04.
           QSGN_BM_PC, PixelsDifferentCount of the BEST MATCHING frame, Only set if QSGN_BM_Flags == 0x08.
           QSGN_BM_PC_Frm, PixelsDifferentCount BEST MATCHING frame, Only set if QSGN_BM_Flags == 0x08.

        If the function returns -1 NOT FOUND, but an EXIT condition was set and at least one candidate frame was found but did
        not satisfy any EXIT condition, then the BEST MATCH flags will be set (if none set then no candidate frames were found
        that were within LumaTol of the target and so no EXIT conditions were tested). If QSGN_BM_Flags is non zero, it should be
        exactly the same as Flags arg, with all selected BEST MATCH status variables returned as noted above.
          Where DBClip and FindClip are quite different in eg brightness, It may be possible to have some kind of self tuning
        routine. Find a single (or multiple) frames with maximum LumaTol, and EXIT conditions that are sure to fail, and use the
        BEST MATCH results to tune both LumaTol and the EXIT conditions, for the remainder of the search session.
          It might though be just as good to do some kind of Luma levelling on each clip, based on a sample number of frames
        and using YPlaneMin and YPlaneMax followed by Levels (With Coring=False, and before DBase creation of course).

    ChromaWeight, Argument to the FD FrameDifference Exit Condition (YUV only).

    PCThresh, Range 0 -> 254. Argument to the PC PixelsDifferentCount Exit Condition. Difference between individual pixels has to be
        greater than this to be counted. (default=0, count all differences).

    The frame FingerPrint consists of 4 floating point component values (0.0 -> 255.0), and stored in the DB FingerPrint DBase.
    The PNDB Frame Locator Dbase holds records with 1024 fields per record (frame). The first 256 of these fields give frame numbers
    of the next nearest frame (previous[PrevDB] or next[NextDB]) that roughly complies with the first component FingerPrint value.
    Eg, field 42 holds the frame number of the nearest frame whose first component FingerPrint value is greater or equal to 42.0
    and less than 43.0. Fields 256 to 511 hold frame info for the 2nd FingerPrint component, etc. A value of -1 means that there is
    no frame whose fingerprint component complies.

    This is roughly how the function works without Exit Conditions (Flags=0):-
        It first establishes a range of component FingerPrint values for FindFrame, based on LumaTol.
        If Inclusive, then checks StartFrame for a FingerPrint match and returns StartFrame if good match.
        Next it Checks the Frame Locator Dbase (PNDB) looking for the next nearest frame that roughly complies with the FingerPrint
        range. It then checks that candidate frame in the FingerPrint DBase to see if it more exactly matches the FingerPrint, if it
        does match, the frame is returned to the client and if not then it moves the 'Cursor' in the Frame Locator DBase up to that
        frame and repeats the searching until found or not.
        So, without Exit conditions, the function returns a sequence of candidate frame numbers that may or may not be the exact frame
        you are looking for, it will likely skip vast swathes of frames and then deliver a stream of frames from the same scene as
        your FindFrame, where you would likely want to establish a more exact match using some other function.

    With Exit Conditions:
        Exit conditions are processed if Flags bits are set, this occurs where the above paragraph description would return a candidate frame
        to the client. If an Exit condition is set, then that exit condition also has to be satisfied, if not satisfied, then the candidate
        frame will NOT be returned to the client, it will instead keep searching until both a FingerPrint match occurs and the Exit
        Condition is satisfied, if not, -1 NOT FOUND is returned.
        You can set one or more Exit Conditions, they are processed in bit number order ie LumaDifference condition first, the first
        condition that succeeds will cause exit and no further exit conditions will be processed. If an Exit Condition is satisfied,
        and the XP arg is set, the function will continue scanning adjacent frames and step forward until a better match for the Exit
        Condition is NOT found. (XP=1 is better than, and XP=2 is better or equal).

    Exit Conditions:-

    LD, LD is the Threshold for RT_LumaDifference, if the match is less or equal to this then the Exit Condition is satisfied.

    LC, LC is the Threshold for RT_LumaCorrelation, if the match is less or equal to this then the Exit Condition is satisfied.
        We have 'swizzled' the values returned by RT_LumaCorrelation(), instead of the normal range -1.0 -> 1.0,
        we use 0.0 -> 255.0 where 0.0 means exact match. We have done this for 2 reasons. Firstly, to make it the same (roughly)
        as the other exit conditions, the closer to zero, the better the match. 2nd reason is, Avisynth Floats have only 6 significant
        digits of decimal precision, so eg 0.999999 is about a good as it gets (closest to 1.0 without actually being 1.0) if we were
        setting a threshold for normal range LumaCorrelation (-1.0 -> 1.0), but when we 'swizzle' the numbers to make 0.0 an exact
        match, we can supply a more precise threshold which will be used at double precision within the function,
        eg 0.0000000000000000000000000000001 is still a valid float (and in this case it is only 1 significant digit of precision).
            RT_LumaCorrelation is slower than RT_LumaDifference but it may be more appropriate if there is a big difference in
        luma beteen DBClip and FindClip, it is less perturbed by difference in brightness or contrast.

    FD, FD is the Threshold for RT_FrameDifference, if the match is less or equal to this then the Exit Condition is satisfied.
        The RT_FrameDifference Exit Condition uses the ChromaWeight arg to weight chroma for YUV colorspaces.
        For RGB, RT_FrameDifference is equivalent to RGBDifference. For Y8 it is equivalent to LumaDifference.
        For non Y8 YUV, returns:- (1.0 - ChromaWeight) * Lumadif + ChromaWeight * ((Udif + Vdif)/2.0).
        EXPERIMENTAL: Also currently accepts ChromaWeight -ve (eg -1.0) where will return
         Lumadif + (1.0 - Lumadif/255.0) * ((Udif + Vdif)/2.0)
         This may well be removed at some future date (although would do no harm to leave in-situ).

    PC, PC is the Threshold for RT_LumaPixelsDifferent, if the match is less or equal to this then the Exit Condition is satisfied.
        PC is a pixel count, ranging 0 -> (Width * Height). Allows you to set maximum number of pixels that are different.
        Also takes PCThresh as an argument, difference between individual pixels has to be greater than this to be counted.
        (PCThresh default=0, count all differences).
        (RGB converted to Luma-Y).

    Usage:-
        Using PAL SD Jurassic Park with 182050 frames (UT_Video Compressed YV12) it took 15:06 to create DB and PrevDB FingerPrint
        and Locator DB on a 2.13Ghz Core Duo, using this script.

        AVISource("D:\AVS\JurassicPark.avi")
        DB  ="JPARK.DB"
        PNDB="PREV_JPARK.DB"
        return RT_QwikScanCreate(Last,DB,prevdb=PNDB,nextdb="",debug=true)

        And test script searching approx 175,000 frames per FindFrame:
        AVISource("D:\AVS\JurassicPark.avi")
        DB  ="JPARK.DB"
        PNDB="PREV_JPARK.DB"
        #RT_QwikScanCreate(Last,DB,prevdb=PNDB,nextdb="",debug=true)
        GScript("""
            LUMATOL=0
            End=FrameCount-1
            For(i=3000,13000,1000) {
                S=RT_TimerHP()
                j = RT_QwikScanGetNear(Last,DB,PNDB,End,i,Last,maxdistance=End-i,lumatol=LUMATOL,flags=$04,fd=0.0,xp=2)
                T=RT_TimerHP-S
                RT_Debugf("%d] Got %d in %f secs",i,j,T)
            }
        """)
        return Last

        Results:- LumaTol = 0
        00000005    398.69018555    RT_DebugF: 3000] Got 3000 in 0.019132 secs
        00000006    398.70736694    RT_DebugF: 4000] Got 4000 in 0.017023 secs
        00000007    398.73089600    RT_DebugF: 5000] Got 5000 in 0.023335 secs
        00000008    398.75195313    RT_DebugF: 6000] Got 6000 in 0.020897 secs
        00000009    398.76660156    RT_DebugF: 7000] Got 7000 in 0.014457 secs
        00000010    398.78686523    RT_DebugF: 8000] Got 8000 in 0.020073 secs
        00000011    398.80563354    RT_DebugF: 9000] Got 9000 in 0.018632 secs
        00000012    398.82150269    RT_DebugF: 10000] Got 10000 in 0.015690 secs
        00000013    398.85241699    RT_DebugF: 11000] Got 11000 in 0.030706 secs
        00000014    398.86682129    RT_DebugF: 12000] Got 12000 in 0.014216 secs
        00000015    398.88012695    RT_DebugF: 13000] Got 13000 in 0.013135 secs

        Results:- LumaTol = 4 (many more candidate frames to test)
        00000016    444.04776001    RT_DebugF: 3000] Got 3000 in 0.059216 secs
        00000017    444.26177979    RT_DebugF: 4000] Got 4000 in 0.213837 secs
        00000018    446.82482910    RT_DebugF: 5000] Got 5000 in 2.562858 secs
        00000019    454.65585327    RT_DebugF: 6000] Got 6000 in 7.830853 secs
        00000020    456.44543457    RT_DebugF: 7000] Got 7000 in 1.789409 secs
        00000021    465.26766968    RT_DebugF: 8000] Got 8000 in 8.822010 secs
        00000022    465.99948120    RT_DebugF: 9000] Got 9000 in 0.731642 secs
        00000023    466.64910889    RT_DebugF: 10000] Got 10000 in 0.649458 secs
        00000024    471.09573364    RT_DebugF: 11000] Got 11000 in 4.446451 secs
        00000025    471.81393433    RT_DebugF: 12000] Got 12000 in 0.718018 secs
        00000026    475.26538086    RT_DebugF: 13000] Got 13000 in 3.451269 secs
Get it here:- http://www.mediafire.com/download/jn...2_20140529.zip
__________________
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 8th August 2014, 02:38   #282  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,867
Hi,
Your RT_Stats has really grown! I'm quite impressed, there's a lot of useful stuff in there. I made good use of it in http://forum.doom9.org/showthread.php?t=170995, but I noticed a few things. Your idea to convert a float to a colour was useful to me, but you didn't complete the idea - you need a way to store/plot the colour into a frame. I came up with a way to plot with layer but it's slow and limited. I've always wanted to operate on images as arrays.

What I would like is something like RT_PutImageAsArrayByte(clip, frame, value, index), RT_GetImageAsArrayByte(clip,frame,value,index), PutImageAsArrayInt(clip, frame, value, index) etc.

These are basically plot functions. Index scans left-to-right and top-to-bottom. This is determined from the clip size. So an 8x8 clip hold 64 values. You could also write a script function to turn it into a (luma) plot. Int would naturally be stored as YU then YV, which is a bit awkward for (writing a function to make a colour) plot, so maybe you could add a real plot as well


Another thing I noticed is that the timer doesn't work for the "compile" phase of the script, which is where all my loops are run, so I can't time them. I suppose avstimer is the solution.
jmac698 is offline   Reply With Quote
Old 8th August 2014, 12:33   #283  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Already answered (+ve-ley) in your thread.
__________________
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 10th August 2014, 01:57   #284  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Quote:
Originally Posted by jmac698 View Post
Another thing I noticed is that the timer doesn't work for the "compile" phase of the script, which is where all my loops are run, so I can't time them. I suppose avstimer is the solution.
No idea what you mean, I use it at compile time all of the time.

Code:
START=RT_TimerHP() # or RT_Timer(), matched pairs ONLY.
...
END=RT_TimerHP()
TIME_TAKEN = END - START # In seconds
EDIT:
Code:
RT_Timer()
 Returns time in seconds since start of process.
 Usage:
   s=RT_Timer()
   Test()
   e=RT_Timer()
   Str="Test Start="+String(s,"%.2f")+" End="+String(e,"%.2f")+" Time="+String(e-s,"%.2f")+"secs"
   SubTitle(str)
   RT_Debug(str)


RT_TimerHP()
    Returns a higher precision time than RT_Timer (If available on your system, otherwise uses same routine as RT_Timer).
    Note, where RT_Timer returns time elapsed in seconds since start of process, RT_TimerHP is not defined to return anything
    in particular, the only thing that is meaningful is the difference between returns from 2 calls to RT_TimerHP.
    DO NOT mix times from RT_Timer with RT_TimerHP, results may be meaningless.
    Usage:
       s=RT_TimerHP()      Test()       e=RT_TimerHP()
       Str="Test Start="+String(s,"%.3f")+" End="+String(e,"%.3f")+" Time="+String(e-s,"%.6")+"secs"
       SubTitle(str)
__________________
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; 10th August 2014 at 02:45.
StainlessS is offline   Reply With Quote
Old 4th September 2014, 19:21   #285  |  Link
Seedmanc
Registered User
 
Join Date: Sep 2010
Location: Russia
Posts: 85
Is there any way to measure rendering speed of a script inside of it, using RT? To disable heavy parts of processing dynamically, for example.
I came up with something quick and dirty like this without gscript
Code:
  pre=0.0
  post=0.0
  frames=0.0
  fps=0.0
scriptclip("
\ post=RT_Timer()
\ time=post-pre
\ pre=(time>=1)?post:pre
\ fps=(time>=1)?current_frame-frames:fps
\ frames=(time>=1)?current_frame:frames
\RT_Subtitle(string(fps))")
It works, but I'm sure there should be a way to make it look less ugly, maybe even an inbuilt function.

Also, another question, how heavy are RT functions? I read somewhere that they are generally slower than similar (if you can even compare) non-runtime functions given their execution for every frame.
The reason I'm asking both questions is that I'm looking for ways of optimizing a somewhat exotic way of using Avisynth - real-time processing of video, captured from a videogame for output on a larger screen. Thus the speed and lag introduced by a script matters. Here's my thread about it, if you wonder: http://forum.doom9.org/showthread.php?t=171105
Seedmanc is offline   Reply With Quote
Old 5th September 2014, 05:01   #286  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
How about this
Code:
Avisource("Test.avi")

Start  = RT_Timer() # Timing relative to start ie average timing for entire length of clip so far.
CondS = """
    T=RT_Timer
    RT_Subtitle("%.3f",current_frame/Max(T-Start,0.000001))
    Return Last
"""
ScriptClip(CondS)
Quote:
To disable heavy parts of processing dynamically
What do you mean by that ?

You cannot generally compare runtime functions with filters, they do a different job.
eg, AverageLuma() returns a float, not a clip.
Some filter functions may eg return the same value as AverageLuma would but as a local variable rather than a function return (ShowChannels can do that).
Any standard filter used in eg Scriptclip, has it's constructor called at every frame, and also destroyed at every frame, and so filters that have 'heavy'
start up costs, have them at every frame.
__________________
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 9th September 2014, 15:21   #287  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
New version RT_Stats v1.40.
Post #1 of 3

Functions added.
Code:
RT_WriteFile(String FileName, string format,dat1,...,datn,bool "Append"=False)
 Writes  a formatted string to FileName file. The unnamed 'format' string and optional unnamed 'dat' args are used to construct the
 text string that is written, uses C/CPP printf() style formatting.
 Format: compulsory string controlling format and describing the datn type args that are expected.
 datn: Variable number of data args of any type (excluding clip).
 Append, Default False, optional and MUST be supplied with name (eg Append=True) as we do not know where optional data args end,
 Appends to file if already exists, else opens new FileName.

 printf Format spec here:- http://msdn.microsoft.com/en-us/library/56e442dc%28v=vs.71%29.aspx
  NOTE, the only support for printing Bool variables is %s as string, ie prints "True" or "False".
 Formatting supported %[flags] [width] [.precision] type
  flags, one of  "-,+,0, ,#"
  width, integer, "*" supported (width supplied via dat arg).
  Precision, integer, "*" supported (precision supplied via dat arg).
  type,
    "c,C,d,i,o,u,x,X",  Integer type, c,C=character, d,i=signed, o,u,x,X=unsigned (o=octal, x=Hex).
    "e,E,f,g,G",        Floating point type
    "s,S",              String type (also Bool).

  Formatting Insertion point is marked with '%' character in the format string (as in Avisynth String function), if you wish to use
  a percent character within the output string, it should be inserted twice in the format string ie '%%' will produce a single '%'.
  The data datn arg strings do not require a double '%' character.

  A Backslash character '\' introduces escape sequences, to insert a backslash character itself, you must supply a double
  backslash sequence ie '\\'.
  Converts embedded escape character sequences (Case Significant):-
    '\\' Converted to '\'       Single Backslash
    '\a' Converted to Chr(7)
    '\b' Converted to Chr(8)
    '\t' Converted to Chr(9)
    '\n' Converted to Chr(10)   NewLine
    '\r' [and Chr(13)] Converted to Chr(10)   NewLine
    '\v' Converted to Chr(11)
    '\f' Converted to Chr(12)
    '\x', where x is ANY OTHER CHARACTER not included above, will be copied verbatim, ie '\x'.

  Escape sequences are replaced only when occurring in the format string, if you need escapes in data string then use RT_String.

  Example:
   RT_WriteFile(FileName,"Hello there %s and %s.\nGoodbye %d.","Fred","Ted",2013,Append=False)

***
***
***

RT_ChanAve(clip c,int "n"=current_Frame,string "Prefix"=RCA_")
    Sets channel averages for clip c frame n, as local variables, 0.0 -> 255.0. RGB24/32, YUY2, Planar.
    Returns the number of channels in clip ie 3 unless Y8 where returns 1.
    Default Prefix is "RCA_" so for YV12, would return 3 (3 channels) and set
    YUV
     RCA_Ave_0 = Luma Ave
     RCA_Ave_1 = U Ave
     RCA_Ave_2 = V Ave.
    RGB,
     RCA_Ave_0 = Red Ave
     RCA_Ave_1 = Grn Ave
     RCA_Ave_2 = Blue Ave.
    Y8
     RCA_Ave_2 = Luma Ave
     RCA_Ave_2 = 128
     RCA_Ave_3 = 128,
    NOTE, No support for alpha channel of RGB32, although could be added if anybody thought it useful.(returns num of channels = 3)

***
***
***

RT_FrameDifference(clip c,clip c2,int "n"=current_frame,int "n2"=current_frame,Float "ChromaWeight"=1.0/3.0)
    Returns difference between clip c frame n and clip c2 frame n2 (0.0 -> 255.0).
    ChromaWeight range 0.0 -> 1.0.
    For RGB, returns same as RGBDifference.
    For Y8 returns same as LumaDifference.
    For non Y8 Planar returns Lumadif + Chromadif with chroma weighted by ChromaWeight arg.
      Returns:- (1.0 - ChromaWeight) * Lumadif + ChromaWeight * ((Udif + Vdif)/2.0).

***
***
***

RT_LumaPixelsDifferent(clip c,clip c2,int "n"=current_frame,int "delta"=0,int "x"=0,int "y"=0,int "w"=0,int "h"=0, \
        int "n2"=current_frame,int "delta2"=current_frame,int "x2"=0,int"y2"=0,bool "interlaced"=false,            \
        int "matrix"=(Width>1100||Height>600?3:2),int "Thresh"=0)

    Compares clip c frame (n+delta) at x,y,w,h, and clip c2 frame (n2+delta2) at x2,y2,w,h, and returns amount of pixels
    whose pixel luma difference is greater than Thresh (RGB converted to Luma-Y using Matrix).
    Matrix 0=Rec601, 1=Rec709, 2=PC601, 3=PC709.
    If Interlaced=True, then skips every other raster line, eg process only y, y+2, y+4 etc.
    Thresh Default 0, returns number of pixels that are not exactly the same.
    Return value is in range 0.0 (meaning none) to 255.0 meaning 100% of pixels.

***
***
***

RT_LumaPixelsDifferentCount(clip c,clip c2,int "n"=current_frame,int "delta"=0,int "x"=0,int "y"=0,int "w"=0,int "h"=0, \
        int "n2"=current_frame,int "delta2"=current_frame,int "x2"=0,int"y2"=0,bool "interlaced"=false,            \
        int "matrix"=(Width>1100||Height>600?3:2),int "Thresh"=0)

    Compares clip c frame (n+delta) at x,y,w,h, and clip c2 frame (n2+delta2) at x2,y2,w,h, and returns number of pixels
    whose pixel luma difference is greater than Thresh (RGB converted to Luma-Y using Matrix).
    Matrix 0=Rec601, 1=Rec709, 2=PC601, 3=PC709.
    If Interlaced=True, then skips every other raster line, eg process only y, y+2, y+4 etc.
    Thresh Default 0, returns number of pixels that are not exactly the same.
    Note, returns the number of pixels whose difference is greater than Thresh, so ranges 0 -> (Width*Height).

***
***
***

RT_TimerHP()
    Returns a higher precision time than RT_Timer (If available on your system, otherwise uses same routine as RT_Timer).
    Note, where RT_Timer returns time elapsed in seconds since start of process, RT_TimerHP is not defined to return anything
    in particular, the only thing that is meaningful is the difference between returns from 2 calls to RT_TimerHP.
    DO NOT mix times from RT_Timer with RT_TimerHP, results may be meaningless.
    Usage:
       s=RT_TimerHP()      Test()       e=RT_TimerHP()
       Str="Test Start="+String(s,"%.3f")+" End="+String(e,"%.3f")+" Time="+String(e-s,"%.6")+"secs"
       SubTitle(str)

***
***
***

RT_SignalDAR2(int darx,int dary)
  As for RT_SignalDAR() except it allows setting of numerator and denominator individually.
  Signal DAR to MEGUI. Sets Global vars MeGUI_darX and MeGUI_darY which are read during MEGUI loading of AVS file.

***
***
***

RT_VarType(var)
  Returns type of var arg as an int.
    Returns,
        0   = Type BOOL
        1   = Type INT.
        2   = Type FLOAT
        3   = Type STRING
        4   = Type CLIP
        -1  = Type UNDEFINED
  Avoids multiple tests in script to establish a variable type.
  eg, RT_VarType(66.6) returns 1, ie FLOAT.
  NOTE, If called without an arg, it will return type of implicit Last (Undefined if no clip implicitly/explicitly assigned to Last).

***
***
***

RT_VarIsSame(var Var1, ...,var Varn,Bool "Sig")
  Accepts two or more variables of any type. NOTE, if only 1 arg supplied, will use implicit Last as first arg.
  Returns Bool, False if args are not all of same type AND/OR value.
  Return True, if all args same type and value.
  Sig, Bool Default True. Only used where variables are either String or Clip.
     Type String,
        Compares strings same length and contents.
        Sig==True,  case significant comparison ('a' != 'A').
        Sig==False, case insignificant comparison ('a' = 'A').
     Type Clip,
        Compares clip video attributes, frame Width, Height, ColorSpace.
        If first clip has no video (HasVideo==False) then all other clips must also have no video (other video attributes not tested).
        If Sig==False, Audio Not considered in comparison.
        If Sig==True, audio is considered.
            If first clip has no audio (HasAudio==False) then all other clips must also have no audio (other audio attributes not tested).
            If first clip does have audio, then all other clips must have audio and same Number of Audio Channels, Sample Rate,
            and Sample Type (int16, Float etc).
        No other attributes are taken into account, (ie FrameRate, FrameCount etc).
  *** NOTE ***, as we cannot tell where variable number of Varn args ends, you must use optional 'sig' arg with the name ie 'sig=True'.

***
***
***

RT_DBaseGetStrAttrib(String Filename,Int ix)
 There are 10 (currently) available String attributes in the DataBase file header, that can be used for whatever purpose you like, they are
 1024 (maximum) characters in length excluding nul terminating character (nul not stored in file).
 Filename, DBASE Filename, no default.
 Ix, String Attribute array element index range 0 -> 9.
 Returns the value of the user set string attribute.
 NOTE, if  supplied ix is -1, then will return the number (Int) of available string attributes (currently 10).
 NOTE, if  supplied ix is -2, then will return the maximum string length allowed (Int) of string attributes (currently 1024).

***
***
***

RT_DBaseSetStrAttrib(String Filename,Int ix, String s)
 There are 10 (currently) available string attributes in the DataBase file header, that can be used for whatever purpose you like,
  RT_DBaseAlloc() initializes all String Attributes to "", ie zero length.
 Filename, DBASE Filename, no default.
 Ix, Attribute array element index range 0 -> 9.
 s, The string that String_Attrib(ix) will be set to.
 Returns 0. Error if type not of type String.

***
***
***

RT_DBaseTypeName(Int Type)
  Type, Int (0 -> 5), as value returned by RT_DBaseFieldType(Filename,Field), returns the type as a string.
  Returns 0="Bool", 1="Int", 2 = "Float", 3 = "String", 4 = "Bin", 5 = "Double".
  NOTE, type 5 "Double" is an RT_Stats Private type, ie used internally by RT_Stats to store floating point values as double,
  if used from within Avisynth script, will get and set values as Type Float (but stored in DB as double, 8 bytes instead of 4).
  There is little point to using type double in avisynth script, will just make files bigger and take a little longer to access.

***
***
***

RT_ArrayGetStrAttrib(String Filename,Int ix)
 There are 10 (currently) available String attributes in the Array file header, that can be used for whatever purpose you like, they are
 1024 (maximum) characters in length excluding nul terminating character (nul not stored in file).
 Filename, Array Filename, no default.
 Ix, String Attribute array element index range 0 -> 9.
 Returns the value of the user set string attribute.
 NOTE, if  supplied ix is -1, then will return the number (Int) of available string attributes (currently 10).
 NOTE, if  supplied ix is -2, then will return the maximum string length allowed (Int) of string attributes (currently 1024).

***
***
***

RT_ArraySetStrAttrib(String Filename,Int ix, String s)
 There are 10 (currently) available string attributes in the Array file header, that can be used for whatever purpose you like,
  RT_ArrayAlloc() initializes all String Attributes to "", ie zero length.
 Filename, ARRAY Filename, no default.
 Ix, Attribute array element index range 0 -> 9.
 s, The string that String_Attrib(ix) will be set to.
 Returns 0. Error if type not of type String.

***
***
***

RT_ArrayTypeName(Int Type)
  Type, Int (0 -> 5), as value returned by RT_DBaseFieldType(Filename,Field), returns the type as a string.
  Returns 0="Bool", 1="Int", 2 = "Float", 3 = "String", 4 = "Bin", 5 = "Double".
  NOTE, type 5 "Double" is an RT_Stats Private type, ie used internally by RT_Stats to store floating point values as double,
  if used from within Avisynth script, will get and set values as Type Float (but stored in DB as double, 8 bytes instead of 4).
  There is little point to using type double in avisynth script, will just make files bigger and take a little longer to access.

***
***
***

RT_FileRename(String OldFilename,String NewFileName)
  Renames a file from OldFilename to NewFilename.
  This function renames the file or directory specified by OldFilename to the name given by NewFilename.
  The OldFilename must be the path of an existing file or directory.
  The NewFilename must not be the name of an existing file or directory.
  You can use the function to move a file from one directory or device to another by giving a different path in the NewFileName argument.
  However, you cannot use the function to move a directory. Directories can be renamed, but not moved.

  Return 0 on success.
  On Error, returns
    -1, Access denied or read only, or NewFileName already exists or could not be created (invalid path),
        or oldname is a directory and newname specifies a different path.
    -2, OldFilename File or Path not found.
    -3, NewFileName contains invalid characters.
    -4, Unknown error.

***
***
***

RT_QwikScanCreate(clip c,string DB,string "PrevDB"="",string "NextDB"="",int "matrix"=(Width>1100||Height>600?3:2),bool "Debug"=False)
    Creates a DataBase set used to quickly scan a clip for frame matching, DataBases used by RT_QwikScan.
    c, clip used to create database frame fingerprint info.
    PrevDB, DBase filename, used to find frames prior to a 'start frame'.
    NextDB, DBase filename, used to find frames after a 'start frame'.
      Either PrevDB or NextDB (or both) must be given.
    Matrix, used to convert RGB to Luma_Y for Fingerprint creation.
    Debug, True sends a little info to DebugView window (google).
    Maximum PrevDB/NextDB size is restricted to 524283 records(frames).

***
***
***
__________________
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; 9th September 2014 at 15:24.
StainlessS is offline   Reply With Quote
Old 9th September 2014, 15:22   #288  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
New version RT_Stats v1.40.
Post #2 of 3
Code:
RT_QwikScan(clip SearchClip,Int SeachStart,clip FindClip,Int FindFrame,string DB,string PNDB,
    \ Int "LumaTol"=1,int "Flags"=1,
    \ Float "LC"=1.0,Float "LD"=1.0,Float "FD"=1.0,Float "PD"=1.0,int "PC"=(SearchClip.Width*SearchClip.Height+128)/255, int "XP"=1,
    \ Float "ChromaWeight"=1.0/3.0,Int "PDThresh"=0
    \ int "Maxdistance"=SearchClip.FrameCount-1,bool "Inclusive"=True,string "Prefix"="QWKS_")

    Developer function only, not for the casual scriptor.
    Function that scans a clip using pair of database files to find a sequence of candidate frames that could match a target FindFrame.
    Returns frame number of possible matching frame, or -1 meaning NOT FOUND.

    ARGS:-

    SearchClip, the clip to search, and used as arg to RT_QwikScanCreate to create DB, PrevDB and NextDB database files that hold
      "FingerPrint" and frame location data to assist in rapid location of candidate frames.

    SearchStart, frame number in SearchClip where searching will start, see also Inclusive.

    FindClip, clip holding FindFrame to match.

    FindFrame, Frame number of the FindClip frame that is to be matched.

    DB, Filename of the 'FingerPrint' Dbase. Created via RT_QwikScanCreate.

    PNDB, Filename of the frame locator Dbase. Created via RT_QwikScanCreate as either PrevDB or NextDB.
      Use the PrevDB if searching frames prior to SearchStart in SearchClip, or the NextDB if search frames after SearchStart.
      See also 'Inclusive'.

   OPTIONAL ARGS:

    LumaTol (default 1), +- Luma Tolerance (0 -> 16). Allow for mismatch in luma between SearchClip and FindClip. If eg the FindClip
      pixels can vary by as much as +- 4 pixel levels, then set LumaTol to 4, the bigger this number the slower the function, but it
      should be still quite fast with most clips even up to a LumaTol of maximum 16, the bigger this number, the more frames will fit
      the fingerprint and so there will be more candidate frames to check.

    Flags (Int, default=1 ie LumaCorrelation Exit Condition), Bit flags, sets the additional Exit Conditions of the function.

        Bit 0 set eg $01, Sets the LumaCorrelation Exit Condition.
        Bit 1 set eg $02, Sets the LumaDifference  Exit Condition.
        Bit 2 set eg $04, Sets the FrameDifference Exit Condition.
        Bit 3 set eg $08, Sets the PixelsDifferent Exit Condition.
        Bit 4 set eg $10, Sets the PixelsDifferentCount Exit Condition.

        To eg set Exit conditions LumaCorrelation + FrameDifference + PixelsDifferent, then add 1 + 4 + 8 (1+4+8=13=$0D).

        If exit conditions set, then there may be info generated in the Exit and Best Match returned local variables.

    LC, LumaCorrelation Exit Condition Threshold (Float, default 1.0, Range 0.0 -> 255.0).
        Selected when bit 0 of Flags is set.
        LC is the Threshold for RT_LumaCorrelation, if the match is less or equal to this then the Exit Condition is satisfied.
        We have 'swizzled' the values returned by RT_LumaCorrelation() here to something akin to half range "Pearson's Distance".
        See Pearson’s Distance here: http://en.wikipedia.org/wiki/Pearson_product-moment_correlation_coefficient
        where Pearson's Distance is equivalent to:

            PD(x,y) = 1.0 - Correlation(x,y)

        and our Swizzled half range version using equivalent to:-

            SwizzledLC(x,y) = Min( (1.0 - RT_LumaCorrelation(x,y)) * 255.0, 255.0 )

        Correlation    Pearsons_Distance    Swizzled_LC
            1.0              0.0               0.0                Total +ve Correlation
            0.0              1.0              255.0                  UnCorrelated
           -1.0              2.0              255.0               Total -ve Correlation

        so instead of the RT_LumaCorrelation normal range -1.0 -> 1.0, we use 0.0 -> 255.0 where 0.0 means exact match and 255.0 means
        unmatched, Swizzled RT_LumaCorrelation results that were -ve are clipped at 255.0 so we consider Total -ve Correlation to be no
        more distant than UnCorrelated, ie photo invert of find frame cannot be more distant than 'totally unmatched'.
          We have done this for 2 reasons. Firstly, to make it the same (roughly) as the other exit conditions, the closer to zero, the
        better the match. 2nd reason is, Avisynth Floats have only 6 significant digits of decimal precision. So eg 0.999999 is about as
        good as it gets (closest to 1.0 without actually being 1.0). When we 'swizzle' the numbers to make 0.0 an exact match, we can
        supply a more precise threshold which will be used at double precision within the function.
        Eg 0.0000000000000000000000000000001 is still a valid float (and in this case it is only 1 significant digit of precision).
        Despite the swizzling, we will keep the name LC LumaCorrelation (PD already taken).
          LumaCorrelation is slower than LumaDifference but it may be more appropriate if there is a big difference in
        luma beteen SearchClip and FindClip, it is less perturbed by difference in brightness or contrast.
        See RT_LumaCorrelation.

    LD, LumaDifference  Exit Condition Threshold (Float, default 1.0, Range 0.0 -> 255.0).
        Selected when bit 1 of Flags is set.
        LD is the Threshold for RT_LumaDifference, if the match is less or equal to this then the Exit Condition is satisfied.
        See RT_LumaDifference.

    FD, FrameDifference Exit Condition Threshold (Float, default 1.0, Range 0.0 -> 255.0).
        Selected when bit 2 of Flags is set.
        FD is the Threshold for RT_FrameDifference, if the match is less or equal to this then the Exit Condition is satisfied.
        The RT_FrameDifference Exit Condition uses the ChromaWeight arg to weight chroma for YUV colorspaces.
        For RGB, RT_FrameDifference is equivalent to RGBDifference. For Y8 it is equivalent to LumaDifference.
        For non Y8 YUV, returns:- (1.0 - ChromaWeight) * Lumadif + ChromaWeight * ((Udif + Vdif)/2.0).
        See RT_FrameDifference.

    PD, PixelsDifferent Exit Condition Threshold (Float, default 1.0, Range 0.0 -> 255.0).
        Selected when bit 3 of Flags is set.
        PD is the Threshold for RT_LumaPixelsDifferent, if the match is less or equal to this then the Exit Condition is satisfied.
        PD is amount of pixels, that are different with 0.0 meaning none and 255.0 meaning 100%.
        Also takes PDThresh as an argument, difference between individual pixels has to be greater than this to be counted.
        PixelsDifferent is similar to below PixelsDifferentCount, but using a frame size relative way of specifiying the exit condition.
        (PDThresh default=0, count all differences). (RGB converted to Luma-Y).
        See RT_LumaPixelsDifferent and also PDThresh.

    PC, PixelsDifferentCount Exit Condition Threshold (int, default=(SearchClip.Width*SearchClip.Height+127)/255,
        Range 0 -> SearchClip.Width*SearchClip.Height).
        Selected when bit 4 of Flags is set.
        PC is the Threshold for RT_LumaPixelsDifferentCount, if the match is less or equal to this then the Exit Condition is satisfied.
        PC is a pixel count, ranging 0 -> (Width * Height). Allows you to set maximum number of pixels that are different.
        Also takes PDThresh as an argument, difference between individual pixels has to be greater than this to be counted.
        (PDThresh default=0, count all differences). (RGB converted to Luma-Y).
        See RT_LumaPixelsDifferentCount and also PDThresh.

    XP, (Default 1), Sets eXtra Paranoia for EXIT Conditions.
        0=Off
        1=Continue searching while next frame is a better Exit Condition match ('next frame' meaning dependant upon search direction).
        2=Continue searching while next frame is a better or equal Exit Condition match ('next frame' meaning dependant upon search direction).
          When an exit condition occurs eg LumaDifference, then QWKS_BM_LD_XP will be set to the count of additional frames traversed due
        to finding a match that is better or equal (depending upon whether XP==1 or XP==2) to the initial frame that caused the exit condition,
        In such cases, both QWKS_BM_LD and QWKS_BM_LD_FRM will also be set to (in this case) LumaDifference and the final frame (with XP offset)
        that was found to be a better or equal match.

    ChromaWeight (Float, default 1.0/3.0, Range 0.0 -> 1.0), Argument to the FD FrameDifference Exit Condition (YUV only).

    PDThresh, (Int, Default 0, Range 0 -> 255). Argument to the PD PixelsDifferent and PC PixelsDifferentCount Exit Conditions.
        Difference between individual pixels has to be greater than this to be counted. (default=0, count all differences).

    MaxDistance (Int, default SearchClip.FrameCount-1). Maximum number of frames to search, defaults SearchClip.FrameCount-1, but silently
      limited to the maximum possible distance depending upon where SearchStart is and whether searching forwards or backwards.
      A MaxDistance of 1 will search only the SearchStart (if Inclusive) and the frame next to it.

    Inclusive, (Bool Default True). If true (default) then also tests SearchStart.

    Prefix, (String Default "QWKS_"). Prefix for names of local variables returned to give status of exit conditions and Best Match.

    -------------------------------------------------------------------------

    RETURNS:-
        Returns frame number of CANDIDATE (possible matching frame), or -1 meaning NOT FOUND.

      LOCAL VARIABLES returned where using default Prefix of "QWKS_":

         QWKS_EXIT_FLAGS,Int, bit flags, (always exists). If Exit condition occurred then there will be one of more bits set for the conditions
           that caused exit, bit numbers same as described for Flags arg. QWKS_EXIT_FLAGS will always be 0 when flags arg == 0 (no exit
           conditions required) OR, function returned -1, ie frame NOT FOUND.
           If exit condition occurred and XP arg is 0, then the function return frame and QWKS_BM_xx_FRM (described below) will be the same,
           if XP arg is non zero, then XP processing is tried on all successful exit conditions and the QWKS_BM_xx_FRM frame numbers
           (and concerned QWKS_BM_xx differences) may all be different from the function return frame. So, when XP processing, the
           function return frame is only the initial frame that caused exit, XP results are in QWKS_BM_xx_FRM and QWKS_BM_xx.

         QWKS_EXIT_COUNT, Int (always exists), Count of set bits in QWKS_EXIT_FLAGS (ie number of exit conditions that succeeded).

         QWKS_BM_FLAGS,Int, bit flags, (always exists). Returns flag bits of valid BEST MATCHES found for requested exit conditions, bit numbers
           are as described for Flags arg. If Flags arg == 0, then QWKS_BM_FLAGS will always be 0, ie no exit conditions were tried.
           If one or more exit conditions caused exit then QWKS_BM_FLAGS will have the same bits set as QWKS_EXIT_FLAGS, and possibly other bits
           set giving info on best matches found for other exit conditions that did not successfully cause exit.

         QWKS_BM_COUNT, Int (always exists), Count of set bits in QWKS_BM_FLAGS. (ie number of Best Match vars set)

          Below Only exist/updated if associated QWKS_BM_FLAGS bit is set.
            NOTE, the below frame numbers are the frames after XP processing if XP arg non zero. The associated difference is also for the
          frame after XP processing is done. If XP arg == 0, then all frame numbers (and associated differences) are for the function result
          frame. (The function result frame is the first frame that was encountered that had a successful exit condition and does not have
          XP processing applied, the valid frame numbers QWKS_BM_xx_FRM can all be different from the function return frame if better or equal
          frames were found via XP processing).

             QWKS_BM_LC,(Float)   LumaCorrelation      of the BEST MATCHING frame, Only valid if QWKS_BM_FLAGS bit 0 is set.
             QWKS_BM_LD,(Float)   LumaDifference       of the BEST MATCHING frame, Only valid if QWKS_BM_FLAGS bit 1 is set.
             QWKS_BM_FD,(Float)   FrameDifference      of the BEST MATCHING frame, Only valid if QWKS_BM_FLAGS bit 2 is set.
             QWKS_BM_PD,(Float)   PixelsDifferent      of the BEST MATCHING frame, Only valid if QWKS_BM_FLAGS bit 3 is set.
             QWKS_BM_PC,(Int)     PixelsDifferentCount of the BEST MATCHING frame, Only valid if QWKS_BM_FLAGS bit 4 is set.

             QWKS_BM_LC_FRM,(Int) LumaCorrelation      BEST MATCHING frame, Only valid if QWKS_BM_FLAGS bit 0 is set.
             QWKS_BM_LD_FRM,(Int) LumaDifference       BEST MATCHING frame, Only valid if QWKS_BM_FLAGS bit 1 is set.
             QWKS_BM_FD_FRM,(Int) FrameDifference      BEST MATCHING frame, Only valid if QWKS_BM_FLAGS bit 2 is set.
             QWKS_BM_PD_FRM,(Int) PixelsDifferent      BEST MATCHING frame, Only valid if QWKS_BM_FLAGS bit 3 is set.
             QWKS_BM_PC_FRM,(Int) PixelsDifferentCount BEST MATCHING frame, Only valid if QWKS_BM_FLAGS bit 4 is set.

             QWKS_BM_LC_XP,Int. Number of additional frames traversed because a better or equal match was found for LumaCorrelation exit condition.
             QWKS_BM_LD_XP,Int. Number of additional frames traversed because a better or equal match was found for LumaDifference exit condition.
             QWKS_BM_FD_XP,Int. Number of additional frames traversed because a better or equal match was found for FrameDifference exit condition.
             QWKS_BM_PD_XP,Int. Number of additional frames traversed because a better or equal match was found for PixelsDifferent exit condition.
             QWKS_BM_PC_XP,Int. Number of additional frames traversed because a better or equal match was found for PixelsDifferentCount exit condition.
                Above only exist/updated for conditions that have a bit set in QWKS_BM_FLAGS otherwise may not exist. They will exist
                whether or not the associated exit condition succeded or whether XP arg is zero or non zero. In cases where XP arg was 0 or where
                associated exit condition failed, or where XP processing failed to find a better or equal match, then the QWKS_BM_xx_XP
                variables will contain 0 (will be non zero only where associated exit condition succeded and found a better/equal XP 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 ???
StainlessS is offline   Reply With Quote
Old 9th September 2014, 15:23   #289  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
New version RT_Stats v1.40 (see 1st post).
Post #3 of 3

RT_QwikScan continued:
Code:
        If the function returns a valid frame number (greater or equal to 0) and exit conditions were set in Flags arg, then QWKS_EXIT_FLAGS
        will be non zero and have 1 bit set for each condition that caused exit, and the best match status variables
        will exist/be updated, the other status variables not flagged in QWKS_EXIT_FLAGS but which are flagged in QWKS_BM_FLAGS will also
        exist and be valid, but are BEST MATCHES ONLY.

        If the function returns -1 NOT FOUND, but an EXIT condition was set in Flags and QWKS_BM_FLAGS is non zero,
        then all associated BEST MATCH status variables will exist and be set (associated to the QWKS_BM_FLAGS set bits).

    -------------------------------------------------------------------------


    FINGERPRINT & LUMATOL:
      The frame FingerPrint consists of 4 floating point component values (0.0 -> 255.0), and stored in the DB FingerPrint DBase.
    Each FingerPint component is derived from a pixel count for a portion of the possible 0 -> 255 luma pixel value range.
    Lets say that one of the fingerprint components is derived from the 128->191 luma pixel value range, the fingerpint component
    is computed for every frame in the SearchClip eg {luma PixelCount in range 128 to 191} * 255.0 / {SearchClip.Width*SearchClip.Height},
    this result is in range 0.0 -> 255.0, with 255.0 being equal to 100%. [There would be another three fingerprint components computed,
    in different ranges. We do not actually use range 128->191, and are reluctant to give any real used ranges as they may change, if you
    want to see the real current ranges used, then see the current source code]. The 4 fingerprint components are stored in the
    FingerPrint DB and are EXACT fingerprint component values. For the FindFrame, we use a FingerPrint component Range with LumaTol
    tolerance. For FindClip(FindFrame), we might compute a fingerprint component range for [128->191]:
      FingerPrintMin = {luma PixelCount in range [128+LumaTol] to [191-LumaTol} * 255.0 / {SearchClip.Width*SearchClip.Height}
      FingerPrintMax = {luma PixelCount in range [128-LumaTol] to [191+LumaTol} * 255.0 / {SearchClip.Width*SearchClip.Height}
    So using computed FingerPrintMin and FingerPrintMax for four different ranges as upper and lower limits, if any frame in the
    SeachClip (DBase) has all four EXACT FingerPrint components within all four fingerprint component limits, then it is a candidate
    frame and eligible for exit condition testing if exit conditions were set, or returned to the client as a result CANDIDATE frame if
    exit conditions were not set.

      The PNDB Frame Locator Dbase holds records with 1024 fields per record (frame). The first 256 of these fields give frame numbers
    of the next nearest frame (previous[PrevDB] or next[NextDB]) that roughly complies with the first component FingerPrint value.
    Eg, field 42 holds the frame number of the nearest frame whose first component FingerPrint value is greater or equal to 42.0
    and less than 43.0. Fields 256 to 511 hold frame info for the 2nd FingerPrint component, etc. A value of -1 means that there is
    no frame whose fingerprint component complies.

    Without Exit Conditions:
        This is roughly how the function works without Exit Conditions (Flags=0):-
        It first establishes a range of component FingerPrint values for FindFrame, based on LumaTol.
        If Inclusive, then checks SearchStart for a FingerPrint match and returns SearchStart if good match.
        Next it Checks the Frame Locator Dbase (PNDB) looking for the next nearest frame that could comply with the FingerPrint
        range. It then checks that candidate frame in the FingerPrint DBase to see if it more exactly matches the FingerPrint, if it
        does match, the frame is returned to the client and if not then it moves the 'Cursor' in the Frame Locator DBase up to that
        frame and repeats the searching until found or not.
        So, without Exit conditions, the function returns a sequence of candidate frame numbers that may or may not be the exact frame
        you are looking for, it will likely skip vast swathes of frames and then deliver a stream of frames from the same scene as
        your FindFrame, where you would likely want to establish a more exact match using some other function.
        Without Exit conditions, QWKS_EXIT_FLAGS and QWKS_BM_FLAGS will both be 0 and no associated exit condition nor Best Match
        local variables will be set (may not even exist).

    With Exit Conditions:
        Exit conditions are processed if Flags bits are set, this occurs where the above paragraph description would return a candidate frame
        to the client. If Exit condition are set, then at least one of those exit conditions also has to be satisfied, if not satisfied, then
        the candidate frame will NOT be returned to the client, it will instead keep searching until both a FingerPrint match occurs and an Exit
        condition is satisfied, if not, -1 NOT FOUND is returned.
          You can set one or more Exit Conditions, if any (or all) of the exit conditions succeed then there will be a +ve frame number
        returned by the function, QWKS_EXIT_FLAGS and QWKS_BM_FLAGS bits will be set, the returned frame number will be the first frame
        that satisfied an exit condition, and does NOT include any XP arg processing.
        If any exit condition is satisfied, and the XP arg is set, the function will continue scanning adjacent frames to the frame
        where an exit condition was satisfied and step onward until a better match for the exit condition is NOT found.
        (XP=1 is better than, and XP=2 is better or equal). XP Processing occurs on satisfied exit conditions and the XP processed frame
        numbers and differences are returned via QWKS_BM_xx and QWKS_BM_xx_FRM local vars.
        When using exit conditions, use the return frame number only as an indicator of success, use the returned local vars irrespective of
        whether or not XP processing is done (although if XP==0, then returned frame will be same as QWKS_BM_xx_FRM).

    Tuning:
        Where there is significant difference between SearchClip and FindClip, it could be problematic to find a suitable value for LumaTol.
        If LumaTol is set too high, then each and every search could take much longer to complete, if set too low then will skip over possible
        matches as it will see them as not fitting the LumaTol fingerprint range (and so not even included in Best Matches).
        Where both matching clip frames are identical (NOT processed/re-encoded) then can use LumaTol=0 (default is 1).
          If you eg apply a ColorYUV(Off_y = 4) on exact copy of frame to find in SearchClip, then you would need at least a LumaTol of 4 for
        the FingerPrint locator to include the frame as a CANDIDATE frame, (in this case, every single pixel luma value would have had 4 added
        to it), ColorYUV(Off_y = -4) would also be detected by LumaTol = 4, and in both cases where using LumaDifference exit condition, you
        would need at least a LD of 4.0 to produce a satisfied exit condition, an LD of eg 1.0 would not produce an exit condition but would
        give a BEST match for the correct frame, if using an LC exit condition on same clip then result diff would be about 0.0.
          We did a test search on SD PAL Jurassic Park frame 173,000, a scene at end of movie where helicopter is flying away into the distance
        across the ocean with caption "Directed by Steven Spielberg".
        Where find frame had Blur(1.58,1.58) applied (ie maximum Blur) it was found that a LumaTol of 5 was required to enable the Fingerprint
        locator to work at all. Even though the original and blurred frame looked reasonably similar, there were obvious differences eg the the
        blurred one looked more dull with indistinct text. Tests showed that there were 2 pixels that were different by 75 luma pixel levels
        and there were no doubt many more that were different to a lesser degree. So, where processing akin to a maximum blur is suspected, a
        rough guess might be about LumaTol=5. Results below where Flags=1, LC=0.0 and StartFrame = 0 (search from frame 0)
        (The below FindFrm->FoundFrm lumadiff is carried out on the found frame, not returned from RT_QwikScan).

                                                                              FindFrm->FoundFrm
        LumaTol  SECONDS   EXIT_FLAGS   BM_FLAGS   RESULT_FRAME    BM_LC      RT_LumaDifference
          0      0.011211      0           0           -1           ---             ---
          1      0.593617      0           1          173087     46.869492       12.616102
          2      0.411454      0           1          173005     19.927631        7.802255
          3      2.059347      0           1          173004     17.460129        7.176220
          4      3.024366      0           1          173004     17.460129        7.176220
          5      5.267460      0           1          173000      2.454145        2.577775     <---
          6      9.544320      0           1          173000      2.454145        2.577775
          8     18.132370      0           1          173000      2.454145        2.577775
         12     55.960625      0           1          173000      2.454145        2.577775
         16    129.069290      0           1          173000      2.454145        2.577775

          It may be possible to write a script function to tune for LumaTol, if a search fails (and you know that the frame is present),
        it could search on LumaCorrelation LC=0.0 (LC less perturbed by brightness/contrast changes) and step through LumaTol from 0 upwards
        until BM_LC no longer changes and QWKS_BM_LC is below some threshold (maybe eg 2.55 ie 1.0%). Also note above that BM_LC is smaller
        than RT_LumaDiff(FindFrm->FoundFrm) when LumaTol is at lowest active setting (5).
        When acceptable LumaTol is found then might test using eg RT_LumaDifference between FindFrame and FoundFrame and after adding
        a little leeway get an approximate value for doing an LD LumaDifference search (if that were what was required exit condition).
          NOTE above, even when LumaTol at maximum 16 with timimg about 2 Mins, it is still considerably quicker than approx 18 Mins to
        to find Frame 173000 (1hr:55:20) doing a standard LumaDifference search (using MatchFrames.avs), although would also need to
        create the DBase set too (only once if multiple frames).
        There is much room for research into how best to use this function.

    Usage:-

        Eg, send to debug window if BEST MATCH for LumaDifference was established (bit 1).
          (RT_BitTst(QWKS_BM_FLAGS,1)) ? RT_DebugF("Best Match for LumaDifference = %f @ frame Number %d",QWKS_BM_FD,QWKS_BM_FD_FRM) : NOP
        Eg, send to debug window if LumaDifference caused exit(bit 1).
          (RT_BitTst(QWKS_EXIT_FLAGS,1)) ? RT_DebugF("LumaDifference Caused EXIT: Diff = %f @ frame Number %d",QWKS_BM_FD,QWKS_BM_FD_FRM) : NOP

        Using PAL SD Jurassic Park with 182050 frames (UT_Video Compressed YV12) it took 15:06 to create DB FingerPrint DB and PrevDB
        Locator DB on a 2.13Ghz Core Duo, using this script. (NOTE, The time taken to create all three DataBases, is not much different
        to the time it would take to scan the clip to find a single frame using usual methods.
          EDIT: Test for single frame match using MatchFrames.avs took ~18:20 to locate a single frame, scanning nearly entire clip using
        RT_FrameDifference as locator, so if searching for more than one frame it is a small price to pay, and perhaps {as in this case}
        even quicker than a standard single frame search (it is quicker to create a DB FingerPrint for one frame than to compare two frames).

        AVISource("D:\AVS\JurassicPark.avi")
        DB  ="JPARK.DB"
        PNDB="JPARK_PREV.DB"
        return RT_QwikScanCreate(Last,DB,prevdb=PNDB,nextdb="",debug=true)

        # And test script searching approx 175,000 frames per FindFrame:
        AVISource("D:\AVS\JurassicPark.avi")
        DB  ="JPARK.DB"
        PNDB="JPARK_PREV.DB"
        #RT_QwikScanCreate(Last,DB,prevdb=PNDB,nextdb="",debug=true)
        GScript("""
            LUMATOL=0
            SearchStart=FrameCount-1 # Search direction from end to beginning, using PrevDB.
            For(FindFrame=3000,13000,1000) {
                S=RT_TimerHP()
                j = RT_QwikScan(Last,SearchStart,Last,FindFrame,DB,PNDB,lumatol=LUMATOL,Flags=1,LD=0.0,maxdistance=SearchStart-FindFrame)
                T=RT_TimerHP-S
                RT_Debugf("%d] Got %d in %f secs",i,j,T)
            }
        """)
        return Last

        Results:- LumaTol = 0
        00000005    398.69018555    RT_DebugF: 3000] Got 3000 in 0.019132 secs
        00000006    398.70736694    RT_DebugF: 4000] Got 4000 in 0.017023 secs
        00000007    398.73089600    RT_DebugF: 5000] Got 5000 in 0.023335 secs
        00000008    398.75195313    RT_DebugF: 6000] Got 6000 in 0.020897 secs
        00000009    398.76660156    RT_DebugF: 7000] Got 7000 in 0.014457 secs
        00000010    398.78686523    RT_DebugF: 8000] Got 8000 in 0.020073 secs
        00000011    398.80563354    RT_DebugF: 9000] Got 9000 in 0.018632 secs
        00000012    398.82150269    RT_DebugF: 10000] Got 10000 in 0.015690 secs
        00000013    398.85241699    RT_DebugF: 11000] Got 11000 in 0.030706 secs
        00000014    398.86682129    RT_DebugF: 12000] Got 12000 in 0.014216 secs
        00000015    398.88012695    RT_DebugF: 13000] Got 13000 in 0.013135 secs

        Results:- LumaTol = 4 (many more candidate frames to test)
        00000016    444.04776001    RT_DebugF: 3000] Got 3000 in 0.059216 secs
        00000017    444.26177979    RT_DebugF: 4000] Got 4000 in 0.213837 secs
        00000018    446.82482910    RT_DebugF: 5000] Got 5000 in 2.562858 secs
        00000019    454.65585327    RT_DebugF: 6000] Got 6000 in 7.830853 secs
        00000020    456.44543457    RT_DebugF: 7000] Got 7000 in 1.789409 secs
        00000021    465.26766968    RT_DebugF: 8000] Got 8000 in 8.822010 secs
        00000022    465.99948120    RT_DebugF: 9000] Got 9000 in 0.731642 secs
        00000023    466.64910889    RT_DebugF: 10000] Got 10000 in 0.649458 secs
        00000024    471.09573364    RT_DebugF: 11000] Got 11000 in 4.446451 secs
        00000025    471.81393433    RT_DebugF: 12000] Got 12000 in 0.718018 secs
        00000026    475.26538086    RT_DebugF: 13000] Got 13000 in 3.451269 secs
__________________
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; 9th September 2014 at 15:27.
StainlessS is offline   Reply With Quote
Old 9th September 2014, 18:41   #290  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,867
Amazing work, from what I can tell, it's a database to quickly match frames in a large range, even approximately. That could help find the different edits in laser/vhs/dvd copies of a movie, or on a smaller scale, find the dropped/duped frames that always show in multiple passes of captures.

Just an idea for autotuning things in general I had though, I used strong matches to get statistics to tune other matches. For example in an experiment with matching by luma correlation on extremely noisy frames, I found a strong indication of where one frame was different from others in the 5 copies, but somewhat similar to itself in the 5 copies, and between the two thresholds I could find other frames. This then helped where there was less motion and less of a strong indicator that the frame was unique compared to surrounding, but then relied more on the indicator that the same frames correlated strongly.

I mean,
p1a p1b p1c
p2a p2b p2c
p3a p3b p3c
I find that p1b<<>>p1a,p1c and p2b<<>>p2a,p2c and p3b<<>>p3a,p3c,
then p1b=p2b=p3b
In frames d,e,f,
p1e?p1d,p1f but p1e==p2e==p3e
<<>> means strongly not equivalent, = means weakly equivalent, == means strongly equivalent, ? means indeterminate
Maybe this could help somehow.
jmac698 is offline   Reply With Quote
Old 10th September 2014, 01:00   #291  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Well have a go Jmac, you can make both PrevDB and NextDB and do bi-directional searches (one at a time), function intended to be quite flexible.
In the no-exit-condition case, it returns a stream of candidate frames where you can do your own comparisons/matching, the
exit conditions are there to save a little time when it can be done automatically, I intend using mixtures of both.
In no-exit-condition mode, you might set up a for/next loop with eg 'j' as loop counter, give j as StartFrame and assign result back to j,
thereby skipping all intervening non-candidate frames.
Could make possible/plausible lots of differing tasks, edits detection, cut and spice where two scenes of separate clips overlap, + lots more
probs I'm sure.

I have not done the histogram thing yet (well I have a version that I hacked up for myself) but have not forgotten, it will come eventually.
I had to get this out of the way so I could finally try to resolve a problem here:- http://forum.doom9.org/showthread.php?t=170332

Its a pig of a prob, and thread that prompted the function.

gotta go, peace bro.
__________________
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; 10th September 2014 at 10:55.
StainlessS is offline   Reply With Quote
Old 10th September 2014, 15:38   #292  |  Link
Seedmanc
Registered User
 
Join Date: Sep 2010
Location: Russia
Posts: 85
@StainlessS:
It looks like your fps measuring script calculates the running average fps, so the "true" fps is only achieved at the end of the video, while I'm going for "current" fps, measured over a short timespan (1 second, for example).
I formatted my script a bit better to demonstrate what I mean:
Code:
  timespan=1
  pre=0.0
  frames=0.0
  fps=0.0
FrameEvaluate(""" 
    post = RT_Timer()
    tick = (post - pre) >= timespan
    pre = tick?
    \   post:
    \   pre
    fps = tick?
    \   current_frame - frames:
    \   fps
    frames = tick?
    \   current_frame:
    \   frames 
""")   
scriptclip("rt_subtitle( string( fps / timespan))")
Unfortunately I can't make this script into a function that would return a numerical value of fps calculated over a timespan supplied as a parameter. I think it's because I can't get rid of having to declare those variables before frameevaluate, but without declaring them, I can't use conditional assignment later. Maybe there's any way to rewrite the assignments differently? Basically I only need it happen when the "tick" is true, which means the needed timespan of seconds has passed already. After that I calculate the amount of frames processed over that time and thus get the fps.

As for what I mean by dynamically disabling heavy filters, it's something like this:
Code:
last=(MeasureFPS(timespan)<30)?last:SlowFilter()
As I said, I'm working on realtime live processing of video so I need to take speed into consideration to avoid framedrops. Of course something like this wouldn't make any sense in the usual "offline" encoding of video.
Dynamical switching already works for me, it's just I can't make the fps measurement nicely into a function and it makes fps rather irregular in its current implementation.
Seedmanc is offline   Reply With Quote
Old 11th September 2014, 07:42   #293  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
How about this (I'm not sure that its correct)

Code:
GSCript("""
    Function MyTimer(clip clp,Int HalfFrameRes) {
        clp
        CurrTime    = RT_TimerHP
        if(current_frame == 0 || !RT_VarExist("Prev") || Prev!=current_frame-1) {
            Global StartFrame = current_frame   Global StartFrame2 = current_frame
            Global StartTime  = CurrTime        Global StartTime2  = CurrTime
            Global Prev=current_frame
        }
        FrameCnt    = current_frame-StartFrame
        TimeExpired = Max(CurrTime-StartTime,0.000001)
        ToggleOnce  = (FrameCnt==HalfFrameRes)
        Toggle2     = (FrameCnt>=HalfFrameRes*2)
        if(ToggleOnce) {
            Global StartFrame2   = current_frame
            Global StartTime2    = CurrTime
        } Else if(Toggle2) {
            Global StartFrame    = StartFrame2
            Global StartTime     = StartTime2
            Global StartFrame2   = current_frame
            Global StartTime2    = CurrTime
        }
        Global Prev=current_frame
        Return FrameCnt/TimeExpired
    }
""")

Avisource("Test.avi")

ScriptClip("""RT_Subtitle("%.3f",MyTimer(25))""")
And multi Instance version putting sub on frame
Code:
Function MyTimer(clip clp,Int "HalfFrameRes") {
    myName="MyTimer: "
    Assert(RT_FunctionExist("GScriptClip"),myName+"Essential GRunT plugin installed, http://forum.doom9.org/showthread.php?t=139337")
    Assert(RT_FunctionExist("GScript"),myName+"Essential GScript plugin installed, http://forum.doom9.org/showthread.php?t=147846")
    HalfFrameRes=Default(HalfFrameRes,25)
    Assert(HalfFrameRes>0,myName+"HalfFrameRes Must be greater than 0")
    FuncS="""
        Function MyTimer@@@(clip clp,Int HalfFrameRes) {
            clp
            CurrTime    = RT_TimerHP
            if(current_frame==0 || !RT_VarExist("Prev@@@") || Prev@@@!=current_frame-1) {
                # Start/Reset timer within script rather than in Multi-instance Global vars init
                Global StartFrame@@@ = current_frame    Global StartFrame2@@@ = current_frame
                Global StartTime@@@  = CurrTime         Global StartTime2@@@  = StartTime@@@
                Global Prev@@@=current_frame
            }
            FrameCnt    = current_frame-StartFrame@@@
            TimeExpired = Max(CurrTime-StartTime@@@,0.000001)
            ToggleOnce  = (FrameCnt==HalfFrameRes)
            Toggle2     = (FrameCnt>=HalfFrameRes*2)
            # Comment out below Lines
            RT_Subtitle("%.3f",FrameCnt/TimeExpired)
            RT_Subtitle("%d] %.3f ToggleOnce=%s Toggle2=%s\nStartFrame =%d StartTime =%f\nStartFrame2=%d StartTime2=%f\nFrameCnt=%d TimeExpired=%f",
                \ current_frame,FrameCnt/TimeExpired,ToggleOnce,Toggle2,
                \ StartFrame@@@,StartTime@@@,StartFrame2@@@,StartTime2@@@,FrameCnt,TimeExpired,align=1)
            if(ToggleOnce) {
                Global StartFrame2@@@   = current_frame
                Global StartTime2@@@    = CurrTime
            } Else if(Toggle2) {
                Global StartFrame@@@    = StartFrame2@@@
                Global StartTime@@@     = StartTime2@@@
                Global StartFrame2@@@   = current_frame
                Global StartTime2@@@    = CurrTime
            }
            Global Prev@@@=current_frame
            # EDIT: Uncomment below line if commenting out RT_Subtitles to give Global MeasuredFPS
            # First Multi-Instance Variable name will be MeasuredFPS_MTIM_1
            # Global MeasuredFPS@@@ = FrameCnt/TimeExpired
            Return Last
        }
        ARGS = "HalfFrameRes"
        clp.GScriptClip("MyTimer@@@(last, "+ARGS+")", local=true, args=ARGS)
    """
    RT_IncrGlobal("MTIM_InstanceNumber")
    InstS = RT_StrReplace(FuncS,"@@@","_MTIM_"+String(MTIM_InstanceNumber))
#   RT_TxtWriteFile(InstS,"DEBUG_MTIM_"+String(MTIM_InstanceNumber)+".TXT")
    Return GScript(InstS)
}

Avisource("Test.avi")
MyTimer()
EDITED: RT_TimerHP requires RT_Stats v1.40, Can use RT_Timer instead.
__________________
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; 11th September 2014 at 13:24.
StainlessS is offline   Reply With Quote
Old 11th September 2014, 12:37   #294  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Dont know if anyone has done a similar function, this seems to yield ApparentFPS {after dupe removal}.
(gives static scene as 0.0 FPS)
Perhaps saves counting duplicates (always a fun pastime).

Code:
GSCript("""
    Function ApparentFPS(clip clp,Int "HalfFrameRes",Float "DupeThresh",Float "FrameRate",Bool "MaxFPS",Float "ChromaWeight") {
        myName="ApparentFPS: "
        clp
        HalfFrameRes=Default(HalfFrameRes,25)
        DupeThresh=Default(DupeThresh,1.0)
        FR=Float(Default(FrameRate,clp.FrameRate))
        MaxFPS=Default(MaxFPS,False)
        ChromaWeight = Float(Default(ChromaWeight,1.0/3.0))
        Assert(HalfFrameRes>0,myName+"HalfFrameRes Must be greater than 0")
        Assert(DupeThresh>0.0,myName+"DupeThresh Must be greater than 0.0")
        Assert(ChromaWeight>=0.0 && ChromaWeight<=1.0,myName+"ChromaWeight 0.0 -> 1.0")
        CurrTime    = current_frame / FR
        if(current_frame==0 || !RT_VarExist("Prev") || Prev!=current_frame-1) {
            Global StartFrame = current_frame   Global StartFrame2 = current_frame
            Global StartTime  = CurrTime        Global StartTime2  = CurrTime
            Global DupeCnt = 0                  Global DupeCnt2    = 0
            Global MaxApparentFPS = (RT_VarExist("MaxApparentFPS")) ? MaxApparentFPS : 0.0
            Global Prev = current_frame
        }
        Diff = RT_FrameDifference(clp,clp,n2=current_frame-1,ChromaWeight=ChromaWeight)
        if(Diff < DupeThresh && current_frame > 0) {
            Global DupeCnt  = DupeCnt  + 1
            Global DupeCnt2 = DupeCnt2 + 1
        }
        FrameCnt        = current_frame-StartFrame
        UniqueFrameCnt  = FrameCnt - DupeCnt
        TimeExpired = Max(CurrTime-StartTime,0.000001)
        ToggleOnce  = (FrameCnt==HalfFrameRes)
        Toggle2     = (FrameCnt>=HalfFrameRes*2)
        ApparentFPS = UniqueFrameCnt/TimeExpired
        Global MaxApparentFPS = (ApparentFPS>MaxApparentFPS) ? ApparentFPS : MaxApparentFPS

        if(ToggleOnce) {
            Global StartFrame2   = current_frame
            Global StartTime2    = CurrTime
            Global DupeCnt2      = 0
        } Else if(Toggle2) {
            Global StartFrame    = StartFrame2
            Global StartTime     = StartTime2
            Global DupeCnt       = DupeCnt2
            Global StartFrame2   = current_frame
            Global StartTime2    = CurrTime
            Global DupeCnt2      = 0
        }
        Global Prev = current_frame
        Return (MaxFPS) ? MaxApparentFPS : ApparentFPS
    }
""")

#Avisource("Test.avi")
Avisource("CAP1.avi")
MAXFPS=False
ScriptClip("""RT_Subtitle("%.3f",ApparentFPS(maxfps=MaxFPS))""")
Requires RT_Stats v1.40

EDIT: And Multi-Instance version

Code:
Function ApparentFPS(clip clp,Int "HalfFrameRes",Float "DupeThresh",Float "FrameRate",Float "ChromaWeight") {
    myName="ApparentFPS: "
    Assert(RT_FunctionExist("GScriptClip"),myName+"Essential GRunT plugin installed, http://forum.doom9.org/showthread.php?t=139337")
    Assert(RT_FunctionExist("GScript"),myName+"Essential GScript plugin installed, http://forum.doom9.org/showthread.php?t=147846")
    HalfFrameRes=Default(HalfFrameRes,25)
    DupeThresh=Default(DupeThresh,1.0)
    FR=Float(Default(FrameRate,clp.FrameRate))
    ChromaWeight=Float(Default(ChromaWeight,1.0/3.0))
    Assert(HalfFrameRes>0,myName+"HalfFrameRes Must be greater than 0")
    Assert(DupeThresh>0.0,myName+"DupeThresh Must be greater than 0.0")
    Assert(ChromaWeight>=0.0 && ChromaWeight<=1.0,myName+"ChromaWeight 0.0 -> 1.0")
    FuncS="""
        Function ApparentFPS@@@(clip clp,Int HalfFrameRes,DupeThresh,Float FR,Float ChromaWeight) {
            clp
            CurrTime    = current_frame / FR
            if(current_frame==0 || !RT_VarExist("Prev@@@") || Prev@@@!=current_frame-1) {
                # Start/Reset timer within script rather than in Multi-instance Global vars init
                Global StartFrame@@@ = current_frame    Global StartFrame2@@@ = current_frame
                Global StartTime@@@  = CurrTime         Global StartTime2@@@  = StartTime@@@
                Global Dropped@@@ = 0
                Global DupeCnt@@@ = 0                   Global DupeCnt2@@@    = 0
                Global MaxApparentFPS@@@ = (RT_VarExist("MaxApparentFPS@@@")) ? MaxApparentFPS@@@ : 0.0
                Global Prev@@@ = current_frame
            }
            Diff = RT_FrameDifference(clp,clp,n2=current_frame-1,ChromaWeight=ChromaWeight)
            if(Diff < DupeThresh && current_frame > 0) {
                Global Dropped@@@  = Dropped@@@  + 1
                Global DupeCnt@@@  = DupeCnt@@@  + 1
                Global DupeCnt2@@@ = DupeCnt2@@@ + 1
            }
            FrameCnt        = current_frame-StartFrame@@@
            UniqueFrameCnt  = FrameCnt - DupeCnt@@@
            TimeExpired = Max(CurrTime-StartTime@@@,0.000001)
            ToggleOnce  = (FrameCnt==HalfFrameRes)
            Toggle2     = (FrameCnt>=HalfFrameRes*2)
            # EDIT: Below lines give Global return values
            # First Multi-Instance ApparentFPS@@@ Variable name will be ApparentFPS_AFR_1
            # First Multi-Instance MaxApparentFPS@@@ Variable name will be MaxApparentFPS_AFR_1
            Global ApparentFPS@@@    = UniqueFrameCnt/TimeExpired
            Global MaxApparentFPS@@@ = (ApparentFPS@@@>MaxApparentFPS@@@) ? ApparentFPS@@@ : MaxApparentFPS@@@
            # Comment out below Lines
            RT_Subtitle("%.3f (Max=%.3f)",UniqueFrameCnt/TimeExpired,MaxApparentFPS@@@)
            RT_Subtitle("%d] FrameRate=%.3f ApparentFrameRate=%.3f (Max=%.3f)" +
                \ "\nToggleOnce=%s Toggle2=%s\nStartFrame =%d StartTime =%f\nStartFrame2=%d StartTime2=%f" +
                \ "\nFrameCnt=%d TimeExpired=%f\nDropped=%d DupeCnt=%d DupeCnt2=%d UniqueFrameCnt=%d",
                \ current_frame,FrameCnt/TimeExpired,UniqueFrameCnt/TimeExpired,MaxApparentFPS@@@,ToggleOnce,Toggle2,
                \ StartFrame@@@,StartTime@@@,StartFrame2@@@,StartTime2@@@,FrameCnt,TimeExpired,
                \ Dropped@@@,DupeCnt@@@,DupeCnt2@@@,UniqueFrameCnt,align=1)
            if(ToggleOnce) {
                Global StartFrame2@@@   = current_frame
                Global StartTime2@@@    = CurrTime
                Global DupeCnt2@@@      = 0
            } Else if(Toggle2) {
                Global StartFrame@@@    = StartFrame2@@@
                Global StartTime@@@     = StartTime2@@@
                Global DupeCnt@@@       = DupeCnt2@@@
                Global StartFrame2@@@   = current_frame
                Global StartTime2@@@    = CurrTime
                Global DupeCnt2@@@      = 0
            }
            Global Prev@@@ = current_frame
            Return Last
        }

        ARGS = "HalfFrameRes,Dupethresh,FR,ChromaWeight"
        clp.GScriptClip("ApparentFPS@@@(last, "+ARGS+")", local=true, args=ARGS)
    """
    RT_IncrGlobal("AFR_InstanceNumber")
    InstS = RT_StrReplace(FuncS,"@@@","_AFR_"+String(AFR_InstanceNumber))
    RT_TxtWriteFile(InstS,"DEBUG_AFR_"+String(AFR_InstanceNumber)+".TXT")
    Return GScript(InstS)
}

#Avisource("TEST.avi")
Avisource("CAP1.avi")
ApparentFPS()
EDITED:
__________________
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; 11th September 2014 at 14:22.
StainlessS is offline   Reply With Quote
Old 11th September 2014, 15:43   #295  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Ooops, posted RT_Stats v1.40 in wrong folder on MediaFire (was not available, was available via SendSpace), Fixed.
__________________
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 15th September 2014, 12:01   #296  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
New Version RT_Stats v1.41, See 1st post.

Code:
    v1.41, 15 Sept 2014, Fixed borked v1.40, (released wrong source + binary), RT_QwikScan PC, PD related stuff.
		   Changed RT_QwikScan LumaTol arg to float.
Code:
RT_QwikScan(clip SearchClip,Int SeachStart,clip FindClip,Int FindFrame,string DB,string PNDB,
    \ Float "LumaTol"=1.0,int "Flags"=1,
    \ Float "LC"=1.0,Float "LD"=1.0,Float "FD"=1.0,Float "PD"=1.0,int "PC"=(SearchClip.Width*SearchClip.Height+127)/255, int "XP"=1,
    \ Float "ChromaWeight"=1.0/3.0,Int "PDThresh"=0
    \ int "Maxdistance"=SearchClip.FrameCount-1,bool "Inclusive"=True,string "Prefix"="QWKS_")
Code:
    FINGERPRINT & LUMATOL:
      The frame FingerPrint consists of 4 floating point component values (0.0 -> 255.0), and stored in the DB FingerPrint DBase.
    Each FingerPint component is derived from a pixel count for a portion of the possible 0 -> 255 luma pixel value range.
    Lets say that one of the fingerprint components is derived from the 128->191 luma pixel value range, the fingerpint component
    is computed for every frame in the SearchClip eg {luma PixelCount in range 128 to 191} * 255.0 / {SearchClip.Width*SearchClip.Height},
    this result is in range 0.0 -> 255.0, with 255.0 being equal to 100%. [There would be another three fingerprint components computed,
    in different ranges. We do not actually use range 128->191, and are reluctant to give any real used ranges as they may change, if you
    want to see the real current ranges used, then see the current source code]. The 4 fingerprint components are stored in the
    FingerPrint DB and are EXACT fingerprint component values. For the FindFrame, we use a FingerPrint component Range with LumaTol
    tolerance. For FindClip(FindFrame), we might compute a fingerprint component range for [128->191]:
      FingerPrintMin = {luma PixelCount in range [128+LumaTol] to [191-LumaTol} * 255.0 / {SearchClip.Width*SearchClip.Height}
      FingerPrintMax = {luma PixelCount in range [128-LumaTol] to [191+LumaTol} * 255.0 / {SearchClip.Width*SearchClip.Height}
    So using computed FingerPrintMin and FingerPrintMax for four different ranges as upper and lower limits, if any frame in the
    SeachClip (DBase) has all four EXACT FingerPrint components within all four fingerprint component limits, then it is a candidate
    frame and eligible for exit condition testing if exit conditions were set, or returned to the client as a result CANDIDATE frame if
    exit conditions were not set.

    v1.41, Have changed LumaTol arg from type Int to type Float, default 1.0. (Will still accept type Int so will not break script).
    Whole number values of LumaTol will behave as previously described.
    Where a non integer value of Lumatol is given, then LumaTol is split into integer and fractional parts, the integer part is
    processed normally where the FingerPrint value is derived from a pixel count for the particular range. After being converted
    into a float via eg {luma PixelCount in range 128 to 191} * 255.0 / {SearchClip.Width*SearchClip.Height}, then the fractional
    part of LumaTol is added to the result and limited to range 0.0->255.0. So, the fractional part is a way of giving an additional
    margin of error to LumaTol in a frame size relative way.
EDIT:
Change to FingerPrint source
Code:
void __cdecl RT_Fingerprint_Lo(const AVSValue &std,const AVSValue &xtra,FINGER &finger,unsigned int *hist,IScriptEnvironment* env,double LTol) {
// NOTE, LTol optional default 0.0
    char *myName="RT_Fingerprint_Lo: ";
    LTol  = max(min(LTol,16.0),0.0);
    MYLO mylo;
    RT_MYstats_Lo(RTHIST_F,std,xtra,mylo,myName,env,hist);
    const int rng[4][2]={{0 ,85},{86,170},{171,255},{64,191}};
    const int Pixels = mylo.pixels;
    double frac,whole;
    frac=modf(LTol,&whole);
    int Tol = int(whole);
    int i,j;
    if(frac == 0.0) {
        for(i=4;--i>=0;) {
            unsigned int sm=0;
            const int s = rng[i][0];
            const int e = rng[i][1];
            int s2 = s+Tol;
            int e2 = e-Tol;
            for(j=s2;j<=e2;++j)
                sm += hist[j];
            finger.lolim[i] = sm * 255.0 / Pixels;
            if(Tol==0) {
                finger.hilim[i]=finger.lolim[i];
            } else {
                sm=0;
                s2 = max(s-Tol,0);
                e2 = min(e+Tol,255);
                for(j=s2;j<=e2;++j)
                    sm += hist[j];
                finger.hilim[i] = sm * 255.0 / Pixels;
            }
        }
    } else {
        for(i=4;--i>=0;) {
            unsigned int sm=0;
            const int s = rng[i][0];
            const int e = rng[i][1];
            int s2 = s+Tol;
            int e2 = e-Tol;
            for(j=s2;j<=e2;++j)
                sm += hist[j];
            finger.lolim[i] = max( (sm * 255.0 / Pixels - frac) ,0.0);
            sm=0;
            s2 = max(s-Tol,0);
            e2 = min(e+Tol,255);
            for(j=s2;j<=e2;++j)
                sm += hist[j];
            finger.hilim[i] = min( (sm * 255.0 / Pixels + frac)  ,255.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 ???

Last edited by StainlessS; 15th September 2014 at 12:06.
StainlessS is offline   Reply With Quote
Old 15th September 2014, 16:35   #297  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
@ Forensic,

Are lurking about out there, not online since April.

You only gave two lines of documentation for AvgLumaDif and I think that you never said finally whether the function was as required,
so I've been waiting to add to RT_Stats, anyway, this is what I've knocked up as docs, is it to your satisfaction, will integrate in next version (v1.42).


Code:
RT_AvgLumaDif(clip clp, int "n"=current_frame,Bool "Slices"=False,Int "Matrix"=(Width>1100||Height>600?3:2) )

  The function, returns the average of pixel pair differentials for a given frame n, ignoring frame perimeter (1 pixel
  perimeter around frame edge), range 0.0 -> 255.0.

  Args:
    n, Int, Default current_frame.
    Slices, Bool Default False.
      False, Analyze every adjacent pixel pair in the frame with the exception of frame perimeter.
      True,  Analyze adjacent pixel pairs in the frame, all 4x4 pixel block boundaries are treated as perimeter pixels
        and omitted from processing along with the frame perimeter pixels.
    Matrix, Int, Default = (Width > 1100 OR Height>600) then 3(PC709) else 2(PC601). YUV not used
      Conversion matrix for conversion of RGB to YUV-Y Luma.  0=REC601 : 1=REC709 : 2 = PC601 : 3 = PC709,

  The function finds the average luminosity differential by analyzing every adjacent pixel pair within the video frame,
  (both horizontal and vertical, not diagonal) with an option to only process every other 2x2 horizontal and vertical block
  to ensure any slice (e.g. h.264, h.265) boundaries are excluded. By calling this function before and again after a given
  filter, this function quantifies a filter's affect on luminosity contrast.
    NOTE: The perimeter pixels are intentionally ignored as they often incur higher quantization errors.

   'x'= Process, '.'=Don't Process

          Slices=false                 Slices=true
    ........................    ........................
    .xxxxxxxxxxxxxxxxxxxxxx.    .xx..xx..xx..xx..xx..xx.
    .xxxxxxxxxxxxxxxxxxxxxx.    .xx..xx..xx..xx..xx..xx.
    .xxxxxxxxxxxxxxxxxxxxxx.    ........................
    .xxxxxxxxxxxxxxxxxxxxxx.    ........................
    .xxxxxxxxxxxxxxxxxxxxxx.    .xx..xx..xx..xx..xx..xx.
    .xxxxxxxxxxxxxxxxxxxxxx.    .xx..xx..xx..xx..xx..xx.
    .xxxxxxxxxxxxxxxxxxxxxx.    ........................
    .xxxxxxxxxxxxxxxxxxxxxx.    ........................
    .xxxxxxxxxxxxxxxxxxxxxx.    .xx..xx..xx..xx..xx..xx.
    .xxxxxxxxxxxxxxxxxxxxxx.    .xx..xx..xx..xx..xx..xx.
    ........................    ........................
__________________
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; 15th September 2014 at 16:59.
StainlessS is offline   Reply With Quote
Old 16th September 2014, 01:34   #298  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Warning of change to RT_Stats v1.42 RT_QwikScan, XP arg (time to give views if any).

Currently implemented:
Code:
    XP, (Default 1), Sets eXtra Paranoia for EXIT Conditions.
        0=Off
        1=Continue searching while next frame is a better Exit Condition match ('next frame' meaning dependant upon search direction).
        2=Continue searching while next frame is a better or equal Exit Condition match ('next frame' meaning dependant upon search direction).
          When an exit condition occurs eg LumaDifference, then QWKS_BM_LD_XP will be set to the count of additional frames traversed due
        to finding a match that is better or equal (depending upon whether XP==1 or XP==2) to the initial frame that caused the exit condition,
        In such cases, both QWKS_BM_LD and QWKS_BM_LD_FRM will also be set to (in this case) LumaDifference and the final frame (with XP offset)
        that was found to be a better or equal match.
Intend to change XP = 1 mode. ('Better Than' mode)

Instead of terminating scan when next frame is not better (even if equal) will do instead:

Code:
0 ) Will search for continually better matching frames, until
    Worse match or MaxDistance reached,
       then returns best so far.

    OR

    Equal Match, will drop anchor (remember where it got to) and continue scanning until
      1) Worse match or MaxDistance reached,
           it will return the remembered frame where it dropped anchor.
      2) Better match,
           then exits the equal match scanning and updates best so far scan position and continues as for step 0).
The last frame returned will be better than all previous matches, but some adjacent previous matches may have been equal to each other.

I could add another XP Mode 3=Strictly Better Match, that did not scan equal match paths if anyone thought it had functionality.

EDIT: I have just encountered a float match condition that did indeed provide better result with above amendment (Hence the change).

EDIT: Will add XP mode 3 = Strictly Better Match (have almost done it).

EDIT: You can treat RT_QwikScan as permanently EXPERIMENTAL, LumaTol Float fractional part stuff may change, as may the
way the fingerprint is computed. The function works just fine at it is but it would be nice if LumaTol could be made purely ornamental.
Currently, the fractional LumaTol thing is really intended for use where integer part is 0.

EDIT: Have now changed slightly the fractional part functionality of LumaTol a bit, works much better and more
targeted at specific frames, speeds it up a bit.
__________________
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 September 2014 at 20:23.
StainlessS is offline   Reply With Quote
Old 19th September 2014, 21:00   #299  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
RT_Stats v1.42, new version see 1st post.

Code:
	v1.40, 9 Sept 2014, Fixed, RT_DBaseGetAttrib returned float instead of Int (for int attrib).
	       Added args Start and End to RT_QueryBorderCrop and RT_QueryLumaMinMax. Added RT_WriteFile + other funcs.
		   Now 1024 Array & DBase Attributes. Array and DBase now supports type double as private type for RT_Stats
		   internal routines, set or get as type Float from Avisynth script.
		   DBase max number of fields increased to 1024. Added DBase/Array String Attributes.
		   Added RT_QwikScan + other stuff.
    v1.41, 15 Sept 2014, Fixed borked v1.40, (released wrong source + binary), RT_QwikScan PC, PD related stuff.
		   Changed RT_QwikScan LumaTol arg to float.
    v1.42, 19 Sept 2014. Modified Float LumaTol imlementation. Added additional XP mode to RT_QwikScan, and affects
		   BEST MATCH results. Added RT_AvgLumaDif.
RT_QwikScan Doc mods.
Code:
    XP, (Default 1), Sets eXtra Paranoia for EXIT Conditions.
        0 = Off
        1 = LOOSELY BETTER THAN (v1.42 changed STRICTLY BETTER THAN to mode 3, and using this one instead).
            Continue searching while next frame is a loosely better Exit Condition match ('next frame' meaning dependant upon search direction).
            Differs from STRICTLY BETTER THAN in that it scans along equal matches and if a better match found along that equal matches
            path, then will return that match, if no better match occurs along an equal match path, then returns the previous frame number
            that was better than previous matches. So, the last frame returned will be better than all previous matches, but some adjacent
            previous matches may have been equal to each other.
        2 = BETTER THAN OR EQUAL
            Continue searching while next frame is a better or equal Exit Condition match ('next frame' meaning dependant upon search direction).
        3 = STRICTLY BETTER THAN
            Continue searching while next frame is a better Exit Condition match ('next frame' meaning dependant upon search direction).
            Does not scan along equal match paths.

          When an exit condition occurs eg LumaDifference, then QWKS_BM_LD_XP will be set to the count of additional frames traversed due
        to finding a match that is better or equal (depending upon whether XP==1 or XP==2, or XP==3) to the initial frame that caused the exit
        condition. In such cases, both QWKS_BM_LD and QWKS_BM_LD_FRM will also be set to (in this case) LumaDifference and the final frame
        (with XP offset) that was found to be a better or equal match.
            v1.42, BEST MATCHES also now comply with XP = 2 (BETTER OR EQUAL) setting, Where XP != 2, then returns the first encountered
        frame position where matches are equal, XP == 2 will returns the last frame position encountered where matches are equal.



    FINGERPRINT & LUMATOL:
      The frame FingerPrint consists of 4 floating point component values (0.0 -> 255.0), and stored in the DB FingerPrint DBase.
    Each FingerPint component is derived from a pixel count for a portion of the possible 0 -> 255 luma pixel value range.
    Lets say that one of the fingerprint components is derived from the 128->191 luma pixel value range, the fingerprint component
    is computed for every frame in the SearchClip eg {luma PixelCount in range 128 to 191} * 255.0 / {SearchClip.Width*SearchClip.Height},
    this result is in range 0.0 -> 255.0, with 255.0 being equal to 100%. [There would be another three fingerprint components computed,
    in different ranges. We do not actually use range 128->191, and are reluctant to give any real used ranges as they may change, if you
    want to see the real current ranges used, then see the current source code]. The 4 fingerprint components are stored in the
    FingerPrint DB and are EXACT fingerprint component values. For the FindFrame, we use a FingerPrint component Range with LumaTol
    tolerance. For FindClip(FindFrame), we might compute a fingerprint component range for [128->191]:

      FingerPrintMin = {luma PixelCount in range [128+LumaTol] to [191-LumaTol]} * 255.0 / {SearchClip.Width*SearchClip.Height}
      FingerPrintMax = {luma PixelCount in range [128-LumaTol] to [191+LumaTol]} * 255.0 / {SearchClip.Width*SearchClip.Height}

    So using computed FingerPrintMin and FingerPrintMax for four different ranges as upper and lower limits, if any frame in the
    SeachClip (DBase) has all four EXACT FingerPrint components within all four fingerprint component limits, then it is a candidate
    frame and eligible for exit condition testing if exit conditions were set, or returned to the client as a result CANDIDATE frame if
    exit conditions were not set.

    v1.42, Have changed LumaTol arg from type Int to type Float, default 1.0. (Will still accept type Int so will not break script).
    Whole number values of LumaTol will behave as previously described.
      Where a non integer value of Lumatol is given, then LumaTol is split into integer and fractional parts, and processed as described
    below.

      PixelCountMin_INT  = PixCount[128+LumaTol.Int] to PixCount[191-LumaTol.Int]                        # Sum of
      PixelCountMin_FRAC = Int((PixCount[128+LumaTol.Int] + PixCount[191-LumaTol.Int]) * LumaTol.Frac)   # Fractional count of extremities
      FingerPrintMin     = (PixCountMin_INT - PixCountMin_FRAC) * 255.0 / {SearchClip.Width*SearchClip.Height}

      PixelCountMax_INT  = PixelCount[128-LumaTol.Int] to PixelCount[191+LumaTol.Int]                    # Sum of
      PixelCountMax_FRAC = Int((PixelCount[128-LumaTol.Int-1] + PixelCount[191+LumaTol.Int+1]) * LumaTol.Frac)  # Frac count expanded
      FingerPrintMax     = (PixelCountMin_INT + PixelCountMin_FRAC) * 255.0 / {SearchClip.Width*SearchClip.Height}

    Fractional LumaTol as implemented in v1.42 is a big improvement on integer only Lumatol, and intended primarily for extending
    LumaTol=0 to have a little extra tolerance. As the fractional part of LumaTol is applied to the actual existing pixel count of a frame,
    so it is to some degree self tuning, if eg a count for PixelCount[128-LumaTol.Int-1] is zero, then there will be no additional speed
    overhead for that particular FindFrame FingerPrint component match, if the count is high, then more candidate frames will be searched,
    this is contrary to v1.41 Float LumaTol where we just added the fractional part where it would incur a speed penalty on all frames.



    With Exit Conditions:
        Exit conditions are processed if Flags bits are set, this occurs where the above paragraph description would return a candidate frame
        to the client. If Exit condition are set, then at least one of those exit conditions also has to be satisfied, if not satisfied, then
        the candidate frame will NOT be returned to the client, it will instead keep searching until both a FingerPrint match occurs and an Exit
        condition is satisfied, if not, -1 NOT FOUND is returned.
          You can set one or more Exit Conditions, if any (or all) of the exit conditions succeed then there will be a +ve frame number
        returned by the function, QWKS_EXIT_FLAGS and QWKS_BM_FLAGS bits will be set, the returned frame number will be the first frame
        that satisfied an exit condition, and does NOT include any XP arg processing.
        If any exit condition is satisfied, and the XP arg is set, the function will continue scanning adjacent frames to the frame
        where an exit condition was satisfied and step onward until a better match for the exit condition is NOT found.
        (XP=1 is LOOSELY BETTER THAN, and XP=2 is BETTER OR EQUAL, XP=2 is STRICTLY BETTER THAN, see XP). XP Processing occurs on satisfied
        exit conditions and the XP processed frame numbers and differences are returned via QWKS_BM_xx and QWKS_BM_xx_FRM local vars.
        When using exit conditions, use the return frame number only as an indicator of success, use the returned local vars irrespective of
        whether or not XP processing is done (although if XP==0, then returned frame will be same as QWKS_BM_xx_FRM).
            v1.42, BEST MATCHES also now comply with XP = 2 (BETTER OR EQUAL) setting, Where XP != 2, then returns the first encountered
        frame position where matches are equal, XP == 2 will returns the last frame position encountered where matches are equal.
New Function:
Code:
RT_AvgLumaDif(clip clp, int "n"=current_frame,Bool "Slices"=False,Int "Matrix"=(Width>1100||Height>600?3:2) )

  The function, returns the average of pixel pair differentials for a given frame n, ignoring frame perimeter (1 pixel
  perimeter around frame edge), range 0.0 -> 255.0.

  Args:
    n, Int, Default current_frame.
    Slices, Bool Default False.
      False, Analyze every adjacent pixel pair in the frame with the exception of frame perimeter.
      True,  Analyze adjacent pixel pairs in the frame, all 4x4 pixel block boundaries are treated as perimeter pixels
        and omitted from processing along with the frame perimeter pixels.
    Matrix, Int, Default = (Width > 1100 OR Height>600) then 3(PC709) else 2(PC601). YUV not used
      Conversion matrix for conversion of RGB to YUV-Y Luma.  0=REC601 : 1=REC709 : 2 = PC601 : 3 = PC709,

  The function finds the average luminosity differential by analyzing every adjacent pixel pair within the video frame,
  (both horizontal and vertical, not diagonal) with an option to only process every other 2x2 horizontal and vertical block
  to ensure any slice (e.g. h.264, h.265) boundaries are excluded. By calling this function before and again after a given
  filter, this function quantifies a filter's affect on luminosity contrast.
    NOTE: The perimeter pixels are intentionally ignored as they often incur higher quantization errors.

   'x'= Process, '.'=Don't Process

          Slices=false                 Slices=true
    ........................    ........................
    .xxxxxxxxxxxxxxxxxxxxxx.    .xx..xx..xx..xx..xx..xx.
    .xxxxxxxxxxxxxxxxxxxxxx.    .xx..xx..xx..xx..xx..xx.
    .xxxxxxxxxxxxxxxxxxxxxx.    ........................
    .xxxxxxxxxxxxxxxxxxxxxx.    ........................
    .xxxxxxxxxxxxxxxxxxxxxx.    .xx..xx..xx..xx..xx..xx.
    .xxxxxxxxxxxxxxxxxxxxxx.    .xx..xx..xx..xx..xx..xx.
    .xxxxxxxxxxxxxxxxxxxxxx.    ........................
    .xxxxxxxxxxxxxxxxxxxxxx.    ........................
    .xxxxxxxxxxxxxxxxxxxxxx.    .xx..xx..xx..xx..xx..xx.
    .xxxxxxxxxxxxxxxxxxxxxx.    .xx..xx..xx..xx..xx..xx.
    ........................    ........................
EDIT: Modified Float LumaTol now implemented as so:
Code:
void __cdecl RT_Fingerprint_Lo(const AVSValue &std,const AVSValue &xtra,FINGER &finger,unsigned int *hist,IScriptEnvironment* env,double LTol) {
// NOTE, LTol optional default 0.0
    char *myName="RT_Fingerprint_Lo: ";
    LTol  = max(min(LTol,16.0),0.0);
    MYLO mylo;
    RT_MYstats_Lo(RTHIST_F,std,xtra,mylo,myName,env,hist);              // Get luma histogram
    const int rng[4][2]={{0 ,85},{86,170},{171,255},{64,191}};          // FingerPrint Component Histogram Ranges
    const int Pixels = mylo.pixels;
    double frac,whole;
    frac=modf(LTol,&whole);
    int Tol = int(whole);
    int i,j;
    if(frac == 0.0) {                                   // Integer LumaTol, no fractional part
        for(i=4;--i>=0;) {
            unsigned int sm=0;
            const int s = rng[i][0];                    // Start of range
            const int e = rng[i][1];                    // End of range
            int s2 = s+Tol;                             // contract lolim range by LumaTol Int
            int e2 = e-Tol;
            for(j=s2;j<=e2;++j)
                sm += hist[j];
            const double  smd = sm * 255.0 / Pixels;    // cannot be bigger than 255.0
            finger.lolim[i] = smd;
            if(Tol==0) {
                finger.hilim[i]=smd;                    // EXACT FINGERPRINT components, search identical frames OR DB FINGER
            } else {
                sm=0;
                s2 = max(s-Tol,0);                      // expand hilim range by LumaTol Int
                e2 = min(e+Tol,255);
                for(j=s2;j<=e2;++j)
                    sm += hist[j];
                finger.hilim[i] = sm * 255.0 / Pixels;  // cannot be bigger than 255.0
            }
        }
    } else {
        for(i=4;--i>=0;) {
            unsigned int sm=0;
            const int s = rng[i][0];
            const int e = rng[i][1];
            int s2 = s+Tol;                                     // contract lolim range by LumaTol Int
            int e2 = e-Tol;
            for(j=s2;j<=e2;++j)
                sm += hist[j];
            sm -= int((hist[s2] + hist[e2]) * frac + 0.5);      // Fractional reduction of extremities
            finger.lolim[i] = sm * 255.0 / Pixels;
            sm=0;
            s2 = max(s-Tol,0);                                  // expand hilim range by LumaTol Int
            e2 = min(e+Tol,255);
            for(j=s2;j<=e2;++j)
                sm += hist[j];
            if(s2 >   0) sm += int(hist[s2-1] * frac + 0.5);    // Add frac parts if possible
            if(e2 < 255) sm += int(hist[e2+1] * frac + 0.5);
            finger.hilim[i] = sm * 255.0 / Pixels;
        }
    }
}
__________________
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; 19th September 2014 at 23:55.
StainlessS is offline   Reply With Quote
Old 30th September 2014, 01:24   #300  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Ah, hem. I dont know what to say here other than I have a recommendation, if you dont want it, dont get it, I am in no way affiliated
with said device other than that I bought one.

Not the best place to post this, but I just got one and am so goddam impressed (my PC is core Duo 2.4, so I'm easlily impressed),
anyway, it does have my sincere recommendation from a company that I've been using (well a few years ago{EDIT: couple} bought out by another internet company)
since about 1984 (originally on Tottenham Court Rd and New Oxford Street), always a good experience. Brilliant tablet PC, if you dont like it, then tell
somebody else, (well you can call me names if you like but I'm used to that). Dont know why I'm posting here other that I think it is magic, If moderator
wants to spank me, then at least put in some other forum, reccomendation is with good intent. Well good buy.
http://www.morgancomputers.co.uk/pro...id-4-3-Tablet/#

PS, Comes with Kit-Kat. (As Avisynth now seems all but dead, me guesses that this will soon become my next fav devolopment thingy).

@IanB, if you are reading this, would be nice if you could say one way or another if you have deserted the project,
I'm sure that you would understand that some would be interested in a such statement, either way.
__________________
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; 30th September 2014 at 02:03.
StainlessS is offline   Reply With Quote
Reply

Tags
averageluma, correlation, lumadifference, runtime


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:05.


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