Log in

View Full Version : Avisynth "morph" function, way to automate it and stability concerns


Pages : 1 [2]

StainlessS
6th December 2018, 23:32
Morpheus.avs v0.02 Part 2 of 2.


Function Morpheus(clip c,String Cmd,Bool "Inclusive",
\ Int "Prefilter", [* Prefilter *]
\ Int "SPad", Int "SPel", Bool "SChroma", Int "SSharp", Int "SRFilter", [* MSuper *]
\ Int "ABlkSize", Int "ABlkSizeV", [* MAnalyse *]
\ Int "ASearch", Int "ASearchParam", Int "APelSearch", [* MAnalyse *]
\ Bool "AChroma", Bool "ATrueMotion", [* MAnalyse *]
\ Int "AOverlap", Int "AOverlapV", [* MAnalyse *]
\ Int "ADct", Bool "ATryMany", [* MAnalyse *]
\ Int "RthSAD", Int "RBlkSize", Int "RBlkSizeV", [* MRecalculate *]
\ Int "RSearch", Int "RSearchParam", [* MRecalculate *]
\ Bool "RChroma", Bool "RTrueMotion", [* MRecalculate *]
\ Int "ROverlap", Int "ROverlapV", Int "RDct", [* MRecalculate *]
\ Float "Iml", Bool "IBlend", Int "IthSCD1", Int "IthSCD2", [* MFlowInter *]
\ Bool "Show"
\ ) {
c myName="Morpheus: "
IsAvsPlus=(FindStr(UCase(versionString),"AVISYNTH+")!=0) HasGScript=RT_FunctionExist("GScript")
HasGRunt =RT_FunctionExist("GScriptClip") HasMvTools=RT_FunctionExist("MSuper")
HasRemoveGrain=RT_FunctionExist("RemoveGrain") HasCallCmd =RT_FunctionExist("CallCmd")
IsAvs26=VersionNumber>=2.6
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(HasRemoveGrain,RT_String("%sNeed RemoveGrain",myName))
Assert(IsYV12||(IsAvs26&&(IsY8||IsYV16||IsYV24)),RT_String("%sOnly Standard v2.6 Planar Supported (excepting YV411)",myname))
Assert(Cmd!="",String("%sCmd cannot be ''",myName))
#
Inclusive = Default(Inclusive,True)
PreFilter=Default(PreFilter,1) # 0=Blur(0.6), 1=RemoveGrain(22), 2=RemoveGrain(1).RemoveGrain(22)
SPad=Default(SPad,16) SPel=Default(SPel,2)
SChroma=Default(SChroma,True)
SSharp=Default(SSharp,1) SRFilter= Default(SRFilter,4)
ABlkSize=Default(ABlkSize,c.Width>1920?32:c.Width>1100?24:c.Width>720?16:8) ABlkSizeV=Default(ABlkSizeV,ABlkSize)
ASearch=Default(ASearch,3) ASearchParam=Default(ASearchParam,2) APelSearch=Default(APelSearch,SPel)
AChroma=Default(AChroma,SChroma) ATrueMotion=Default(ATrueMotion,ABlksize<16)
AOverlap=Default(AOverlap,4) AOverlapV=Default(AOverlapV,AOverlap)
ADct=Default(ADct,0) ATryMany=Default(ATryMany,False)
RthSAD=Default(RthSAD,100) RBlkSize=Default(RBlkSize,ABlkSize/4*2) RBlkSizeV=Default(RBlkSizeV,RBlkSize)
RSearch=Default(RSearch,ASearch) RSearchParam=Default(RSearchParam,ASearchParam)
RChroma=Default(RChroma,AChroma) RTrueMotion=Default(RTrueMotion,ATrueMotion)
ROverlap=Default(ROverlap,RBlkSize>2?2:0) ROverlapV=Default(ROverlapV,ROverlap) RDct=Default(RDct,ADct)
Iml=Default(Iml,200.0) IBlend=Default(IBlend,True)
IthSCD1=Default(IthSCD1,400) IthSCD2= Default(IthSCD2,130)
Show=Default(Show,False)
####
FuncS="""
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,String DB,Bool Show,String Fmt1,String Fmt2) {
c n=current_frame
if(RT_DBaseGetField(DB,n,0)) { # Is an Interpolated frame
Start = RT_DBaseGetField(DB,n,1) # Start of Interpolated Frames (Inclusive)
End = RT_DBaseGetField(DB,n,2) # End of Interpolated Frames (Inclusive)
Count = End - Start + 1 # Count of Interpolated frames in this run
Index = n-Start # Index into Count (0 relative, 0 -> Count-1)
OFrms=4 # Max number of frames to use from either side of Interpolated run (Src Frames, before & after)
LS=Max(Start-OFrms,0)
LCnt=Start-LS RCnt=Min(c.FrameCount-1-End,OFrms)
TmpC = c.Trim(LS,-LCnt) + c.Trim(End+1,-RCnt) # Src used for interpolation, (with some extra frames[higher quality sometimes])
FixFrm=LCnt-1 # Frame where Interpolated frame will be created
PreFilter=PreFilter@@@
PreFilt=Prefilter==0?TmpC.Blur(0.6):Prefilter==1?TmpC.RemoveGrain(22):TmpC.RemoveGrain(1).RemoveGrain(22)
SPad=SPad@@@ SPel=SPel@@@ SChroma=SChroma@@@
SSharp=SSharp@@@ SRfilter=SRFilter@@@
Super=TmpC.MSuper(hpad=SPad,vpad=SPad,pel=SPel,levels=1,Chroma=SChroma,sharp=SSharp,rfilter=SRfilter)
Superfilt=Prefilt.MSuper(hpad=SPad,vpad=SPad,pel=SPel,chroma=SChroma,sharp=SSharp,rfilter=SRfilter)
ABlksize=ABlkSize@@@ ABlksizeV=ABlkSizeV@@@
ASearch=ASearch@@@ ASearchParam=ASearchParam@@@ APelSearch=APelSearch@@@
AChroma=AChroma@@@ ATrueMotion=ATrueMotion@@@
AOverLap=AOverLap@@@ AOverLapV=AOverLapV@@@
ADct=ADct@@@ ATryMany=ATryMany@@@
bv=Superfilt.MAnalyse(isb=true ,delta=1,blksize=ABlksize,blksizeV=ABlksizeV,
\ search=ASearch,searchParam=ASearchParam,pelSearch=APelSearch,
\ chroma=AChroma,trueMotion=ATrueMotion,overlap=AOverLap,overlapV=AOverLapV,dct=ADct,trymany=ATryMany)
fv=Superfilt.MAnalyse(isb=false,delta=1,blksize=ABlksize,blksizeV=ABlksizeV,
\ search=ASearch,searchParam=ASearchParam,pelSearch=APelSearch,
\ chroma=AChroma,trueMotion=ATrueMotion,overlap=AOverLap,overlapV=AOverLapV,dct=ADct,trymany=ATryMany)
RBlkSize=RBlkSize@@@
if(RBlkSize>0) {
RthSAD=RthSAD@@@ RBlkSizeV=RBlkSizeV@@@
RSearch=RSearch@@@ RSearchParam=RSearchParam@@@ RChroma=RChroma@@@
RTrueMotion=RTrueMotion@@@ ROverLap=ROverLap@@@ ROverLapV=ROverLapV@@@ RDct=RDct@@@
bv=Super.MRecalculate(bv,thSAD=RthSAD,blksize=RBlkSize,blksizeV=RBlkSizeV,
\ Search=RSearch,searchParam=RSearchParam,chroma=RChroma,truemotion=RTrueMotion,
\ overlap=ROverLap,overlapV=ROverLapV,dct=RDct)
fv=Super.MRecalculate(fv,thSAD=RthSAD,blksize=RBlkSize,blksizeV=RBlkSizeV,
\ Search=RSearch,searchParam=RSearchParam,chroma=RChroma,truemotion=RTrueMotion,
\ overlap=ROverLap,overlapV=ROverLapV,dct=RDct)
}
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) # Interpolated Frame to return
if(Show) { RT_Subtitle(Fmt2,n,Index+1,Count) }
} Else if(Show) { RT_Subtitle(Fmt1,n) }
Return Last
}
if(ChrIsStar(CMD)) {
CMD=MidStr(CMD,2)
} else {
Cmd=RT_GetFullPathName(Cmd)
Assert(Exist(CMD),RT_String("%sCMD File does not exist",myName))
CMD=RT_ReadTxtFromFile(CMD)
}
LINES=RT_TxtQueryLines(CMD) FC=Framecount
DB = RT_GetFullPathName("~@@@_"+RT_LocalTimeString+".DB") RT_DBaseAlloc(DB,FrameCount,"bii")
for(i=0,LINES-1) {
SS=RT_TxtGetLine(CMD,i).ChrEatWhite
S=SS
if(!S.ChrIsNul && !S.ChrIsHash) {
if(S.ChrIsDigit) {
StartF = S.RT_NumberValue
EndF=StartF
S=S.ChrEatDigits.ChrEatWhite
if(S.ChrIsComma) {S=S.MidStr(2).ChrEatWhite}
IsNeg = S.ChrIsHyphen
if(IsNeg) {S=S.MidStr(2).ChrEatWhite}
if(S.ChrIsDigit) {
EndF=S.RT_NumberValue
if(IsNeg) {
Assert(Inclusive,RT_String("%sCMD: Error@Line_%d, Exclusive End Frame Cannot be -ve\n%s",myName,i+1,SS))
EndF=StartF+EndF-1
}
S=S.ChrEatDigits
} Else if(!Inclusive) {
Assert(False,RT_String("%sCMD: Error@Line_%d, Exclusive must have End Frame\n%s",myName,i+1,SS))
} Else if(IsNeg) { Assert(False,RT_String("%sCMD: Error@Line_%d, Expecting End Frame\n%s",myName,i+1,SS)) }
Start_I = (Inclusive) ? StartF : StartF+1
End_I = (Inclusive) ? EndF : EndF-1
Assert(Start_I>0,RT_String("%sCMD: Error@Line_%d, Illegal Start frame\n%s",myName,i+1,SS))
Assert(End_I<FC-1,RT_String("%sCMD: Error@Line_%d, EndFrame(%d)+1 Out Of Clip\n%s",myName,i+1,End_I+1,SS))
Inclusive
\ ? Assert(Start_I<=End_I,RT_String("%sCMD: Error@Line_%d, StartFrame(%d) <= EndFrame(%d)\n%s",myName,i+1,Start_I,End_I,SS))
\ : Assert(StartF<EndF-1,RT_String("%sCMD: Error@Line_%d, None to interpolate, Start(%d) End(%d)\n%s",myName,i+1,StartF,EndF,SS))
Assert(!(RT_DBaseGetField(DB,Start_I-1,0)||RT_DBaseGetField(DB,End_I+1,0)),
\ RT_String("%sCMD: Error@Line_%d, Adjacent Interpolation\n%s",myName,i+1,SS))
for(n=Start_I,End_I) {
if(RT_DBaseGetField(DB,n,0)) {
if(RT_DBaseGetField(DB,n,1)!=Start_I || RT_DBaseGetField(DB,n,2)!=End_I) {
Assert(False,RT_String("%sCMD: Error@Line_%d, Overlapping Interpolation\n%s",myName,i+1,SS))
}
}
RT_DBaseSet(DB,n,True,Start_I,End_I)
}
S=S.ChrEatWhite
}
if(!S.ChrIsHash) { Assert(S.ChrIsNul,RT_String("%sCMD: Error@Line_%d, *** NON-PARSE ***\n'%s'",myName,i+1,SS)) }
}

}
Global PreFilter@@@=PreFilter
Global SPad@@@=SPad Global SPel@@@=SPel Global SChroma@@@=SChroma
Global SSharp@@@=SSharp Global SRFilter@@@=SRFilter
Global ABlkSize@@@=ABlkSize Global ABlkSizeV@@@=ABlkSizeV
Global ASearch@@@=ASearch Global ASearchParam@@@=ASearchParam Global APelSearch@@@=APelSearch
Global AChroma@@@=AChroma Global ATrueMotion@@@=ATrueMotion
Global AOverLap@@@=AOverLap Global AOverLapV@@@=AOverLapV Global ADct@@@=ADct Global ATryMany@@@=ATryMany
Global RthSAD@@@=RthSAD Global RBlkSize@@@=RBlkSize Global RBlkSizeV@@@=RBlkSizeV
Global RSearch@@@=RSearch Global RSearchParam@@@=RSearchParam
Global RChroma@@@=RChroma Global RTrueMotion@@@=RTrueMotion
Global ROverLap@@@=ROverLap Global ROverLapV@@@=ROverLapV Global RDct@@@=RDct
Global Iml@@@=Iml Global IBlend@@@=IBlend Global IthSCD1@@@=IthSCD1 Global IthSCD2@@@=IthSCD2
###
Fmt1="%d]"
Fmt2="%d] I%d/%d"
ARGS = "DB,Show,Fmt1,Fmt2"
ScriptLine = "Fn@@@("+ARGS+")"
Last.GScriptClip(ScriptLine, local=true, args=ARGS)
"""
GIFunc="MORPHEUS" # 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" """,DB), hide=true, Synchronous=7):NOP
Return Last
}

