Log in

View Full Version : Duplicity2/DropDeadGorgeous v2.13 - Dupe Tool - 17 Nov 2018


Pages : [1] 2

StainlessS
1st April 2018, 21:08
Post #1 of 2.

/*
Duplicity2(), v2.13, by StainlessS @ Doom9:- https://forum.doom9.org/showthread.php?t=175357

A two faced scheming and double dealing [on your behalf] dupe tool.

Three modes of operation,
0) Write duplicate Frames file only (as single frames or ranges).
1) Replace duplicates with exact duplicates. (Can also write Frames file).
2) Replace duplicates with Interpolated or Blended frames (control via MaxDuplen and MaxInterp). (Can also write Frames file).

Req:-
RT_Stats v2.00_Beta_11 + CallCmd (c) StainlessS,
GSCript, Grunt, (c) Gavino,
MaskTools2, MvTools2, (c) Manoa/Fizick/Pinterf & Others (Pinterf Versions).
RemoveGrain, (c) Kassandro.

GScript not needed if Avs+ [(c) Ultim, Pinterf and others.].
If CallCmd available then will AutoDelete DBase on clip closure, otherwise requires manual deletion.

ColorSpace:- All v2.6 standard PLANAR colorspaces except YV411, no support for YUY2, RGB24 or RGB32.

Function Duplicity2(clip c,"Mode"=0,Float "ThG"=1.0,Float "ThB"=ThG*2.0, Int "ThP"=64,Float "IgP"=0.0,Int "ThK"=7,
\ Int "MaxDupLen"=9,Int "LagMax"=MaxDupLen,Int "MaxInterp"=Min(9,MaxDupLen),
\ int "BlkW"=64,int "BlkH"=BlkW,int "OLapX"=BlkW/2,Int "OLapY=BlkH/2",
\ Int "X"=0,Int "Y"=0,Int"W"=0,Int "H"=0,Float "CW"=0.0,Bool "ChromaI"=False,Bool "AltScan"=False,
\ Int "SPad"=16, Int "SSharp"=1, Int "SRFilter"=4, [* MSuper *]
\ Int "ABlkSize"=16, Int "AOverlap"=4, Int "ASearch"=3,Int "ADct"=0, [* MAnalyse *]
\ Int "RBlkSize"=8, Int "ROverlap"=2, Int "RthSAD"=100, [* MRecalculate *]
\ Float "Iml"=200.0, Bool "IBlend"=True, Int "IthSCD1"=400, Int "IthSCD2"=130, [* MFlowInter *]
\ Int "OthSCD1"=400,Int "OthSCD2"=130, [* Dupe Detect Override @ Scene Change *]
\ String "OverRide"="",String "Frames"="Frames.txt",Bool "Ranges"=True,Bool "FrameAsRange"=False,
\ Bool "Show"=True,Bool "Verb"=True,Bool "ShowBlk"=True,Bool "Dim"=True,Bool "ShowDot"=False,
\ Bool "InterpFast"=True,String "DBase"=""
\ )

Duplicity2() uses 3 RT_Stats measurement functions, RT_FrameDifference(), RT_FrameMovement(), and RT_LumaPixelsDifferent().
the first two may difference using either luma only, or with a combined weighted chroma difference. Also see CW,
and ChromaI args. RT_LumaPixelsDifferent() differences luma only.

DeDuppers use some method to determine if a frame is a duplicate of its predecessor, a typical measuring method might be
RT_FrameDifference (average absolute difference per pixel), unfortunately the result of such measure may be due to a small
frame global change (lots and lots of pixels change by a small amount), or a smaller number of pixels change by a
larger amount, both these cases could produce the exact same result. Another case may be that of a very small number of
pixels change by a very large amount (eg a person blinks an eye with remainder of frame static) and such measure might seem
to be a duplicate as it could produce much smaller numbers than a frame global change of a small amount.

Duplicity2() uses a triple measurement system (maybe it should be called Triplicity), Primary measurement (RT_FrameDifference)
to detect frames 'Unique' to their immediate predecessor (large or 'frame Global' changes), and second and third methods to
determine if 'Non-Unique' frames are either 'Low Motion' or 'Duplicate' frames. The second method is a block differencing
method (RT_FrameMovement) where it splits the frame up into BlkW by BlkH blocks and finds the maximum average pixel difference
of any one block. The third measurement method is RT_LumaPixelsDifferent (result 0.0->255.0 where 255.0 is equivalent to 100.0%,
user args for this method actually require Duplicity2 arg 'IgP' in range 0.0->100.0%, and also show results in range 0->100.0%).
RT_LumaPixelsDifferent, compares frames and shows percent of pixels whose corresponding absolute luma pixel difference is
greater than Int arg 'ThP', if this percent difference is greater than 'IgP', then it is deemed to be a 'Low motion' frame and if
less or equal to 'IgP' then is a duplicate ('IgP' can be 0.0, meaning any pixels at all with difference greater than 'ThP' is a
'Low Motion' Frame). Where both 'ThP' and 'IgP' are 0 and 0.0 respectively, will show percentage of pixels that are not Exactly the same.
'IgP' could be set to 0.0 (Default) in which case the function is governed solely by any pixel differences exceeding 'ThP', or can set
'IgP'= eg 0.001% meaning the it will disregard as noise 1 pixel difference exceeding 'ThP' in every 100,000 pixels
[eg 1 pixel in every 316x316 region]. It is probably easiest to always use IgP of 0.0 and only adjust ThP.

The function examines the DBase to determine if status for current frame is already known, if not already known then,
the function determines if the current frame is a 'Unique' frame or not (via 'ThG' RT_FrameDifference to predecessor), if Unique,
then the job is done and is considered a Non-Duplicate, these Unique frames are marked in a DBase as Unique. If a frame is
'Non-Unique', then the function scans both backwards and forwards looking for 'Unique Start' and 'Unique End' frames (and if
necessary, marking them in DBase). This Backwards/Forwards scanning permits jumping around in the clip for perusal and getting
exact same results as if travelling forwards only (even backwards traversal only, should work just fine). When the
'Unique Start' and 'Unique End' frames are established, we then know the extent of the unknown (unvisited) frames, and can scan
and measure those with the second and third measurement methods (RT_FrameMovement and RT_LumaPixelsDifferent) to determine
Low Motion/Dupe status. When determining Low Motion/Dupe status, we compare with an 'Anchor Frame', which at the beginning of a
'Non-Unique' sequence is the 'Unique Start' frame. When scanning a non-unique sequence the 'Anchor Frame' is the predecessor frame
to the very first frame in the current sub sequence of the 'Non-Unique' sequence, so potential duplicates are not necessarily
compared with their immediate predecessor. When a frame is determined to be 'Low Motion' (not a dupe), any detected duplicates are
written to the DBase and also to the output Frames file, and it switches to detecting sequences of 'Low Motion' frames within the
'Non-Unique' sequence. On each detected 'Low Motion' frame, the Anchor frame for the next frame (whether it be another
'Low Motion' frame or a new 'Dupe' frame) will be switched to that newly detected 'Low Motion' frame. With this method,
all frames BETWEEN (but excluding) the 'Unique Start' and 'Unique End' in the 'Non-Unique' sequence are detected as perhaps
multiple 'Low Motion' and 'Duplicate' sub sequences.
Setting LagMax arg to some low number (min 1), will limit distance of the Anchor frame prior to the current frame, eg setting
LagMax=1, would always do LoMo/Dupe compare with the current frame and its predecessor. A LagMax greater than 1 allows better detection
of Low-Motion frames where there is only very slow creeping movement in the sequence.

The above method allows for reasonably fast processing, where a 'unique' frame is encountered [where it is clearly different from
its predecessor] but where not so clear, will examine the LoMo/dupe suspect frames more closely. ThG sets the boundary between
'Unique' frames and non unique, and so has some effect on speed, setting too high for your source will slow processing speed as many
non dupes will be examined more closely, and setting ThG too low for your source, may increase speed but may miss duplicates in noisy
sources (probably better to set too high than too low).

Although you might be able to scan backwards and get same detections, results are written to the Frames file in visited sequence and
you should NOT jump about whilst writing the final frames file. Also, this is a Multi-Instance script, can use multiple instances
at the same time (view side by side metrics) but you should really choose a unique 'Frames' filename for each instance.

Args:-
Mode, Default 0, (Range 0->2)
0) Write Frames file only (where Frames file="" then not written so only Show=true does anything).
1) Make duplicate sequences Exact Dupes.
2) Interpolate/Blend Duplicates (depends upon MaxDupLen and MaxInterp).

ThG, Default 1.0 (0.0 < ThG <= 255.0) Suggest 1.0, never below 0.5.
Primary Global Unique detect threshold. [current_frame-1 <-> current_frame].
If using 255.0 will likely scan all of the way to both Start and End frames, and then
detect LoMo/Dupe frames of entire clip using the 2nd & 3rd detection methods, will seem to pause for a long time,
dont do it (no error if using daft numbers).

ThB, Default Float ThG * 2.0, (Range ThG <= ThB < 255.0, Suggested about 1.5->3.5).
Secondary Local LoMo/Dupe Block detect threshold, [Anchor<->current_frame]
Tune for source and Block Size. (For smaller block size, just by random chance there may be several noisy pixels
in duplicate frame block, that produce considerably higher metric than most other blocks).

ThP, Default Int 64. (Advised Range ThB < ThP <= 64, or 255=OFF)
Ternary Local [single pixel] LoMo/Dupe detect threshold, [Anchor<->current_frame].
On a test with 256 artificial generated 640x480 identical frames of random coloured pixels, encoded at
MeGUI AVC CRF 23.0(default), RT_LumaPixelsDifferent(Thresh=1) found no frames where any single pixel was
different by more than 1 luma level when compared with the first encoded frame from that sequence. Mpeg2
and flv might not fare as well. This test was on a totally clean artificial source without artefacts
and such, you will likely need considerably higher values of ThP than 1.
I have seen multiple clips exhibiting some kind of minute (perhaps sub pixel) frame shift (both horizontal and
vertical) where frame should have been an exact duplicate, no idea to the cause.
This setting is an additional knob to twiddle, and you could turn it off and rely on ThG and ThB
completely [ThP=255, turns off]. The default of 64 and the below setting IgP=0.0, will consider any single pixel
with a luma difference of 64 or more, to be a non dupe, unfortunately any clip having above mentioned sub pixel
shifting at dupe frames, may need a high setting to not trigger a lomo detection, I have not I think
seen so far any clip that needed ThP more than about 48. 64 might seem ridiculously high but if frames are shifted,
then a little preposterous-ness is likely necessary, in a true non-dupe, there will most usually be at least
one pixel that differs in luma by more than 64.
We have thusly decided to make the default an emergency fallback detect value of 64, the user may decide to lower
this value or indeed turn it off completely[ThP=255].

IgP, Default 0.0, (Range 0.0 <= IgP < 100.0). Percent noise threshold for Ternary Local [pixel] LoMo/Dupe Detect,
Note, default 0.0% means that any frame with any single pixel with abs luma difference greater than ThP will
be detected as LoMotion.

ThK, Default = 7, (0 <= ThK <= 255). 0 = K Overrides off.
If RT_YPlaneMinMaxDifference(Threshold=0.2) of current_frame is less ThK then will Override any detection,
ie black (or narrow luma range) frames are ignored as not duplicates.
[Threshold=0.2 ignores as noise, 1 in 500 extreme pixels when establishing loose minimum and loose maximum & luma range].

MaxDupLen, Default 9. Maximum permitted detection length of duplicate run, If detected dupe run exceeds this setting,
then it is totally ignored and presumed to be a static scene.

LagMax, Default MaxDupLen. Setting to a low number (min 1) will limit the distance of the Anchor frame prior to
the current frame, eg setting LagMax=1, would always do LoMo/Dupe compare with the current frame and its
predecessor. Maybe best left alone.

MaxInterp, Default Min(MaxDupLen,9), (Range 0->9). For Mode=2(Interpolate/Blend mode) only. Max length of interpolated frames.
Sequences longer than this but less or equal to MaxDupLen will be blended instead.

BlkW, Default 64, 8 <= BlkW, Mod 2, Best Mod 4. Width of Blocks for Secondary Metric.
BlkH, Default BlkW, 8 <= BlkH, Mod 2, Best Mod 4. Height of Blocks for Secondary Metric.
OLapX, Default BlkW/2, 0 <= OLapX <= BlkW/2, Horizontal block overlap for Secondary Block metric.
OLapY, Default BlkH/2, 0 <= OLapY <= BlkH/2, Vertical block overlap for Secondary Block metric.
Where CW==0.0 and AltScan==True, might try eg OLapY=(BlkH/2)-1, where might be faster due to AltScan and,
also in overlapped 'Y_Block' scan will then scan alternate scanlines that were not scanned in previous non overlapped
scan (if that makes any sense, ie even scanlines sampled in first block, odd lines sampled in overlapped block scan).

X,Y,W,H, All Default 0, Coordinates of test area, as in crop (all 0 = full frame).
The x,y coords will be rounded up mod4, and w,h coords rounded down mod 4.
Ignore eg animated logo.

CW [ChromaWeight] Default 0.0. (0.0 <= CW <=1.0).
For Primary Frame Global and Secondary Block Mode difference detection, weighting of combined chroma diff to luma diff.
If required, recommend about 0.1, where difference would be weighted as
TotDif = ((1.0 - CW) * YDif) + (CW * ((UDif+VDif)/2.0))
Suggest always CW=0.0 where Night Capture.


See Post #22 for current script

Zip Includes DropDeadGorgeous()

For Zip, See Mediafire in sig below this post, or SendSpace.

StainlessS
1st April 2018, 21:08
Post #2 of 2.


ChromaI Default False, Primary + Secondary Block Mode setting. YV12 Only(otherwise ignored), Set True if Interlaced Chroma.
Also ignored if CW=0.0. DO NOT use Interlaced material with Mode=2(Interpolate/Blend).

AltScan Default False. Secondary (only) Block Mode setting. Scans only every other scanline of blocks.

MvTools2 Args, for Interpolation.
MSuper args:
SPad, Default 16, See MvTools MSuper(hpad=8,vpad=8) [We use same for both].
SSharp, Default 1, See MvTools MSuper(sharp=2)
SRFilter, Default 4, See MvTools MSuper(rfilter=2)

MAnalyse args:
ABlkSize, Default 16, See MvTools MAnalyse(BlkSize=8,BlkSizeV=8) [We use same for both].
AOverLap, Default 4, See MvTools MAnalyse(OverLap=0)
ASearch, Default 3, See MvTools MAnalyse(Search=4)
ADct, Default 0, See MvTools MAnalyse(Dct=0). Using other than default value can be VERY slow.

MRecalculate args:
RBlkSize, Default 8, See MvTools MRecalculate(BlkSize)
NOTE, RBlkSize = 0 Will Switch OFF MRecalculate, probably a bit faster at possible expense of quality.
ROverlap, Default 2, See MvTools MRecalculate(Overlap)
RthSAD, Default 100, See MvTools MRecalculate(thSAD=200)

MFlowInter args:
Iml, Default 200.0, See MvTools MFlowInter(ml=100.0)
IBlend, Default True, See MvTools MFlowInter(Blend=True). Blend or copy frame at scene change.
IthSCD1, Default 400, See MvTools MFlowInter(thSCD1=400) : (0 < IthSCD1 <= (8*8)*255)
IthSCD2, Default 130, See MvTools MFlowInter(thSCD1=130) : (0 < IthSCD1 <= 255)
Threshold which sets how many blocks have to change for the frame to be considered as a
scene change. It is ranged from 0 to 255, 0 meaning 0 %, 255 meaning 100 %.
Default is 130 (which means 51.0%).
Used by MvTools2 MFlowInter during interpolation.

Duplicate detection Override due to scene change following dupes, args: (Modes 0 & 2 only)
OthSCD1, Default 400. as MVTools MSCDetection arg. (0 < OthSCD1 <= (8*8)*255). See MvTools2.
OthSCD2, Default 130. as MVTools MSCDetection arg. (0 < OthSCD2 <= 255)
These two thresholds govern whether frames either side of duplicate sequence are determined to be
from the same scene, if not from same scene then duplicate detection is overridden and 'E' flag is set in metrics,
on what would have been the duplicate sequence.
NOTE, If OthSCD1 >= 8*8*255 or OthSCD2 >= 255 then switches OFF scene change testing, will NOT override
any duplicate detections (will likely result in blended scene transitions where frame after dupes is from
a different scene).
NOTE, For Mode=1(Replace dupes with exact dupes), scene change detection is omitted as no blending nor
interpolation is done and so no blending across scene change is possible and so not necessary to detect.

OverRide, Default "" (ie not used).
Provide list of frames/ranges to OverRide as NOT DUPLICATES, can give filename or string of Overrides, eg
".\Overrides.txt", text file "Overrides.txt" in current directory containing something like
the contents between to ############ lines.
############
100,199 # Frames 100 to 199 overridden (as NOT dupes)
300,-100 # Frames 300 to 399 overridden (100 frames)
500 # Frame 500 Overridden.
############
Or Preceded in string by "*" Star or Asterisk character, then remainder of string as contents of above file example.

Frames, Default "Frames.txt", Frames filename for output, ("" will not write Frames file).
Ranges, Default True (True=Write comma separated frame ranges to Frames file, else single frames only).
FrameAsRange, Default False. If Ranges=True and FrameAsRange=default false, and single frame, then writes single frame number and
not range. If Ranges=True and FrameAsRange=True then writes single frame as range eg '23,23' for frame 23.

Show, Default True, Show metrics.
Verb, Default True, Additional Verbose Metrics when Show=True (Verbose Metrics not shown below).
ShowBlk, Default True. If true (and Show=True), then mark block on frame where secondary Block Detections occur.
Motion detection shown in Orange/Yellow, and greatest non 0.0 non detection block shown in Green.
Perhaps of use in tuning for ThB.
Dim, Default True. If True (AND Show=True AND Mode==0), then dims any outer area excluded by X,Y,W,H args.
When Mode!=0 then Dim is Ignored [ie only valid when Mode=0(Write Frames file mode)], ignored when modifying
source frames ie Mode=1(Make dupes exact dupes) or Mode=2(Interpolate dupes).
Perhaps switch to Mode=0, to examine X,Y,W,H, coords correct.
ShowDot, Default False. If Show AND ShowDot both True, then switches OFF Show and instead shows
an Asterisk/Star in top left corner of duplicates detections (after frame mods eg Exact copy or Interpolation etc).

InterpFast, Default True. If True, then Interpolation clips are pre-calculated, if false then calculations done in real time.
Pre-Calc clips a bit (maybe 10%) faster, but perhaps not quite as good quality.
NOTE, If experiencing Out Of Memory errors, then try switch to InterpFast=False.

DBase, Default "", If named DBase suppled, then is not deleted on clip closure.
[ If name supplied, result DB may be re-used by other scripts, eg DropDeadGorgeous() function ].
NOTE, If using multiple instances and named DBase, then give each DBase as different name.

Metrics show eg
"nnnn] OKSE:GBP:ULD {1/32 : L1/5 : uS=12 : uE=45}"
"pG= p.gggggg : pB= p.bbbbbb : pP%= p.pppppp"
"aG= a.gggggg : aB= a.bbbbbb : aP%= a.pppppp
"{K=200 : a=567 : Lag=1}"

Where,
'nnnn' = current frame
'OKSE:GBP:ULD' = Flags highlighted where relevant.
OKSE, OverRide flags (overridden to not duplicates),
O=User OverRide, (via OverRide arg)
User_Overrides are set in DBase to 'Not A Duplicate', prior to scanning and cannot be changed via the
detection scan.
K=Low Luma Range Override (black or low luma range frames not detected as dupes), via ThK arg.
K_Override via ThK can override all of the other conditions (except User Override as above).
S=Static Scene OverRide, via MaxDupLen arg.
Static_OverRide flagged if detected as Duplicate run but exceeds MaxDupLen.
E=End+1 of current dupe sequence is change of scene, so if Mode=2 then Interpolation
or Blending is skipped for that dupe sequence.
NOTE, Mode=0(Write Frames), also processes scene change detection, unless disabled via eg OthSCD2=256.
Mode 1(replace with exact dupes), skips scene change detection as no purpose to it.

GBP, Motion detection reason flags,
G=Frame Global detection via Primary detector. [Orange, Unique to current - 1]
B=Block detection via Secondary Detector. [Orange, motion between current and anchor in LoMo seq]
P=Pixel detection via Ternary Detector. [Orange, motion between current and anchor in LoMo seq]

ULD, Current frame detection Status.
U=Unique Frame, detect via ThG
L=Low_Motion Frame, detect via ThB, ThP and IgP.
D=Dupe Frame, not Unique or LoMotion.

'1/32' = The 1st of 32 frames in a 'Non Unique', perhaps mixed LoMo/Dupe sequence.
'L1/5' = The 1st of 5 frames of Low Motion sub sequence of the 'Non Unique' sequence
D1/5=1st of 5 dupes.
I1/5=1st of 5 dupes, Where Mode=2, and Interpolated.
B1/5=1st of 5 dupes, Where Mode=2, and Blended.
E4/7=4th of 7 dupes that were not processed because frame after dupes is from a different scene.
Will not occur when Mode=1 (replace with exact dupes).
K3/4 3rd of 4 K_Override frames.
S2/99 2nd of 99 Static_OverRide frames.

'uS=12 : uE=45' Unique Start and End frames, 'Non Unique' LoMo/Dupe sequence is between these two frames (exclusive).

'pG= p.gggggg.' = Primary 'Unique Frame' Frame difference metric between current and Predecessor frame.
'pB= p.bbbbbb.' = Secondary 'Low Motion/Dupe' Block difference metric between current and Predecessor frame. (info only)
'pP= p.pppppp.' = Ternary 'Low Motion/Dupe' Pixel difference metric between current and Predecessor frame. (Info Only)
'aG= a.gggggg.' = Primary Unique Frame difference metric between current and Anchor frame in Non Unique sequence.
'aB= a.bbbbbb.' = Secondary 'Low Motion/Dupe' Block difference metric between current and Anchor frame in Non Unique sequence.
'aP= a.pppppp.' = Ternary 'Low Motion/Dupe' Pixel difference metric between current and Anchor frame in Non Unique sequence.
'K=200' = Current_frame RT_YPLaneMinMaxDifference(Threshold=0.2), Unique or Non Unique sequences.
'a=567' = Comparison Anchor frame number in Non Unique sequence.
'Lag=1' = Frame Count between current frame and Anchor Frame (Lag=1, Anchor is Predecessor) in Non Unique sequence.

For 'Unique' frames, Only shows "nnnn] OKSE:GBP:ULD" on top line and also the 2nd line & 'K=2', 'Low Motion/Dupe' show the remainder.
*/


