View Full Version : Brain freeze
johnmeyer
10th September 2021, 20:54
I always have problems figuring out how to do conditionals.
This is a line from a function that, when clip tests below the "badthreshold" should return the clip (c). If it is above the threshold, then I want to return the previous frame if it is an odd frame, and the next frame if it is an even frame.
I just can't quite noodle it out.
replacement1 = SHOWDOT ? c.subtitle("***").selectevery(1,-1) : c.selectevery(1,-1)
replacement2 = SHOWDOT ? c.subtitle("***").selectevery(1,1) : c.selectevery(1,1)
fixed = scriptclip("""YDifferenceFromPrevious()/Max(YDifferenceFromPrevious( selectevery( 1, -2) ),0.001 ) < badthreshold
\ ? c : (current_frame %2 <> 0) ? replacement1 : replacement2""")
StainlessS
10th September 2021, 21:53
Looks ok to me except for selectevery( 1, -2).
This shows all three outcomes in first 3 frames. [EDIT: on frame 0, D1 and also D will be zero so below threshold and then frame 1 = odd, frame 2 = even]
/*
This is a line from a function that, when clip tests below the "badthreshold" should return the clip (c).
If it is above [EDIT: or EQUAL] the threshold, then I want to return the previous frame if it is an odd frame, and the next frame if it is an even frame.
*/
c=ColorBars(Pixel_type="YV12").ShowFrameNumber.KillAudio
c
SHOWDOT=TRUE
badthreshold=0.5
Prev = SHOWDOT ? c.subtitle("*** Prev [Odd]",y=20).selectevery(1,-1) : c.selectevery(1,-1) # replacement1
Next = SHOWDOT ? c.subtitle("*** Next [Even]",y=20).selectevery(1,1) : c.selectevery(1,1) # replacement2
SSS="""
D1 = YDifferenceFromPrevious() # diff n, n-1
# D2 = YDifferenceFromPrevious( selectevery( 1, -2) ) # diff n-2, n-3 # Not sure that this is what you want
D2 = YDifferenceFromPrevious( selectevery( 1, -1) ) # diff n-1, n-2 # Maybe this required
D = D1 / Max(D2,0.001) # avoid Div by Zero [OK]
D < badthreshold
\ ? ((SHOWDOT) ? c.Subtitle("below the badthreshold",y=20) : c)
\ : (current_frame %2 <> 0)
\ ? Prev [* Odd, Prev replacement1 *]
\ : Next [* Even, Next replacement2 *]
(SHOWDOT) ? Subtitle(String(current_frame,"%.0f] ")+String(D1,"D1=%f ")+String(D2,"D2=%f ")+String(D,"D=%f ")) : NOP
return last
"""
scriptclip(SSS)
Think thats what you were aiming for. [you can just mod your selectevery( 1, -2) thingy]
So,
replacement1 = SHOWDOT ? c.subtitle("***").selectevery(1,-1) : c.selectevery(1,-1)
replacement2 = SHOWDOT ? c.subtitle("***").selectevery(1,1) : c.selectevery(1,1)
fixed = scriptclip("""YDifferenceFromPrevious()/Max(YDifferenceFromPrevious( selectevery( 1, -1) ),0.001 ) < badthreshold
\ ? c : (current_frame %2 <> 0) ? replacement1 : replacement2""")
EDIT: EDITED test script so SHOWDOT controls all subs, and mod to badthreshold=0.5 (from 0.1) so that shows "below the badthreshold" at some additional frames as well as frame 0.
Moved all subs to top LHS of frame.
johnmeyer
11th September 2021, 22:52
Thanks for your help. I couldn't get it to play at all.
I've spent way too much time on this (hours) and have made no progress. This is the test clip:
http://www.mediafire.com/folder/vovhrmkoeccqs,pee74qgnlo3x5fd/shared
If you bob or separatefields() you will see that the problem is that one field captures the film pulldown during the transfer. I simply want to replace the bad field with the good field from the same frame. The slight reduction in spatial quality is virtually undetectable.
The problem is that sometimes the bad field is the upper field and sometimes the lower field. The following works when the bad field is the second of the two fields in the frame. I was trying to add a conditional so that when the bad frame was the first field, it would grab the following field ("frame", since it is bobbed).
The ReplaceBadField() function is the only thing that needs work, but every attempt to use ConditionalSelect or ScriptClip ends up replacing the wrong thing, adding or decimating fields, and other stuff that is quite weird. As I said in my original post, I have never gotten my mind around conditionals in AVISynth.
Getting old is a bitch. I don't think I can do this much longer.
#Find And (Optionally) Fix Bad Workprinter Frames
loadplugin("C:\Program Files\AviSynth 2.5\plugins\MVTools\mvtools2.dll")
#Control script operation by changing the following values :
#=====================================================================
VideoFile = "e:\fs.avi"
#VideoFile = "S:\Video\Rosen Video\Rosen Movies\1 (yellow sticker); 11 on can; Europe June 15 1952 to August 18, 1952.avi"
global badthreshold = 2.0 # Set METRICS=TRUE to determine best value
METRICS = FALSE # TRUE will show Metrics ONLY (i.e., TRUE overrides all other selctions)
SHOWDOT = TRUE # TRUE will add "***" to each replacment frame (for troubleshooting)
REPLACE = TRUE # TRUE will replace each bad frame with a one that is interpolated from adjacent frames
FILEWRITE = FALSE # TRUE will create a file which contains the frame numbers of all bad frames
filename = "E:\Bad.txt" # Set to name and location where you want the frame numbers stored
#=====================================================================
source = AVISource(VideoFile).convertTOYV12().killaudio().bob(0.0,1.0)
script = """Subtitle("\nPrevious Ratio = " + String( YDifferenceFromPrevious(source) /
\ Max(YDifferenceFromPrevious( selectevery(source, 1, -2) ),0.001 ) ) , lsp=0)"""
MetClip = Scriptclip(source, script)
FileFixed = (FILEWRITE)
\ ? WriteFileIf(source, filename, "
\ YDifferenceFromPrevious(source) / Max(YDifferenceFromPrevious( selectevery(source, 1, -2) ),0.001 )
\ > badthreshold && (current_frame %2 <> 0)", "((current_frame-1)/2)", append = false) : Source
output = (METRICS) ? MetClip : (REPLACE) ? ReplaceBadField(FileFixed,showdot) : FileFixed
return output.separatefields().selectevery(4,1,2).weave()
#------------------------------
function ReplaceBadField (clip c, bool SHOWDOT)
{
replacement = SHOWDOT ? c.subtitle("***").selectevery(1,-1) : c.selectevery(1,-1)
fixed = ConditionalSelect(c, "
YDifferenceFromPrevious()/Max(YDifferenceFromPrevious( selectevery( 1, -2) ),0.001 ) > badthreshold && (current_frame %2 <> 0) ? 0 : 1", \
replacement, c)
return fixed
}
StainlessS
12th September 2021, 01:22
ArHa, you woz bobbing and weaving, and stuff :)
In that case there was nothing wrong with your ternary conditionals thingies at all, just the logic is not working well, I aint figured it out either yet.
Basically, in differencing with previous bobbed field, it only differences within the same pair of bobbed fields when current frame is odd.
Because of this, can fix bad fields when is odd field, but not when even field. [EDIT: fields meaning frames, b'cos bobbed]
Fixed fields [all ODD]
7
11
35
49
59
Unfixed [All EVEN, and also adds more bad fields]
70
84
98
112
126
140
This does same as your [EDIT: Opening post] script, but as my mod without the bad SelectEvery(1,-1) fix.
VideoFile = ".\Replace Bad Fields.avi"
AviSource(VideoFile).convertToYV12(Matrix="rec601")
AssumeBFF
#return SeparateFields
Bob(0.0,1.0)
#Return Last
c=Last
SHOWDOT=True
badthreshold=2.0
Prev = SHOWDOT ? c.subtitle("*** Prev [Odd]",y=20).selectevery(1,-1) : c.selectevery(1,-1) # replacement1
Next = SHOWDOT ? c.subtitle("*** Next [Even]",y=20).selectevery(1,1) : c.selectevery(1,1) # replacement2
SSS="""
D1 = YDifferenceFromPrevious() # diff n , n-1
D2 = YDifferenceFromPrevious(selectevery(1,-2)) # diff n-2, n-3
D = D1 / Max(D2,0.001) # avoid Div by Zero
D < badthreshold
\ ? ((SHOWDOT) ? c.Subtitle("below the badthreshold",y=20) : c)
\ : (current_frame %2 <> 0)
\ ? Prev [* Odd, Prev replacement1 *]
\ : Next [* Even, Next replacement2 *]
(SHOWDOT) ? Subtitle(String(current_frame,"%.0f] ")+String(D1,"D1=%f ")+String(D2,"D2=%f ")+String(D,"D=%f ")) : NOP
return last
"""
scriptclip(SSS)
StackVertical(c,Last) # Original on top, fixed + subs on bottom
Original on top, fixed + subs on bottom
Only fixes bad ODD fields.
will try find better working code.
johnmeyer
12th September 2021, 03:46
StainlessS,
Yup, you understand.
This code almost works, but I can't get the replacement to work when the bad field is the second of the two from the bobbed frame.
function ReplaceBadField (clip c, bool SHOWDOT)
{
replacement1 = SHOWDOT ? c.subtitle("***").selectevery(1,-1) : c.selectevery(1,-1)
replacement2 = SHOWDOT ? c.subtitle("***").selectevery(1,1) : c.selectevery(1,1)
fixed = ConditionalSelect(c, "
YDifferenceFromPrevious()/Max(YDifferenceFromPrevious( selectevery( 1, -2) ),0.001 ) > badthreshold
\ ? ((current_frame %2 <> 0) ? 0:1) : 2", replacement1, replacement2, c)
return fixed
}
[edit]Ah, it is slowly dawning on me that I have to have a completely different comparison for odd fields than for even fields. This is because I always need to be comparing two "bobbed fields" from the same frame, and I should never involve fields from adjacent frames. The comparison for the first (odd) field must be to the next field, and the comparison for the next (even) field must look back at the previous field. The replacement logic is probably OK, but the comparison isn't. I'll work on it some more tomorrow when I'm fresher.
StainlessS
12th September 2021, 04:14
Maybe I've gone off on a wild goose chase, but this is what I was tryin' [going to beddy-byes].
VideoFile = ".\Replace Bad Fields.avi"
AviSource(VideoFile).convertToYV12(Matrix="rec601")
AssumeBFF
#return SeparateFields
Bob(0.0,1.0)
#Return Last
c=Last
SHOWDOT=True
badthreshold=2.0
Prev = SHOWDOT ? c.subtitle("*** Prev [Odd]",y=40).selectevery(1,-1) : c.selectevery(1,-1) # replacement1
Next = SHOWDOT ? c.subtitle("*** Next [Even]",y=40).selectevery(1,1) : c.selectevery(1,1) # replacement2
SSS="""
IsOdd = current_frame %2 <> 0
D1 = (IsOdd) ? YDifferenceFromPrevious() : YDifferenceToNext() # ODD diff n , n-1 : EVEN diff n , n+1 [Difference fields from SAME current frame]
D2 = (IsOdd) ? YDifferenceFromPrevious(selectevery(1,-2)) : YDifferenceToNext(selectevery(1,-2)) # ODD diff n-2, n-3 : EVEN diff n-2, n-1 [Difference fields from SAME previous frame]
D = D1 / Max(D2,0.001) # This only detects if ONE OF the current field pair is bad, we dont know which one is bad
if(D < badthreshold) {
(SHOWDOT) ? c.Subtitle("below the badthreshold",y=20) : c
} else {
if(IsOdd) {
O = YDifferenceToNext(-2) # current odd field to prev odd field
E = YDifferenceToNext(selectevery(1,-1),-2) # current even field to prev even field
(O>E) ? Prev : c # If Odd bigger diff then fix Odd, else will fix even when even is current field
(SHOWDOT) ? Subtitle(String(E,"ODD:- E=%f ")+String(O,"O=%f : ")+(O>E?"Odd Bigger Chose Prev":"Skip"),y=20) : NOP
} Else {
E = YDifferenceToNext(-2) # current even field to prev even field
O = YDifferenceToNext(selectevery(1,1),-2) # current odd field to prev odd field
(E>O) ? Next : c # If Even bigger diff then fix Even, else will fix Odd when odd is current field
(SHOWDOT) ? Subtitle(String(E,"EVEN:- E=%f ")+String(O,"O=%f : ")+(E>O?"Even Bigger Chose Next":"Skip"),y=20) : NOP
}
}
(SHOWDOT) ? Subtitle(String(current_frame,"%.0f] ")+String(D1,"D1=%f ")+String(D2,"D2=%f ")+String(D,"D=%f ")) : NOP
return last
"""
scriptclip(SSS)
StackVertical(c,Last) # Original on top, mod + subs on bottom
Still only works on ODD fields.
johnmeyer
12th September 2021, 04:49
I did a few more tests before retiring tonight, and the first set of code works for the even fields and the other code below works for the odd fields.
Progress!
function ReplaceBadFieldOdd (clip c, bool SHOWDOT)
{
replacement = SHOWDOT ? c.subtitle("***").selectevery(1,1) : c.selectevery(1,1)
fixed = ConditionalSelect(c, "
YDifferenceFromPrevious()/Max(YDifferenceFromPrevious( selectevery( 1, -2) ),0.001 ) > badthreshold
\ ? 0 : 1", replacement, c)
return fixed
}
function ReplaceBadFieldEven (clip c, bool SHOWDOT)
{
replacement = SHOWDOT ? c.subtitle("***").selectevery(1,1) : c.selectevery(1,1)
fixed = ConditionalSelect(c, "
YDifferenceToNext()/Max(YDifferenceToNext( selectevery( 1, -2) ),0.001 ) > badthreshold
\ ? 0 : 1", replacement, c)
return fixed
}
The only difference is that one looks backwards ("FromPrevious") and the other looks forward ("ToNext").
BTW, the reason for using a ratio to the adjacent even or odd field is that the AVISYnth difference metrics get larger or smaller, depending on the motion and noise, and by using a ratio, the test is much more sensitive to jumps in noise compared to what's happening in the surrounding frames.
I now need to figure out how to choose one function for the even, and the other for the odd.
johnmeyer
12th September 2021, 04:52
You posted as I was writing. I have no idea how you are still up.
It looks like you too came up with the "FromPrevious" and "ToNext."
It looks like the If-Else construct is from RT_Stats. I think I have that loaded. I'll try your code tomorrow.
Thanks for the help!
StainlessS
12th September 2021, 06:09
If Else from either GScript or Avs+ [recommend Avs+]. are you still on v2.60 std ?
Bingo !
# Req AVS+
VideoFile = ".\Replace Bad Fields.avi"
AviSource(VideoFile).convertToYV12(Matrix="rec601")
AssumeBFF
#return SeparateFields
Bob(0.0,1.0)
#Return Last
c=Last
SHOWDOT=True
METRICS=True
STACK=True
badthreshold=2.0
Prev = SHOWDOT ? c.subtitle("***"+(METRICS?" Prev [Odd]" :""),y=(METRICS)?40:0).selectevery(1,-1) : c.selectevery(1,-1) # replacement1
Next = SHOWDOT ? c.subtitle("***"+(METRICS?" Next [Even]":""),y=(METRICS)?40:0).selectevery(1, 1) : c.selectevery(1,1) # replacement2
SSS="""
c
IsOdd = current_frame %2 <> 0
D1 = (IsOdd) ? YDifferenceFromPrevious() : YDifferenceToNext() # ODD diff n , n-1 : EVEN diff n , n+1 [Difference fields from SAME current frame]
D2 = (IsOdd) ? YDifferenceFromPrevious(selectevery(1,-2)) : YDifferenceToNext(selectevery(1,-2)) # ODD diff n-2, n-3 : EVEN diff n-2, n-1 [Difference fields from SAME previous frame]
D = D1 / Max(D2,0.001) # This only detects if ONE OF the current field pair is bad, we dont know which one is bad
if(D < badthreshold) {
(METRICS) ? c.Subtitle("below the badthreshold",y=20) : c
} else {
if(IsOdd) {
O = AverageLuma
E = AverageLuma(SelectEvery(1,-1))
(O>E) ? Prev : c
(METRICS) ? Subtitle(String(E,"ODD:- E=%f ")+String(O,"O=%f : ")+(O>E?"Odd Bigger Chose Prev":"Skip"),y=20) : NOP
} Else {
E = AverageLuma
O = AverageLuma(SelectEvery(1,+1))
(E>O) ? Next : c
(METRICS) ? Subtitle(String(E,"EVEN:- E=%f ")+String(O,"O=%f : ")+(E>O?"Even Bigger Chose Next":"Skip"),y=20) : NOP
}
}
(METRICS) ? Subtitle(String(current_frame,"%.0f] ")+String(D1,"D1=%f ")+String(D2,"D2=%f ")+String(D,"D=%f ")) : NOP
return last
"""
Scriptclip(SSS)
(STACK)?StackVertical(c,Last):NOP # Original on top, mod + subs on bottom
Return Last
was not really expecting it work at all.
EDIT: Backported changes from later script.
kedautinh12
12th September 2021, 06:20
Wow, Stain you're man of scripts
StainlessS
12th September 2021, 06:31
Wow
"We can rebuild him. We have the technology. We can make him better than he was. Better, stronger, faster."
Oscar Goldman.
[they replaced all my parts with nice shiny metal ones]
StainlessS
12th September 2021, 07:25
John,
Can use prev given script under AVS+, or if v2.60 std only, then try this,
Needs GScript and Grunt plugins. [AVS+ is way easier]
Will ALSO work with AVS+ and Grunt Only. [Untested under v2.60 std, but should work ok]
#LoadPlugin("...\GScript.dll")
#LoadPlugin("...\Grunt.dll")
VideoFile = ".\Replace Bad Fields.avi"
AviSource(VideoFile).convertToYV12(Matrix="rec601")
AssumeBFF
#return SeparateFields
Bob(0.0,1.0)
#Return Last
c=Last
SHOWDOT=True
METRICS=True
STACK=True
badthreshold=2.0
Prev = SHOWDOT ? c.subtitle("***"+(METRICS?" Prev [Odd]" :""),y=(METRICS)?40:0).selectevery(1,-1) : c.selectevery(1,-1) # replacement1
Next = SHOWDOT ? c.subtitle("***"+(METRICS?" Next [Even]":""),y=(METRICS)?40:0).selectevery(1, 1) : c.selectevery(1,1) # replacement2
SSS="""
Function OhYouAreAwfulButterLikeYou(clip c,float badthreshold,bool SHOWDOT,bool METRICS, clip Prev, clip next) {
c
IsOdd = current_frame %2 <> 0
D1 = (IsOdd) ? YDifferenceFromPrevious() : YDifferenceToNext() # ODD diff n , n-1 : EVEN diff n , n+1 [Difference fields from SAME current frame]
D2 = (IsOdd) ? YDifferenceFromPrevious(selectevery(1,-2)) : YDifferenceToNext(selectevery(1,-2)) # ODD diff n-2, n-3 : EVEN diff n-2, n-1 [Difference fields from SAME previous frame]
D = D1 / Max(D2,0.001) # This only detects if ONE OF the current field pair is bad, we dont know which one is bad
if(D < badthreshold) {
(METRICS) ? c.Subtitle("below the badthreshold",y=20) : c
} else {
if(IsOdd) {
O = AverageLuma
E = AverageLuma(SelectEvery(1,-1))
(O>E) ? Prev : c
(METRICS) ? Subtitle(String(E,"ODD:- E=%f ")+String(O,"O=%f : ")+(O>E?"Odd Bigger Chose Prev":"Skip"),y=20) : NOP
} Else {
E = AverageLuma
O = AverageLuma(SelectEvery(1,+1))
(E>O) ? Next : c # If Even bigger diff then fix Even, else will fix Odd when odd is current field
(METRICS) ? Subtitle(String(E,"EVEN:- E=%f ")+String(O,"O=%f : ")+(E>O?"Even Bigger Chose Next":"Skip"),y=20) : NOP
}
}
(METRICS) ? Subtitle(String(current_frame,"%.0f] ")+String(D1,"D1=%f ")+String(D2,"D2=%f ")+String(D,"D=%f ")) : NOP
return last
}
"""
IsPlus=FindStr(VersionString,"AviSynth+")!=0
Assert(HasGrunt,"We Require Grunt Plugin")
Assert(IsPlus|| HasGScript,"We Require Avs+ OR GScript Plugin")
(IsPlus) ? Eval(SSS) : GEval(SSS) # can run with either Avs+ or GScript, Install OhYouAreAwfulButterLikeYou() function.
Gscriptclip("OhYouAreAwfulButterLikeYou(badthreshold,SHOWDOT,METRICS,Prev,next)",args="badthreshold,SHOWDOT,METRICS,Prev,next",Local=True)
(STACK)?StackVertical(c,Last):NOP # Original on top, mod + subs on bottom
Return Last
########################
Function FuncNameExists(String Fn) { Try{Eval(Fn+"()")B=True}catch(e){Assert(e.FindStr("syntax")==0,"FuncNameExists: Error in Function Name '"+Fn+"'")B=(e.FindStr("no function named")==0)}Return B}
Function HasGrunt() { Return FuncNameExists("GSCriptClip") }
Function HasGScript() { Return FuncNameExists("GSCript") }
EDIT: Mod to add METRICS option, can switch off metrics just leaving SHOWDOT or neither.
EDIT: DAMN, it will not work under v2.60 std, eg AverageLuma(-1) to get ave luma of previous frame only in AVs+.
Changed AverageLuma(-1) to AverageLuma(SelectEvery(1,-1)) and AverageLuma(+1) to AverageLuma(SelectEvery(1,+1)), so working, hopefully, still untested on v2.60std.
EDIT: Changes in above script backported to previous AVS+ only script a few posts earlier.
EDIT: Perhaps difference in averageLuma against a threshold, would work alone.
StainlessS
12th September 2021, 14:28
EDIT: Perhaps difference in averageLuma against a threshold, would work alone.
Yep,
#LoadPlugin("...\GScript.dll")
#LoadPlugin("...\Grunt.dll")
VideoFile = ".\Replace Bad Fields.avi"
AviSource(VideoFile).convertToYV12(Matrix="rec601")
AssumeBFF
#return SeparateFields
Bob(0.0,1.0)
#Return Last
c=Last
SHOWDOT=True
METRICS=True
STACK=True
badthreshold=0.5
Prev = SHOWDOT ? c.subtitle("***"+(METRICS?" Prev [Odd]" :""),y=(METRICS)?40:0).selectevery(1,-1) : c.selectevery(1,-1) # replacement1
Next = SHOWDOT ? c.subtitle("***"+(METRICS?" Next [Even]":""),y=(METRICS)?40:0).selectevery(1, 1) : c.selectevery(1,1) # replacement2
SSS="""
Function OhYouAreAwfulButterLikeYou2(clip c,float badthreshold,bool SHOWDOT,bool METRICS, clip Prev, clip next) {
c
if(current_frame %2 <> 0) { # ODD
O = AverageLuma
E = AverageLuma(SelectEvery(1,-1))
D = abs(O-E)
T = (D > badthreshold) && (O > E)
(T) ? Prev : c
(METRICS) ? Subtitle("ODD:- "+(T?"D>Th && O>E, Choose Prev":D>badthreshold?"Skip, Gonna Fix EVEN":"Skip"),y=20) : NOP
} Else { # EVEN
E = AverageLuma
O = AverageLuma(SelectEvery(1,+1))
D = abs(O-E)
T = (D > badthreshold) && (E > O)
(T) ? Next : c
(METRICS) ? Subtitle("EVEN:- "+(T?"D>Th && E>O, Choose Next":D>badthreshold?"Skip, Gonna Fix ODD":"Skip"),y=20) : NOP
}
(METRICS) ? Subtitle(String(current_frame,"%.0f] ")+String(E,"E=%f ")+String(O,"O=%f ")+String(D,"D=%f ")) : NOP
return last
}
"""
IsPlus=FindStr(VersionString,"AviSynth+")!=0
Assert(HasGrunt,"We Require Grunt Plugin")
Assert(IsPlus|| HasGScript,"We Require Avs+ OR GScript Plugin")
(IsPlus) ? Eval(SSS) : GEval(SSS) # can run with either Avs+ or GScript, Install OhYouAreAwfulButterLikeYou2() function.
Gscriptclip("OhYouAreAwfulButterLikeYou2(badthreshold,SHOWDOT,METRICS,Prev,next)",args="badthreshold,SHOWDOT,METRICS,Prev,next",Local=True)
(STACK)?StackVertical(c,Last):NOP # Original on top, mod + subs on bottom
Return Last
########################
Function FuncNameExists(String Fn) { Try{Eval(Fn+"()")B=True}catch(e){Assert(e.FindStr("syntax")==0,"FuncNameExists: Error in Function Name '"+Fn+"'")B=(e.FindStr("no function named")==0)}Return B}
Function HasGrunt() { Return FuncNameExists("GSCriptClip") }
Function HasGScript() { Return FuncNameExists("GSCript") }
Previous scripts did not detect frame 63 as BAD [well it is only a teeny-weeny bit bad anyway], but this one picks out all bads, odd or even, and also frame 63.
Frame 63 requires a badthreshold of less than 1.299, we are using 0.5 here, so a bit of leeway for change if necessary.
Say if you want an AVS+ only version.
johnmeyer
12th September 2021, 15:02
Just got up (7:00 a.m. here). I'll look at this after I get a bite. Thanks!
StainlessS
12th September 2021, 15:50
Wolf it down John, you got work to do :)
For you, it replaces bright fields with its partner darker field, if set ChooseBright=true, then will do the opposite and both of your fields pairs will be messed up :) [for where dark field is the bad one]
#LoadPlugin("...\GScript.dll")
#LoadPlugin("...\Grunt.dll")
VideoFile = ".\Replace Bad Fields.avi"
AviSource(VideoFile).convertToYV12(Matrix="rec601")
AssumeBFF
#return SeparateFields
Bob(0.0,1.0)
#Return Last
c=Last
SHOWDOT=True
METRICS=True
STACK=True
badthreshold=0.5 # Difference in AverageLuma that will detect bad field in field pair. If greater, then is bad.
ChooseBright=False # If true, replace darker of field pair with brighter field, ELSE replace brighter of field pair with darker field. [where fields refers to pre-bobbed fields]
Prev = SHOWDOT ? c.subtitle("***"+(METRICS?" Prev" :""),y=(METRICS)?40:0).selectevery(1,-1) : c.selectevery(1,-1) # replacement1
Next = SHOWDOT ? c.subtitle("***"+(METRICS?" Next":""),y=(METRICS)?40:0).selectevery(1, 1) : c.selectevery(1,1) # replacement2
SSS="""
Function OhYouAreAwfulButterLikeYou2(clip c,float badthreshold,ChooseBright,bool METRICS, clip Prev, clip next) {
c
if(current_frame %2 <> 0) { # ODD
O = AverageLuma
E = AverageLuma(SelectEvery(1,-1))
D = abs(O-E)
T = (D > badthreshold) && (ChooseBright? E > O : E < O)
(T) ? Prev : c
(METRICS) ? Subtitle("ODD:- "+(T?("D>Th && "+(ChooseBright?"E>O":"E<O"))+", Choose Prev":D>badthreshold?"Skip, Gonna Fix EVEN":"Skip"),y=20) : NOP
} Else { # EVEN
E = AverageLuma
O = AverageLuma(SelectEvery(1,+1))
D = abs(O-E)
T = (D > badthreshold) && (ChooseBright ? O > E : O < E)
(T) ? Next : c
(METRICS) ? Subtitle("EVEN:- "+(T?("D>Th && "+(ChooseBright?"E<O":"E>O"))+", Choose Next":D>badthreshold?"Skip, Gonna Fix ODD":"Skip"),y=20) : NOP
}
(METRICS) ? Subtitle(String(current_frame,"%.0f] ")+String(E,"E=%f ")+String(O,"O=%f ")+String(D,"D=%f ")) : NOP
return last
}
"""
IsPlus=FindStr(VersionString,"AviSynth+")!=0
Assert(HasGrunt,"We Require Grunt Plugin")
Assert(IsPlus || HasGScript,"We Require Avs+ OR GScript Plugin")
(IsPlus) ? Eval(SSS) : GEval(SSS) # can run with either Avs+ or GScript, Install OhYouAreAwfulButterLikeYou2() function.
Gscriptclip("OhYouAreAwfulButterLikeYou2(badthreshold,ChooseBright,METRICS,Prev,next)",args="badthreshold,ChooseBright,METRICS,Prev,next",Local=True)
(STACK)?StackVertical(c,Last):NOP # Original on top, mod + subs on bottom
Return Last
########################
Function FuncNameExists(String Fn) { Try{Eval(Fn+"()")B=True}catch(e){Assert(e.FindStr("syntax")==0,"FuncNameExists: Error in Function Name '"+Fn+"'")B=(e.FindStr("no function named")==0)}Return B}
Function HasGrunt() { Return FuncNameExists("GSCriptClip") }
Function HasGScript() { Return FuncNameExists("GSCript") }
EDIT: Removed SHOWDOT as arg to function, now only used outside of func.
EDIT: With SHOWDOT, Metrics and STACK, Avsmeter 102FPS.
With all those switched off, I get "Script is too short to get meaningful measurements".
However, with a RT_ForceProcess at end of script I get this as debug output
00000430 0.19137581 RT_ForceProcess: Commencing Forced process
00000431 0.19838420 RT_ForceProcess: 6] 4.73% nFrms=7 T=0.000sec : 70000.00FpS 0.000014SpF
00000432 0.20374130 RT_ForceProcess: 13] 9.46% nFrms=7 T=0.015sec : 466.67FpS 0.002143SpF
00000433 0.21019851 RT_ForceProcess: 21] 14.86% nFrms=8 T=0.000sec : 80000.00FpS 0.000013SpF
00000434 0.21632010 RT_ForceProcess: 28] 19.59% nFrms=7 T=0.000sec : 70000.00FpS 0.000014SpF
00000435 0.22279990 RT_ForceProcess: 36] 25.00% nFrms=8 T=0.016sec : 500.00FpS 0.002000SpF
00000436 0.22777440 RT_ForceProcess: 43] 29.73% nFrms=7 T=0.000sec : 70000.00FpS 0.000014SpF
00000437 0.23377401 RT_ForceProcess: 50] 34.46% nFrms=7 T=0.015sec : 466.67FpS 0.002143SpF
00000438 0.24005461 RT_ForceProcess: 58] 39.86% nFrms=8 T=0.000sec : 80000.00FpS 0.000013SpF
00000439 0.24518070 RT_ForceProcess: 65] 44.59% nFrms=7 T=0.000sec : 70000.00FpS 0.000014SpF
00000440 0.25168139 RT_ForceProcess: 73] 50.00% nFrms=8 T=0.016sec : 500.00FpS 0.002000SpF
00000441 0.25780240 RT_ForceProcess: 80] 54.73% nFrms=7 T=0.000sec : 70000.00FpS 0.000014SpF
00000442 0.26295540 RT_ForceProcess: 87] 59.46% nFrms=7 T=0.000sec : 70000.00FpS 0.000014SpF
00000443 0.26950711 RT_ForceProcess: 95] 64.86% nFrms=8 T=0.016sec : 500.00FpS 0.002000SpF
00000444 0.27534881 RT_ForceProcess: 102] 69.59% nFrms=7 T=0.000sec : 70000.00FpS 0.000014SpF
00000445 0.28122160 RT_ForceProcess: 110] 75.00% nFrms=8 T=0.015sec : 533.33FpS 0.001875SpF
00000446 0.28599450 RT_ForceProcess: 117] 79.73% nFrms=7 T=0.000sec : 70000.00FpS 0.000014SpF
00000447 0.29150170 RT_ForceProcess: 124] 84.46% nFrms=7 T=0.007sec : 1000.00FpS 0.001000SpF
00000448 0.29741639 RT_ForceProcess: 132] 89.86% nFrms=8 T=0.000sec : 80000.00FpS 0.000013SpF
00000449 0.30222189 RT_ForceProcess: 139] 94.59% nFrms=7 T=0.000sec : 70000.00FpS 0.000014SpF
00000450 0.30883649 RT_ForceProcess: 147] 100.00% nFrms=8 T=0.015sec : 533.33FpS 0.001875SpF
00000451 0.30885091 RT_ForceProcess: Time=0.115secs (0.002mins) : Avg 1286.957FpS 0.000777SpF
So pretty fast. [i7-8700 @ 3.2GHz 6C 12T, but may be higher CPU clock on single core]
EDIT:
Repeated above test with ALL options switched on [repeat of AvsMeter run] and got this
00000108 0.19652100 RT_ForceProcess: Commencing Forced process
00000109 0.26522079 RT_ForceProcess: 6] 4.73% nFrms=7 T=0.069sec : 101.45FpS 0.009857SpF
00000110 0.33590570 RT_ForceProcess: 13] 9.46% nFrms=7 T=0.073sec : 95.89FpS 0.010429SpF
00000111 0.42199001 RT_ForceProcess: 21] 14.86% nFrms=8 T=0.074sec : 108.11FpS 0.009250SpF
00000112 0.48589271 RT_ForceProcess: 28] 19.59% nFrms=7 T=0.078sec : 89.74FpS 0.011143SpF
00000113 0.56315547 RT_ForceProcess: 36] 25.00% nFrms=8 T=0.069sec : 115.94FpS 0.008625SpF
00000114 0.62707257 RT_ForceProcess: 43] 29.73% nFrms=7 T=0.069sec : 101.45FpS 0.009857SpF
00000115 0.69163859 RT_ForceProcess: 50] 34.46% nFrms=7 T=0.063sec : 111.11FpS 0.009000SpF
00000116 0.76478219 RT_ForceProcess: 58] 39.86% nFrms=8 T=0.069sec : 115.94FpS 0.008625SpF
00000117 0.82840842 RT_ForceProcess: 65] 44.59% nFrms=7 T=0.069sec : 101.45FpS 0.009857SpF
00000118 0.91102540 RT_ForceProcess: 73] 50.00% nFrms=8 T=0.085sec : 94.12FpS 0.010625SpF
00000119 0.97799438 RT_ForceProcess: 80] 54.73% nFrms=7 T=0.062sec : 112.90FpS 0.008857SpF
00000120 1.04363227 RT_ForceProcess: 87] 59.46% nFrms=7 T=0.069sec : 101.45FpS 0.009857SpF
00000121 1.11848259 RT_ForceProcess: 95] 64.86% nFrms=8 T=0.069sec : 115.94FpS 0.008625SpF
00000122 1.18456686 RT_ForceProcess: 102] 69.59% nFrms=7 T=0.063sec : 111.11FpS 0.009000SpF
00000123 1.25859165 RT_ForceProcess: 110] 75.00% nFrms=8 T=0.084sec : 95.24FpS 0.010500SpF
00000124 1.32315111 RT_ForceProcess: 117] 79.73% nFrms=7 T=0.054sec : 129.63FpS 0.007714SpF
00000125 1.40408862 RT_ForceProcess: 124] 84.46% nFrms=7 T=0.078sec : 89.74FpS 0.011143SpF
00000126 1.46626163 RT_ForceProcess: 132] 89.86% nFrms=8 T=0.069sec : 115.94FpS 0.008625SpF
00000127 1.53277755 RT_ForceProcess: 139] 94.59% nFrms=7 T=0.069sec : 101.45FpS 0.009857SpF
00000128 1.60882473 RT_ForceProcess: 147] 100.00% nFrms=8 T=0.069sec : 115.94FpS 0.008625SpF
00000129 1.60884047 RT_ForceProcess: Time=1.404secs (0.023mins) : Avg 105.413FpS 0.009486SpF
which matches pretty well to AvsMeter result. [102FPS vs 105FPS]
johnmeyer
12th September 2021, 17:11
Wow. I don't think I've ever copy/pasted an AVISynth script and had it work perfectly the first time (had to plug in the AVI, of course).
Brilliant! :goodpost:
I need to spend more time studying AverageLuma because I didn't think it would be sensitive to the problem I was trying to detect, but in looking at the metrics, it appears to do a MUCH better job than my more contorted test using YDifferenceNext/Prev.
In answer to one of your earlier questions, I am using AVISynth+, although it is a very early version (0.1, r2508). I should probably upgrade, but I never upgrade until I need a specific feature.
I do feel a little guilty using it, since you've done all the work. However, while I may feel guilty, I am not stupid, so I am definitely going to use it. However, do I have to keep the "OhYouAreAwfulButterLikeYou2" function name? :)
Things I cleaned up:
I got rid of the VideoFile name (left over, I assume, from intermediate versions).
Removed commented out lines (debugging stuff, I think)
I added note to myself to keep ChooseBright set to False. I tried it with True, but I'm not sure when I'd want to use that, since it breaks the fixing of the pulldown frames
Replaced function name "OhYouAreAwfulButterLikeYou2" with "FixWorkprinterPulldown" (sorry, it had to go)
Added killaudio() to the AVISource line to avoid error/crash when I click on the "play" icon in VirtualDub
Replaced Return Last with:return last.separatefields().selectevery(4,1,2).weave()in order to un-bob and put the fields back into frames.
BTW, the reason I need to do this fix is that I no longer have a working computer with a fast disk that still uses a native PS/2 mouse, and my 8mm film workprinter transfer machine works by sending its capture signal via a PS/2 mouse that has its left mouse button tied to the pulldown cam on the film projector. I now go through a PS/2 to USB adapter and the delay this causes sometimes causes the capture "click" to be late, resulting in the capture of a field where the film is being pulled down to the next frame. I'm using an interlaced HD camera, my old Sony FX1, to capture the image, so that's why the problem only happens on one field, thus permitting this near-perfect fix. (I'd be hosed if I used a more modern progressive camera). With the relatively low resolution of 8mm and Super 8 film, you really can't detect the one-frame loss of the odd or even field, after running your script.
I really need to find a fix for my Workprinter problem because even though this new function produces a near-perfect result, it is one more step I must go through. Also, it is always better to do the job right in the first place.
So thank you StainlessS. I am very happy now, and my client will also be happy in a few days when he receives the results.
johnmeyer
12th September 2021, 17:12
Just to finish the thread, here is my very slightly-edited version of what StainlessS wrote:#Script written by StainlessS Copyright (c) September 11, 2021
#Fixes bad Workprinter frames
AviSource("E:\fs.avi").convertToYV12(Matrix="rec601").killaudio()
AssumeBFF
Bob(0.0,1.0)
c=Last
SHOWDOT=True
METRICS=True
STACK=True
badthreshold=0.5 # Difference in AverageLuma that will detect bad field in field pair. If greater, then is bad.
ChooseBright=False # If true, replace darker of field pair with brighter field, ELSE replace brighter of field pair with darker field. [where fields refers to pre-bobbed fields]
# JHM note: keep false
Prev = SHOWDOT ? c.subtitle("***"+(METRICS?" Prev" :""),y=(METRICS)?40:0).selectevery(1,-1) : c.selectevery(1,-1) # replacement1
Next = SHOWDOT ? c.subtitle("***"+(METRICS?" Next":""), y=(METRICS)?40:0).selectevery(1, 1) : c.selectevery(1,1) # replacement2
SSS="""
Function FixWorkprinterPulldown(clip c,float badthreshold,ChooseBright,bool METRICS, clip Prev, clip next) {
c
if(current_frame %2 <> 0) { # ODD
O = AverageLuma
E = AverageLuma(SelectEvery(1,-1))
D = abs(O-E)
T = (D > badthreshold) && (ChooseBright? E > O : E < O)
(T) ? Prev : c
(METRICS) ? Subtitle("ODD:- "+(T?("D>Th && "+(ChooseBright?"E>O":"E<O"))+", Choose Prev":D>badthreshold?"Skip, Gonna Fix EVEN":"Skip"),y=20) : NOP
} Else { # EVEN
E = AverageLuma
O = AverageLuma(SelectEvery(1,+1))
D = abs(O-E)
T = (D > badthreshold) && (ChooseBright ? O > E : O < E)
(T) ? Next : c
(METRICS) ? Subtitle("EVEN:- "+(T?("D>Th && "+(ChooseBright?"E<O":"E>O"))+", Choose Next":D>badthreshold?"Skip, Gonna Fix ODD":"Skip"),y=20) : NOP
}
(METRICS) ? Subtitle(String(current_frame,"%.0f] ")+String(E,"E=%f ")+String(O,"O=%f ")+String(D,"D=%f ")) : NOP
return last
}
"""
# Test for presence of required plugins
IsPlus=FindStr(VersionString,"AviSynth+")!=0
Assert(HasGrunt,"We Require Grunt Plugin")
Assert(IsPlus|| HasGScript,"We Require Avs+ OR GScript Plugin")
(IsPlus) ? Eval(SSS) : GEval(SSS) # can run with either Avs+ or GScript, Install FixWorkprinterPulldown() function.
Gscriptclip("FixWorkprinterPulldown(badthreshold,ChooseBright,METRICS,Prev,next)",args="badthreshold,ChooseBright,METRICS,Prev,next",Local=True)
(STACK)?StackVertical(c,Last):NOP # Original on top, mod + subs on bottom
#Return Last #Use this to see the individual fields during debugging and when viewing metrics
return last.separatefields().selectevery(4,1,2).weave()
########################
Function FuncNameExists(String Fn) { Try{Eval(Fn+"()")B=True}catch(e){Assert(e.FindStr("syntax")==0,"FuncNameExists: Error in Function Name '"+Fn+"'")B=(e.FindStr("no function named")==0)}Return B}
Function HasGrunt() { Return FuncNameExists("GSCriptClip") }
Function HasGScript() { Return FuncNameExists("GSCript") }
StainlessS
12th September 2021, 18:00
I didn't think it would be sensitive to the problem
Bad ones are visibly brighter, YDifference, maybe better for detect movement, sort of.
[EDIT: and with this func version, we dont need test outside of current field pair, test on adjacent pair can stymie result when eg pan]
although it is a very early version (0.1, r2508)
Aarh John, you know how upset Pinterf gets when he reads stuff like that, dont be mean.
I'm on v3.70 [although I think I have several updates in my in-box],
At Least get v3.70:- https://github.com/AviSynth/AviSynthPlus/releases
Much more flavoursome :)
I'm gonna assume that you're updating, and will mod [your mod] to be more useful to you.
[with ChooseBright optional and default false, and the Prev, Next and scriptclip stuff contained within a function, ie can save as avsi in plugins. Grunt will be required.].
johnmeyer
12th September 2021, 18:04
BTW, StainlessS, this script may have a far wider use than my somewhat esoteric problem. In particular, we've both seen lots of video where one field is screwed up. This will probably fix quite a few of those problems (although not as cleanly as this case, since real interlaced video has temporal movement between fields, rather than just spatial offset). You might want to put this function wherever you keep your "fix-it" functions, because I'll bet someone else will need it.
[edit]We posted simultaneously. Yes, good sir, I promise to update to a version that is from this decade.
StainlessS
12th September 2021, 18:23
John, do you does, or do you doesn't normally have RT_Stats in plugins ?
I'll add option to write list of fixed field [or frame, you decide] to a frames file [but only if RT_stats present, if option selected and missing then error abort and plug required message].
If writing frame number, and afterwards with source and result clips [each stacked with field pair, OR pre-bob,post-weave ] then could use FrameSel to extract only fixed [before and after] for checking OK.
Easier than scan entire clip looking for errors.
johnmeyer
12th September 2021, 18:43
John, do you does, or do you doesn't normally have RT_Stats in plugins ?
I'll add option to write list of fixed field [or frame, you decide] to a frames file [but only if RT_stats present, if option selected and missing then error abort and plug required message].
If writing frame number, and afterwards with source and result clips [each stacked with field pair, OR pre-bob,post-weave ] then could use FrameSel to extract only fixed [before and after] for checking OK.
Easier than scan entire clip looking for errors.Yes, I did have the "write frame number to file" option in my original script, but I don't have an immediate need for it in this application. Also, I can add the needed lines on my own.
Interesting idea to extract just the changed frames so one could view just those which changed, rather than going through twenty minutes of mostly-OK film (which is what I have in this project) trying to remember not to blink too much as the frames sail by. Again, I don't have an immediate need for this, and wouldn't use it in this project, but unlike the "Choosebright" which I'm not sure I'd ever use, this feature might be useful in the future.
Yes, I do have RT_Stats in the plugin folder because I've used some of your earlier scripts which use it.
StainlessS
12th September 2021, 19:01
trying to remember not to blink too much
I hear that matchsticks are just the job for that.
Choosebright, easy to add so why not, might at some future date have some weird clip that could benefit.
I'll do the mods, should not take too long I think.
EDIT:
FixWorkprinterPulldown, just doesn't have the same magical ring to it :(
OhYouAreAwfulButterLikeYou2 = Oh You Are Awful But I Like You [+ too, I was up all night thinking of that, you make it seem like it was a total waste of time]
Mandy - Dick Emery:- https://www.youtube.com/watch?v=wkLRZzukcJc
johnmeyer
12th September 2021, 19:40
I hear that matchsticks are just the job for that.Yeah, I saw that Malcolm McDowell movie when it first came out. Brilliant, but disturbing.https://i.imgur.com/Q1pK0V6.jpg
I'll do the mods, should not take too long I think.No need to do them for me, 'cause what you've done lets me finish my project.
FixWorkprinterPulldown, just doesn't have the same magical ring to it :(Yeah, "pedestrian" doesn't even come close to describing my title. It's totally uninspired, but functional.
OhYouAreAwfulButterLikeYou2 = Oh You Are Awful But I Like You [+ too, I was up all night thinking of that, you make it seem like it was a total waste of time] I'm glad you told me that. I actually Googled it (with quotes) and got a rare result: zero hits. Sorry to rain on your parade by renaming it. :)
Dick Emery ...Don't think he's ever been seen on this side of the pond. I definitely hadn't seen him (her).
StainlessS
12th September 2021, 20:49
JFYI, the prison Malcolm McDowell was in was Wandsworth Prison [South West London], I recognised it from the area around it [helicopter aerial view in movie].
No need to do them for me
No Sweat, nearly done.
EDIT:
I no longer have a working computer with a fast disk that still uses a native PS/2 mouse
I've only one machine with PS2 mouse / Keyboard, so much better than USB.
Also got a PS2 KVM which is useless to me.
But I do got a wireless USB Keyboard / Mouse combo, I keep one front slot reserved for it [USB dongle], so I can easily pull it out
and plug into some other machine, [usually tablet or even mobile phone <with Type-A to Micro USB adapter>] and I'm good to go, I love that one.
EDIT:
I definitely hadn't seen him
Not my favourite, but he was on every week for years and years. [Every week it seemed like years and years].
But you must know of Dame Edna Everage, Aussie Royalty.
StainlessS
12th September 2021, 22:45
OK, say if you try and encounter problems.
FixWorkprinterPulldown.avsi
# FixWorkprinterPulldown.avsi @ https://forum.doom9.org/showthread.php?p=1952051#post1952051
Function FixWorkprinterPulldown(clip c,Bool DoBob,Bool DoWeave, float "BadThreshold",bool "Metrics",bool "ShowDot",Bool "Stack",Int "WrMode",String "FramesFile",Bool "ChooseBright") {
# Fixes bad Workprinter frames
# If DoBob, Should call with correct field order set.
# DoWeave, Turns OFF metrics etc, final result.
myName = "FixWorkprinterPulldown: "
BadThreshold = Default(BadThreshold,0.5)
ShowDot = DoWeave ? False : Default(ShowDot,True)
Metrics = DoWeave ? False : Default(Metrics,True)
Stack = DoWeave ? False : Default(Stack ,True)
WrMode = Default(WrMode,0).Max(0).Min(4) # default 0, 0 -> 4 : Mode for writing frameno to FramesFile. 0=none, 1=Fixed PreBob FrameNo, 2=Fixed FieldNo, 3=Both FieldNos in fixed pair, 4=Log All Fields.
FramesFile = (WrMode==0) ? "" : Default(FramesFile,".\FWP_Frames.Txt") # Only valid if WrMode != 0.
ChooseBright = Default(ChooseBright,False) # JHM note: keep false
Assert(FWP_HasRT_Stats,myName+"We Require RT_Stats Plugin")
Assert(FWP_HasGrunt,myName+"We Require Grunt Plugin")
Assert(FindStr(VersionString,"AviSynth+")!=0,myName+"We Require Avs+")
Assert(c.IsPlanar && !c.IsRGB,myName+"Planar YUV/Y Only")
WrMode = (FramesFile=="") ? 0 : WrMode # And switch off WrMode if no FramesFile.
(DoBob) ? c.Bob(0.0,1.0) : c #
ORG = Last
Prev = ShowDot ? subtitle("***"+(Metrics?" Prev" :""),y=(Metrics)?40:0).selectevery(1,-1) : selectevery(1,-1)
Next = ShowDot ? subtitle("***"+(Metrics?" Next":""), y=(Metrics)?40:0).selectevery(1, 1) : selectevery(1, 1)
FramesFile = (WrMode!=0) ? RT_GetFullPathname(FramesFile) : ""
(WrMode!=0) ? RT_FileDelete(FramesFile) : NOP
(0 < WrMode < 4) ? RT_WriteFile(FramesFile,"##################\n%s\n##################","# nnnn Diff #") : NOP
(WrMode==4) ? RT_WriteFile(FramesFile,"#######################################\n%s\n#######################################","# nnnn AveLuma Diff Fixed #") : NOP
Gscriptclip("FixWorkprinterPulldown_LOW(BadThreshold,Metrics,WrMode,FramesFile,ChooseBright,Prev,next)",args="BadThreshold,Metrics,WrMode,FramesFile,ChooseBright,Prev,next",Local=True)
STK = StackVertical(ORG,Last) # Original [may be bobbed] on top, mod + subs on bottom
WEEV = separatefields().selectevery(4,1,2).weave()
(DoWeave) ? WEEV : (Stack) ? STK : Last
return last
}
###############################
###### PRIVATE LOW LEVEL ######
###############################
Function FWP_FuncNameExists(String Fn) { Try{Eval(Fn+"()")B=True}catch(e){Assert(e.FindStr("syntax")==0,"FWP_FuncNameExists: Error in Function Name '"+Fn+"'")B=(e.FindStr("no function named")==0)}Return B}
Function FWP_HasGrunt() { Return FWP_FuncNameExists("GSCriptClip") }
Function FWP_HasRT_Stats() { Return FWP_FuncNameExists("RT_Stats") }
Function FixWorkprinterPulldown_LOW(clip c,float BadThreshold,bool Metrics, int WrMode,String FramesFile,Bool ChooseBright,clip Prev, clip next) {
c n = current_frame
if(n % 2 != 0) { # ODD
O = AverageLuma # Y of cur odd
E = AverageLuma(-1) # Y of prv even
D = abs(O-E)
T = (D > badthreshold) && (ChooseBright? E > O : E < O)
(T) ? Prev : NOP
(METRICS) ? Subtitle("ODD:- "+(T?("D>Th && "+(ChooseBright?"E>O":"E<O"))+", Choose Prev":D>badthreshold?"Skip, Gonna Fix EVEN":"Skip"),y=20) : NOP
} Else { # EVEN
E = AverageLuma # Y of cur even
O = AverageLuma(+1) # Y of nxt odd
D = abs(O-E)
T = (D > badthreshold) && (ChooseBright ? O > E : O < E)
(T) ? Next : NOP
(METRICS) ? Subtitle("EVEN:- "+(T?("D>Th && "+(ChooseBright?"E<O":"E>O"))+", Choose Next":D>badthreshold?"Skip, Gonna Fix ODD":"Skip"),y=20) : NOP
}
(METRICS) ? Subtitle(String(n,"%.0f] ")+String(E,"E=%f ")+String(O,"O=%f ")+String(D,"D=%f ")) : NOP
if ((T && wrMode>0) || WrMode==4) {
if(WrMode==1) { RT_WriteFile(FramesFile,"%-6d # %f",n/2,D,Append=True) } # Fixed Pre-Bob FrameNo
else if(WrMode==2) { RT_WriteFile(FramesFile,"%-6d # %f",n,D,Append=True) } # Fixed FieldNo
else if(WrMode==3) { # Both FieldNos in fixed pair.
(n % 2 == 0)
\ ? RT_WriteFile(FramesFile,"%-6d # %f <<====\n%-6d",n/2*2,D,n/2*2+1,Append=True)
\ : RT_WriteFile(FramesFile,"%-6d\n%-6d # %f <<====",n/2*2,n/2*2+1,D,Append=True)
} else { # Log all Fields
RT_WriteFile(FramesFile,"%-6d # %f %f%s",n,(n % 2 == 0)?E:O,D,T?" <<====":"",Append=True)
}
}
return last
}
FixWorkprinterPulldown_Client.avs
# FixWorkprinterPulldown_Client.avs
# Import(".\FixWorkprinterPulldown.avsi")
#AviSource(".\Replace Bad Fields.avi").convertToYV12(Matrix="rec601").killaudio().AssumeBFF
AviSource(".\Test Clip.avi").convertToYV12(Matrix="rec601").killaudio().AssumeBFF
SHOWDOT = True
METRICS = True
STACK = True
WRMODE = 4 # 0 ) Mode for writing frameno to FramesFile. 0=none, 1=Fixed PreBob FrameNo, 2=Fixed FieldNo, 3=Both FieldNos in fixed pair, 4=Log All Fields.
BADTHRESHOLD = 0.5 # 0.5) Difference in AverageLuma that will detect bad field in field pair. If greater, then is bad.
FixWorkprinterPulldown(True,False,badthreshold=BADTHRESHOLD,Metrics=METRICS,ShowDot=SHOWDOT,Stack=STACK,WrMode=WRMODE) # TEST
#FixWorkprinterPulldown(True,True,badthreshold=BADTHRESHOLD,Metrics=METRICS,ShowDot=SHOWDOT,Stack=STACK,WrMode=WRMODE) # FINAL
Return Last
EDIT:
WrMode=3=Both FieldNos in fixed pair. [For Extraction <via FrameSel>, Stacking and viewing, maybe for both Src and result compare]
6
7
10
11
34
35
48
49
58
59
62
63
70
71
84
85
98
99
112
113
126
127
140
141
EDIT:
Oops, added in blue
Assert(c.IsPlanar && !c.IsRGB,myName+"Planar YUV Only")
EDIT: Added check for RT_Stats plugin.
EDIT: Update, with WrMode=4=Log All Fields.
johnmeyer
12th September 2021, 23:36
I am not sure what issues you are addressing with this latest revision. While I'd love to try it, I am not going to use it, at least for now, because I have much bigger issues to address. I talked about these earlier in this thread, and anticipated that they would be a problem.
And they are.
Here's the issue: the threshold using these metrics changes significantly depending on the contrast (and other factors) of that local section of the video. Thus, what works well on one section, may totally fail elsewhere. This is why I always use metric ratios.
Here is a test clip which illustrates the problem:
https://www.mediafire.com/file/9qpxfz5styfdyo0/Test+Clip.avi/file
As you will see, during the 1960s kid's football match, any O-E metric that is less than 0.1 is normal, and most fields with metrics above that indicate a bad field.
When you get to the second scene (the dog), there are lots of normal fields above 0.1, and most of the bad ones are above 2.0. The lower threshold that would be perfect for the football match would result in way too many replacements.
Thus, I need an extra set of comparisons: one which establishes a local "norm," and the other which is the comparison to that norm. In other words, the metric has to be relative to the local situation, not absolute for the whole clip.
I'm working on that issue right now. The important thing is to only compare the two fields within a frame (as your original script does), because this eliminates any issues we might have at scene changes (to name one issue). However, either the threshold must vary, or the metrics must be ratioed to the surrounding fields. In the past I've done this with a moving average, although that obviously can be a problem around scene changes.
I'll let you know if I come up with a solution to this key issue.
StainlessS
12th September 2021, 23:45
Here is a test clip which illustrates the problem:
Thank you.
johnmeyer
12th September 2021, 23:52
Here is my mod to fix the issue. It works, but at the moment the metric display is not synced correctly. You can see the metrics "blow up" when you get to a bad field (they blow up much more nicely than before, methinks), but they do it a frame before they should. It's probably an easy fix, but since you're looking at this now I wanted to save you having to duplicate my work. I'll go back and try to fix the metric sync issue now.
Like all works in progress, it is a bit buggered up. Despite the lack of elegance, it does seem to work across all three scenes in the test clip, without having to modify the threshhold.
I added "C", "P", and "N" to your metrics, indicating Current, Previous, and Next.
#Script written by StainlessS Copyright (c) September 11, 2021
#Fixes bad Workprinter frames
AviSource("E:\test clip.avi").convertToYV12(Matrix="rec601").killaudio()
AssumeBFF
Bob(0.0,1.0)
c=Last
SHOWDOT=True
METRICS=True
STACK=True
badthreshold=10. # Difference in AverageLuma that will detect bad field in field pair. If greater, then is bad.
ChooseBright=False # If true, replace darker of field pair with brighter field, ELSE replace brighter of field pair with darker field. [where fields refers to pre-bobbed fields]
# JHM note: keep false
Prev = SHOWDOT ? c.subtitle("***"+(METRICS?" Prev" :""),y=(METRICS)?40:0).selectevery(1,-1) : c.selectevery(1,-1) # replacement1
Next = SHOWDOT ? c.subtitle("***"+(METRICS?" Next":""), y=(METRICS)?40:0).selectevery(1, 1) : c.selectevery(1,1) # replacement2
SSS="""
Function FixWorkprinterPulldown(clip c,float badthreshold,ChooseBright,bool METRICS, clip Prev, clip next) {
c
if(current_frame %2 <> 0) { # ODD
OC = AverageLuma
EC = AverageLuma(SelectEvery(1,-1))
DC = abs(OC-EC)
OP = AverageLuma(SelectEvery(1,-2))
EP = AverageLuma(SelectEvery(1,-3))
DP = abs(OP-EP)
D = DC/DP
T = (D > badthreshold)
(T) ? Prev : c
(METRICS) ? Subtitle("ODD:- "+(T?("D>Th && "+(ChooseBright?"EC>OC":"EC<OC"))+", Choose Prev":D>badthreshold?"Skip, Gonna Fix EVEN":"Skip"),y=20) : NOP
} Else { # EVEN
EC = AverageLuma
OC = AverageLuma(SelectEvery(1,+1))
DC = abs(OC-EC)
ON = AverageLuma(SelectEvery(1,+2))
EN = AverageLuma(SelectEvery(1,+3))
DN = abs(ON-EN)
D = DC/DN
T = (D > badthreshold) && (ChooseBright ? OC > EC : OC < EC)
(T) ? Next : c
(METRICS) ? Subtitle("EVEN:- "+(T?("D>Th && "+(ChooseBright?"EC<OC":"EC>OC"))+", Choose Next":D>badthreshold?"Skip, Gonna Fix ODD":"Skip"),y=20) : NOP
}
(METRICS) ? Subtitle(String(current_frame,"%.0f] ")+String(EC,"E=%f ")+String(OC,"O=%f ")+String(D,"D=%f ")) : NOP
return last
}
"""
# Test for presence of required plugins
IsPlus=FindStr(VersionString,"AviSynth+")!=0
Assert(HasGrunt,"We Require Grunt Plugin")
Assert(IsPlus|| HasGScript,"We Require Avs+ OR GScript Plugin")
(IsPlus) ? Eval(SSS) : GEval(SSS) # can run with either Avs+ or GScript, Install FixWorkprinterPulldown() function.
Gscriptclip("FixWorkprinterPulldown(badthreshold,ChooseBright,METRICS,Prev,next)",args="badthreshold,ChooseBright,METRICS,Prev,next",Local=True)
(STACK)?StackVertical(c,Last):NOP # Original on top, mod + subs on bottom
Return Last #Use this to see the individual fields during debugging and when viewing metrics
#return last.separatefields().selectevery(4,1,2).weave()
########################
Function FuncNameExists(String Fn) { Try{Eval(Fn+"()")B=True}catch(e){Assert(e.FindStr("syntax")==0,"FuncNameExists: Error in Function Name '"+Fn+"'")B=(e.FindStr("no function named")==0)}Return B}
Function HasGrunt() { Return FuncNameExists("GSCriptClip") }
Function HasGScript() { Return FuncNameExists("GSCript") }
johnmeyer
13th September 2021, 00:35
The script below works better. I took out the Choosebright logic, because I don't need it and it was obscuring what I wanted to do. The one remaining issue I'm not 100% happy with is the test to inhibit a replacement if the second field in the pair (the odd field) is the broken field. This is the line that does that:
T = (D > badthreshold) && (OC/ON < EC/EN)
The issue, as StainlessS obviously knows, is that you get the same metrics looking forward from the even field to the odd field, or backward from the odd field to the even field. So, which is the bad field? The original logic did it by assuming that the blurred pulldown field is always going to have a higher averageluma value. Perhaps that will always be so, but I attempted to improve on that. However, my logic (shown above) may be worse (it will likely fail if there are two frames in a row containing a bad field). It seems to work on the test clip, but I'm not convinced that I've nailed it. I could improve it by using a moving average, something I've done for other similar issues, but that has problems across scene boundaries (as may my approach).
I may end up just going back to what StainlessS did for this comparison.
This is what I'm going to use on the final reel of film that showed up the problems. The previous four reels worked fine with my StainlessS' original script.
I'm REALLY happy with how nicely the metric skyrockets when even the slightest hint of blur shows up, although I'm not sure why the "D" metric isn't almost identical when looking forward from even to odd, compared to looking back from odd to even. The metrics are derived from the fields in the two adjacent (previous and next), but when those frames look almost identical, you'd think the metrics would be very close. They both blow up, to be sure, but they're not close. I need to think on that some more.
#Script written by StainlessS Copyright (c) September 11, 2021
#Fixes bad Workprinter (film transfer machine) frames
#Modified by John Meyer September 12, 2021
#Made metrics relative to adjacent frames
#Work needed: better OC/ON comparison to determine which field is atually bad
AviSource("E:\test clip.avi").convertToYV12(Matrix="rec601").killaudio()
AssumeBFF
Bob(0.0,1.0)
c=Last
SHOWDOT=True
METRICS=True
STACK =True
badthreshold=10.0 # Difference in AverageLuma that will detect bad field in field pair. If greater, then is bad.
Prev = SHOWDOT ? c.subtitle("***"+(METRICS?" Prev" :""),y=(METRICS)?40:0).selectevery(1,-1) : c.selectevery(1,-1) # replacement1
Next = SHOWDOT ? c.subtitle("***"+(METRICS?" Next":""), y=(METRICS)?40:0).selectevery(1, 1) : c.selectevery(1,1) # replacement2
SSS="""
Function FixWorkprinterPulldown(clip c,float badthreshold,bool METRICS, clip Prev, clip next) {
c
if(current_frame %2 <> 0) { # ODD
OC = AverageLuma
EC = AverageLuma(SelectEvery(1,-1))
DC = abs(OC-EC)
OP = AverageLuma(SelectEvery(1,-2))
EP = AverageLuma(SelectEvery(1,-3))
DP = abs(OP-EP)
D = DC/DP
T = (D > badthreshold)
(T) ? Prev : c #Perform field replacement, depending on T value
(METRICS) ? Subtitle("ODD:- "+(T?("D>Th")+", Choose Prev":D>badthreshold?"Skip, Gonna Fix EVEN":"Skip"),y=20) : NOP
} Else { # EVEN
EC = AverageLuma
OC = AverageLuma(SelectEvery(1,+1))
DC = abs(OC-EC)
ON = AverageLuma(SelectEvery(1,+2))
EN = AverageLuma(SelectEvery(1,+3))
DN = abs(ON-EN)
D = DC/DN
T = (D > badthreshold) && (OC < EC) # This is the older way of doing it, and it should
# avoid scene change probs & will catch consecutive faults
# T = (D > badthreshold) && (OC/ON < EC/EN) # *** The OC/ON comparison determines which field is bad -- NEEDS WORK
(T) ? Next : c #Perform field replacement, depending on T value
(METRICS) ? Subtitle("EVEN:- "+(T?("D>Th")+", Choose Next":D>badthreshold?"Skip, Gonna Fix ODD":"Skip"),y=20) : NOP
}
# Display comparison metrics that are common to both even and odd frames
(METRICS) ? Subtitle(String(current_frame,"%.0f] ")+String(EC,"EC=%f ")+String(OC,"OC=%f ")+String(D,"D=%f ")) : NOP
return last
}
"""
# Test for presence of required plugins
IsPlus=FindStr(VersionString,"AviSynth+")!=0
Assert(HasGrunt,"We Require Grunt Plugin")
Assert(IsPlus|| HasGScript,"We Require Avs+ OR GScript Plugin")
(IsPlus) ? Eval(SSS) : GEval(SSS) # can run with either Avs+ or GScript, Install FixWorkprinterPulldown() function.
Gscriptclip("FixWorkprinterPulldown(badthreshold,METRICS,Prev,next)",
\args="badthreshold,METRICS,Prev,next",Local=True)
(STACK)?StackVertical(c,Last):NOP # Original on top, mod + subs on bottom
#Return Last #Use this to see the individual fields during debugging and when viewing metrics
return last.separatefields().selectevery(4,1,2).weave()
########################
Function FuncNameExists(String Fn) { Try{Eval(Fn+"()")B=True}catch(e){Assert(e.FindStr("syntax")==0,
\"FuncNameExists: Error in Function Name '"+Fn+"'")B=(e.FindStr("no function named")==0)}Return B}
Function HasGrunt() { Return FuncNameExists("GSCriptClip") }
Function HasGScript() { Return FuncNameExists("GSCript") }
StainlessS
13th September 2021, 02:04
Post #25 updated, WrMode=4=Log All fields.
Your posted clip, only frame [EDIT: field] 61 failed, with D=0.38 [EDIT: the only one that I saw] whereas my totally guessed Badthreshold was 0.5.
Your ratio of difference in aveLuma could be promising, certainly better than YDifference between frames,
I was already looking in that direction, and that promted the WrMode=4 thingy.
Here WrMode=4 from your last sample with missed detect on field 61.
#######################################
# nnnn AveLuma Diff Fixed #
#######################################
0 # 125.455017 0.034393
1 # 125.489410 0.034393
2 # 125.819099 0.116074
3 # 125.935173 0.116074
4 # 125.360497 1.268410
5 # 126.628906 1.268410 <<====
6 # 125.731522 0.049706
7 # 125.781227 0.049706
8 # 125.593620 0.637985
9 # 126.231606 0.637985 <<====
10 # 125.804405 0.035271
11 # 125.839676 0.035271
12 # 125.864136 0.147331
13 # 126.011467 0.147331
14 # 125.706070 0.051224
15 # 125.757294 0.051224
16 # 125.466141 0.073837
17 # 125.539978 0.073837
18 # 125.523743 0.783722
19 # 126.307465 0.783722 <<====
20 # 125.637672 0.050980
21 # 125.688652 0.050980
22 # 125.982826 0.141350
23 # 126.124176 0.141350
24 # 125.859314 0.037117
25 # 125.896431 0.037117
26 # 125.698952 0.102867
27 # 125.801819 0.102867
28 # 125.899979 1.110207
29 # 127.010185 1.110207 <<====
30 # 126.173897 0.032188
31 # 126.206085 0.032188
32 # 126.122627 0.120651
33 # 126.243279 0.120651
34 # 126.472343 0.020424
35 # 126.492767 0.020424
36 # 125.698624 0.291580
37 # 125.990204 0.291580
38 # 125.968933 0.038864
39 # 126.007797 0.038864
40 # 125.943413 0.068031
41 # 126.011444 0.068031
42 # 126.127106 0.101044
43 # 126.228149 0.101044
44 # 126.765472 0.071220
45 # 126.836693 0.071220
46 # 126.634323 0.571220
47 # 127.205544 0.571220 <<====
48 # 126.715385 0.047447
49 # 126.762833 0.047447
50 # 127.414787 0.126289
51 # 127.541077 0.126289
52 # 127.967926 0.048737
53 # 128.016663 0.048737
54 # 127.695663 0.023804
55 # 127.719467 0.023804
56 # 127.990540 0.768860
57 # 128.759399 0.768860 <<====
58 # 128.123734 0.032547
59 # 128.156281 0.032547
60 # 127.987144 0.380959
61 # 128.368103 0.380959
62 # 128.434006 0.036316
63 # 128.470322 0.036316
64 # 128.617844 0.117371
65 # 128.735214 0.117371
66 # 128.572540 0.081451
67 # 128.653992 0.081451
68 # 128.572433 0.007217
69 # 128.579651 0.007217
70 # 128.476120 0.518951
71 # 128.995071 0.518951 <<====
72 # 129.034332 0.010818
73 # 129.045151 0.010818
74 # 130.014038 0.158066
75 # 130.172104 0.158066
76 # 130.594833 0.024414
77 # 130.619247 0.024414
78 # 129.461746 0.044464
79 # 129.506210 0.044464
80 # 127.972092 0.055893
81 # 128.027985 0.055893
82 # 127.710648 0.004936
83 # 127.705711 0.004936
84 # 128.066788 0.116394
85 # 128.183182 0.116394
86 # 128.428452 0.003845
87 # 128.432297 0.003845
88 # 127.991714 0.097885
89 # 128.089600 0.097885
90 # 128.063828 0.043472
91 # 128.107300 0.043472
92 # 127.407967 0.042595
93 # 127.450562 0.042595
94 # 127.849670 0.103462
95 # 127.953133 0.103462
96 # 127.961983 0.030037
97 # 127.992020 0.030037
98 # 127.717369 0.210052
99 # 127.927422 0.210052
100 # 127.207642 0.011589
101 # 127.196053 0.011589
102 # 136.815063 0.227829
103 # 137.042892 0.227829
104 # 136.648621 0.141861
105 # 136.790482 0.141861
106 # 136.673584 0.142212
107 # 136.815796 0.142212
108 # 136.393875 3.255783
109 # 139.649658 3.255783 <<====
110 # 136.491730 0.159882
111 # 136.651611 0.159882
112 # 136.587875 0.245560
113 # 136.833435 0.245560
114 # 135.946655 0.169937
115 # 136.116592 0.169937
116 # 136.459106 0.131897
117 # 136.591003 0.131897
118 # 137.143509 0.212784
119 # 137.356293 0.212784
120 # 137.398468 0.131546
121 # 137.530014 0.131546
122 # 137.717545 0.192886
123 # 137.910431 0.192886
124 # 137.110886 3.902100
125 # 141.012985 3.902100 <<====
126 # 137.175858 0.139786
127 # 137.315643 0.139786
128 # 137.206467 2.132385
129 # 139.338852 2.132385 <<====
130 # 137.626999 0.030884
131 # 137.596115 0.030884
132 # 137.400803 0.201019
133 # 137.601822 0.201019
134 # 137.532776 0.182556
135 # 137.715332 0.182556
136 # 137.054626 0.140915
137 # 137.195541 0.140915
138 # 137.188614 1.755142
139 # 138.943756 1.755142 <<====
140 # 137.200760 0.123245
141 # 137.324005 0.123245
142 # 136.945511 0.165146
143 # 137.110657 0.165146
144 # 135.969589 3.206268
145 # 139.175858 3.206268 <<====
146 # 134.964294 0.075607
147 # 135.039902 0.075607
148 # 133.396332 1.336243
149 # 134.732574 1.336243 <<====
150 # 134.259583 0.109238
151 # 134.368820 0.109238
152 # 134.894348 0.151169
153 # 135.045517 0.151169
154 # 135.259735 0.124512
155 # 135.384247 0.124512
156 # 135.497650 0.073120
157 # 135.570770 0.073120
158 # 88.783913 0.023956
159 # 88.807869 0.023956
160 # 89.163750 0.025177
161 # 89.188927 0.025177
162 # 88.417282 0.009148
163 # 88.408134 0.009148
164 # 88.186531 2.339546
165 # 90.526077 2.339546 <<====
166 # 88.680969 0.007813
167 # 88.688782 0.007813
168 # 88.560059 0.002998
169 # 88.563057 0.002998
170 # 88.305946 5.681381
171 # 93.987328 5.681381 <<====
172 # 87.845833 0.018669
173 # 87.864502 0.018669
174 # 87.693596 0.060783
175 # 87.754379 0.060783
176 # 88.278656 0.046379
177 # 88.325035 0.046379
178 # 87.379143 0.025620
179 # 87.404762 0.025620
180 # 86.689636 0.071144
181 # 86.760780 0.071144
182 # 87.113434 0.021111
183 # 87.134544 0.021111
184 # 86.923080 0.049881
185 # 86.972961 0.049881
186 # 88.872055 8.996414
187 # 97.868469 8.996414 <<====
188 # 88.408707 0.000359
189 # 88.409065 0.000359
190 # 87.576607 0.088493
191 # 87.665100 0.088493
192 # 86.136765 0.034271
193 # 86.171036 0.034271
194 # 86.605690 0.015671
195 # 86.621361 0.015671
196 # 86.113792 0.060577
197 # 86.174370 0.060577
198 # 85.023735 0.020729
199 # 85.044464 0.020729
200 # 85.060577 0.036766
201 # 85.097343 0.036766
202 # 85.331879 0.043861
203 # 85.375740 0.043861
204 # 85.810226 0.008659
205 # 85.818886 0.008659
206 # 85.872612 0.204613
207 # 86.077225 0.204613
208 # 86.278328 0.017502
209 # 86.295830 0.017502
210 # 86.488510 0.062675
211 # 86.551186 0.062675
212 # 86.685562 0.058296
213 # 86.743858 0.058296
214 # 86.699158 0.038902
215 # 86.738060 0.038902
216 # 86.808762 0.043068
217 # 86.851830 0.043068
218 # 86.085899 8.967361
219 # 95.053261 8.967361 <<====
220 # 86.054733 0.030113
221 # 86.084846 0.030113
222 # 85.797203 0.068939
223 # 85.866142 0.068939
224 # 85.067467 0.027519
225 # 85.094986 0.027519
226 # 84.612137 0.010689
227 # 84.622826 0.010689
228 # 85.313469 0.027870
229 # 85.341339 0.027870
230 # 85.892998 0.007759
231 # 85.885239 0.007759
232 # 85.941322 0.039284
233 # 85.980606 0.039284
234 # 86.025291 0.085136
235 # 86.110428 0.085136
236 # 86.709053 0.027412
237 # 86.736465 0.027412
238 # 86.039063 0.450119
239 # 86.489182 0.450119
Straddled either side by nice low diffs
58 # 128.123734 0.032547 ] nice low diff 0.03
59 # 128.156281 0.032547 ]
60 # 127.987144 0.380959
61 # 128.368103 0.380959 <<< Missed
62 # 128.434006 0.036316 ] nice low diff 0.03
63 # 128.470322 0.036316 ]
EDIT: I'm not really feelin' the urge to stay up till 08:30 or thereabouts tonight, so I will not be doing much else, I hope :)
johnmeyer
13th September 2021, 03:13
I'm not really feelin' the urge to stay up till 08:30 or thereabouts tonight, so I will not be doing much else, I hope :)You've done yeoman's work, far more than I could ever have expected, so don't think you need to do more. Thanks to you I've now fixed all seven reels, and the results look perfect. I'm now editing and then feeding the results of those edits into my film restoration script. I should be able to deliver the final tomorrow.
Thanks for everything, Mr. StainlessS, whoever you are. I really needed the help this time to "get over the hump."
Humps get harder to get over as one gets older.
StainlessS
13th September 2021, 03:22
Lovely, dont forget to post your final script, so I can steal some off you.
EDIT: I'll drop the ChooseBright arg too.
johnmeyer
13th September 2021, 04:03
Lovely, dont forget to post your final script, so I can steal some off you.Post #29 (https://forum.doom9.org/showpost.php?p=1952060&postcount=29)
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.