EDIT: Added some checking for overlapping commands in BLUE.

Client

#Import(".\Morpheus.avs") # or put in plugins dir

Colorbars(Pixel_type="YV12").KillAudio.ShowFrameNumber
INCLUSIVE=True
SHOW=True

INCLUSIVE_CMD="""* # <<<<==== Asterisk(Star) is first character, ie is a String Command, else is a Filename.
10 11 # This Is a Comment
15
20 -2
"""

EXCLUSIVE_CMD="""* # <<<<==== Asterisk(Star) is first character, ie is a String Command, else is a Filename.
9 12
14 16
19 22
"""

# Select Inclusive or Exclusive CMD depending upon value of INCLUSIVE
CMD = (INCLUSIVE) ? INCLUSIVE_CMD : EXCLUSIVE_CMD

Morpheus(Cmd,Inclusive=INCLUSIVE,Show=SHOW)

abolibibelot
10th December 2018, 04:02
I know how much I trust my own memory, so forgive me for not being 100% convinced by yours :)
Only suggestion to re-install old stuff and check, then maybe start thread with concrete and provable and repeatable results.
Well, I get what you're saying about the general unreliability of memory, but in this case, that statement was based on screenshots I made in January...
And now that I've re-installed Avisynth+ r1576, it works again as intended, as I wrote in the other thread (https://forum.doom9.org/showthread.php?p=1859302#post1859302). But I can no longer load an AVS script as input for ffmpeg, it says that Avisynth is too old... :( And yet strangely on the seemingly official page for Avisynth+ (http://avs-plus.net/), r1576 is presented as the most recent version. Oh well...