Greatest low motion block detected shown by Yellow rectangular marker. Dimm'ed area shows X,Y,W,H excluded area.
Just inside that block marker @ top LHS corner, there is an almost invisible fox (the light in doorway is due to motion detector).
Difficult scene, shimmering road due to raining.
https://i.postimg.cc/XYk0NgBb/Duplicity_2.00_Beta_2.jpg (https://postimages.org/)

And again in frame where fox (below doorway) after activating motion sensor (sniffing at something).
https://i.postimg.cc/ZKgLBk3P/Duplicity_2.00_Beta_2_b.jpg (https://postimages.org/)


See Post #22 for script

EDIT: Posted elsewhere about DropDeadGorgeous2():

Duplicity2(), is a dupe Detector, Dupe frame list creator, Dupes replaced with exact dupes, Dupes replaced with interpolated frames + DBase of dupes creator.
DropDeadGorgeous2() uses Duplicity2 DBase to do the almost impossible, smoothing out jerking clips (where source has jerks and dupes, much better than simple interpolation of dupes).
DropDeadGorgeous2 can also [EDIT: help] up framerate (eg 25.0 -> 29.97) keeping all source frames verbatim, and creating smooth result
[squeezes out dupes, where are replaced by interpolated frames between frames of most movement - non dupe frames are relocated between jerk interpolations and dupes to squeeze out dupes (hard to explain it)].

EDIT: Perhaps this explains better

abcXdefgDDhi Src, Two dupe [D] frames preceded (within a set range) by a jerk frame. Jerk frame X, has greater motion to its predecessor than do d, e, f, or g.
abc12Xdefghi DropDeadGorgeous dupe removal and Jerk interpolation

Lower case non dupe non Jerk
X = Frame of greatest motion from predecessor (Jerk)
D = Dupe Frames
Digit = Interpolated frames between X and its predecessor c (Same Count as D dupes)


# below assumes that 2 frames both dropped and duped, similar where 1 frame dropped. [2 frames dropped is extreme and more difficult case, we describe the more difficult]

abc12Xdefghi # How it should have been in capture, 1,2 will both be dropped, X is jerk frame following frames that will be dropped.
abcXdefgDDhi # when 1,2 dropped by CAP device, and DD dupes inserted.
abc12Xdefghi # DropDeadGorgeous() fixed. (1,2 are both interpolated frames {with c and X as interp source frames}, original 1,2 GONE $4E4 [forever])

StainlessS
1st April 2018, 21:09
Script Removed. See post #22 for script.


@ Motenai Yoda,
I see you on-line there, give a whirl please, took some time to do, sorry. Somewhat better (I hope) than previous posted in FrameSel thread. Still need use Frames rather than ranges with the other script, I'll get down to doing it as a FrameSel plug mod soon.
@ Orum, hope you can do better than this with your new plug in devs forum, good luck.
@ JohnMeyer, I know that you aint ever completely happy with anything video related, but maybe this tickles your fancy, just a tad :)

StainlessS
1st April 2018, 21:10
SPARE for Growth

Motenai Yoda
1st April 2018, 21:23
Sorry, I wasn't avoiding to try previous one, just there is something dependency related I have to fix.
btw CallCmd work on x64 avs+?

StainlessS
1st April 2018, 21:28
CallCmd work on x64 ?

Not yet, I'll make it work.
Can just comment out that line, delete file by hand.

EDIT: 2nd last line of script function, ie

CallCmd(close=RT_String("""CMD /C chcp 1252 && del "%s" """,DB), hide=true, Synchronous=7) # Auto delete DBase file on clip closure.

Motenai Yoda
1st April 2018, 22:52
you should delete those last 2 lines.
also it throw a "Script error: There is no function named 'GScript'."

StainlessS
1st April 2018, 23:10
There is no function named 'GScript'."
I guess that is something that was forgotten during the emulation implementation.

Req RT_Stats v1.43 + CallCmd (c) StainlessS, + GSCript + Grunt (c) Gavino.

Even if Avs+ has GScript functionality, you are likely to have problems having to comment out lines in GScript using scripts that can run on either avs standard and avs+.
I always have Gscript and Grunt [required for GScriptClip(arg=Args,Local=True)] in my plugins, whether avs or avs+ is in use.

you should delete those last 2 lines.
Which other line are you talking about, the GScript(InstS) thing actually calls the function, and so of course cannot be commented out and still function as expected (or at all).

StainlessS
1st April 2018, 23:15
try

# GScript(InstS)
Eval(InstS)


Works for me in avs+ 32bit.

EDIT: I'll fix it so that it works on avs 2.6 standard or avs+(without GSCript or script editing).

Motenai Yoda
1st April 2018, 23:45
https://thumbs2.imgbox.com/2a/37/J2rfcfDs_t.png (http://imgbox.com/J2rfcfDs)
I have those 2 lines at the end, from .zip

StainlessS
1st April 2018, 23:59
Link and posts updated to v1.01.

EDIT: Actually, I mistakenly used RT_VarExist("GScript") when I should have used RT_FunctionExist("Gscript"),
but it works OK anyway, arh well, I'll leave as it is for just now, I'll fix it for next time.

EDIT: I'll fix in the posted script, I'll just leave the zip as it is for now.

johnmeyer
2nd April 2018, 00:08
I'll be out for several days but would like to try this. I do a LOT of work that involves detecting and then doing something with duplicates.

However ...

The most typical scenario that I come across that creates duplicates is from either a capture card or streaming video drops a frame and then, to keep the audio in sync, adds a duplicate frame. In those scenarios, the duplicate is a true duplicate, and no fancy logic is needed to find it. The much, much bigger issue is find the place where the dropped frame happened because it is at THAT point you have to do something, typically synthesizing a new frame using motion estimation.

As for how to detect differences and thereby determine which frames are dups, I haven't used RTStats for a while so I don't remember all the functions, but when using native AVISynth functions, it is the YDifference functions that are the most useful because, if I remember correctly, they compute their metric by the absolute differences between each pixel position in one frame with the same pixel position in the adjacent frame and then summing all of those differences. It will be interesting to see how your new function compares with that.

StainlessS
2nd April 2018, 00:29
RT_LumaDifference can use two separate clips if required + any two frame numbers (one for each clip), [YDifference is single clip], but same measurement.

Yoda wanted to list dupe frames and temporarily remove them for MC processing, and then replace with identical dupes from the
MC processed clip.

ie here:- https://forum.doom9.org/showthread.php?p=1832814#post1832814

I think he may want this for vfr stuff, not sure.

Motenai Yoda
2nd April 2018, 00:47
Yep something about full of dups stuff
but as lossy codecs will introduce artifacts between dups, loss of detail et simila iirc TDecimate uses a threshold to filter out small differences (default 0) and a block based metric to find slight differences in small area only.

StainlessS
2nd April 2018, 01:10
I use a block based metric in SecurityCamExtractMotion.avs as shown in action here:- https://forum.doom9.org/showthread.php?p=1775305#post1775305

Is too big to post, but included in RT_Stats v2.0 beta.

I did at one time use it in the Duplicity script, maybe I'll add as an option or something.

StainlessS
2nd April 2018, 02:23
If anybody has wanted to try SecurityCamExtractMotion.avs as mentioned in previous post but has had trouble down to Gscript and Avs+,
find fixed version works on AVS/AVS+ :- SecurityCamExtractMotion.AVS v2.02 :- https://www.mediafire.com/file/c6kqosweqmk82my/SecurityCamExtractMotion.AVS/file

Or on SendSpace below in my sig.

Looks like this
https://s20.postimg.cc/5ix37af7h/SCMD2_zpsiuzq505m.png (https://postimg.cc/image/uc6n7xy7t/)

johnmeyer
2nd April 2018, 03:16
I used that security cam motion detect logic several years ago and it worked incredibly well. This looks like a much later version because I don't remember being able to draw a box on the screen to define the "live" area for the detection logic to use (or ignore).

StainlessS
2nd April 2018, 03:25
The dimmed area stuff (edge of frame) is highlited in Blue, the marker stuff hilited in purple, was updated at least 12 months ago.


# SecurityCamExtractMotion.AVS, v2.01, By StainlessS.
#
# Requires RT_Stats v2.0, FrameSel v1.03, GScript, Grunt, mt_tools_2. [GScript not needed if Avs+]
#
# Clip, Planar, YUY2 or RGB clip, YV411 not supported due to non support in Overlay.
# (RGB, will likely require different thresholds)
#
# MUST SCAN STRAIGHT THROUGH, NO JUMPING ABOUT IN MotDetect.
#
# MotDetect() creates four .txt command files for KEEP frames (movement), DROP frames (not movement), DUPE frames and HOLD frames.
# HOLD frames are combination of all KEEP frames and, DROP frames where block with greatest difference is in close proximity to previous
# KEEP frame block with greatest difference (ie there seems to be possible movement very near previously identified movement).
# Using SelectFrames() you can select frames types of each of the 4 command files, or using the Reject mode of FrameSel, you can
# instead return the frames NOT in the command file, so using the 4 created command files, you can extract 8 variations of frame types
# after a single detection scan.
#
############################################
Th = 6.0 # Greater or equal KEEP (movement), below is DROP(or DUPE, or possibly HOLD).
# Need check against source, block size and almost all other settings.
#
dTH = 4.0 # Below or equal is DUPE, 0.0 <= dTh < Th (above dTh and below Th is DROP [or possibly HOLD]).
#
BLKW = 64 # Suggest about 16 -> 64 (even only, mod 4 else probably slower). Metrics will change with block size.
BLKH = BLKW # Localized movement, adjust for smallest size of moving objects to detect, makes only little difference to speed,
# bigger, may be a bit faster.
# For human target, suggest box encompassing head + shoulders of most distant human.
# RT_FrameMovement returns greatest average pixel difference for any one of the blocks.
# Block searches may be overlapped by up to half a block both horizontally and vertically and so total x,y,w,h area
# of each pair of frames is compared up to about 4 times due to the half block overlaps.

#
X = 16 # Area Of Interest, avoid eg passing traffic or timecode (or could use eg Overlay to blot out stuff for dclip).
Y = 16 # Suggest cut out eg sky unless looking for flying saucers (less to search, faster).
W = -16 # As for Crop. Best MOD 4 only
H = -16
#
CW = 0.0 # ChromaWeight, 0.0->1.0. 0.0 = Luma ONLY, about 0.1 suggested for color (luma ONLY faster for YUV).
# For RGB, Matrix used where CW==0.0 to convert to Luma-Y. If CW != 0.0, then returns average pixel differences,
# (apdR+apdG+apdB)/3.0.
# Perhaps always CW=0.0 [luma only] for YUV night captures.
# Can convert RGB to YUV for Luma-Y detect and SelectFrames() using original RGB, if required.
#
AltScan=false # If True, Scan only every other raster line starting from Y (maybe faster, especially YUV Luma scan only).
#
ChromaI=False # If True, YV12 chroma is interlaced (ignored if not YV12 or if Luma ONLY scan [CW==0.0]).
#
Matrix=(Width>1100||Height>600)?3:2 # Matrix used for RGB conversion to Luma-Y.
# Default, If (Width>1100 || Height>600) then 3(PC.709), else 2(PC.601). (0=Rec.601, 1=Rec.709)
# NOTE, default PClevels conversions will likely require different thresholds to YUV because of the
# greater differences in Y (after RGB-Luma-Y conversion), probably about (255.0/219.0) times greater.
#
OLapX= BlkW/2 # X Block Overlap. 0->BLKW/2 (bigger more accurate, slower)
OLapY= BlkH/2 # Y Block Overlap. 0->BLKH/2
# Where YUV, CW==0.0 and AltScan==True, might try eg OLapY=(BlkH/2)-1, where would be faster due to AltScan and,
# also in overlapped 'Y_Block' scan will then scan alternate scanlines that were not scanned in previous non overlapped
# scan (if that makes any sense, ie even scanlines sampled in first block, odd lines sampled in overlapped block scan).

LAG = 1 # Lag (default 1, ie no lag. 1 or more). Compares current frame n with frame n-Lag. Detection is always
# initially compared(n,n-1), if neither DUPE nor KEEP detected and Lag>1, then will redetect using comparison(n,n-Lag)
# where n-lag frame is limited to no earlier than the most recent KEEP frame.
# A moderate Lag (up to about 50 or so), may be more sensitive to very small amount of movement,
# it introduces a time delay between compared frames. There is no upper limit to Lag arg.
# NOTE, Lag > 1 will likely produce more KEEP and HOLD frames (ie identify more movement), and also a bit slower
# due to 2nd detection scan where initial scan identified DROP frame (ie DROP may be converted to KEEP or HOLD).
# Lag will not make any huge difference to results, small amount of movement at beginning of sequence of movements may be
# detected, use lag > 1 only where every possible movement frame is required.

SHOWDCLIP=false # If True, then shows DClip in MotDetect rather than source clip (Only useful if dclip pre-processed in some fashion)
#
dclip=Last # Detection clip.
# Or some kind of denoise or whatever, used for detection (visible in ShowMetrics if SHOWDCLIp==True).
# Use SPATIAL denoise ONLY.
#dclip=dclip.MaxContrast(Samples=64,Gamma=1.0).VagueDenoiser(threshold=0.8,method=1,nsteps=6,chromaT=0,interlaced=false) # SLOWISH
#dclip=dclip.MaxContrast(Samples=64,Gamma=1.0).hqdn3d(2.0, 0.0,0.0,0.0,0) # A bit FASTER

###
### Show Metrics ONLY
DIM=False # Dim/darken area outside of the x,y,w,h search area. A little faster with Dim==False when showing metrics only.
SHOWMISS =true # Show block 'Marker' for greatest moving DROP block (miss), (markers never shown for dupes).
MISSCOLOR =$AAFF00 # Color, block 'Marker' for greatest DROP block (when SHOWMISS==True).
HITCOLOR =$FFFF44 # Color, block 'Marker' for greatest KEEP block (hit).
HOLDCOLOR =$FF8800 # Color, block 'Marker' for HOLD block (Miss converted to HIT due to Miss proximity to previous Hit).
VERBOSE=True # Show additional metrics, Th, dTh, BLK Args


worked incredibly well
With RT_Stats v2.0, have implemented RT_FrameMovement (I think may have been implemented as RT_LumaMovement, ie luma only) in version that your tried,
yep, it works damned lovely :)

The Block marker in yellow show area of max change/movement.

EDIT:
HOLD frames are combination of all KEEP frames and, DROP frames where block with greatest difference is in close proximity to previous
KEEP frame block with greatest difference (ie there seems to be possible movement very near previously identified movement).


I remember about time I did the above frame cap, that a bloke walking down the street went behind a car, and you could only just see the top of his hat above the car/van bobbing up and down, and the HOLD frame thing above managed to track only a few pixels of the oscillating hat until he emerged a few yards on, was quite fascinating to see it actually working profoundly well, in the words of Harry Potter, "I Love Magic", :)

