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. |
|
|
Thread Tools | Search this Thread | Display Modes |
29th May 2014, 01:41 | #281 | Link |
HeartlessS Usurer
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
__________________
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 ??? |
8th August 2014, 02:38 | #282 | Link |
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. |
8th August 2014, 12:33 | #283 | Link |
HeartlessS Usurer
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 ??? |
10th August 2014, 01:57 | #284 | Link | |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
Quote:
Code:
START=RT_TimerHP() # or RT_Timer(), matched pairs ONLY. ... END=RT_TimerHP() TIME_TAKEN = END - START # In seconds 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. |
|
4th September 2014, 19:21 | #285 | Link |
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))") 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 |
5th September 2014, 05:01 | #286 | Link | |
HeartlessS Usurer
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:
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 ??? |
|
9th September 2014, 15:21 | #287 | Link |
HeartlessS Usurer
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. |
9th September 2014, 15:22 | #288 | Link |
HeartlessS Usurer
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 ??? |
9th September 2014, 15:23 | #289 | Link |
HeartlessS Usurer
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. |
9th September 2014, 18:41 | #290 | Link |
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. |
10th September 2014, 01:00 | #291 | Link |
HeartlessS Usurer
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. |
10th September 2014, 15:38 | #292 | Link |
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))") As for what I mean by dynamically disabling heavy filters, it's something like this: Code:
last=(MeasureFPS(timespan)<30)?last:SlowFilter() 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. |
11th September 2014, 07:42 | #293 | Link |
HeartlessS Usurer
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))""") 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()
__________________
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. |
11th September 2014, 12:37 | #294 | Link |
HeartlessS Usurer
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))""") 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()
__________________
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. |
11th September 2014, 15:43 | #295 | Link |
HeartlessS Usurer
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 ??? |
15th September 2014, 12:01 | #296 | Link |
HeartlessS Usurer
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. 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. |
15th September 2014, 16:35 | #297 | Link |
HeartlessS Usurer
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. |
16th September 2014, 01:34 | #298 | Link |
HeartlessS Usurer
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. 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). 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. |
19th September 2014, 21:00 | #299 | Link |
HeartlessS Usurer
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. 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. 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. ........................ ........................ 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. |
30th September 2014, 01:24 | #300 | Link |
HeartlessS Usurer
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. |
Tags |
averageluma, correlation, lumadifference, runtime |
|
|