If you find one, let me know. (likely would be a sort of 'if its like this, do that, and if its like the other then do alternative, and if its a bit like both, then do something else').
Experimentation, and hard work is probably best way to understanding, although Zorr has 'Avisynth Optimizer' thread in Avisynth Development forum.
Well, I'm quite admirative of the work you collectively accomplish here to create and improve those wonderful little scripts, but I'm currently operating at a much lower level, the task I'm trying to finish is already overwhelming in and of itself, with many, many “moving parts”, I might get completely lost if I begin to try every single combination of parameters with every single script and command and plugin I gather along the way, while reading hundreds of pages of discussions relevant to each one of them, without even having a clear reference as to what can possibly be accomplished and what I should aim for. Sometimes when being completely immersed in some highly complex task it's easy to lose track of what had to be done in the first place, because “a fanatic is one who redoubles his effort when he has forgotten his aim” (George Santayana – quoted by Chuck Jones to describe the behaviour of the Coyote toward the Roadrunner) and “you can't depend on your eyes when your imagination is out of focus” (Mark Twain – but I've heard it in the series Dexter, in its second season, when it was actually very good, that was such a long time ago...).

Morpheus.avs v0.02 Part 1 of 2.
Morpheus.avs v0.02 Part 2 of 2.
I've never seen a script in two parts, how are they supposed to be combined ?