`Orum
3rd April 2018, 03:19
Yoda wanted to list dupe frames and temporarily remove them for MC processing, and then replace with identical dupes from the MC processed clip.
Interesting. Why does he want the duplicates put back in? Does some playback device not support VFR?

Edit: Thinking about this, it shouldn't be too hard to do; just parse the timestamp file and insert duplicate frames when necessary.
@ Orum, hope you can do better than this with your new plug in devs forum, good luck.
Heh, thanks for the vote of confidence! Anyway if you give it a shot let me know what you think. It really needs block-level metrics but that should be coming very soon (probably in the next release).

StainlessS
3rd April 2018, 08:11
Interesting. Why does he want the duplicates put back in? Does some playback device not support VFR?

I have never played with vfr, but I'm guessin' that he wants to put back [EDIT: Identical] dupes so that some other vfr stuff can then work with the
inserted identical duplicates to produce the vfr 'thingy'.

Here is a working demo for removing the dupes for some MC processing of only non-dupes, and then to replace the removed dups with
identical dups from the newly processed MC result, I'm gonna add the "MakeReDupCmd()" functionality to FrameSel plug.
https://forum.doom9.org/showthread.php?p=1832814#post1832814

Looking forward to seeing what your plug can do, Peace bro :)

Motenai Yoda
7th April 2018, 22:58
Nope just leave it cfr as is, since I don't like how most tdecimate vfr looks, and "true" vfr as dedup ones doesn't even play on a lot of devices/players
I tried it and work well, I'm looking forward to Orum's plug too

StainlessS
4th August 2018, 15:12
Post #1 of Many.

Duplicity2() v2.13 (see post #1 for docs)

Function Duplicity2(clip c,"Mode",Float "ThG",Float "ThB", Int "ThP",Float "IgP",Int "ThK",
\ Int "MaxDupLen",Int "LagMax",Int "MaxInterp",
\ int "BlkW",int "BlkH",int "OLapX",Int "OLapY",
\ Int "X",Int "Y",Int"W",Int "H",Float "CW",Bool "ChromaI",Bool "AltScan",
\ Int "SPad", Int "SSharp", Int "SRFilter", [* MSuper *]
\ Int "ABlkSize", Int "AOverlap", Int "ASearch",Int "ADct", [* MAnalyse *]
\ Int "RBlkSize", Int "ROverlap", Int "RthSAD", [* MRecalculate *]
\ Float "Iml", Bool "IBlend", Int "IthSCD1", Int "IthSCD2", [* MFlowInter *]
\ Int "OthSCD1",Int "OthSCD2", [* Duplicates Detection Override *]
\ String "OverRide",String "Frames",Bool "Ranges",Bool "FrameAsRange",
\ Bool "Show",Bool "Verb",Bool "ShowBlk",Bool "Dim",Bool "ShowDot",
\ Bool "InterpFast",String "DBase"
\ ){

Function D2_Hit_Marker(int W, Int H, Bool "Hit", Int "BW", Int "BH",Int "PW",Int "PH",Bool "YV12",Bool "Mod2") {
Hit=Default(hit,False) BW=Max(Default(BW,W/8),1) BH=Max(Default(BH,H/8),1)
BW2=(W>4)?BW*2:BW BH2=(H>4)?BH*2:BH
PW=Max(Default(PW,BW/8),1) PH=Max(Default(PH,BH/8),1) is26 = VersionNumber>=2.6
YV12=(!is26) ? True : Default(YV12,False) Mod2=Default(Mod2,True) Mod = (YV12||Mod2) ? 2 : 1
CanvasW=(W+Mod-1)/Mod*Mod CanvasH=(H+Mod-1)/Mod*Mod
Rpn= RT_String("x %d < x %d >= | y %d < | y %d >= | x %d < x %d >= | & y %d < y %d >= | & ",BW,W-BW,BH,H-BH,BW2,W-BW2,BH2,H-BH2)
Rpn= (Hit) ? Rpn + RT_String("x %d < x %d >= | y %d < | y %d >= | | ",PW,W-PW,PH,H-PH) : Rpn
Rpn= Rpn + RT_String("x %d < y %d < & & 255 0 ?",W,H)
Blankclip(width=CanvasW,height=CanvasH,Length=1,pixel_type=YV12?"YV12":"Y8").Killaudio
return mt_lutspa(relative = false,yExpr=Rpn, chroma = "-128")
}
c myName="Duplicity2: " VER=2.13
Assert(RT_Version() >= 1.99911,RT_String("%sNeed RT_Stats v2.00Beta11(%s)",myName,RT_VersionString))
IsAvsPlus=(FindStr(UCase(versionString),"AVISYNTH+")!=0) HasGScript=RT_FunctionExist("GScript")
HasGRunt =RT_FunctionExist("GScriptClip") HasMvTools=RT_FunctionExist("MSuper")
HasMaskTools=RT_FunctionExist("MT_Lutxy") HasRemoveGrain=RT_FunctionExist("RemoveGrain")
HasCallCmd = RT_FunctionExist("CallCmd") IsAvs26=VersionNumber>=2.6
###
Mode = Default(Mode,0)
ThG=Default(ThG,1.0) ThB=Default(ThB,ThG*2.0) ThP=Default(ThP,64) IgP=Default(IgP,0.0)
ThK=Default(ThK,7) MaxDupLen=default(MaxDupLen,9) LagMax=default(LagMax,MaxDupLen) MaxInterp = Default(MaxInterp,9)
BlkW=Default(BlkW,64) BlkH=Default(BlkH,BlkW) OLapX=Default(OLapX,BlkW/2) OLapY=Default(OLapY,BlkH/2)
X=default(X,0) Y=default(Y,0) W=default(W,0) H=default(H,0)
CW=Default(CW,0.0) ChromaI=Default(ChromaI,False) AltScan=Default(AltScan,False)
SPad = Default(SPad,16) SSharp = Default(SSharp,1) SRFilter= Default(SRFilter,4)
ABlkSize = Default(ABlkSize,16) AOverlap= Default(AOverlap,4) ASearch = Default(ASearch,3) ADct = Default(ADct,0)
RBlkSize = Default(RBlkSize,8) ROverlap= Default(ROverlap,2) RthSAD = Default(RthSAD,100)
Iml = Default(Iml,200.0) IBlend = Default(IBlend,True) IthSCD1 = Default(IthSCD1,400) IthSCD2= Default(IthSCD2,130)
OthSCD1 = Default(OthSCD1,400) OthSCD2 = Default(OthSCD2,130)
Override=Default(OverRide,"") Frames=Default(Frames,"Frames.txt") Ranges=Default(Ranges,True) FrameAsRange=Default(FrameAsRange,False)
Show=Default(Show,True) Verb=Default(Verb,True)
Showblk=Default(ShowBlk,true) Dim=Default(Dim,true) ShowDot=Show?Default(ShowDot,False):False
InterpFast=Default(InterpFast,True) DBase=Default(DBase,"")
####
Assert(0 <= Mode <= 2,RT_String("%s0 <= Mode(%d) <= 2",myName,Mode))
Assert(1 <= MaxDupLen,RT_String("%s1 <= MaxDupLen(%d)",myName,MaxDupLen))
Assert(1 <= LagMax,RT_String("%s1 <= LagMax(%d)",myName,LagMax))
Assert(0 <= MaxInterp <= 9,RT_String("%s0 <= MaxInterp(%d) <= 9",myName,MaxInterp))
Assert(IsAvsPlus || HasGScript,RT_String("%sNeed either GScript or AVS+",myName))
Assert(HasGRunt,RT_String("%sNeed GRunt:-https://forum.doom9.org/showthread.php?t=139337 ",myName))
Assert(HasMVTools,RT_String("%sNeed MvTools2:-http://forum.doom9.org/showthread.php?t=131033",myName))
Assert(HasMaskTools,RT_String("%sNeed MaskTools",myName))
Assert(Mode!=2 || MaxInterp==0 || HasRemoveGrain,RT_String("%sNeed RemoveGrain",myName))
Assert(IsYV12||(IsAvs26&&(IsY8||IsYV16||IsYV24)),RT_String("%sOnly Standard v2.6 Planar Supported (excepting YV411)",myname))
MaxInterp=Min(MaxInterp,MaxDupLen)
W = (W > 0) ? (W + X) - Width : W H = (H > 0) ? (H + Y) - Height : H # Make -ve relative width,height
X = (X+3) / 4 * 4 Y = (Y+3) / 4 * 4 # Round UP (inwards) Mod 4
W = (W-3) / 4 * 4 H = (H-3) / 4 * 4 # Round DOWN(inwards) Mod 4
W = Width - X + W H = Height - Y + H # +ve width,height
DC=Crop(X,Y,W,H) BlkW=Min(DC.Width,BlkW) BlkH=Min(DC.Height,BlkH)
(Show && !ShowDot && DIM && Mode==0 && (W!=Width || H!=Height)) ? levels(16,1.0,235,16+48,235-48,Coring=False).Overlay(DC,x=X,y=Y) : Last
DB=(DBase=="") ? RT_GetFullPathName("~@@@_"+RT_LocalTimeString+".DB") : RT_GetFullPathName(DBase)
FuncS="""
Function EndOfSceneClip(clip c,Int "thSCD1",Int "thSCD2") { # All Luma Samples set 255 at EOS
thSCD1=Default(thSCD1,400) thSCD2=Default(thSCD2,130)
sup=c.MSuper(pel=1,sharp=0,rfilter=2,hpad=16, vpad=16)
bv=sup.MAnalyse(isb=true, delta=1,blksize=16)
Return c.MSCDetection(bv,thSCD1=thSCD1,thSCD2=thSCD2)
}
###
Function ChrIsNul(String S) {return RT_Ord(S)== 0}
Function ChrIsHash(String S) {return RT_Ord(S)==35}
Function ChrIsStar(String S) {return RT_Ord(S)==42}
Function ChrIsComma(String S) {return RT_Ord(S)==44}
Function ChrIsHyphen(String S) {return RT_Ord(S)==45}
Function ChrIsDigit(String S) {C=RT_Ord(S) return C>=48&&C<=57}
Function ChrEatWhite(String S) {i=1 C=RT_Ord(S,i) While(C==32||C>=8&&C<=13) {i=i+1 C=RT_Ord(S,i)} return i>1?MidStr(S,i):S}
Function ChrEatDigits(String S) {i=1 C=RT_Ord(S,i) While(C>=48&&C<=57) {i=i+1 C=RT_Ord(S,i)} return i>1?MidStr(S,i):S}
###
Function Fn@@@(clip c,clip dc,String DB,Int Mode,Float ThG,Float ThB,Int ThP,Float IgP,Int ThK,
\ Int MaxDupLen, Int LagMax,Int MaxInterp,
\ Int BlkW,Int BlkH,Int OLapX,Int OLapY,Int X,Int Y,Float CW,Bool ChromaI,Bool Altscan,
\ Int OthSCD1,Int OthSCD2,String Frames,Bool Ranges,Bool FrameAsRange,
\ Bool Show,Bool Verb,Bool ShowBlk,Bool ShowDot,Bool InterpFast
\) {
c n=current_frame FC=c.FrameCount
Stat=RT_DBaseGetField(DB,n,FLD_STAT@@@)
if(Stat == 0) { # In here if unvisited
if(RT_FrameDifference(dc,dc,n=n,n2=n-1,ChromaWeight=CW,chromai=ChromaI) > ThG) { # dif to prev
# Uniq_KOverride OR Unique
Stat=(ThK>0 && RT_YPlaneMinMaxDifference(dc,n=n,Threshold=0.2)<ThK)?FLG_UK@@@:FLG_UU@@@
RT_DBaseSetField(DB,n,FLD_STAT@@@,Stat)
Global nDone@@@=nDone@@@+1
if(nDone@@@==FC) { RT_DBaseSetId(DB,1,FC) }
} else {
# MUST scan backwards to find frame that is Unique to its predecessor(we're not necessarily a dupe of that frame)
StartU = -1
for(i=n-1,0,-1) { # Exit with i==-1 (should NEVER HAPPEN, frame 0 is Unique)
if(RT_DBaseGetField(DB,i,FLD_STAT@@@)==0) { # Stat Unknown
if(RT_FrameDifference(dc,dc,n=i,n2=i-1,ChromaWeight=CW,chromai=ChromaI) > ThG) {
StartU=i
# Set Unique/Uniq_KOverride Stat
RT_DBaseSetField(DB,StartU,FLD_STAT@@@,(ThK>0&&RT_YPlaneMinMaxDifference(dc,n=i,Threshold=0.2)<ThK)?FLG_UK@@@:FLG_UU@@@)
Global nDone@@@=nDone@@@+1
if(nDone@@@==FC) { RT_DBaseSetId(DB,1,FC) }
i = -1 # Break, Exit with i==-2
}
} Else { StartU=i i = -2 } # Break, Exit with i==-3
}
# Assert(i!=-1,myName@@@+"Uniq Not Found backwards")
EndU = FC
for(i=n+1,FC-1) { # Exit with i==FC (should NEVER HAPPEN, last frame is Unique)
if(RT_DBaseGetField(DB,i,FLD_STAT@@@)==0) { # Stat Unknown
if(RT_FrameDifference(dc,dc,n=i,n2=i-1,ChromaWeight=CW,chromai=ChromaI) > ThG) {
EndU=i
# Set Unique/Uniq_KOverride Stat
RT_DBaseSetField(DB,EndU,FLD_STAT@@@,(ThK>0 && RT_YPlaneMinMaxDifference(dc,n=i,Threshold=0.2)<ThK)?FLG_UK@@@:FLG_UU@@@)
Global nDone@@@=nDone@@@+1
if(nDone@@@==FC) { RT_DBaseSetId(DB,1,FC) }
i = FC # Break, Exit with i==FC=+1
}
} Else { EndU=i i = FC+1 } # Break, Exit with i==FC+2
}
# Assert(i > FC,myName@@@+"Uniq Not Found forwards")
Anchor=StartU
for(i=StartU+1,EndU-1) {
Count=1 Stat=0
if(ThK>0 && RT_YPlaneMinMaxDifference(dc,n=i,Threshold=0.2)<ThK) {
Anchor=Max(Anchor,i-LagMax)
RT_DBaseSetField(DB,i,0,FLG_NUK@@@,StartU,EndU,Anchor,0) # Count Field NOT SET
for(j=i+1,EndU-1) {
Anchor=j-1
if(RT_YPlaneMinMaxDifference(dc,n=j,Threshold=0.2)<ThK) {
Count=Count+1
RT_DBaseSetField(DB,j,0,FLG_NUK@@@,StartU,EndU,Anchor,j-i) # Count Field NOT SET
} else { j=EndU }
}
} Else {
Anchor=Max(Anchor,i-LagMax)
if((RT_FrameMovement(dc,dc,n=i,n2=Anchor,ChromaWeight=CW,AltScan=AltSCan,
\ ChromaI=ChromaI,BlkW=BlkW,BlkH=BlkH,OLapX=OLapX,OLapY=OLApY,BlkTh=ThB)>ThB) ||
\(RT_LumaPixelsDifferent(dc,dc,n=i,n2=Anchor,Thresh=ThP)>IgP) ||
\(RT_FrameDifference(dc,dc,n=i,n2=Anchor,ChromaWeight=CW,chromai=ChromaI)> ThG)
\) { # Start of LoMotion SubSequence
RT_DBaseSetField(DB,i,0,FLG_LM@@@,StartU,EndU,Anchor,0) # Count Field NOT SET
for(j=i+1,EndU-1) {
Anchor=j-1
if(
\ (
\ (RT_FrameMovement(dc,dc,n=j,n2=Anchor,ChromaWeight=CW,AltScan=AltSCan,
\ ChromaI=ChromaI,BlkW=BlkW,BlkH=BlkH,OLapX=OLapX,OLapY=OLApY,BlkTh=ThB)>ThB) ||
\ (RT_LumaPixelsDifferent(dc,dc,n=j,n2=Anchor,Thresh=ThP)>IgP) ||
\ (RT_FrameDifference(dc,dc,n=j,n2=Anchor,ChromaWeight=CW,chromai=ChromaI)>ThG)
\ ) && (ThK<=0 || RT_YPlaneMinMaxDifference(dc,n=j,Threshold=0.2)>=ThK)
\ ) {
Count=Count+1
RT_DBaseSetField(DB,j,0,FLG_LM@@@,StartU,EndU,Anchor,j-i) # Count Field NOT SET
} Else { j=EndU }
}
} Else { # Start of Dupe SubSequence
RemAnchor=Anchor # Remember Anchor at start of dupe run
for(j=i+1,EndU-1) {
Anchor=Max(Anchor,j-LagMax)
if(
\ (RT_FrameMovement(dc,dc,n=j,n2=Anchor,ChromaWeight=CW,AltScan=AltSCan,
\ ChromaI=ChromaI,BlkW=BlkW,BlkH=BlkH,OLapX=OLapX,OLapY=OLApY,BlkTh=ThB)<=ThB) &&
\ (RT_LumaPixelsDifferent(dc,dc,n=j,n2=Anchor,Thresh=ThP)<=IgP) &&
\ (RT_FrameDifference(dc,dc,n=j,n2=Anchor,ChromaWeight=CW,chromai=ChromaI) <= ThG) &&
\ (ThK<=0 || RT_YPlaneMinMaxDifference(dc,n=j,Threshold=0.2)>=ThK)
\ ) {
Count=Count+1
} Else { j=EndU }
}
Anchor=RemAnchor # restore duprun anchor
if(Count>MaxDupLen) {Stat=FLG_DS@@@} # MaxDupLen OverRide
Else {
if(Mode!=1 && i+Count==EndU && OthSCD2 < 255 && OthSCD1 < 8*8*255) {
Tmp_c = c.Trim(i-1,-1) + c.Trim(i+Count,-1)
Stat=(EndOfSceneClip(Tmp_c,OthSCD1,OthSCD2).RT_AverageLuma(n=0,w=1,h=1).Int != 0)?FLG_DE@@@:FLG_DUP@@@
} Else {Stat=FLG_DUP@@@}

StainlessS
4th August 2018, 15:13
Post #2 of Many.


if(Stat==FLG_DUP@@@) {
if(Frames!="") {
if(!Ranges) { for(j=0,Count-1) { RT_WriteFile(Frames,"%d",i+j,Append=True) }}
Else if(Count>1) { RT_WriteFile(Frames,"%d,%d",i,i+Count-1,Append=True)}
Else if(!FrameAsRange) { RT_WriteFile(Frames,"%d",i,Append=True)}
Else if(i==0 && Count==1) { RT_WriteFile(Frames,"%d,-1",i,Append=True)}
Else { RT_WriteFile(Frames,"%d,%d",i,i,Append=True)}
}
if(Show) {
Global nDupeSeq@@@=nDupeSeq@@@+1
if(Count > DupeLenMax@@@) {Global DupeLenMax@@@=Count Global DupePosMax@@@=i}
Global nDupes@@@=nDupes@@@+Count
}
}
}
for(j=i,i+Count-1) {
Anchor=Max(Anchor,j-LagMax)
RT_DBaseSetField(DB,j,0,Stat,StartU,EndU,Anchor,j-i) # Count Field NOT SET
}
}
RT_DBaseSetField(DB,i,FLD_COUNT@@@,Count) # set SubSequence Start count field
}
i=i+Count-1 # Last K frame (next time for/next incr to i+1)
} # end for i
seqLen=(EndU-StartU-1)
Global nDone@@@=nDone@@@+seqLen
if(nDone@@@==FC) { RT_DBaseSetId(DB,1,FC) }
if(Show) {
Global nSeq@@@=nSeq@@@+1
if(seqLen>MaxSeqLen@@@) { Global MaxSeqLen@@@=seqLen Global MaxSeqPos@@@=StartU+1 }
}
Stat=RT_DBaseGetField(DB,n,FLD_STAT@@@) # Get Status of 1st SubSequence
} # End, If(pG > ThG)
} # End Stat==0
###
if(Show || (Mode>0 && Stat==FLG_DUP@@@)) {
Index=RT_DBaseGetField(DB,n,FLD_INDEX@@@)
SStart=n-Index # Start of Current SubSequence
Count=RT_DBaseGetField(DB,SStart,FLD_COUNT@@@) # Count stored only in first Record of Sub Sequence
if(Mode == 1 && Stat==FLG_DUP@@@) { # Mode==1, Exact Dupe
c.Trim(SStart-1,-1)
ShowDot?RT_Subtitle(DotE@@@):NOP
} Else if(Mode==2 && Stat==FLG_DUP@@@) { # Mode==2, Interpolate/Blend
if(Count > MaxInterp) { # Blend Morph
Weight = (Index + 1).Float / (Count+1)
Merge(c.Trim(SStart-1,-1),c.Trim(SStart+Count,-1), Weight)
ShowDot?RT_Subtitle(DotB@@@):NOP
} else if(InterpFast) { # Interpolate
if (Count==1) { I10@@@ }
Else if (Count==2) { Index==0?I20@@@:I21@@@ }
Else if (Count==3) { Index==0?I30@@@:(Index==1)?I31@@@:I32@@@ }
Else if (Count==4) { Index==0?I40@@@:(Index==1)?I41@@@:(Index==2)?I42@@@:I43@@@ }
Else if (Count==5) { Index==0?I50@@@:(Index==1)?I51@@@:(Index==2)?I52@@@:(Index==3)?I53@@@:I54@@@ }
Else if (Count==6) { Index==0?I60@@@:(Index==1)?I61@@@:(Index==2)?I62@@@:(Index==3)?I63@@@:(Index==4)?I64@@@:I65@@@ }
Else if (Count==7) { Index==0?I70@@@:(Index==1)?I71@@@:(Index==2)?I72@@@:(Index==3)?I73@@@:(Index==4)?I74@@@:
\(Index==5)?I75@@@:I76@@@ }
Else if (Count==8) { Index==0?I80@@@:(Index==1)?I81@@@:(Index==2)?I82@@@:(Index==3)?I83@@@:(Index==4)?I84@@@:
\ (Index==5)?I85@@@:(Index==6)?I86@@@:I87@@@ }
Else if (Count==9) { Index==0?I90@@@:(Index==1)?I91@@@:(Index==2)?I92@@@:(Index==3)?I93@@@:(Index==4)?I94@@@:
\ (Index==5)?I95@@@:(Index==6)?I96@@@:(Index==7)?I97@@@:I98@@@ }
ShowDot?RT_Subtitle(DotI@@@):NOP
} Else {
fillMax=3
LS=Max(SStart-fillMax,0) RS=SStart+Count # Range limit for trim (cannot eg trim prior frame 0)
LCnt=SStart-LS RCnt=Min(FC-RS,fillMax)
Tmp_c = c.Trim(LS,-LCnt) + c.Trim(RS,-RCnt) # Dupes trimmed out, with ideally two frames before & two after.
Prefilt=Tmp_c.RemoveGrain(22)
Super=Tmp_c.MSuper(hpad=SPad@@@,vpad=SPad@@@,levels=1,sharp=SSharp@@@,rfilter=SRFilter@@@)
Superfilt=Prefilt.MSuper(hpad=SPad@@@,vpad=SPad@@@,sharp=SSharp@@@,rfilter=SRFilter@@@)
bv=Superfilt.MAnalyse(isb=true ,blksize=ABlkSize@@@,overlap=AOverLap@@@,search=ASearch@@@,delta=1,dct=ADct@@@)
fv=Superfilt.MAnalyse(isb=False ,blksize=ABlkSize@@@,overlap=AOverLap@@@,search=ASearch@@@,delta=1,dct=ADct@@@)
if(RBlkSize@@@>0) {
bv=Super.MRecalculate(bv,blksize=RBlkSize@@@,overlap=ROverLap@@@,thSAD=RthSAD@@@)
fv=Super.MRecalculate(fv,blksize=RBlkSize@@@,overlap=ROverLap@@@,thSAD=RthSAD@@@)
}
Tmp_I=Tmp_c.MFlowInter(Super,bv,fv,time=100.0*(Index+1)/(Count+1),ml=Iml@@@,blend=IBlend@@@,thSCD1=IthSCD1@@@,thSCD2=IthSCD2@@@)
Tmp_I.Trim(LCnt-1,-1) # NO SHIFT, fixed frame @ LCnt-1 ie same as Left PreDupe frame
ShowDot?RT_Subtitle(DotI@@@):NOP
} # End, Count > MaxInterp
} Else If(Mode==0 && Stat==FLG_DUP@@@ && ShowDot) {
ShowDot?RT_Subtitle(DotD@@@):NOP
}
if(Show&&!ShowDot) {
pG = RT_FrameDifference(dc,dc,n=n,n2=n-1,ChromaWeight=CW,chromai=ChromaI) # dif to prev
pB = RT_FrameMovement(dc,dc,n=n,n2=n-1,ChromaWeight=CW,AltScan=AltSCan,ChromaI=ChromaI,
\ BlkW=BlkW,BlkH=BlkH,OLapX=OLapX,OLapY=OLApY,BlkTh=ThB,Prefix="p@@@")
pP = RT_LumaPixelsDifferent(dc,dc,n=n,n2=n-1,Thresh=ThP)
kG = RT_YPlaneMinMaxDifference(dc,n=n,Threshold=0.2)
if(Stat<=FLG_UU@@@&&Stat>=FLG_OO@@@) { # Unique-ish (Anchor not tested)
if (ShowBlk && pB>0.0) {
if(pB>ThB) { Overlay(HitMrk@@@, x=X+p@@@XOFF,y=Y+p@@@YOFF,Mask=HitMsk@@@, Mode="Blend",output=OutCS@@@) }
Else { Overlay(MissMrk@@@,x=X+p@@@XOFF,y=Y+p@@@YOFF,Mask=MissMsk@@@,Mode="Blend",output=OutCS@@@) }
}
if(Stat==FLG_OO@@@) { RT_Subtitle(FmtOO@@@,n,pG,pB,pP*100.0/255.0,kG) } # 1 User Override FLG_OO@@@
Else if(Stat==FLG_UK@@@) { RT_Subtitle(FmtUK@@@,n,pG,pB,pP*100.0/255.0,kG) } # 2 K Override
Else if(Stat==FLG_UU@@@) { RT_Subtitle(FmtUU@@@,n,(pB>ThB)?45:76,(pP>igP)?45:76,pG,pB,pP*100.0/255.0,kG) } # 3 Unique
} Else {
StartU=RT_DBaseGetField(DB,n,FLD_START@@@)
EndU=RT_DBaseGetField(DB,n,FLD_END@@@)
Anchor=RT_DBaseGetField(DB,n,FLD_ANCHOR@@@)
UIndex=n-StartU # LoMo Index relative StartU (1 relative)
UCount=EndU-StartU-1 # Total LoMo sequence count
aG=RT_FrameDifference(dc,dc,n=n,n2=Anchor,ChromaWeight=CW,chromai=ChromaI)
aB=RT_FrameMovement(dc,dc,n=n,n2=Anchor,ChromaWeight=CW,AltScan=AltSCan,ChromaI=ChromaI,
\ BlkW=BlkW,BlkH=BlkH,OLapX=OLapX,OLapY=OLApY,BlkTh=ThB,Prefix="a@@@")
aP=RT_LumaPixelsDifferent(dc,dc,n=n,n2=Anchor,Thresh=ThP)
if (ShowBlk && aB>0.0) {
if(aB>ThB) { Overlay(HitMrk@@@, x=X+a@@@XOFF,y=Y+a@@@YOFF,Mask=HitMsk@@@, Mode="Blend",output=OutCS@@@) }
Else { Overlay(MissMrk@@@,x=X+a@@@XOFF,y=Y+a@@@YOFF,Mask=MissMsk@@@,Mode="Blend",output=OutCS@@@) }
}
if(Stat==FLG_LM@@@) { # LoMo
GCol=(aG>ThG)?33:76 BCol=(aB>ThB)?33:76 PCol=(aP>IgP)?33:76
RT_Subtitle(FmtLM@@@,n,GCol,BCol,PCol,UIndex,UCount,Index+1,Count,StartU,EndU,
\ pG,pB,pP*100.0/255.0,GCol==33?33:45,aG,BCol==33?33:45,aB,PCol==33?33:45,aP*100.0/255.0,kG,Anchor,n-Anchor)
} Else if(Stat==FLG_DUP@@@) { # Dupe
ch=Mode==2?(Count>MaxInterp?66:73):68
RT_Subtitle(FmtDUP@@@,n,UIndex,UCount,ch,Index+1,Count,StartU,EndU,pG,pB,pP*100.0/255.0,aG,aB,aP*100.0/255.0,kG,Anchor,n-Anchor)
} Else if(Stat==FLG_DE@@@) { # Dupe_EndOfScene_Override FLG_DE@@@
RT_Subtitle(FmtDE@@@,n,UIndex,UCount,Index+1,Count,StartU,EndU,pG,pB,pP*100.0/255.0,aG,aB,aP*100.0/255.0,kG,Anchor,n-Anchor)
} Else if(Stat==FLG_NUK@@@) { # Dupe_KOverride FLG_NUK@@@
RT_Subtitle(FmtNUK@@@,n,UIndex,UCount,Index+1,Count,StartU,EndU,pG,pB,pP*100.0/255.0,aG,aB,aP*100.0/255.0,kG,Anchor,n-Anchor)
} Else if(Stat==FLG_DS@@@) { # Dupe_MaxDupLen_Override FLG_DS@@@
RT_Subtitle(FmtDS@@@,n,UIndex,UCount,Index+1,Count,StartU,EndU,pG,pB,pP*100.0/255.0,aG,aB,aP*100.0/255.0,kG,Anchor,n-Anchor)
} Else {
Assert(False,RT_String("%s[%d] Error Unknwn Stat(%d)",myName@@@,n,Stat))
}
}
if(Verb) {
EstFps=(nDone@@@-nDupes@@@)*FrameRate/nDone@@@
RT_SubTitle(vFmt@@@,
\ Mode,ThG,ThB,ThP,IgP*100.0/255.0,ThK,MaxDupLen,MaxInterp,LagMax,nSeq@@@,MaxSeqLen@@@,MaxSeqPos@@@,
\ nDupes@@@,DupeLenMax@@@,DupePosMax@@@,nDupeSeq@@@,nDone@@@*100.0/FC,EstFPS,Align=1)
}
}
} # End, if(Show || (Mode>0 && Stat==FLG_DUP@@@))
Return Last
}

StainlessS
4th August 2018, 16:13
Post #3 of many.



if(Frames!="") {
Frames=RT_GetFullPathName(Frames) RT_FileDelete(Frames)
RT_WriteFile(Frames,"###\n# Duplicate frames file. [ Generated by Duplicity2() ]\n###\n\n")
}
RT_DBaseAlloc(DB,FrameCount,"iiiiii")
### DBase Fields:-
Global FLD_STAT@@@ = 0 # Holds Status FLGS
Global FLD_START@@@ = 1 # Unique Start Frame
Global FLD_END@@@ = 2 # Unique End Frame
Global FLD_ANCHOR@@@ = 3 # Anchor Frame
Global FLD_INDEX@@@ = 4 # Index into Count (0 Relative, 0->Count-1)
Global FLD_COUNT@@@ = 5 # Sequence Frame Count
### Status Flags in Field FLD_STAT@@@
Global FLG_OO@@@ = 1 # User Override
Global FLG_UK@@@ = 2 # K Override
Global FLG_UU@@@ = 3 # Unique Frame
Global FLG_NUK@@@ = 4 # Non Unique Sequence K Override
Global FLG_LM@@@ = 5 # LoMotion Frame
Global FLG_DS@@@ = 6 # Static Sequence [detected as duplicates but Longer than MaxDupLen]
Global FLG_DE@@@ = 7 # Duplicate Sequence is followed by Scene Change (will NOT occar when Mode==1)
Global FLG_DUP@@@ = 8 # Duplicate Sequence
###
RT_DBaseSetField(DB,0,FLD_STAT@@@,FLG_OO@@@) RT_DBaseSetField(DB,FrameCount-1,FLD_STAT@@@,FLG_OO@@@) # Set first and Last Frames to Override Frame
RT_DBaseSetId(DB,0,VER)
Global nDone@@@=2 # Start and End frames already done
Global nDupes@@@=0 Global nDupeSeq@@@=0 Global DupeLenMax@@@=0 Global DupePosMax@@@=0
Global nSeq@@@=0 Global MaxSeqLen@@@=0 Global MaxSeqPos@@@=0
if(OverRide!="") {
if(ChrIsStar(Override)) {
OverRide=MidStr(OverRide,2)
} else {
Assert(Exist(OverRide),RT_String("%sOverRide File does not exist",myName))
OverRide=RT_ReadTxtFromFile(Override)
}
LINES=RT_TxtQueryLines(OverRide)
for(i=0,LINES-1) {
SS=ChrEatWhite(RT_TxtGetLine(Override,i))
S=SS
if(!ChrIsNul(S) && !ChrIsHash(S)) {
if(ChrIsDigit(S)) {
StartF = S.RT_NumberValue
EndF=StartF
S=S.ChrEatDigits.ChrEatWhite
if(ChrIsComma(S)){S=S.MidStr(2).ChrEatWhite}
IsNeg = ChrIsHyphen(S)
if(IsNeg){S=S.MidStr(2).ChrEatWhite}
if(ChrIsDigit(S)) {
EndF=S.RT_NumberValue
S=S.ChrEatDigits
if(EndF==0) {EndF=FrameCount-1 }
Else if(IsNeg) {EndF=StartF+(EndF)-1}
Assert(StartF<=EndF,RT_String("%sOverRide: Error@Line_%d, StartFrame(%d) > EndFrame(%d)\n%s",myName,i+1,StartF,EndF,SS))
} Else if(IsNeg) {Assert(False,RT_String("%sOverRide: Error@Line_%d, Expecting End Frame\n%s",myName,i+1,SS))}
Assert(EndF<FrameCount,RT_String("%sOverRide: Error@Line_%d, EndFrame(%d) Out Of Clip\n%s",myName,i+1,EndF,SS))
RT_DebugF("OverRiding Range %d,%d",StartF,EndF,name=myName)
for(n=StartF,EndF) {
if(n!=0 && n!= FrameCount-1) {
RT_DBaseSetField(DB,n,FLD_STAT@@@,FLG_OO@@@)
Global nDone@@@=nDone@@@+1
}
}
}
S=ChrEatWhite(S)
if(ChrIsHash(S)) {S=""}
Assert(ChrIsNul(S),RT_String("%sOverride: Error@Line_%d, *** NON-PARSE ***\n'%s'",myName,i+1,SS))
}
}
}
####
Global myName@@@ = myName
if(Mode==2 && MaxInterp>0) {
if(InterpFast) {
Prefilt = c.RemoveGrain(22)
Super = c.MSuper(hpad=SPad,vpad=SPad,levels=1,sharp=SSharp,rfilter=SRFilter) # One level is enough for MRecalculate
Superfilt= Prefilt.MSuper(hpad=SPad,vpad=SPad,sharp=SSharp,rfilter=SRFilter) # All levels for MAnalyse
For(i=1, MaxInterp) {
Eval(RT_String("bv=Superfilt.MAnalyse(isb=true ,blksize=ABlkSize,overlap=AOverLap,search=ASearch,delta=%d,dct=ADct)",i+1))
Eval(RT_String("fv=Superfilt.MAnalyse(isb=false,blksize=ABlkSize,overlap=AOverLap,search=ASearch,delta=%d,dct=ADct)",i+1))
if(RBlkSize>0) {
Eval(RT_String("bv=Super.MRecalculate(bv,blksize=RBlkSize,overlap=ROverLap,thSAD=RthSAD)"))
Eval(RT_String("fv=Super.MRecalculate(fv,blksize=RBlkSize,overlap=ROverLap,thSAD=RthSAD)"))
}
for(j=1,i) {
Eval(RT_String("Global I%d%d@@@=c.MFlowInter(Super,bv,fv,time=100.0*%d/%d," +
\ "ml=Iml,blend=IBlend,thSCD1=IthSCD1,thSCD2=IthSCD2).SelectEvery(1,%d).Trim(0,-c.FrameCount)", i,j-1, j,i+1,-j))
}
}
} Else {
Global SPad@@@=SPad Global SSharp@@@=SSharp Global SRFilter@@@=SRFilter
Global ABlkSize@@@=ABlkSize Global AOverLap@@@=AOverLap Global ASearch@@@=ASearch Global ADct@@@=ADct
Global RBlkSize@@@=RBlkSize Global ROverLap@@@=ROverLap Global RthSAD@@@=RthSAD
Global Iml@@@=Iml Global IBlend@@@=IBlend Global IthSCD1@@@=IthSCD1 Global IthSCD2@@@=IthSCD2
}
}
###
Global HitMsk@@@ = D2_Hit_Marker(BlkW,BlkH,true)
Global HitMrk@@@ = HitMsk@@@.BlankClip(Color=$FFCC00,pixel_type="YV12")
Global MissMsk@@@ = D2_Hit_Marker(BlkW,BlkH,false)
Global MissMrk@@@ = MissMsk@@@.BlankClip(Color=$00FF00,pixel_type="YV12")
Global OutCS@@@=IsYV12?"YV12":IsY8?"Y8":IsYV16?"YV16":"YV24"
####
Global FmtOO@@@="%d] \a!O\aLKSE\a-:\aLGBP:ULD\a- \npG=%9.6f : pB=%9.6f : pP%%=%9.6f\n{K=%d}"
Global FmtUK@@@="%d] \aLO\a!K\aLS\a-:\aLGBP\a-:\aLULD\a-\n\a!pG=%9.6f\a- : pB=%9.6f : pP%%=%9.6f\n{K=%d}"
Global FmtUU@@@="%d] \aLOKSE\a-:\a!G\a%cB\a%cP\a-:U\aLLD\a- \n\a!pG=%9.6f\a- : pB=%9.6f : pP%%=%9.6f\n{K=%d}"
Global FmtLM@@@="%d] \aLOKSE\a-:\a%cG\a%cB\a%cP\a-:\aLU\a-L\aLD\a- {%d/%d:L%d/%d:uS=%d:uE=%d}\npG=%9.6f : pB=%9.6f : pP%%=%9.6f\n"
\ + "\a%caG=%9.6f : \a%caB=%9.6f\a- : \a%caP%%=%9.6f\a-\n{K=%d : a=%d : Lag=%d}"
Global FmtDUP@@@="%d] \aLOKSE\a-:\aLGBP\a-:\aLUL\a-D\aL\a- {%d/%d:%c%d/%d:uS=%d:uE=%d}\npG=%9.6f :" +
\ " pB=%9.6f : pP%%=%9.6f\naG=%9.6f : aB=%9.6f : aP%%=%9.6f\n{K=%d : a=%d : Lag=%d}"
Global FmtDE@@@="%d] \aLOKS\a!E\a-:\aLGBP\a-:\aLULD\a- {%d/%d:E%d/%d:uS=%d:uE=%d}\npG=%9.6f : pB=%9.6f : pP%%=%9.6f\naG=%9.6f :" +
\ " aB=%9.6f : aP%%=%9.6f\n{K=%d : a=%d : Lag=%d}"
Global FmtNUK@@@="%d] \aLO\a!K\aLSE\a-:\aLGBP\a-:\aLULD\a- {%d/%d:K%d/%d:uS=%d:uE=%d}\npG=%9.6f : pB=%9.6f : pP%%=%9.6f\naG=%9.6f :" +
\ " aB=%9.6f : aP%%=%9.6f\n{\a!K=%d\a- : a=%d : Lag=%d}"
Global FmtDS@@@="%d] \aLOK\a!S\aLE\a-:GBP\a-:\aLULD\a- {%d/%d:S%d/%d:uS=%d:uE=%d}\npG=%9.6f : pB=%9.6f : pP%%=%9.6f\naG=%9.6f :" +
\ " aB=%9.6f : aP%%=%9.6f\n{K=%d : a=%d : Lag=%d}"
Global VFmt@@@="Md=%d:ThG=%.3f:ThB=%.3f:ThP=%d:IgP%%=%.3f\nThK=%d:MaxDupLen=%d:MaxInterp=%d:LagMax=%d\nNuSeq: Cnt=%d:LenMax=%d@%d\nDupe:" +
\ " Cnt=%d:MaxLen=%d@%d:nSeq=%d\nComplete%%=%.3f:EstFPS=%.3f"
Global DotD@@@="\a2*\a!D\a9*\n\a- D\n\a4*\a9D\a!*"
Global DotE@@@="\a2*\a!E\a9*\n\a- E\n\a4*\a9E\a!*"
Global DotI@@@="\a2*\a!I\a9*\n\a- I\n\a4*\a9I\a!*"
Global DotB@@@="\a2*\a!B\a9*\n\a- B\n\a4*\a9B\a!*"
###
IgP=IgP*255.0/100.0 # To range 0.0 -> 255.0
ARGS = "dc,DB,Mode,ThG,ThB,ThP,IgP,ThK,MaxDupLen,LagMax,MaxInterp,BlkW,BlkH,OLapX,OLapY,X,Y,CW,ChromaI,Altscan," +
\ "OthSCD1,OthSCD2,Frames,Ranges,FrameAsRange,Show,Verb,ShowBlk,ShowDot,InterpFast"
ScriptLine = "Fn@@@("+ARGS+")"
Last.GScriptClip(ScriptLine, local=true, args=ARGS)
"""
GIFunc="DUPLICITY2" # Function Name, Supply unique name for your multi-instance function.
GIName=GIFunc+"_InstanceNumber" # Name of the Instance number Global
RT_IncrGlobal(GIName) # Increment Instance Global (init to 1 if not already exists)
GID = GIFunc + "_" + String(Eval(GIName))
InstS = RT_StrReplace(FuncS,"@@@","_"+GID)
# Write current instance Debug GScript File to current directory (line numbers will correspond to error messages)
# RT_WriteFile("DEBUG_"+GID+".TXT","%s",InstS)
HasGScript ? GScript(InstS) : Eval(InstS,"GS_EVAL") # Use GSCript if installed (loaded plugs override builtin)
# if UnNamed DBase && CallCmd available, Auto delete DBase file on clip closure.
(DBase=="" && HasCallCmd) ? CallCmd(close=RT_String("""CMD /C chcp 1252 && del "%s" """,DB), hide=true, Synchronous=7) : NOP
Return Last
}

StainlessS
4th August 2018, 16:14
Post #4 of Many.

Client

Import(".\Duplicity2.Avsi")

######
FN = "D:\G.AVI" DBase = "D:\G_Det.DB" ThB=2.0
#FN = "D:\GTEST.AVI" DBase = "D:\GTEST_Det.DB" ThB=2.0
#FN = "D:\HAR.AVI" DBase = "D:\HAR_Det.DB" ThB=2.5
#FN = "D:\DeDupTest.AVI" DBase = "D:\DeDupTest_Det.DB" ThB=2.0
######
Avisource(FN)
SRC=Last
###
Mode=2 # 0=Write Frames only : 1=Replace Dupes with Exact Dupes : 2= Interpolate/Blend Duplicates.
ThG=1.0 # Primary Frame Global Detect
ThP=64 # Pixel Count Detect
MaxDupLen=9 # Max detected, if more then is considered static sequence not duplicate)
MaxInterp=9 # Max Interpolated frames when Mode=2 (More than MaxInterp & less or equal to MaxDupLen then uses Blend mode)
InterpFast=true
Show=True
ShowDot=False
ShowBlk=true
VERB=False
###
TITLE=False
STACK=True
STACK4=False
###

Result=SRC.Duplicity2(Mode=Mode,ThG=ThG,ThB=ThB,ThP=ThP,MaxDupLen=MaxDupLen,MaxInterp=MaxInterp,
\ Show=False,InterpFast=InterpFast,DBase=(STACK4||!SHOW)?DBase:"")

Metrics=SRC.Duplicity2(Mode=Mode,ThG=ThG,ThB=ThB,ThP=ThP,MaxDupLen=MaxDupLen,MaxInterp=MaxInterp,
\ Show=True,Verb=VERB,ShowBlk=ShowBlk,ShowDot=ShowDot,InterpFast=InterpFast,DBase=(STACK4||!SHOW)?"":DBase)

Dif=Subtract(Result,SRC)

SRC = (TITLE) ? SRC.TSub("Src") : SRC
Result = (TITLE) ? Result.TSub("Result") : Result
Metrics = (TITLE) ? Metrics.TSub("Metrics") : Metrics
Dif = (TITLE) ? Dif.TSub("Dif(Result,Src)") : Dif

LFT=StackVertical((STACK4||!SHOW)?Result:Metrics,SRC)
RGT=StackVertical(Metrics,Dif)
STK4=StackHorizontal(LFT,RGT)

(STACK4) ? STK4 : (STACK) ? LFT : (Show)?Metrics:Result

Return Last


# Stack Overhead Subtitle Text, with optional FrameNumber shown.
Function TSub(clip c,string Tit,Bool "ShowFrameNo",Int "Col"){
c.BlankClip(height=20,Color=Default(Col,0))
(Default(ShowFrameNo,False))?ScriptClip("""Subtitle(String(current_frame,"%.f] """+Tit+""""))"""):Subtitle(Tit)
Return StackVertical(c).AudioDubEx(c)
}

StainlessS
23rd September 2018, 04:29
Post #5 of 6.

Post removed. NOW SPARE

StainlessS
23rd September 2018, 04:30
Post #6 of 6.

Post removed. NOW SPARE

StainlessS
27th September 2018, 01:40
Update, Thread Renamed, to Duplicity2, see first post.

Posts #22 to 27 updated to current script.

StainlessS
30th September 2018, 20:26
Anybody wanna test this out, my eyes dont see any difference (crap eyes).

Duplicity2_v2.02_Beta LINK REMOVED

Have implemented FillDrops modes.


Function Duplicity2(clip c,"Mode"=0,Float "ThG"=1.0,Float "ThB"=ThG, Int "ThP"=64,Float "IgP"=0.0,Int "ThK"=7,
\ Int "MaxDupLen"=9,Int "LagMax"=MaxDupLen,Int "MaxInterp"=Min(9,MaxDupLen),
\ int "BlkW"=64,int "BlkH"=BlkW,int "OLapX"=BlkW/2,Int "OLapY=BlkH/2",
\ Int "X"=0,Int "Y"=0,Int"W"=0,Int "H"=0,Float "CW"=0.0,Bool "ChromaI"=False,Bool "AltScan"=False,
\ Int "SPad"=16, Int "SSharp"=1, Int "SRFilter"=4, [* MSuper *]
\ Int "ABlkSize"=16, Int "AOverlap"=4, Int "ASearch"=3,Int "ADct"=0, [* MAnalyse *]
\ Int "RBlkSize"=8, Int "ROverlap"=2, Int "RthSAD"=100, [* MRecalculate *]
\ Float "Iml"=200.0, Bool "IBlend"=True, Int "IthSCD1"=400, Int "IthSCD2"=130, [* MFlowInter *]
\ Int "OthSCD1"=400,Int "OthSCD2"=130, [* Dupe Detect Override @ Scene Change *]
\ String "OverRide"="",String "Frames"="Frames.txt",Bool "Ranges"=True,Bool "FrameAsRange"=False,
\ Bool "Show"=True,Bool "Verb"=True,Bool "ShowBlk"=True,Bool "Dim"=True,Bool "ShowDot"=False,
\ Int "FillDrops"=0
\ )

...


FillDrops, Default 0 (OFF). [Valid only for Mode=2, Interpolate]
0) Standard precalculated Interpolation clips mode. (Fastest)
1) Standard Interpolated clip mode, except for N_Dupes==1, where Precalculated FillDrops clip method.
2) FillDrops Interpolated mode, except for N_Dupes==1, where Precalculated FillDrops clip.
3) Pure FillDrops mode where all Interpolation clips created during frameserving. (Slowest).


Gavino explanation of FillDrops mode with Delta=1.
https://forum.doom9.org/showthread.php?p=1409378#post1409378
You're right, the function certainly does work, and now I see why.
What happens is that if a duplicate is found at frame n, it interpolates between n and n+1, since delta=1.
At first sight, this is wrong, but since frame n is a duplicate of frame n-1, it is equivalent to the desired interpolation between n-1 and n+1, so the final result comes out OK. (Whether by accident or by design, I'm not sure. )

And Also here:- https://forum.doom9.org/showthread.php?p=1409954#post1409954
Didée's explanation is the same as mine (but clearer!), and would suggest that the delta=2 approach cannot be improved upon. Your results are therefore puzzling and invite further explanation, which I believe I have found.

By looking at the source code, I have discovered that for occlusion areas, MVFlowInter also uses information from the two further surrounding frames (current-delta and current+2*delta).
So the diagram becomes, when interpolating between C and C+d,
----> <----
C-d C C+d C+2d
----> <----
It is this additional information that will be more accurate when delta=1, explaining your findings and making your two-stage approach a better one. Well done.

Just to clarify further my remark about ConditionalFilter, what I am saying is this.
In ConditionalFilter(c1, c2, c3, "...", "...", "..."), 'last' is always set to the value of 'c1' before the expression strings are evaluated (on each frame). Therefore your code
goodframes = ConditionalFilter(clip, trim(clip,1,0), clip, \
"(YDifferenceFromPrevious(clip)/YDifferenceFromPrevious(loop(clip,2,0,0))) * \
(YDifferenceToNext(clip)/YDifferenceToNext(trim(clip,1,0)))", "greaterthan", "bad_thresh")
can be replaced by
goodframes = ConditionalFilter(c, trim(c,1,0), c, \
"(YDifferenceFromPrevious()/YDifferenceFromPrevious(loop(2,0,0))) * \
(YDifferenceToNext()/YDifferenceToNext(trim(1,0)))", "greaterthan", "bad_thresh")
and similarly for 'fixed', with the global variable being removed.
Using a global variable for this purpose in a function is in general a bad idea as the function will not work if called more than once.

Above in BLUE what I mean by FillDrops mode, allows extra data from additional frames where occlusions occur, and so better quality interpolation. The FillDrops=3 mode, we also trim out all dupes and so even better quality than original FillDrops method should be expected.
For the stuff about extra data from additional frames where occlusions occur, because in the filldrop original method the n-1 frame is the frame that n is a duplicate of, and so part of the extra data (where occlusions) comes from n-1 (dupe) and so is no better than using n,
the only extra info comes from n+2. For our Filldrops mode=3, all dupes are trimmed out (no matter what length, 0-9) and interpolation using frames either side of dupe sequence, so we expect even better than original FillDrops method.

We can only pre-create Interpolated FillDrops clips (created before framesering starts) where number of consecutive dupes==1.
N_dupes==1 pre-calc clip used for FillDrops modes 1 and 2 (exactly same as in FillDrops script), but for FillDrops mode==3,
then duplicates are trimmed out (for identical to FillDrops mode with delta=1, the frame of which the single dupe is a copy, is not trimmed out
and so takes some small part in result, whereas for FillDrops mode=3, all dupes trimmed out and so play NO PART in result).


# FillDrops Mode==2 and longer than single dupe (For single dupe, fix with precalc clip I10@@@ above)
# OR, FillDrops==3 and all length dupes interpolated Slow FillDrops method
# NOTE, FillDrops mode uses DELTA=1, and NO SHIFT,
fillMax=3
LS=Max(SStart-fillMax,0) RS=SStart+Count # Range limit for trim (cannot eg trim prior frame 0)
LCnt=SStart-LS RCnt=Min(c.FrameCount-RS,fillMax)
Tmp_c = c.Trim(LS,-LCnt) + c.Trim(RS,-RCnt) # Dupes trimmed out, with ideally two frames before & two after.
Prefilt=Tmp_c.RemoveGrain(22)
Super=Tmp_c.MSuper(hpad=SPad@@@,vpad=SPad@@@,levels=1,sharp=SSharp@@@,rfilter=SRFilter@@@)
Superfilt=Prefilt.MSuper(hpad=SPad@@@,vpad=SPad@@@,sharp=SSharp@@@,rfilter=SRFilter@@@)
bv=Superfilt.MAnalyse(isb=true ,blksize=ABlkSize@@@,overlap=AOverLap@@@,search=ASearch@@@,delta=1,dct=ADct@@@)
fv=Superfilt.MAnalyse(isb=False ,blksize=ABlkSize@@@,overlap=AOverLap@@@,search=ASearch@@@,delta=1,dct=ADct@@@)
if(RBlkSize@@@>0) {
bv=Super.MRecalculate(bv,blksize=RBlkSize@@@,overlap=ROverLap@@@,thSAD=RthSAD@@@)
fv=Super.MRecalculate(fv,blksize=RBlkSize@@@,overlap=ROverLap@@@,thSAD=RthSAD@@@)
}
Tmp_I=Tmp_c.MFlowInter(Super,bv,fv,time=100.0*(Index+1)/(Count+1),ml=Iml@@@,blend=IBlend@@@,thSCD1=IthSCD1@@@,thSCD2=IthSCD2@@@)
Tmp_I.Trim(LCnt-1,-1) # NO SHIFT, fixed frame @ LCnt-1 ie same as Left PreDupe frame


@Zorr, in part, is what you asked in this thread:- https://forum.doom9.org/showthread.php?t=175373

@John Meyer, The N_Dupes==1, for both FillDrops modes=1 and 2, then should be (I think) identical result to your filldrops method.
For N_Dupes > 1 and FillDrops mode=2, or any N_dupes>0 and FillDrops mode==3, then all dupes trimmed out and play no part in
interpolation, so perhaps even better than original FillDrops where result affected by single dupe.


Also John, any chance you could post all yiou know about the FillDrops weirdness, I have a clip where there seems to be 2 dropped frames(big jump)
and then some time later (some times immediately after) there are two dupes,
ALSO, sometimes single frame dropped, and single dupe some time later.
Is there a maximum distance between drops, max number of dropped, max number of dupes etc, any info/rules that you may have observed, thanx.

EDIT: Included in zip, shows difference (where Mode=2) between two Filldrops modes.

#Import("Duplicity2.Avs")

FN="d:\HAR.AVI"
AviSource(FN)
#########
Mode=2 # 0=Write Frames only : 1=Replace Dupes with Exact Dupes : 2= Interpolate/Blend Duplicates.
MaxDupLen=9 # Max detected, if more then is considered static sequence not duplicate)
MaxInterp=9 # Max Interpolated frames when Mode=2 (More than MaxInterp & less or equal to MaxDupLen then uses Blend mode)
ThG=1.0 # Primary Frame Global Detect
ThB=1.5 # Block Detect
ThP=64 # Pixel Count Detect
Show=True
ShowDot=false
ShowBlk=True
VERB=True
FillDropsA=1 # For A clip only
FillDropsB=3 # For B clip only (return default if STACK4=False)
###
STACK4=True
ORG=Last

A=ORG.Duplicity2(Mode=Mode,ThG=ThG,ThB=ThB,ThP=ThP,
\ MaxDupLen=MaxDupLen,MaxInterp=MaxInterp,
\ CW=0.0,ChromaI=False,AltScan=False,
\ Ranges=True,FrameAsRange=False,
\ Show=Show,Verb=VERB,ShowBlk=ShowBlk,ShowDot=ShowDot,FillDrops=FillDropsA
\ )

B=ORG.Duplicity2(Mode=Mode,ThG=ThG,ThB=ThB,ThP=ThP,
\ MaxDupLen=MaxDupLen,MaxInterp=MaxInterp,
\ CW=0.0,ChromaI=False,AltScan=False,
\ Ranges=True,FrameAsRange=False,
\ Show=Show,Verb=VERB,ShowBlk=ShowBlk,ShowDot=ShowDot,FillDrops=FillDropsB
\ )

D1=Subtract(A,B).Levels(125,1,127,0,255,coring=false)
LFT=StackVertical(A,B)
RGT=StackVertical(ORG,D1)
Return STACK4?StackHorizontal(LFT,RGT):B

bblogoss
30th October 2018, 20:46
I am testing a clip full of exact duplicates (metric=0.00000), so detection is not a problem, but I still get some frames that are not interpolated (generally when there are 2 or more consecutives dups) even with MaxDupLen and MaxInterp = 9
Is it normal ?

StainlessS
31st October 2018, 01:27
No idea, what do the metrics show at the dupes.
What is the length of the skipped seqs, ? (greater than MaxDupLen ?)
Are they flagged as Low motion ?

Post image of non detect dupe on PostImage.org, with show=true, Verb=True.

Are you using most recent script ?

bblogoss
31st October 2018, 02:18
I think I get it, the frames are flagged as E=End+1

like it says in the script E=End+1 of current dupe sequence is change of scene, so if Mode=2 then Interpolation or Blending is skipped for that dupe sequence

It's a big jump detected as a scene change. But now even when trying to switch OFF scene change detection with OthSCD1 and OthSCD2 the are stilled flagged as E

What should we exactly do to avoid scene change detection ?

OthSCD2=256 or OthSCD1=8*8*255 and no change at all.

StainlessS
31st October 2018, 03:00
OK, I think I see what problem is, perhaps I should have labored it in docs a little more.

OthSCD2 >=255 will switch off End + 1 scene change detect (which would avoid any attempt to interpolate or count sequence as duplicates,
might want to avoid any processing at all where possibility of of creating blends across scene change [also omit from any Frames file]).

In addition to End + 1 scene change detect, the Interplator (MFlowInter) also has scene change detection args, which may need switching off also.
Take special note of ALL below args

Bool "IBlend"=True, Int "IthSCD1"=400, Int "IthSCD2"=130, [* MFlowInter *]
Int "OthSCD1"=400,Int "OthSCD2"=130, [* Dupe Detect Override @ Scene Change *]


EDIT:
are stilled flagged as E
Sorry, missed that, which script are you using ?

EDIT: Ignore most of above, me a bit confused.
Post a sequence (PM if like), with about 5 frames prior to first in any enclosing low motion sequence, + 5 frames after end frame,
also say which script you are using (v2.01 or v2.02) and provide client script.
If you provide OthSCD2>=255 then it should not set E flag ie

if(Count>MaxDupLen) {Stat=FLG_DS@@@} # MaxDupLen OverRide ### STATIC SCENE
Else {
if(Mode!=1 && i+Count==EndU && OthSCD2 < 255 && OthSCD1 < 8*8*255) {
Tmp_c = c.Trim(i-1,-1) + c.Trim(i+Count,-1) ### IN HERE ONLY IF OthSCD2 < 255
### BELOW ONLY PLACE WHERE stat set to FLG_DE@@@
Stat=(EndOfSceneClip(Tmp_c,OthSCD1,OthSCD2).RT_AverageLuma(n=0,w=1,h=1).Int != 0)?FLG_DE@@@:FLG_DUP@@@
} Else {Stat=FLG_DUP@@@}
# ...
}

bblogoss
31st October 2018, 10:29
Ok, problem is solved. I was using V2.01 and still having the E flag no matter if OthSCD2 or IthSCD2 >=255

in V2.02 after changing mode!=1 to mode!=2 in the part of the script you provide it seems Ok now

if(Count>MaxDupLen) {Stat=FLG_DS@@@} # MaxDupLen OverRide ### STATIC SCENE
Else {
if(Mode!=2 && i+Count==EndU && OthSCD2 < 255 && OthSCD1 < 8*8*255) {
Tmp_c = c.Trim(i-1,-1) + c.Trim(i+Count,-1) ### IN HERE ONLY IF OthSCD2 < 255
### BELOW ONLY PLACE WHERE stat set to FLG_DE@@@
Stat=(EndOfSceneClip(Tmp_c,OthSCD1,OthSCD2).RT_AverageLuma(n=0,w=1,h=1).Int != 0)?FLG_DE@@@:FLG_DUP@@@
} Else {Stat=FLG_DUP@@@}
# ...
}

Thanks for the help :)

StainlessS
31st October 2018, 11:10
That will not be best fix, should defo not enter that code block if OthSCD2 >= 255,
That fix just kludge fix and will move problem to mode==1 (will not skip END+1 switch off if mode==1 [Replace With Exact Dupes mode]).

Try replace with this, what does debugview show


if(Count>MaxDupLen) {Stat=FLG_DS@@@} # MaxDupLen OverRide ### STATIC SCENE
Else {
if(Mode!=1 && i+Count==EndU && OthSCD2 < 255 && OthSCD1 < 8*8*255) {
RT_DebugF("%d] OthSCD1=%d OthSCD2=%d",i,OthSCD1,OthSCD2)
Tmp_c = c.Trim(i-1,-1) + c.Trim(i+Count,-1) ### IN HERE ONLY IF OthSCD2 < 255
### BELOW ONLY PLACE WHERE stat set to FLG_DE@@@
Stat=(EndOfSceneClip(Tmp_c,OthSCD1,OthSCD2).RT_AverageLuma(n=0,w=1,h=1).Int != 0)?FLG_DE@@@:FLG_DUP@@@
RT_DebugF("%d] Stat=%d",i,Stat)
} Else {Stat=FLG_DUP@@@}
# ...
}

Above i, is first duplicate in dupe run.

bblogoss
31st October 2018, 17:28
I'm not so used with debug mode. What should I exactly do after adding the two RT_DebugF lines ?

StainlessS
1st November 2018, 16:05
DebugView, by SysInternals (now owned by M$):- https://docs.microsoft.com/en-us/sysinternals/downloads/debugview

NOTE, some other software may also output to debugview.

There is a massive number of free utilities from same site, and can download the whole lot as a single zip.
(SysInternals Suite, a few lines below in the LHS pane)

EDIT: I also like (amongst others from that site) AutoLogon, does what it says on the tin.

bblogoss
2nd November 2018, 02:55
Well here is what Debugview shows

00000001 0.00000000 [15600] FFMS2 avs plugin: Initializing...
00000002 0.00003070 [15600] FFMS2 - avs 2.6 mode
00000003 22.96657753 [15600] RT_DebugF: 522] OthSCD1=400 OthSCD2=130
00000004 22.97030830 [15600] RT_DebugF: 522] Stat=8
00000005 23.06452370 [15600] RT_DebugF: 525] OthSCD1=400 OthSCD2=130
00000006 23.06820679 [15600] RT_DebugF: 525] Stat=8
00000007 23.30171204 [15600] RT_DebugF: 531] OthSCD1=400 OthSCD2=130
00000008 23.30541229 [15600] RT_DebugF: 531] Stat=8
00000009 23.53751755 [15600] RT_DebugF: 538] OthSCD1=400 OthSCD2=130
00000010 23.54120636 [15600] RT_DebugF: 538] Stat=8
00000011 23.73814964 [15600] RT_DebugF: 544] OthSCD1=400 OthSCD2=130
00000012 23.74173164 [15600] RT_DebugF: 544] Stat=8
00000013 23.93748283 [15600] RT_DebugF: 550] OthSCD1=400 OthSCD2=130
00000014 23.94121933 [15600] RT_DebugF: 550] Stat=8
00000015 24.13818169 [15600] RT_DebugF: 556] OthSCD1=400 OthSCD2=130
00000016 24.14183044 [15600] RT_DebugF: 556] Stat=8
00000017 24.33157349 [15600] RT_DebugF: 562] OthSCD1=400 OthSCD2=130
00000018 24.33519936 [15600] RT_DebugF: 562] Stat=8
00000019 24.53227234 [15600] RT_DebugF: 568] OthSCD1=400 OthSCD2=130
00000020 24.53590775 [15600] RT_DebugF: 568] Stat=8
00000021 24.73389816 [15600] RT_DebugF: 574] OthSCD1=400 OthSCD2=130
.......
........

That's the default settings. Am I missing something or it seems like the OthSCD2 setting in the client part of the script is not loaded ?
After manually changing the default setting of OthSCD2 in the script there is no E flag and DebugView says logically nothing

so here is the client part of the script

Import("Duplicity2_v2.02_Beta.Avs")

FN="server.vdr"
AviSource(FN).ConvertToYV24(matrix="Rec601")
#########
Mode=2 # 0=Write Frames only : 1=Replace Dupes with Exact Dupes : 2= Interpolate/Blend Duplicates.
MaxDupLen=9 # Max detected, if more then is considered static sequence not duplicate)
MaxInterp=9 # Max Interpolated frames when Mode=2 (More than MaxInterp & less or equal to MaxDupLen then uses Blend mode)
ThG=1.0 # Primary Frame Global Detect
ThB=1.5 # Block Detect
ThP=64 # Pixel Count Detect
OthSCD2=255
Show=true
ShowDot=false
ShowBlk=false
VERB=false
FillDropsA=1 # For A clip only
FillDropsB=3 # For B clip only (return default if STACK4=False)
###
STACK4=false
ORG=Last

A=ORG.Duplicity2(Mode=Mode,ThG=ThG,ThB=ThB,ThP=ThP,
\ MaxDupLen=MaxDupLen,MaxInterp=MaxInterp,
\ CW=0.0,ChromaI=False,AltScan=False,
\ Ranges=True,FrameAsRange=False,
\ Show=Show,Verb=VERB,ShowBlk=ShowBlk,ShowDot=ShowDot,FillDrops=FillDropsA
\ )

B=ORG.Duplicity2(Mode=Mode,ThG=ThG,ThB=ThB,ThP=ThP,
\ MaxDupLen=MaxDupLen,MaxInterp=MaxInterp,
\ CW=0.0,ChromaI=False,AltScan=False,
\ Ranges=True,FrameAsRange=False,
\ Show=Show,Verb=VERB,ShowBlk=ShowBlk,ShowDot=ShowDot,FillDrops=FillDropsB
\ )

D1=Subtract(A,B).Levels(125,1,127,0,255,coring=false)
LFT=StackVertical(A,B)
RGT=StackVertical(ORG,D1)
Return STACK4?StackHorizontal(LFT,RGT):B

StainlessS
2nd November 2018, 04:55
OOoops, how embarrassing, I did not spot the fact that we did not call the functions wth OthSCD2, ie


Import("Duplicity2_v2.02_Beta.Avs")

FN="server.vdr"
AviSource(FN).ConvertToYV24(matrix="Rec601")
#########
Mode=2 # 0=Write Frames only : 1=Replace Dupes with Exact Dupes : 2= Interpolate/Blend Duplicates.
MaxDupLen=9 # Max detected, if more then is considered static sequence not duplicate)
MaxInterp=9 # Max Interpolated frames when Mode=2 (More than MaxInterp & less or equal to MaxDupLen then uses Blend mode)
ThG=1.0 # Primary Frame Global Detect
ThB=1.5 # Block Detect
ThP=64 # Pixel Count Detect
OthSCD2=255
IthSCD2=255
Show=true
ShowDot=false
ShowBlk=false
VERB=false
FillDropsA=1 # For A clip only
FillDropsB=3 # For B clip only (return default if STACK4=False)
###
STACK4=false
ORG=Last

A=ORG.Duplicity2(Mode=Mode,ThG=ThG,ThB=ThB,ThP=ThP,
\ MaxDupLen=MaxDupLen,MaxInterp=MaxInterp,
\ CW=0.0,ChromaI=False,AltScan=False,
\ Ranges=True,FrameAsRange=False,
\ Show=Show,Verb=VERB,ShowBlk=ShowBlk,ShowDot=ShowDot,FillDrops=FillDropsA,OthSCD2=OthSCD2,IthSCD2=IthSCD2
\ )

B=ORG.Duplicity2(Mode=Mode,ThG=ThG,ThB=ThB,ThP=ThP,
\ MaxDupLen=MaxDupLen,MaxInterp=MaxInterp,
\ CW=0.0,ChromaI=False,AltScan=False,
\ Ranges=True,FrameAsRange=False,
\ Show=Show,Verb=VERB,ShowBlk=ShowBlk,ShowDot=ShowDot,FillDrops=FillDropsB,OthSCD2=OthSCD2,IthSCD2=IthSCD2
\ )

D1=Subtract(A,B).Levels(125,1,127,0,255,coring=false)
LFT=StackVertical(A,B)
RGT=StackVertical(ORG,D1)
Return STACK4?StackHorizontal(LFT,RGT):B


Just too obvious I guess :(

bblogoss
2nd November 2018, 18:25
Everything works like a charm now :thanks:

Also, does it change something if we save the main script as an AVSI file in the plugin directory and then make a final script in a classic way ?

AviSource("videofile.avi")
Duplicity2(mode=2, show=false, ShowBlk=false, OthSCD2=255, IthSCD2=255, FillDrops=3, IBlend=false)

StainlessS
2nd November 2018, 18:46
Should work fine as avsi in plugs directory.

StainlessS
4th November 2018, 14:45
Duplicity2, v2.10, new version, see 1st post.

Main diffs.

Function Duplicity2(clip c,"Mode"=0,Float "ThG"=1.0,Float "ThB"=ThG*2.0, Int "ThP"=64,Float "IgP"=0.0,Int "ThK"=7,
\ Int "MaxDupLen"=9,Int "LagMax"=MaxDupLen,Int "MaxInterp"=Min(9,MaxDupLen),
\ int "BlkW"=64,int "BlkH"=BlkW,int "OLapX"=BlkW/2,Int "OLapY=BlkH/2",
\ Int "X"=0,Int "Y"=0,Int"W"=0,Int "H"=0,Float "CW"=0.0,Bool "ChromaI"=False,Bool "AltScan"=False,
\ Int "SPad"=16, Int "SSharp"=1, Int "SRFilter"=4, [* MSuper *]
\ Int "ABlkSize"=16, Int "AOverlap"=4, Int "ASearch"=3,Int "ADct"=0, [* MAnalyse *]
\ Int "RBlkSize"=8, Int "ROverlap"=2, Int "RthSAD"=100, [* MRecalculate *]
\ Float "Iml"=200.0, Bool "IBlend"=True, Int "IthSCD1"=400, Int "IthSCD2"=130, [* MFlowInter *]
\ Int "OthSCD1"=400,Int "OthSCD2"=130, [* Dupe Detect Override @ Scene Change *]
\ String "OverRide"="",String "Frames"="Frames.txt",Bool "Ranges"=True,Bool "FrameAsRange"=False,
\ Bool "Show"=True,Bool "Verb"=True,Bool "ShowBlk"=True,Bool "Dim"=True,Bool "ShowDot"=False,
\ Bool "InterpFast"=True,String "DBase"=""
\ )



InterpFast, Default True. If True, then Interpolation clips are pre-calculated, if false then calculations done in real time.
Pre-Calc clips a bit (maybe 10%) faster, but perhaps not quite as good quality.

DBase, Default "", If named DBase suppled, then is not deleted on Function exit.
[ If name supplied, result DB may be re-used by other scripts, eg DropDeadGorgeous() function ].
NOTE, If using multiple instances and named DBase, then give each DBase as different name.

StainlessS
4th November 2018, 15:56
Also see previous post (needed by this script).

Here its play time,


/*

DropDeadGorgeous() v -1.0, Beta -1, by the Gorgeous & Truly Scrumptious StainlessS @ Doom9

Using DBase as Created by Duplicity2 v2.10,
Corrects problems where frames were dropped in clip, and then some time later duplicates were inserted to maintain timing.
ScanAhead is number of frames scanned ahead of current frame looking for duplicates, currently no maximum, default 9.
If duplicates found (no current limit on length of duplicate run), then biggest frame jump (movement) prior to dupes is
located, and a number of frames interpolated prior to it (same number as in dupe run).
Fixes jumpy jaunty clips that constantly and repeatedly jump and then freeze.

Simple metrics on Show, "nnn] CIR", where nnn is frame number, and character Flags highlited where,
C=Copy frame (original as source frame)
I=Interpolated frame
R=Relocated frame from earlier in clip (interpolated frames shove following frames to later in clip, removing dupes)

Can use Duplicity Modes 1 or 2 in creating DBase.

*/

Function DropDeadGorgeous(clip c,String DB,Int "ScanAhead",
\ Int "X",Int "Y",Int"W",Int "H",
\ Int "SPad", Int "SSharp", Int "SRFilter", [* MSuper *]
\ Int "ABlkSize", Int "AOverlap", Int "ASearch",Int "ADct", [* MAnalyse *]
\ Int "RBlkSize", Int "ROverlap", Int "RthSAD", [* MRecalculate *]
\ Float "Iml", Bool "IBlend", Int "IthSCD1", Int "IthSCD2", [* MFlowInter *]
\ Bool "Show"
\ ){
c myName="DropDeadGorgeous: "
IsAvsPlus=(FindStr(UCase(versionString),"AVISYNTH+")!=0) HasGScript=RT_FunctionExist("GScript")
HasGRunt =RT_FunctionExist("GScriptClip") HasMvTools=RT_FunctionExist("MSuper")
HasMaskTools=RT_FunctionExist("MT_Lutxy") HasRemoveGrain=RT_FunctionExist("RemoveGrain")
HasCallCmd=RT_FunctionExist("CallCmd")
ScanAhead = Default(ScanAhead,9)
X=default(X,0) Y=default(Y,0) W=default(W,0) H=default(H,0)
SPad = Default(SPad,16) SSharp = Default(SSharp,1) SRFilter= Default(SRFilter,4)
ABlkSize = Default(ABlkSize,16) AOverlap= Default(AOverlap,4) ASearch = Default(ASearch,3) ADct = Default(ADct,0)
RBlkSize = Default(RBlkSize,8) ROverlap= Default(ROverlap,2) RthSAD = Default(RthSAD,100)
Iml = Default(Iml,200.0) IBlend = Default(IBlend,True) IthSCD1 = Default(IthSCD1,400) IthSCD2= Default(IthSCD2,130)
Show = Default(Show,False)
Assert(0 < ScanAhead,RT_String("%s0 < ScanAhead(%d)",myName,ScanAhead))
####
Assert(DB!="",RT_String("%sDB Cannot be ''",myName))
DB1 = RT_GetFullPathName(DB)
DB2 = RT_GetFullPathName("~@@@_"+RT_LocalTimeString+".DB") RT_DBaseAlloc(DB2,FrameCount,"iii")
W = (W > 0) ? (W + X) - Width : W H = (H > 0) ? (H + Y) - Height : H # Make -ve relative width,height
X = (X+3) / 4 * 4 Y = (Y+3) / 4 * 4 # Round UP (inwards) Mod 4
W = (W-3) / 4 * 4 H = (H-3) / 4 * 4 # Round DOWN(inwards) Mod 4
W = Width - X + W H = Height - Y + H # +ve width,height
DC=Crop(X,Y,W,H)
Global G_DIFMOD=1 # Tmp setting
FuncS="""
Function Fn@@@(clip c,clip dc,String DB1,String DB2,int ScanAhead,Bool Show) {
c n=current_frame
Stat2 = RT_DBaseGetField(DB2,n,0)
if(Stat2 == 0) {
Stat1 = RT_DBaseGetField(DB1,n,FLD_STAT@@@)
if(Stat1 < FLG_DE@@@ && SOS@@@.RT_AverageLuma(n=n,w=1,h=1).Int == 0) { # Non dupe and NOT Start Of Scene
de = Min(n+(ScanAhead*2),FrameCount-1)
DupN = -1
for(i=n+1,de) { if(RT_DBaseGetField(DB1,i,FLD_STAT@@@) >= FLG_DE@@@) { DupN = i i=de } }
if(DupN<0) {
ds=Max(de-ScanAhead,n+1)
for(i=n,ds-1) { RT_DBaseSetField(DB2,i,0,1) } # Copy
} Else { # Both n and DupN, NOT SOS
ds = Max(DupN - ScanAhead, n)
for(i=DupN-1,ds, -1) {
if(SOS@@@.RT_AverageLuma(n=i,w=1,h=1).Int != 0) { tmp=i i=ds ds=tmp+1}
}
for(i=n,ds-1) { RT_DBaseSetField(DB2,i,0,1) } # Copy
if(ds<DupN) {
Index=RT_DBaseGetField(DB1,DupN,FLD_INDEX@@@)
SSTart=DupN-Index
Count=RT_DBaseGetField(DB1,SSTart,FLD_COUNT@@@) # Dup Count stored only in first Record of Sub Sequence
mxi = ds
if(G_DIFMOD==0) { mxdif = MFPC@@@.RT_AverageLuma(n=ds) }
Else { mxdif = dc.RT_LumaDifference(dc,n=ds,n2=ds-1) }
for(i=ds+1,DupN-1) {
if(G_DIFMOD==0) { dif = MFPC@@@.RT_AverageLuma(n=i) }
Else { dif = dc.RT_LumaDifference(dc,n=i,n2=i-1) }
if(dif>mxDif) {
mxDif=dif
mxi = i
}
}
for(i=mxi+Count,DupN+Count-1) {
RT_DBaseSetField(DB2,i,0,2) # Copy Frame relative
RT_DBaseSetField(DB2,i,1,COUNT) # Copy Frame
}
for(i=mxi,mxi+Count-1) {
RT_DBaseSetField(DB2,i,0,3) # Interp
RT_DBaseSetField(DB2,i,1,COUNT) # Interp count
RT_DBaseSetField(DB2,i,2,i-mxi) # Index
}
for(i=ds,mxi-1) {
RT_DBaseSetField(DB2,i,0,1)
} # copy
}
}
} Else { RT_DBaseSetField(DB2,n,0,1) } # Dupe or Start Of Scene
Stat2 = RT_DBaseGetField(DB2,n,0)
}
if(Stat2==1) { # Copy (already correct frame)
Stat1 = RT_DBaseGetField(DB1,n,0)
if(Show) { RT_Subtitle("%d] C\aLIR",n) }
} Else if(Stat2==2) { # Copy previous relative
Count = RT_DBaseGetField(DB2,n,1)
Stat1 = RT_DBaseGetField(DB1,n,0)
c.Trim(n-Count,-1)
if(Show) { RT_Subtitle("%d] \aLCI\a-R",n) }
} Else if(Stat2==3) {
Index = RT_DBaseGetField(DB2,n,2)
Count = RT_DBaseGetField(DB2,n,1)
SStart= n-Index
fillMax=3
LS=Max(SStart-fillMax,0) RE=Min(SStart+FillMax-1,c.FrameCount-1)
LCnt=SStart-LS
Tmp_c = c.Trim(LS,-(RE-LS+1))
Prefilt=Tmp_c.RemoveGrain(22)
Super=Tmp_c.MSuper(hpad=SPad@@@,vpad=SPad@@@,levels=1,sharp=SSharp@@@,rfilter=SRFilter@@@)
Superfilt=Prefilt.MSuper(hpad=SPad@@@,vpad=SPad@@@,sharp=SSharp@@@,rfilter=SRFilter@@@)
bv=Superfilt.MAnalyse(isb=true ,blksize=ABlkSize@@@,overlap=AOverLap@@@,search=ASearch@@@,delta=1,dct=ADct@@@)
fv=Superfilt.MAnalyse(isb=False ,blksize=ABlkSize@@@,overlap=AOverLap@@@,search=ASearch@@@,delta=1,dct=ADct@@@)
if(RBlkSize@@@>0) {
bv=Super.MRecalculate(bv,blksize=RBlkSize@@@,overlap=ROverLap@@@,thSAD=RthSAD@@@)
fv=Super.MRecalculate(fv,blksize=RBlkSize@@@,overlap=ROverLap@@@,thSAD=RthSAD@@@)
}
Tmp_I=Tmp_c.MFlowInter(Super,bv,fv,time=100.0*(Index+1)/(Count+1),ml=Iml@@@,blend=IBlend@@@,thSCD1=IthSCD1@@@,thSCD2=IthSCD2@@@)
Tmp_I.Trim(LCnt-1,-1) # NO SHIFT, fixed frame @ LCnt-1 ie same as Left PreDupe frame
Stat1 = RT_DBaseGetField(DB1,n,0)
if(Show) { RT_Subtitle("%d] \aLC\a-I\aLR",n) }
} Else {
RT_Subtitle("%d] %d %d BUG BUG BUG",n,Stat1,Stat2)
}
Return Last
}
Function StartOfSceneClip(clip c,Int "thSCD1",Int "thSCD2") { # All Luma Samples set 255 at SOS, else 0
thSCD1=Default(thSCD1,400) thSCD2=Default(thSCD2,130)
sup=c.MSuper(pel=1,sharp=0,rfilter=2,hpad=16, vpad=16)
fv=sup.MAnalyse(isb=false,delta=1,blksize=16)
Return c.MSCDetection(fv,thSCD1=thSCD1,thSCD2=thSCD2)
}
Function MMaskFromPrevClip(clip c,Int "MaskType",Float "Gamma",Int "thSCD1",Int "thSCD2") {
# MaskType:- 0=Motion, 1=SAD, 2=Occlusion, 3=Horizontal, 4=Vertical, 5=ColorMap.
MaskType=Default(MaskType,0) Gamma=Default(Gamma,1.0) thSCD1=Default(thSCD1,400) thSCD2=Default(thSCD2,130)
sup=c.MSuper(pel=1,sharp=0,rfilter=2,hpad=16, vpad=16)
fv=sup.MAnalyse(isb=false,delta=1,blksize=16)
Return c.MMask(fv,Gamma=1.0,kind=MaskType,thSCD1=thSCD1,thSCD2=thSCD2)
}
Global SOS@@@ = dc.StartOfSceneClip(thSCD1=IthSCD1,thSCD2=IthSCD2)
Global MFPC@@@= dc.MMaskFromPrevClip(Gamma=2.0,MaskType=0,thSCD1=IthSCD1,thSCD2=IthSCD2)
### DB1 Fields:-
Global FLD_STAT@@@ = 0 # Holds Status FLGS
Global FLD_START@@@ = 1 # Unique Start Frame
Global FLD_END@@@ = 2 # Unique End Frame
Global FLD_ANCHOR@@@ = 3 # Anchor Frame
Global FLD_INDEX@@@ = 4 # Index into Count (0 Relative, 0->Count-1)
Global FLD_COUNT@@@ = 5 # Sequence Frame Count
### DB1 Status Flags in Field FLD_STAT@@@
Global FLG_OO@@@ = 1 # User Override
Global FLG_UK@@@ = 2 # K Override
Global FLG_UU@@@ = 3 # Unique Frame
Global FLG_NUK@@@ = 4 # Non Unique Sequence K Override
Global FLG_LM@@@ = 5 # LoMotion Frame
Global FLG_DS@@@ = 6 # Static Sequence [detected as duplicates but Longer than MaxDupLen]
Global FLG_DE@@@ = 7 # Duplicate Sequence is followed by Scene Change (will NOT occar when Mode==1)
Global FLG_DUP@@@ = 8 # Duplicate Sequence
###
Global SPad@@@=SPad Global SSharp@@@=SSharp Global SRFilter@@@=SRFilter
Global ABlkSize@@@=ABlkSize Global AOverLap@@@=AOverLap Global ASearch@@@=ASearch Global ADct@@@=ADct
Global RBlkSize@@@=RBlkSize Global ROverLap@@@=ROverLap Global RthSAD@@@=RthSAD
Global Iml@@@=Iml Global IBlend@@@=IBlend Global IthSCD1@@@=IthSCD1 Global IthSCD2@@@=IthSCD2
###
ARGS = "dc,DB1,DB2,ScanAhead,Show"
ScriptLine = "Fn@@@("+ARGS+")"
Last.GScriptClip(ScriptLine, local=true, args=ARGS)
"""
GIFunc="DROPDEADGORGEOUS" # Function Name, Supply unique name for your multi-instance function.
GIName=GIFunc+"_InstanceNumber" # Name of the Instance number Global
RT_IncrGlobal(GIName) # Increment Instance Global (init to 1 if not already exists)
GID = GIFunc + "_" + String(Eval(GIName))
InstS = RT_StrReplace(FuncS,"@@@","_"+GID)
# Write Debug GScript File to current directory (line numbers will correspond to error messages)
# RT_WriteFile("DEBUG_"+GID+".TXT","%s",InstS)
HasGScript ? GScript(InstS) : Eval(InstS,"GS_EVAL") # Use GSCript if installed (loaded plugs override builtin)
# if CallCmd available, Auto delete DBase file on clip closure.
HasCallCmd?CallCmd(close=RT_String("""CMD /C chcp 1252 && del "%s" """,DB2), hide=true, Synchronous=7):NOP
Return Last
}

FN = "D:\G.AVI" DBase = "D:\G_Det.DB" # DBase Created by Duplicity2
#FN = "D:\HAR.AVI" DBase = "D:\HAR_Det.DB"
Avisource(FN)
ORG=Last
SHOW=True
DropDeadGorgeous(DBase,show=Show)
StackVertical(Last,ORG)

EDIT: Fixed I flag, was not hilted.

Strictly sequential, play forwards ONLY.

StainlessS
6th November 2018, 19:30
Duplicity2 v2.11 bugfix update, see first post.

Two bugs, first one probably a copy paste of existing bug, suspect other scripts might suffer from same bug.

Was

X = (X+3) / 4 * 4 Y = (Y+3) / 4 * 4 # Round UP Mod 4
W = (W<=0) ? Width() - X + W : W H = (H<=0) ? Height() - Y + H : H
W = W / 4 * 4 H = H / 4 * 4 # Round DOWN Mod 4


Fixed

W = (W > 0) ? (W + X) - Width : W H = (H > 0) ? (H + Y) - Height : H # Make -ve relative width,height
X = (X+3) / 4 * 4 Y = (Y+3) / 4 * 4 # Round UP (inwards) Mod 4
W = (W-3) / 4 * 4 H = (H-3) / 4 * 4 # Round DOWN(inwards) Mod 4
W = Width - X + W H = Height - Y + H # +ve width,height

Rounding up X mod 4 should also have affected width, but did not, I always use -ve width, height (as for crop) where problem does not arise.
Same fix applied to previous post above, DropDeadGorgeous() script.

2nd bug, in Client script

Import(".\Duplicity2.Avsi")


######
FN = "D:\G.AVI" DBase = "D:\G_Det.DB" ThB=2.0
#FN = "D:\HAR.AVI" DBase = "D:\HAR_Det.DB" ThB=2.5
######
Avisource(FN)
SRC=Last
###
Mode=2 # 0=Write Frames only : 1=Replace Dupes with Exact Dupes : 2= Interpolate/Blend Duplicates.
ThG=1.0 # Primary Frame Global Detect
ThP=64 # Pixel Count Detect
MaxDupLen=9 # Max detected, if more then is considered static sequence not duplicate)
MaxInterp=9 # Max Interpolated frames when Mode=2 (More than MaxInterp & less or equal to MaxDupLen then uses Blend mode)
InterpFast=true
Show=True
ShowDot=False
ShowBlk=True
VERB=True
###
TITLE=true
STACK=False
STACK4=True
###

Result=SRC.Duplicity2(Mode=Mode,ThG=ThG,ThB=ThB,ThP=ThP,MaxDupLen=MaxDupLen,MaxInterp=MaxInterp,
\ Show=False,InterpFast=InterpFast,DBase=DBase)

Metrics=SRC.Duplicity2(Mode=Mode,ThG=ThG,ThB=ThB,ThP=ThP,MaxDupLen=MaxDupLen,MaxInterp=MaxInterp,
\ Show=Show,Verb=VERB,ShowBlk=ShowBlk,ShowDot=ShowDot,InterpFast=InterpFast)

Dif=Subtract(Result,SRC)

SRC = (TITLE) ? SRC.TSub("Src") : SRC
Result = (TITLE) ? Result.TSub("Result") : Result
Metrics = (TITLE) ? Metrics.TSub("Metrics") : Metrics
Dif = (TITLE) ? Dif.TSub("Dif(Result,Src)") : Dif

LFT=StackVertical((STACK4||!SHOW)?Result:Metrics,SRC)
RGT=StackVertical(Metrics,Dif)
STK4=StackHorizontal(LFT,RGT)

(STACK4) ? STK4 : (STACK) ? LFT : (Show)?Metrics:Result

Return Last


# Stack Overhead Subtitle Text, with optional FrameNumber shown.
Function TSub(clip c,string Tit,Bool "ShowFrameNo",Int "Col"){
c.BlankClip(height=20,Color=Default(Col,0))
(Default(ShowFrameNo,False))?ScriptClip("""Subtitle(String(current_frame,"%.f] """+Tit+""""))"""):Subtitle(Tit)
Return StackVertical(c).AudioDubEx(c)
}

Moved DBase to result clip call instead of metrics clip (would not create named DBase if not showing metrics).

NOTE. I have found a problem in AVS+ (dont happen in Avs 2.6 standard), not sure if avs+ bug or not.
With all metrics showing and also SHOWBLK=True, and INTERPFAST=True, after playing about 1000 or so frames,
go backwards a number of frames and you get out of memory error. Does not happen on AVS standard, or with InterpFast=False.
Possibly a different system resources requirement of Avs+ (dont know). [Tested using VDub2 and VDubMod, Win7 x64 Avs/+ 32bit]

I've also noticed that ClipClop() included DoctorFrames script now fails at MaxInterp of 15 for Avs+ where using same method as used in Duplicity2
when InterpFast=True. Avs 2.6 standard achieves about 20 sets of precalculated clips before failing (with SetMemoryMax could get as hi as 22).

EDIT: Zip on mediafire/SendSpace updated, scripts from posts #22 updated
(also version number update @ top of 1st doc page on post #1).

EDIT: This is the pre-calculated set of interpolation clips where INTERPFAST=True in duplicity2, and similar used in ClipClop DoctorFrames().

if(Mode==2 && MaxInterp>0) {
if(InterpFast) {
Prefilt = c.RemoveGrain(22)
Super = c.MSuper(hpad=SPad,vpad=SPad,levels=1,sharp=SSharp,rfilter=SRFilter) # One level is enough for MRecalculate
Superfilt= Prefilt.MSuper(hpad=SPad,vpad=SPad,sharp=SSharp,rfilter=SRFilter) # All levels for MAnalyse
For(i=1, MaxInterp) {
Eval(RT_String("bv=Superfilt.MAnalyse(isb=true ,blksize=ABlkSize,overlap=AOverLap,search=ASearch,delta=%d,dct=ADct)",i+1))
Eval(RT_String("fv=Superfilt.MAnalyse(isb=false,blksize=ABlkSize,overlap=AOverLap,search=ASearch,delta=%d,dct=ADct)",i+1))
if(RBlkSize>0) {
Eval(RT_String("bv=Super.MRecalculate(bv,blksize=RBlkSize,overlap=ROverLap,thSAD=RthSAD)"))
Eval(RT_String("fv=Super.MRecalculate(fv,blksize=RBlkSize,overlap=ROverLap,thSAD=RthSAD)"))
}
for(j=1,i) {
Eval(RT_String("Global I%d%d@@@=c.MFlowInter(Super,bv,fv,time=100.0*%d/%d," +
\ "ml=Iml,blend=IBlend,thSCD1=IthSCD1,thSCD2=IthSCD2).SelectEvery(1,%d).Trim(0,-c.FrameCount)", i,j-1, j,i+1,-j))
}
}
} Else {
Global SPad@@@=SPad Global SSharp@@@=SSharp Global SRFilter@@@=SRFilter
Global ABlkSize@@@=ABlkSize Global AOverLap@@@=AOverLap Global ASearch@@@=ASearch Global ADct@@@=ADct
Global RBlkSize@@@=RBlkSize Global ROverLap@@@=ROverLap Global RthSAD@@@=RthSAD
Global Iml@@@=Iml Global IBlend@@@=IBlend Global IthSCD1@@@=IthSCD1 Global IthSCD2@@@=IthSCD2
}
}



EDIT: Could not get Avs+ to fail where STACK and STACK4 both false in client script, ie where only single instance of Duplicity2 called [EDIT: Displayed].

EDIT: Updated Duplicty2 Client script a little bit in post 25 (No zip update).

StainlessS
8th November 2018, 03:44
Duplicity2 v2.12, update, see first post.

Zip now included DropDeadGorgeous() script versioned at v0.00.

SCRIPT REMOVED.

StainlessS
17th November 2018, 14:58
Duplicity2(), DropDeadGorgeous(), v2.13 updates, see first post.

See post #22 for current Duplicity2 script, or download see 1st post (re-directs to MediaFire or SendSpace below this post).

Current DropDeadGorgeous() reversioned to v2.13, will now always be same version as Duplicity2 (and require similar version Duplicity2).

DropDeadGorgeous.avsi part 1

/*

DropDeadGorgeous() v2.13, by the Gorgeous & Truly Scrumptious StainlessS @ Doom9
Same Requirements as Duplicity2(). https://forum.doom9.org/showthread.php?t=175357

Using DBase as Created by Duplicity2 v2.13.
Corrects problems where frames were dropped in clip, and then some time later duplicates were inserted to maintain timing,
ie 'jumpy' clips that repeatedly jerk and then freeze.
ScanAhead is number of frames scanned ahead of current_frame looking for duplicates, default 9. Any detected dupe run will
start between current_frame and current_frame + ScanAhead.
If duplicates found (limit on length of duplicate run set in Duplicity2 via MaxDupLen), then a JerkFrame is found.
A JerkFrame is searched for backwards, from DupeStartFrame-1 to to current_frame and search stops if a StartOfScene is detected.
The JerkFrame is the frame prior to first dupe, with greatest movement/jerk when compared with its predecessor.
If JerkFrame is found, a number of frames are interpolated starting at the JerkFrame position, (same number as in dupe run,
and source frames to interpolation are JerkFrame and JerkFrame-1), interpolated frames shove following frames to later in clip,
removing dupes.
If no JerkFrame is found, ie where duplicates are of a StartOfScene frame, then so long as DupeEndFrame+1 is not another StartOfScene
frame, then duplicates are interpolated using DupeStartFrame-1 and DupeEndFrame+1 as interpolation source frames.

Function DropDeadGorgeous(clip c,String DB,Int "ScanAhead"=9,
\ Int "X"=0,Int "Y"=0,Int"W"=0,Int "H"=0,
\ Int "SPad"=16, Int "SSharp"=1, Int "SRFilter"=4, [* MSuper *]
\ Int "ABlkSize"=16, Int "AOverlap"=4, Int "ASearch"=3,Int "ADct"=0, [* MAnalyse *]
\ Int "RBlkSize"=8, Int "ROverlap"=2, Int "RthSAD"=100, [* MRecalculate *]
\ Float "Iml"=200.0, Bool "IBlend"=True, Int "IthSCD1"=400, Int "IthSCD2"=130, [* MFlowInter *]
\ Bool "Show"=True, Bool "Verb"=True,Int "SOSthSCD2"=130
\ )

DB, DBase as created by Duplicity2, v2.13, error if wrong version DBase.

ScanAhead, Default 9, 1 <= ScanAhead <= 60. Distance in frames to scan ahead of current frame. If first duplicate is always eg
3 frames after a jerk, then set this to 3.
ScanAhead, is deliberatley set quite high by default, then maybe reduce ScanAhead to MostCommonScanDist after full scan.
ALSO SEE Verbose Metrics MostCommonScanDist.

X,Y,W,H, All Default 0, Coordinates of test area, as in crop (all 0 = full frame).
The x,y coords will be rounded up mod4, and w,h coords rounded down mod 4.
Ignore eg animated logo.

MvTools2 Args, for Interpolation.
MSuper args:
SPad, Default 16, See MvTools MSuper(hpad=8,vpad=8) [We use same for both].
SSharp, Default 1, See MvTools MSuper(sharp=2)
SRFilter, Default 4, See MvTools MSuper(rfilter=2)

MAnalyse args:
ABlkSize, Default 16, See MvTools MAnalyse(BlkSize=8,BlkSizeV=8) [We use same for both].
AOverLap, Default 4, See MvTools MAnalyse(OverLap=0)
ASearch, Default 3, See MvTools MAnalyse(Search=4)
ADct, Default 0, See MvTools MAnalyse(Dct=0). Using other than default value can be VERY slow.

MRecalculate args:
RBlkSize, Default 8, See MvTools MRecalculate(BlkSize)
NOTE, RBlkSize = 0 Will Switch OFF MRecalculate, probably a bit faster at possible expense of quality.
ROverlap, Default 2, See MvTools MRecalculate(Overlap)
RthSAD, Default 100, See MvTools MRecalculate(thSAD=200)

MFlowInter args:
Iml, Default 200.0, See MvTools MFlowInter(ml=100.0)
IBlend, Default True, See MvTools MFlowInter(Blend=True). Blend or copy frame at scene change.
IthSCD1, Default 400, See MvTools MFlowInter(thSCD1=400) : (0 < IthSCD1 <= (8*8)*255)
IthSCD2, Default 130, See MvTools MFlowInter(thSCD1=130) : (0 < IthSCD1 <= 255)
Threshold which sets how many blocks have to change for the frame to be considered as a
scene change. It is ranged from 0 to 255, 0 meaning 0 %, 255 meaning 100 %.
Default is 130 (which means 51.0%).
Used by MvTools2 MFlowInter during interpolation.

Show, Default True, Show Metrics.
Verb, Default True, If Verb And Show, then show additional metrics.

SOSthSCD2 Default 130. As for MSCDetection(thSCD2=SOSthSCD2). Halt backwards search for JerkFrame where StartOfScene.

Simple metrics on Show, "nnnn] UD : S : CIR", where nnnn is frame number, and character Flags highlited where,
Duplicity2 Status:
U = Unique frame status from Dupliicty DBase (non dupe, includes low motion static scene etc).
D = Dupe frame status from Dupliicty DBase.

:
S = Current frame is Start Of Scene.

: DropDeadGorgeous Decisions :
C = Copy frame (original as source frame)
I = Interpolated frame
Interpolated frames also show eg {I1/2:ILft=1275,IRgt=1276}
where, first of 2 Interpolated frames, and interpolate source frames are 1275 and 1276(JerkFrame usually, unless DupeS-1=SOS).
R = Relocated frame from earlier in clip (interpolated frames shove following frames to later in clip, removing dupes)
Reloacted frames also show eg {R1/8:Src=1276,n-2}
where, first of 8 relocated frames, source for current relocated frame is frame 1276, which is current frame-2.

If Verb=True, also shows eg below
Motion(n-1,n)=0.367 # Motion metric between current frame and current frame-1 (JerkFrame search metric).
ScanMaxdist=9 (Cnt=7) @ 3458 # Maximum ScanAhead distance found to dupes (count of instances found), and most recent @ frame 3458.
MostCommonScanDist=8 (Cnt=190) # The most common ScanAhead distance found between jerkframe and dupes, and instance count.
# Maybe reduce ScanAhead arg to value as shown for MostCommonScanDist.

Can use any Duplicity Mode in creating DBase, the Duplicity2 End+1 Scene change thing has no effect here (not necessary).

It may be possible to up framerate to a non multiple of source whilst keeping all source frames verbatim, where eg source
is 24 FPS and required = 25 FPS, and using,
Src24.ChangeFPS(25) to produce a new clip at 25 FPS with an exact duplicate every 24 source frames and save new source as eg Src25.avi.
Process new source with eg src25.Duplicity2(ThG=0.1,DBase="D:\Src25_Det.DB"), to produce a DBase (perhaps with MaxDupLen=1, perhaps not).
Then use Src25.DropDeadGorgeous("D:\Src25_Det.DB",ScanAhead=12) to interpolate dupe frames achieving 25.0 and with all original
source frames. With a ScanAhead of eg 12, will locate dupes and then backwards scan up to 12 frames before the dupes looking for
frame of greatest movement, insert an interpolated frame prior to that greatest movement frame and shove all following frames along one
to remove the dupe. Might be worth someone experimenting.
Or, you could just use eg Duplicity2(Mode=2,ThG=0.1) to interpolate the exact dupes directly and without DropDeadGorgeous but that might
produce a more rhythmic stutter every 25 frames.

*/

StainlessS
17th November 2018, 14:59
DropDeadGorgeous.avsi part 2


Function DropDeadGorgeous(clip c,String DB,Int "ScanAhead",
\ Int "X",Int "Y",Int"W",Int "H",
\ Int "SPad", Int "SSharp", Int "SRFilter", [* MSuper *]
\ Int "ABlkSize", Int "AOverlap", Int "ASearch",Int "ADct", [* MAnalyse *]
\ Int "RBlkSize", Int "ROverlap", Int "RthSAD", [* MRecalculate *]
\ Float "Iml", Bool "IBlend", Int "IthSCD1", Int "IthSCD2", [* MFlowInter *]
\ Bool "Show", Bool "Verb",Int "SOSthSCD2"
\ ) {
c myName="DropDeadGorgeous: " VER=2.13
# RT_Version(), x.yyyzz where yyy==999, denotes version (x.yyy+0.001) Beta zz ie 1.99911 = v2.00 Beta 11.
Assert(RT_Version() >= 1.99911,RT_String("%sNeed RT_Stats v2.00Beta11(%s)",myName,RT_VersionString))
IsAvsPlus=(FindStr(UCase(versionString),"AVISYNTH+")!=0) HasGScript=RT_FunctionExist("GScript")
HasGRunt =RT_FunctionExist("GScriptClip") HasMvTools=RT_FunctionExist("MSuper")
HasMaskTools=RT_FunctionExist("MT_Lutxy") HasRemoveGrain=RT_FunctionExist("RemoveGrain")
HasCallCmd=RT_FunctionExist("CallCmd")
ScanAhead = Default(ScanAhead,9)
X=default(X,0) Y=default(Y,0) W=default(W,0) H=default(H,0)
SPad = Default(SPad,16) SSharp = Default(SSharp,1) SRFilter= Default(SRFilter,4)
ABlkSize = Default(ABlkSize,16) AOverlap= Default(AOverlap,4) ASearch = Default(ASearch,3) ADct = Default(ADct,0)
RBlkSize = Default(RBlkSize,8) ROverlap= Default(ROverlap,2) RthSAD = Default(RthSAD,100)
Iml = Default(Iml,200.0) IBlend = Default(IBlend,True) IthSCD1 = Default(IthSCD1,400) IthSCD2= Default(IthSCD2,130)
Show = Default(Show,True) Verb=Show?Default(Verb,True):False SOSthSCD2=Default(SOSthSCD2,130)
Assert(0 < ScanAhead <= 60,RT_String("%s0 < ScanAhead(%d) <= 60",myName,ScanAhead))
####
Assert(DB!="",RT_String("%sDB Cannot be ''",myName))
DB1 = RT_GetFullPathName(DB)
NameOnly=RT_FilenameSplit(DB,12) # Just name and extension parts, no Drive/Path
Assert(RT_DBaseGetID(DB,0) == VER,RT_String("%s'%s' Wrong version DBase(v%.2f), require v%.2f",myName,NameOnly,RT_DBaseGetID(DB,0),VER))
Assert(RT_DBaseGetID(DB,1) == c.Framecount,RT_String("%s'%s' DBase is incomplete",myName,NameOnly))
W = (W > 0) ? (W + X) - Width : W H = (H > 0) ? (H + Y) - Height : H # Make -ve relative width,height
X = (X+3) / 4 * 4 Y = (Y+3) / 4 * 4 # Round UP (inwards) Mod 4
W = (W-3) / 4 * 4 H = (H-3) / 4 * 4 # Round DOWN(inwards) Mod 4
W = Width - X + W H = Height - Y + H # +ve width,height
DC=Crop(X,Y,W,H)
FuncS="""
Function Fn@@@(clip c,clip dc,String DB1,String DB2,int ScanAhead,Int SOSthSCD2,Bool Show,Bool Verb) {
c n=current_frame
Stat2 = RT_DBaseGetField(DB2,n,0)
if(Stat2 == 0) {
Stat1 = RT_DBaseGetField(DB1,n,FLD_STAT@@@)
if(Stat1 >= FLG_DE@@@) { # Is a dupe (user musta jumped about), do backwards scan
Index=RT_DBaseGetField(DB1,n,FLD_INDEX@@@)
DupS=n-Index # Start of duplicate run
Count=RT_DBaseGetField(DB1,DupS,FLD_COUNT@@@) # Dup Count stored only in first Record of Sub Sequence
DupE=DupS+Count-1 # End of dupe run
if(DupS < 2) { # Not enough prev frames to interpolate
for(i=0,DupE) { RT_DBaseSet(DB2,i,1,0,0,0) } # Copy from 0, cant do anything else.
} Else {
ScanS = Max(DupS - ScanAhead, 1)
for(i=DupS-1,ScanS,-1) { # Make sure no dupes in backwards scan range
if(RT_DBaseGetField(DB1,i,FLD_STAT@@@) >= FLG_DE@@@) { ScanS=i+1 i=-1 }
}
mxi = -1
mxDif = -1.0
for(i=DupS-1,ScanS,-1) {
if(SOS@@@.RT_AverageLuma(n=i).Int!=0) { i=-1 } # Break at Start Of Scene with current max
Else {
dif = MFPC@@@.RT_AverageLuma(n=i)
if(dif>mxDif) { mxDif=dif mxi = i }
}
}
if(mxi<0) { # No JerkFrame found, ie DupS-1 is StartOfScene
if(DupE+1==c.FrameCount || SOS@@@.RT_AverageLuma(n=DupE+1).Int!=0) {
for(i=ScanS,DupE) { RT_DBaseSet(DB2,i,1,0,0,0) } # Copy all, Cannot Interpolate.
} Else { # DupS-1 is SOS, and DupE+1 is NOT SOS, Interpolate dupes using source DupS-1 and DupE+1
for(i=ScanS,DupS-1) { RT_DBaseSet(DB2,i, 1,0,0,0) } # Copy frames up to SOS frame
for(i=DupS,DupE) { RT_DBaseSet(DB2,i, 2,COUNT,i-DupS,1) } # Interp, Type SOS
}
} Else {
for(i=mxi,mxi+Count-1) { RT_DBaseSet(DB2,i, 2,COUNT,i-mxi,0) } # Interpolate
Cnt2=DupE-(mxi+Count)+1
for(i=mxi+Count,DupE) { RT_DBaseSet(DB2,i, 3,COUNT,i-mxi,Cnt2) } # Relocate Frame relative (frame n = frame n - COUNT)
if(Verb) {
scandist = DupS - mxi
cnt = RT_DBaseGetAttrib(DB2,scandist) + 1
RT_DBaseSetAttrib(DB2,scandist,cnt)
if(cnt >= ScanComCnt@@@) {
if(cnt == ScanComCnt@@@) {
Global ScanComDist@@@=Max(ScanComDist@@@,scandist)
} Else {
Global ScanComCnt@@@ = cnt
Global ScanComDist@@@ = scandist
}
}
if(scandist>=ScanMaxDist@@@) {
if(scandist==ScanMaxDist@@@) {
Global ScanMaxPos@@@ = Max(mxi,ScanMaxPos@@@)
} Else {
Global ScanMaxDist@@@=scandist
Global ScanMaxPos@@@=mxi
}
}
}
}
}
# Frame Following this dupe run is a NON DUPE.
} Else { # Non dupe
ScanE = Min(n+(ScanAhead*2),c.FrameCount-1)
DupS = -1
for(i=n+1,ScanE) { if(RT_DBaseGetField(DB1,i,FLD_STAT@@@) >= FLG_DE@@@) { DupS = i i=ScanE } } # find 1st dupe
if(DupS<0) { # dupe not found
for(i=n,Max(ScanE-ScanAhead,n)) { RT_DBaseSet(DB2,i,1,0,0,0) } # Copy
} Else {
Count=RT_DBaseGetField(DB1,DupS,FLD_COUNT@@@) # Dup Count stored only in first Record of Sub Sequence
DupE=DupS+Count-1
ScanS = Max(DupS - ScanAhead, n)
mxi = -1
mxDif = -1.0
for(i=DupS-1,ScanS,-1) { # Search for JerkFrame
if(SOS@@@.RT_AverageLuma(n=i).Int!=0) { i=-1 } # Break @ Start Of Scene with current max
Else {
dif = MFPC@@@.RT_AverageLuma(n=i)
if(dif>mxDif) { mxDif=dif mxi = i }
}
}
if(mxi<0) { # No JerkFrame found, ie DupS-1 is StartOfScene
if(DupE+1==c.FrameCount || SOS@@@.RT_AverageLuma(n=DupE+1).Int!=0) {
for(i=n,DupE) { RT_DBaseSet(DB2,i,1,0,0,0) } # Copy all, Cannot Interpolate.
} Else { # DupS-1 is SOS, and DupE+1 is NOT SOS, Interpolate dupes using source DupS-1 and DupE+1
for(i=n,DupS-1) { RT_DBaseSet(DB2,i, 1,0,0,0) } # Copy frames up to SOS frame
for(i=DupS,DupE) { RT_DBaseSet(DB2,i, 2,COUNT,i-DupS,1) } # Interp, Type=SOS
}
} Else {
for(i=n,mxi-1) { RT_DBaseSet(DB2,i,1,0,0,0) } # Copy frames prior to frame of greatest movement
for(i=mxi,mxi+Count-1) { RT_DBaseSet(DB2,i, 2,COUNT,i-mxi,0) } # Interp
Cnt2=DupE-(mxi+Count)+1
for(i=mxi+Count,DupE) { RT_DBaseSet(DB2,i, 3,COUNT,i-mxi,Cnt2) } # relocate frames
if(Verb) {
scandist = DupS - mxi
cnt = RT_DBaseGetAttrib(DB2,scandist) + 1
RT_DBaseSetAttrib(DB2,scandist,cnt)
if(cnt >= ScanComCnt@@@) {
if(cnt == ScanComCnt@@@) {
Global ScanComDist@@@=Max(ScanComDist@@@,scandist)
} Else {
Global ScanComCnt@@@ = cnt
Global ScanComDist@@@ = scandist
}
}
if(scandist>=ScanMaxDist@@@) {
if(scandist==ScanMaxDist@@@) {
Global ScanMaxPos@@@ = Max(mxi,ScanMaxPos@@@)
} Else {
Global ScanMaxDist@@@=scandist
Global ScanMaxPos@@@=mxi
}
}
}
}
}
}
Stat2 = RT_DBaseGetField(DB2,n,0)
}
if(Stat2==2) { # Interpolated
Count = RT_DBaseGetField(DB2,n,1)
Index = RT_DBaseGetField(DB2,n,2)
iType = RT_DBaseGetField(DB2,n,3) # 0) Normal Interpolate with shove duplicates, 1) DupS-1=SOS
if(iType==0) {
TmpC=c
FixFrm=n-Index-1
} Else {
DupS=n-Index DupE=DupS+Count-1
IFrms=3
LS=Max(DupS-IFrms,0)
LCnt=DupS-LS RCnt=Min(c.FrameCount-1-DupE,IFrms)
TmpC = c.Trim(LS,-LCnt) ++ c.Trim(DupE+1,-RCnt)
FixFrm=LCnt-1
}
Prefilt=TmpC.RemoveGrain(22)
Pad=SPad@@@ Sharp=SSharp@@@ srfilter=SRFilter@@@ Ablksize=ABlkSize@@@ AOverLap=AOverLap@@@ ASearch=ASearch@@@ ADct=ADct@@@
Super=TmpC.MSuper(hpad=Pad,vpad=Pad,levels=1,sharp=Sharp,rfilter=srfilter)
Superfilt=Prefilt.MSuper(hpad=Pad,vpad=Pad,sharp=Sharp,rfilter=srfilter)
bv=Superfilt.MAnalyse(isb=true ,blksize=Ablksize,overlap=AOverLap,search=ASearch,delta=1,dct=ADct)
fv=Superfilt.MAnalyse(isb=False ,blksize=Ablksize,overlap=AOverLap,search=ASearch,delta=1,dct=ADct)
if(RBlkSize@@@>0) {
RBlkSize=RBlkSize@@@ ROverLap=ROverLap@@@ RthSAD=RthSAD@@@
bv=Super.MRecalculate(bv,blksize=RBlkSize,overlap=ROverLap,thSAD=RthSAD)
fv=Super.MRecalculate(fv,blksize=RBlkSize,overlap=ROverLap,thSAD=RthSAD)
}
TmpC=TmpC.MFlowInter(Super,bv,fv,time=100.0*(Index+1)/(Count+1),ml=Iml@@@,blend=IBlend@@@,thSCD1=IthSCD1@@@,thSCD2=IthSCD2@@@)
TmpC.Trim(FixFrm,-1)
if(Show) {
DStat=(RT_DBaseGetField(DB1,n,0)>=FLG_DE@@@)
sos = (SOS@@@.RT_AverageLuma(n=n).Int!=0)
if(iType==0) { iLft=FixFrm iRgt=iLft+1 }
else { iLft=DupS-1 iRgt=DupE+1 }
if(Verb) {
mot = MFPC@@@.RT_AverageLuma(n=n)
ScanMaxDist=ScanMaxDist@@@
ScanMaxDistCnt=RT_DBaseGetAttrib(DB2,ScanMaxDist)
RT_Subtitle(Fmtv_I@@@,n,DStat?76:45,DStat?45:76,sos?45:76,Index+1,Count,ILft,IRgt,
\ mot,ScanMaxDist,ScanMaxDistCnt,ScanMaxPos@@@,ScanComDist@@@,ScanComCnt@@@)
} Else { RT_Subtitle(Fmt_I@@@,n,DStat?76:45,DStat?45:76,sos?45:76,Index+1,Count,ILft,IRgt) }
}
} Else if(Stat2==3) { # Relocated
DStat=(RT_DBaseGetField(DB1,n,0)>=FLG_DE@@@)
RelocOffset = RT_DBaseGetField(DB2,n,1)
c.Trim(n-RelocOffset,-1) # Relocated, n - count
if(Show) {
Count = RT_DBaseGetField(DB2,n,3)
Index = RT_DBaseGetField(DB2,n,2) - RelocOffset
sos = (SOS@@@.RT_AverageLuma(n=n).Int!=0)
if(Verb) {
mot = MFPC@@@.RT_AverageLuma(n=n)
ScanMaxDist=ScanMaxDist@@@
ScanMaxDistCnt=RT_DBaseGetAttrib(DB2,ScanMaxDist)
RT_Subtitle(Fmtv_R@@@,n,DStat?76:45,DStat?45:76,sos?45:76,Index+1,Count,n-RelocOffset,RelocOffset,
\ mot,ScanMaxDist,ScanMaxDistCnt,ScanMaxPos@@@,ScanComDist@@@,ScanComCnt@@@)
} Else { RT_Subtitle(Fmt_R@@@,n,DStat?76:45,DStat?45:76,sos?45:76,Index+1,Count,n-RelocOffset,RelocOffset) } }
} Else if(Show) { # Copy original
DStat=(RT_DBaseGetField(DB1,n,0)>=FLG_DE@@@)
sos = (SOS@@@.RT_AverageLuma(n=n).Int!=0)
if(Verb) {
mot = MFPC@@@.RT_AverageLuma(n=n)
ScanMaxDist=ScanMaxDist@@@
ScanMaxDistCnt=RT_DBaseGetAttrib(DB2,ScanMaxDist)
RT_Subtitle(Fmtv_C@@@,n,DStat?76:45,DStat?45:76,sos?45:76,
\ mot,ScanMaxDist,ScanMaxDistCnt,ScanMaxPos@@@,ScanComDist@@@,ScanComCnt@@@)
} Else { RT_Subtitle(Fmt_C@@@,n,DStat?76:45,DStat?45:76,sos?45:76) }
}
Return Last
}

StainlessS
17th November 2018, 15:00
DropDeadGorgeous.avsi part 3


Function StartOfSceneClip(clip c,Int "thSCD1",Int "thSCD2") { # All Luma Samples set 255 at SOS, else 0
thSCD1=Default(thSCD1,400) thSCD2=Default(thSCD2,130)
sup=c.MSuper(pel=1,sharp=0,rfilter=2,hpad=16, vpad=16)
fv=sup.MAnalyse(isb=false,delta=1,blksize=16)
Return c.MSCDetection(fv,thSCD1=thSCD1,thSCD2=thSCD2)
}
Function MMaskFromPrevClip(clip c,Int "MaskType",Float "Gamma",Int "thSCD1",Int "thSCD2") {
# MaskType:- 0=Motion, 1=SAD, 2=Occlusion, 3=Horizontal, 4=Vertical, 5=ColorMap.
MaskType=Default(MaskType,0) Gamma=Default(Gamma,1.0) thSCD1=Default(thSCD1,400) thSCD2=Default(thSCD2,130)
sup=c.MSuper(pel=1,sharp=0,rfilter=2,hpad=16, vpad=16)
fv=sup.MAnalyse(isb=false,delta=1,blksize=16)
Return c.MMask(fv,Gamma=1.0,kind=MaskType,thSCD1=thSCD1,thSCD2=thSCD2)
}
DB2 = RT_GetFullPathName("~@@@_"+RT_LocalTimeString+".DB") RT_DBaseAlloc(DB2,FrameCount,"iiii")
Global ScanComDist@@@=0 Global ScanComCnt@@@=0
Global ScanMaxDist@@@=0 Global ScanMaxPos@@@=0
Global SOS@@@ = dc.StartOfSceneClip(thSCD2=SOSthSCD2)
Global MFPC@@@= dc.MMaskFromPrevClip(Gamma=1.0,MaskType=0,thSCD1=8*8*255,thSCD2=255) # Motion, Switched OFF SC detection, we want all results.
### Some DB1 Fields:-
Global FLD_STAT@@@ = 0 # Holds Status FLGS
Global FLD_INDEX@@@ = 4 # Index into Count (0 Relative, 0->Count-1)
Global FLD_COUNT@@@ = 5 # Sequence Frame Count
### Some DB1 Status Flags in Field FLD_STAT@@@
Global FLG_DE@@@ = 7 # Duplicate Sequence is followed by Scene Change (below is non dupe, greater or equalis dupe)
###
Global SPad@@@=SPad Global SSharp@@@=SSharp Global SRFilter@@@=SRFilter
Global ABlkSize@@@=ABlkSize Global AOverLap@@@=AOverLap Global ASearch@@@=ASearch Global ADct@@@=ADct
Global RBlkSize@@@=RBlkSize Global ROverLap@@@=ROverLap Global RthSAD@@@=RthSAD
Global Iml@@@=Iml Global IBlend@@@=IBlend Global IthSCD1@@@=IthSCD1 Global IthSCD2@@@=IthSCD2
Global Fmt_C@@@ ="%d] \a%cU\a%cD\a- : \a%cS\a- : C\aLIR"
Global Fmt_I@@@ ="%d] \a%cU\a%cD\a- : \a%cS\a- : \aLC\a-I\aLR\a- {I%d/%d:Lft=%d,IRgt=%d}"
Global Fmt_R@@@ ="%d] \a%cU\a%cD\a- : \a%cS\a- : \aLCI\a-R\a- {R%d/%d:Src=%d,n-%d}"
Global Fmtv_C@@@=Fmt_C@@@ + "\a-\nMotion(n-1,n)=%.3f\nScanMaxDist=%d (Cnt=%d) @ %d\nMostCommonScanDist=%d (Cnt=%d)"
Global Fmtv_I@@@=Fmt_I@@@ + "\a-\nMotion(n-1,n)=%.3f\nScanMaxDist=%d (Cnt=%d) @ %d\nMostCommonScanDist=%d (Cnt=%d)"
Global Fmtv_R@@@=Fmt_R@@@ + "\a-\nMotion(n-1,n)=%.3f\nScanMaxDist=%d (Cnt=%d) @ %d\nMostCommonScanDist=%d (Cnt=%d)"
###
ARGS = "dc,DB1,DB2,ScanAhead,SOSthSCD2,Show,Verb"
ScriptLine = "Fn@@@("+ARGS+")"
Last.GScriptClip(ScriptLine, local=true, args=ARGS)
"""
GIFunc="DROPDEADGORGEOUS" # Function Name, Supply unique name for your multi-instance function.
GIName=GIFunc+"_InstanceNumber" # Name of the Instance number Global
RT_IncrGlobal(GIName) # Increment Instance Global (init to 1 if not already exists)
GID = GIFunc + "_" + String(Eval(GIName))
InstS = RT_StrReplace(FuncS,"@@@","_"+GID)
# Write Debug GScript File to current directory (line numbers will correspond to error messages)
# RT_WriteFile("DEBUG_"+GID+".TXT","%s",InstS)
HasGScript ? GScript(InstS) : Eval(InstS,"GS_EVAL") # Use GSCript if installed (loaded plugs override builtin)
# if CallCmd available, Auto delete DBase file on clip closure.
HasCallCmd?CallCmd(close=RT_String("""CMD /C chcp 1252 && del "%s" """,DB2), hide=true, Synchronous=7):NOP
Return Last
}

StainlessS
19th November 2018, 01:48
From post #46,
It may be possible to up framerate to a non multiple of source whilst keeping all source frames verbatim, where eg source
is 24 FPS and required = 25 FPS, and using,
Src24.ChangeFPS(25) to produce a new clip at 25 FPS with an exact duplicate every 24 source frames and save new source as eg Src25.avi.
Process new source with eg src25.Duplicity2(ThG=0.1,DBase="D:\Src25_Det.DB"), to produce a DBase (perhaps with MaxDupLen=1, perhaps not).
Then use Src25.DropDeadGorgeous("D:\Src25_Det.DB",ScanAhead=12) to interpolate dupe frames achieving 25.0 and with all original
source frames. With a ScanAhead of eg 12, will locate dupes and then backwards scan up to 12 frames before the dupes looking for
frame of greatest movement, insert an interpolated frame prior to that greatest movement frame and shove all following frames along one
to remove the dupe. Might be worth someone experimenting.


I tried above converting [EDIT: true] 25.0 FPS to 30.0FPS, using ChangeFPS(30.0), and Duplicity2(ThG=0.1,MaxDuplen=1),
Then, used DropDeadGorgeous(ScanAhead=5), result produced is 30FPS with all original source frames, and with good fluid motion throughout.
ChangeFPS(30.0) inserts duplicate after every five source frames, and DropDeadGorgeous(ScanAhead=5) introduces
an interpolated frame within 5 frames prior to the duplicate (between frames of greatest motion) and pushes the following frames one position
along to squeeze out the duplicate.
Works pretty good.
EDIT: If source clip was badly decimated from eg 30FPS to 25 and with jerky motion due to decimation, above should produce pretty much the best possible result and repair/tween the jerk frames produced by the decimation.
EDIT: Should also perform well in cases where cadence changes, eg where source was decimated from 29.97 FPS to 25 FPS,
or where source was edited after decimation, neither one should be any problem.

Frank62
19th November 2018, 11:53
A few months ago this could have saved my life...
I have some sources to test - when I will have time (can last longer) - I will tell you the result!