StainlessS
10th December 2018, 16:17
it says that Avisynth is too old
I'm guessin' that r1576 [2014] uses old version 5 header/interface which is not compatible with current v2.60 avs/+, perhaps even crashes (and your ffmpeg probably written for Version 6 interface). Version 6 header/interface came in with avs 2.60 Alpha 4, any avs 2.60 before that should never now be used.

The official avs+ page is owned by Ultim, and he no longer visits, Pinterf (current numero uno) is thinking about opening his own avs+ thread, apparently (dig, dig) :)

I think that the only person that really understood mvtools usage (excluding original authors) was probably Didee, and he only very rarely visits (maybe in response to some particularly inciting post). I certainly dont fully (or even halfly, quarterly) understand mvtools, is almost a total mystery. Best one can do is read the docs/examples and try to make some sense of it. If anybody ever did write a mvtools 'guide', he would have a monumental task on his hands, methinks.

I've never seen a script in two parts, how are they supposed to be combined ?

Copy & paste should work just fine. (Part 1 is only Documentation enclosed in /* ... */ comments).
EDIT: Comments:- http://avisynth.nl/index.php/The_full_AviSynth_grammar#Whitespace.2C_Line_Continuation_and_Comments
EDIT:
Maximum post size is 16KB in Usage Forum, hence 2 posts [Developer Forum 20KB).
And you would need an Import() in client, will add now.

EDIT:
I certainly dont fully (or even halfly, quarterly) understand mvtools
I'm not sure if I've done below wrong [EDIT: or non optimal], (used MRecalculate on Super clip instead of SuperFilt clip, maybe I do some testing), they would both ways work, but I suspect that the other way may work better.
[ie change the clip below in red to the clip in blue]

bv=Superfilt.MAnalyse(isb=true ,delta=1,blksize=ABlksize,blksizeV=ABlksizeV,
\ search=ASearch,searchParam=ASearchParam,pelSearch=APelSearch,
\ chroma=AChroma,trueMotion=ATrueMotion,overlap=AOverLap,overlapV=AOverLapV,dct=ADct,trymany=ATryMany)
fv=Superfilt.MAnalyse(isb=false,delta=1,blksize=ABlksize,blksizeV=ABlksizeV,
\ search=ASearch,searchParam=ASearchParam,pelSearch=APelSearch,
\ chroma=AChroma,trueMotion=ATrueMotion,overlap=AOverLap,overlapV=AOverLapV,dct=ADct,trymany=ATryMany)
RBlkSize=RBlkSize@@@
if(RBlkSize>0) {
RthSAD=RthSAD@@@ RBlkSizeV=RBlkSizeV@@@
RSearch=RSearch@@@ RSearchParam=RSearchParam@@@ RChroma=RChroma@@@
RTrueMotion=RTrueMotion@@@ ROverLap=ROverLap@@@ ROverLapV=ROverLapV@@@ RDct=RDct@@@
bv=Super.MRecalculate(bv,thSAD=RthSAD,blksize=RBlkSize,blksizeV=RBlkSizeV,
\ Search=RSearch,searchParam=RSearchParam,chroma=RChroma,truemotion=RTrueMotion,
\ overlap=ROverLap,overlapV=ROverLapV,dct=RDct)
fv=Super.MRecalculate(fv,thSAD=RthSAD,blksize=RBlkSize,blksizeV=RBlkSizeV,
\ Search=RSearch,searchParam=RSearchParam,chroma=RChroma,truemotion=RTrueMotion,
\ overlap=ROverLap,overlapV=ROverLapV,dct=RDct)
}

abolibibelot
13th December 2018, 09:49
I'm guessin' that r1576 [2014] uses old version 5 header/interface which is not compatible with current v2.60 avs/+, perhaps even crashes (and your ffmpeg probably written for Version 6 interface). Version 6 header/interface came in with avs 2.60 Alpha 4, any avs 2.60 before that should never now be used.
In the mean time I found this :
https://video.stackexchange.com/questions/20742/unable-to-convert-avisynth-script-in-ffmpeg

The official avs+ page is owned by Ultim, and he no longer visits, Pinterf (current numero uno) is thinking about opening his own avs+ thread, apparently (dig, dig)
As if all this needed to be moar complicated ! é_è

I think that the only person that really understood mvtools usage (excluding original authors) was probably Didee, and he only very rarely visits (maybe in response to some particularly inciting post). I certainly dont fully (or even halfly, quarterly) understand mvtools, is almost a total mystery. Best one can do is read the docs/examples and try to make some sense of it. If anybody ever did write a mvtools 'guide', he would have a monumental task on his hands, methinks.
That's doubly, quadruply humbling ! That Didee seems to be a real virtuoso... It feels like the “legend” from Franz Kafka's The Trial, where a poor dude wants to access the Law, but is blocked at the door by a guard, and the guard tells him that there are other doors guarded by other guards, each of them much more powerful than the one before, and he is himself freaked out by the next one...

Copy & paste should work just fine. (Part 1 is only Documentation enclosed in /* ... */ comments).
Maximum post size is 16KB in Usage Forum, hence 2 posts [Developer Forum 20KB).
Alright... I feel doubly dumb !

And you would need an Import() in client, will add now.
Indeed it doesn't work if the script is simply put in the “plugins” folder.

A quick test...

Base frame (https://www.cjoint.com/c/HLnaHZMFQbL) :
https://www.cjoint.com/doc/18_12/HLnaHZMFQbL_136-base.png

FrameSurgeon (https://www.cjoint.com/c/HLnaILVq3SL) :
https://www.cjoint.com/doc/18_12/HLnaILVq3SL_136-FrameSurgeon.png

Morpheus v1 (https://www.cjoint.com/c/HLnaJaVwdAL) (v2 seems to produce the same result) :
https://www.cjoint.com/doc/18_12/HLnaJaVwdAL_136-Morpheus-v1.png

Morpheus v3 (https://www.cjoint.com/c/HLnaJxk1rtL) :
https://www.cjoint.com/doc/18_12/HLnaJxk1rtL_136-Morpheus-v3.png

Morph (https://www.cjoint.com/c/HLnaJWg88lL) :
https://www.cjoint.com/doc/18_12/HLnaJWg88lL_136-Morph.png

=> In a case like this, with a “large object” moving quickly, especially laterally and over a non uniform background, Morph usually produces the less ugly result. And for this particular frame (which is only slightly blurred), none of those filters is significantly improving over the original.

By the way :
OK, compiled SawBones for above NotePad2 from http://notepad2.com/
Available from SendSpace below this post, until link expires.
I missed that, and apparently the link has expired, could you please re-upload it if you still have that file lying around ?

StainlessS
13th December 2018, 18:51
Despite what the StackExchange post said, version 6 Header came in with v2.6 Alpha 4 (not RC1), however it is possible (even likely) that one or two more
changes did occur between those versions (and even since RC1, at least in avs+).

Indeed it doesn't work if the script is simply put in the “plugins” folder.
Yep, sorry, autoload avs scripts in plugin dir should have extension '.avsi'. (something you should watch out for if putting any auto load script there).

the link has expired
I do not have it lying around, deleted after upload, I do not wanna get into doing specials for everybody that dont have system NotePad lying around.
I think that I posted the mods that needed to be done (by you), to get around your self imposed problem.
Are you saying that you cannot run system NotePad at all ? (If so, then I may [when time permits] do it all again for you, but I dont like doing specials).

abolibibelot
14th December 2018, 01:31
I do not have it lying around, deleted after upload, I do not wanna get into doing specials for everybody that dont have system NotePad lying around.
I think that I posted the mods that needed to be done (by you), to get around your self imposed problem.
Are you saying that you cannot run system NotePad at all ? (If so, then I may [when time permits] do it all again for you, but I dont like doing specials).

No, it does work with system Notepad, as I explained I have to remove a registry key to be able to launch it (otherwise it launches Notepad2, which has been configured to replace the original Notepad), and that's how I used Sawbones when I did the bulk of the work in April/May, that's what I did again earlier today. It's just that it's less convenient; aside from having to tinker with the registry (not a big deal, it's just one key, I saved it before deleting it, I just have to reload the .reg file to recover the former behaviour), a significant drawback is that the native Notepad doesn't indicate if a file has been modified, contrary to Notepad2 which displays the name with a “*” when it hasn't been saved ; another is that the original Notepad has only one “undo” / “redo” level, whereas Notepad2 has A LOT (I've already undone or redone hundreds of edits successfully), which is definitely useful for a task like this. So it's OK if you don't re-compile and re-upload it for me this time, but that may be something beneficial for anybody in need of this already very special tool if you plan a future revision. Or at least provide detailed instructions to re-compile it for an alternative text editor.
For now, if anyone using Notepad2 has the same issue, here's the registry key to save and delete :
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\notepad.exe

So I resumed using Sawbones (v. 1.09), and after a few minutes I noticed a similar behaviour to what I experienced a few months ago : the actual commands are fine so far (so it's an improvement over v. 1.04 which I used at first), but there are several errors in the comments as you can see below.
I1 2345 # 2345,2345
I2 2348 # 2348,2349
I1 2351 # 235&,2351
I1 2354 # 2"54,2354
I1 2356 # 2"56,2356
I1 2364 " 2364,2364
I1 2366 " 2366,2366
I2 2373 # 2373,2"74
I1 2377 # 2377,2377
I1 2380 # 2"80,2380
I1 2383 # 23_3,2383
I2 2392 # 2392,23ç3
I1 2397 # 2397,2397
And it's not reproducible : if I use the same keyboard shortcut again right afterward (CTRL+SHIFT+ALT+[number]) it's displayed correctly, or it can be erroneous again. Usually the same erroneous character replaces the same correct caracter (for instance a “9” becomes a “ç”, a “3” becomes a “"”, the “#” can also become a “"” as it's on the same key on an AZERTY keyboard).
I1 2418 2418,2418
I1 2418 " 2418,2418
I1 2418 # 2418,2418
It's not a big deal as most commands come out right (and so far only the comments are affected, with v. 1.04 there were no comments and the commands themselves had errors, it caused the script to malfunction, when there were thousands of commands it was quite tricky to track down), but it means that the output has to be verified regularly.

StainlessS
14th December 2018, 13:36
OK, I've removed the # comments following interpolations, think that there may be a bug in the AutoIt ControlSend() function for raw keys,
the '#' key denotes the Windows Key when sending cooked (special) characters, somehow its mis interpreting the # when raw, and when it should not
change anything at all. Anyway, have removed # chars and following comment frame ranges so we avoid whether bug or not.

Here v1.10, source AutoIt code:- http://www.mediafire.com/file/a9x9h92xu6ckwgf/SawBones.7z/file
You need AutoIt current version, and also best use SciTE editor (find on AutoIt web site downloads along with AutoIt), and make changes near beginning of source.


#cs ----------------------------------------------------------------------------
This program is free software; you can redistribute it and/or modify it under any terms terms you like.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Use at you own risk.

#ce ----------------------------------------------------------------------------
; SawBones v1.10 by StainlessS ... compiled with AutoIt v3.3.14.5

#include <MsgBoxConstants.au3>
#include <Misc.au3>
Opt("MustDeclareVars", 1)
;;;
Global Const $Version = "SawBones v1.10"
Global Const $APP_NAME = "SawBones.Exe"
Global Const $APP_INI = "SawBones.ini"
Global Const $Watching = " SawBones is WATCHING "
Global Const $APPTitle = "VirtualDub2" ; VirtualDub2 matches as "VirtualDub2" with traiiling "Build number" on title bar.
Global Const $ScriptTitle = "VirtualDub2 Script Editor" ; VirtualDub2 Script Editor Window
Global Const $ScriptControl = "[CLASS:Scintilla; INSTANCE:1]"
Global Const $VdFrameNo = "[CLASS:Edit; INSTANCE:1]" ; Frame Indicator box (bottom middle of window, just above status line)
Global Const $VDRange = "[CLASS:msctls_statusbar32; INSTANCE:1]" ; Frame Range (bottom Left of window, 'Selecting Frames...' when range selected)
;
; CAN CHANGE below "Notepad" and "Edit" to change editor, use AutoIt Au3Info program to get names (try 1st with NotePad.exe to see how to use it).
Global Const $EdTitle = "[CLASS:Notepad]" ; NotePad Window name.
Global Const $EditControl = "[CLASS:Edit; INSTANCE:1]" ; NotePad text editor window control.
; eg for NotePad2, Comment out above two lines and uncomment below two lines (Semi Colon is comment character).
; After changes, in AutoIt SciTE source editor, hit F7 to rebuild executable. (probably the same key in the basic AutoIt included editor).
;Global Const $EdTitle = "[CLASS:Notepad2]" ; NotePad2 Window name.
;Global Const $EditControl = "[CLASS:SysListView32; INSTANCE:1]" ; NotePad2 text editor window control.


Make changes (as described in the above code), hit F7 to rebuild.

EDIT: I think it should work ok, dont think I ever did get a response when asking if I had located the correct NotePad2 program that you use.
Just make similar changes to any future versions of Sawbones.
EDIT: Install the 32 bit version of AutoIt (option in installer), I've never tried it on 64 bit, and see no advantage whatsoever in doing so.
Edit Control "[CLASS:SysListView32; INSTANCE:1]" might be specific to 32 bit version and so may not work in x64 AutoIt.
If you do install 64bit, and it dont work, suggest try change to "[CLASS:SysListView64; INSTANCE:1]".
EDIT: Above wrong, might need change to "[CLASS:SysListView64; INSTANCE:1]" if using 64 bit Notepad2, not 64 bit AutoIt.

zorr
15th December 2018, 23:27
I might get completely lost if I begin to try every single combination of parameters with every single script and command and plugin I gather along the way, while reading hundreds of pages of discussions relevant to each one of them, without even having a clear reference as to what can possibly be accomplished and what I should aim for.

I can relate to that, that's basically the reason I created AvisynthOptimizer. The idea of the optimizer is that you don't have to figure out anything, just let the computer find the optimal values for each script and source (or even a single frame). I have focused on MVTools because it's
A) incredibly useful in itself and the backbone of many advanced filters
B) very complex with dozens of parameters and therefore hard to understand
C) has the features which make an automatic optimization process possible

If you want to try the optimizer then this is all you need to do:
1) download the package (https://drive.google.com/open?id=1s5LbJkas6-H7X5FfCEg0MoiNyl0cEbzB) and install it
2) make an "augmented" script where you tell which parameters the optimizer will try to optimize (and you don't need to do this yourself, I can provide an augmented MVTools script ready to go)
3) set the source and choose which frame or frames you want to optimizer to focus on
4) start the optimizer and wait for the results (which you can also inspect visually while the optimization is in progress). Note that this part can take a long time, I am using 50 000 iterations with my optimization tasks and it takes about 3 days per run. If you're in a hurry just set the iterations lower (default is 2000) or even tell how long time optimizer can run (in days, hours, minutes).

The best parameters found by the optimizer you can then use with Morpheus and/or FrameSurgeon as they are both using MVTools.

I'm currently running an MVTools optimization myself but after it's finished (probably tomorrow) I'd like to start another one using some of those difficult frames of yours. I'm interested in finding out how the optimal paramers change with different source videos. Perhaps with enough tests I can start writing the 'MVTools guide' StainlessS mentioned. :)

[EDIT]
It's also possible to reduce the artifacts you're seeing by doing another MVTools pass after the first one using MCompensate (just learned today that Didée suggested the same thing in 2012).

Also forgot to mention that the optimization process needs "good" frames to figure out the optimal parameters, so in this case you should let it focus on frames before and after your bad frame (with similar motion than in the bad frame) and then try to reconstruct the bad frame using the settings found.

StainlessS
16th December 2018, 00:06
I'm not sure if I've done below wrong [EDIT: or non optimal], (used MRecalculate on Super clip instead of SuperFilt clip, maybe I do some testing), they would both ways work, but I suspect that the other way may work better.
[ie change the clip below in red to the clip in blue]

bv=Superfilt.MAnalyse(isb=true ,delta=1,blksize=ABlksize,blksizeV=ABlksizeV,
\ search=ASearch,searchParam=ASearchParam,pelSearch=APelSearch,
\ chroma=AChroma,trueMotion=ATrueMotion,overlap=AOverLap,overlapV=AOverLapV,dct=ADct,trymany=ATryMany)
fv=Superfilt.MAnalyse(isb=false,delta=1,blksize=ABlksize,blksizeV=ABlksizeV,
\ search=ASearch,searchParam=ASearchParam,pelSearch=APelSearch,
\ chroma=AChroma,trueMotion=ATrueMotion,overlap=AOverLap,overlapV=AOverLapV,dct=ADct,trymany=ATryMany)
RBlkSize=RBlkSize@@@
if(RBlkSize>0) {
RthSAD=RthSAD@@@ RBlkSizeV=RBlkSizeV@@@
RSearch=RSearch@@@ RSearchParam=RSearchParam@@@ RChroma=RChroma@@@
RTrueMotion=RTrueMotion@@@ ROverLap=ROverLap@@@ ROverLapV=ROverLapV@@@ RDct=RDct@@@
bv=Super.MRecalculate(bv,thSAD=RthSAD,blksize=RBlkSize,blksizeV=RBlkSizeV,
\ Search=RSearch,searchParam=RSearchParam,chroma=RChroma,truemotion=RTrueMotion,
\ overlap=ROverLap,overlapV=ROverLapV,dct=RDct)
fv=Super.MRecalculate(fv,thSAD=RthSAD,blksize=RBlkSize,blksizeV=RBlkSizeV,
\ Search=RSearch,searchParam=RSearchParam,chroma=RChroma,truemotion=RTrueMotion,
\ overlap=ROverLap,overlapV=ROverLapV,dct=RDct)
}
TmpC=TmpC.MFlowInter(Super,bv,fv,time=100.0*(Index+1)/(Count+1),ml=Iml@@@,blend=IBlend@@@,thSCD1=IthSCD1@@@,thSCD2=IthSCD2@@@)

EDIT: Added line in Green.

Any comment on above Zorr ?
I was gonna test it out when I get the time, but maybe you know already.
If above is correct, and I have done it sub optimal, then I also messed up Precise (MRecalculate) in McDegrainSharp(Precise=true)

EDIT: If my effort was not optimal, then the legendary jm_fps() is similarly non optimal.

zorr
16th December 2018, 02:03
Any comment on above Zorr ?

Yes I have a comment: I don't know. :)

I was gonna test it out when I get the time, but maybe you know already. If above is correct, and I have done it sub optimal, then I also messed up Precise (MRecalculate) in McDegrainSharp(Precise=true)

EDIT: If my effort was not optimal, then the legendary jm_fps() is similarly non optimal.

Yes I noticed that jm_fps() is using the non-filtered super clip with MRecalculate. The way I used it in my tests so far was using the filtered super clip in both. I have no idea which way works better generally, it's worth finding out. Yippee, more tests to run...

StainlessS
16th December 2018, 03:33
Below, Bottom left is a copy of previous frame, due to being too different (seen as scene change, Blend=False) and was using MRecalculate via Super clip.
Bottom right, MRecalculate via SuperFilt is not a copy of prev frame (not seen as scene change) and so presume that Superfilt is indeed the better option for MRecalculate.
EDIT: Or maybe rather that so much identical grey, and harder to figure out what goes where (rather than scene change), but same conclusion, SuperFilt better.

https://i.postimg.cc/zbsB4k0v/StarWars.jpg (https://postimg.cc/zbsB4k0v)

Script

VideoFileName ="D:\STARWARS\VIDEO_TS\StarWars.d2v"
Mpeg2Source(VideoFileName)
Crop(0,72,0,-72) # strip borders
ORG=Last
#return last
AMP=true
#FRAME=6995 # -1 = NO TRIM, else return trimmed single FRAME
FRAME=-1
FPS=250.0 # Lower to play slower (Also set FRAME = -1)
AMP_MARGIN=8 # for AMP Levels
TXT=RT_GetFullPathName(".\SWFrame.TXT")
RT_FileDelete(TXT)
LIMIT=1.0
#######################
SelectEven # Half framerate
J1 = jm_fps(fps=ORG.FrameRate) # Doubled to same as original, recalc on super
J2 = jm_fps2(fps=ORG.FrameRate) # Doubled to same as original, recalc on superfilt
ORG=RTSub(ORG,"Source")
d=Subtract(j1,j2) # Centered on TV Levels Y = 126.0
d=(AMP) ? d.levels(126-AMP_MARGIN,1.0,126+AMP_MARGIN,126-126,126+126,coring=false).GreyScale : d.GreyScale
BigDif= -1
BigDifFrm=-1
SSS="""
dif=RT_AverageLuma
Curdif=Abs(dif - 126.0) # TV Levels mid point(126.0)
if(Curdif>BigDif) {
BigDifFrm=current_frame
BigDif=Curdif
if(BigDif > LIMIT) {
RT_WriteFile(TXT,"%d] %.3f",current_frame,BigDif,Append=True)
}
}
return RT_Subtitle("BigDifFrm=%d BigDif=%.3f Curdif=%.3f",BigDifFrm,BigDif,Curdif)
"""
d=(FRAME<0) ? d.ScriptClip(SSS) : d

# Return d.Assumefps(FPS) # show only difference clip

d=RTSub(d,AMP?"diff AMP=True":"diff AMP=False")
J1E=J1.SelectEven.RTSub("Recalc Super")
J1O=J1.SelectOdd.RTSub("Recalc Super Interpolated")
J1=Interleave(J1E,J1O)
J2E=J2.SelectEven.RTSub("Recalc SuperFilt")
J2O=J2.SelectOdd.RTSub("Recalc SuperFilt Interpolated")
J2=Interleave(J2E,J2O)
V=ORG.BlankClip(Width=4,Color=$FF00FF)
TOP = StackHorizontal(ORG,V,D)
BOT = StackHorizontal(J1,v,J2)
H=TOP.BlankClip(Height=4,Color=$FF00FF)
StackVertical(TOP,H,BOT)
(FRAME==-1) ? Last : Trim(FRAME,-1)
Return Assumefps(FPS)
#######################

Function jm_fps(clip source, float "fps", int "BlkSize", int "Dct") {
fps = default(fps, 25.000)
fps_num = int(fps * 1000)
fps_den = 1000
BlkSize = default(BlkSize, 16)
Dct = default(Dct, 0)

prefiltered = RemoveGrain(source, 22)
super = MSuper(source, hpad = 16, vpad = 16, levels = 1, sharp = 1, rfilter = 4) # one level is enough for MRecalculate
superfilt = MSuper(prefiltered, hpad = 16, vpad = 16, sharp = 1, rfilter = 4) # all levels for MAnalyse
backward = MAnalyse(superfilt, isb = true, blksize = BlkSize, overlap = 4, search = 3, dct = Dct)
forward = MAnalyse(superfilt, isb = false, blksize = BlkSize, overlap = 4, search = 3, dct = Dct)
forward_re = MRecalculate(super, forward, blksize = 8, overlap = 2, thSAD = 100)
backward_re = MRecalculate(super, backward, blksize = 8, overlap = 2, thSAD = 100)
return MFlowFps(source, super, backward_re, forward_re, num = fps_num, den = fps_den, blend = false, ml = 200, mask = 2)
}

Function jm_fps2(clip source, float "fps", int "BlkSize", int "Dct") {
fps = default(fps, 25.000)
fps_num = int(fps * 1000)
fps_den = 1000
BlkSize = default(BlkSize, 16)
Dct = default(Dct, 0)

prefiltered = RemoveGrain(source, 22)
super = MSuper(source, hpad = 16, vpad = 16, levels = 1, sharp = 1, rfilter = 4) # one level is enough for MRecalculate
superfilt = MSuper(prefiltered, hpad = 16, vpad = 16, sharp = 1, rfilter = 4) # all levels for MAnalyse
backward = MAnalyse(superfilt, isb = true, blksize = BlkSize, overlap = 4, search = 3, dct = Dct)
forward = MAnalyse(superfilt, isb = false, blksize = BlkSize, overlap = 4, search = 3, dct = Dct)
forward_re = MRecalculate(superfilt, forward, blksize = 8, overlap = 2, thSAD = 100)
backward_re = MRecalculate(superfilt, backward, blksize = 8, overlap = 2, thSAD = 100)
return MFlowFps(source, super, backward_re, forward_re, num = fps_num, den = fps_den, blend = false, ml = 200, mask = 2)
}

# Stack Overhead RT_Subtitle Text, with optional FrameNumber shown.
Function RtSub(clip c,string Tit, Bool "ShowFrameNo") {
c.BlankClip(height=20)
(Default(ShowFrameNo,False)) ? ScriptClip("""RT_Subtitle("%d] %s",current_frame,""""+Tit+"""")""") : RT_Subtitle("%s",Tit)
Return StackVertical(c).AudioDubEx(c)
}

EDIT: Some Mods
EDIT: Can probably just play clip until you see a massive difference frame with AMP=true. (as I did). [Maybe slow down via Assumefps() at end of script]
EDIT: So it seems that many scripts need be amended.
EDIT: Added FPS.
EDIT: Setting jp_fps() MFlowFPS(ThSCD2=255) to switch off scene change detection stuff results in frame that is pretty much identical
to jp_fps2(), I cant really see much difference, but the metrics sure do. Anyways, SuperFilt probably still better.

EDIT: Although, in above case, would copy prev frame or blend be better option with fewer artefacts, any views ?
EDIT: Think I'm sticking with original conclusion, too much of a jerk if copying prev frame, superfilt version is more fluid and will just look better playing normal speed.

EDIT: More mods, writes file of bad frames.

zorr
16th December 2018, 22:33
...but same conclusion, SuperFilt better.

It would make sense that the filtered super works better for both, if it works better for the first MAnalyze. But I think I will do a more comprehensive test of this... some day.

There's also an option to do filtering for both MAnalyze and MRecalculate but use different kind of filtering (or different parameters) for MRecalculate.

So far in my tests I have concluded that doing multiple RemoveGrains can help the quality. In the latest test doing RemoveGrain(16) followed by RemoveGrain(23) was the best combination, but that was just for one source video (VHS quality) and might be different with other kind of videos. MRecalculate was not used in that test so it tells nothing about what kind of filtering to use with it.

zorr
16th December 2018, 22:38
abolibibelot, will you accept my offer to search the optimal MVTools parameters for some of your bad frames? In that case could you please share a short video segment (10-20 frames), preferably in original size and using lossless compression which includes at least one bad frame you'd like to replace. Thanks!