Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Usage

Reply
 
Thread Tools Search this Thread Display Modes
Old 3rd August 2018, 21:53   #1  |  Link
greymouse
Registered User
 
Join Date: Aug 2007
Posts: 36
automate static removal

hi film friends

I need some help, i'm currently working on this video, which has static noise going often through my video,

I am at this time dropping the frames but i'm doing this manually and theres a lot of noise every and so many frames in an hour of footage

I was using morph() but that again due to the number of frames that need fixing is a laborious task

is there a way to automate this?



I know there's black lines going through the video as well but I know how to fix that

the noise I refer to are on frames
71,88,94,116,167




sample Video:
https://www.sendspace.com/file/1o6sp0



any help would be great in the mean time i'll keep plodding along

Thanks!
Gordon

Last edited by greymouse; 3rd August 2018 at 21:56.
greymouse is offline   Reply With Quote
Old 3rd August 2018, 22:02   #2  |  Link
greymouse
Registered User
 
Join Date: Aug 2007
Posts: 36
this is my drop frame list so far

22371
22483
22519
22529
22765
23329,23330
24624
24987
25045
25063
25153
25200
25260,25261
25310
25324
25366
25419,25420
25460,25461
25490
25552,25554
25596,25597
25712
25777
26017
26174
26249
26656
26892
27021
27686,27687
27703
27764
27790
27932,27933
28081
28128
28164,28173
28321,28323
28410
28455
28473
28611
28691 ,28692
28872
28885
28923
28974,28984
29036
29051
29181
29210
29318
29324
29531,29538
29849
29876
29946
29962
30028
30208
30214
30237
30418
30546,30547
30970
31008
31015
31024
31102
31113
31504
31609
31842
31876,31884
31957
32010
32123
32156
32225
32325
32553,32554
32830 ,32831
32946
32987
33138
33445
33483,33491
33562
33830
34044
34573
34663
34692
34705
34750
34798
34805
34807
34861
34868,34875
34934,34944
34948
34985
35140
35346
35411,35412
35483,35492
35506,35526
35530,35538
35553
35581
35677 ,35685
35688,35689
35761
36163
36163
36276
36333
36356,36365
36407,36415
36598
36739
36773
37156,37164
37186
37306,37322
37331
37336,37337
37374
37569,37570
37602,37610
37610
37653
37681,37689
37730
37794,37802
37957,37965
38020,38021
38147
38165,38166
38311,38312
38343
38385,38393
38421
38436,38437
38463
38531
38649
38853
39103
39186
39321,39331
39598
39603
39819
39863,39874
39883
39951,39952
39954,39956
40250,40251
40301
40479
40707,40708
41003
41654,41662
41868
42074
42132,42134
42237,42238
42278
43590
43774
43995,44002
44189
44444
44468
44492
44509
44511
44557
44574
44643
44646
44647
44650
44694
44723
44749
44775
44868
44926
44953
44985,44986
45041
45047
45182
45385
45442,45443
45448
45462
45500
45532,45534
45730
45737
45765
45868,45870
45883
45906
45984
45989
45992,46003
46016
46028
46058
46062
46093,46094
46096
46152
46281
46297
46430
46555
46703
46721
46744
46782
46801
46811,46813
46849
46866
46974
47029
47062
47141
47182
47201,47202
47222
47270,47271
47278
47366
47533
47573
47615
47620
47631
47653
47699
47755
47843
47851,47853
47892,49156
49233,49235
49322
49394,49395
49417
49448
49471,49472
49497
49510
49545
49573
49596
49601
49619
49653,49656
49660
49666
49675
49687
49690,49691
49696
49724
49734
49760
49838
49871
49927
49948
49974
49989
50012
50128
50136,50137
50189
50207,50208
50237
50265
50278
50312
50363
50397,50398
50401
50407
50420
50425,50426
50456
50494
50572,50573
50591
50593
50606
50615
50682
50711
50736
50949,50952
50965
50976
50996
51082
51085
51089
51119
51136
51146
51174,51175
51255,51256
51308
51358
51406
51410
51473,51475
51501
51510
51532,51534
51591
51797
51947
52119
52155
52180
52302,52303
52319
52329,52330
52346,52347
52671
52674
52682
52699
52810
52821,52822
52826,52837
52840
52846
52900,52902
52918
53006
53011
53025
53062
53287
53395
53492
53514
53564 ,53565
53703
53715
53746
53798
53829
53901
53911
53957
54072
54140
54147

this is me going frame by frame and dropping those frames

Last edited by greymouse; 3rd August 2018 at 22:03. Reason: clarifaction
greymouse is offline   Reply With Quote
Old 3rd August 2018, 23:04   #3  |  Link
johnmeyer
Registered User
 
Join Date: Feb 2002
Location: California
Posts: 2,184
I developed a script, and posted it here:

Finding individual "bad" frames in video; save frame number; or repair


This will replace any bad frame with a motion estimated version, created using adjacent frames.

The bad frame detection logic might be able to notice the noise frames, and handle everything for you automatically.

[edit]OK, I tried it on your video. My "bad frame" detection logic needs to be modified to better detect only the frames with the break up (StainlessS??). This should be easy to do because the tearing is mostly pure white. However, even with the existing logic, the following code does a pretty good job of fixing the problems, and it does so automatically. If you use it exactly as posted, it will automatically replace frames, and will show a few dots in the upper left corner on any frame that has been synthesized from adjacent frames. By changing the TRUE/FALSE values in the control section, you can change the script to output frame numbers, or actually write new video to a file.

Feel free to play around with it, especially the threshold.
Code:
#Find And (Optionally) Fix Bad Frames
#John Meyer - December 13, 2016
#Rev. 2.0
#Thanks to Gavino and StainlessS for making the script more professional.

#This script detects single bad frames. 

#You can configure the script to write, to a file, the frame numbers of all frames which are detected as "bad".
#You can also configure it to automatically replace each bad frame with a new
#frame interpolated from its neighbors. 

#This script will fail if the bad frame happens immediately before or after a scene change.
#This script will also fail to find a bad frame if there is more than one bad frame in a row.

#It works very well for finding both blank frames and also "flash" frames (like those caused
#by a photographer's flash). It will also find single frames which have lots of 
#static or pixels. It can also find a frame with large x or y displacement from adjacent frames, like
#a film frame that wasn't properly registered in the film gate, or an analog
#video frame that lost vertical sync.

#When using VirtualDub, to create the text file containing the bad frame numbers,
#select "Run Video Analysis Pass" in the VirtualDub File menu. If you are simultaneously
#creating a fixed video file, you don't need to do this because the file will
#be created simultaneously as the fixed video file is created.

#The script uses ratios of the metrics for the current frame to the same metrics 
#on the two adjacent frames. Under normal circumstances, the metrics should be quite
#similar, and therefore the ratio should be very near to unity (i.e., 1.00). 

#Run through the video with the "METRICS" variable set to "True" and look at the metrics
#in order to determine an optimum threshold value. A larger threshhold will
#catch fewer bad frames, and a lower threshold will eventually create false positives. 
#The replacement code works well enough that if you end up replacing a few frames that are
#actually good, you probably won't notice it.


#-----------------------------
loadplugin("C:\Program Files\AviSynth 2.5\plugins\MVTools\mvtools2.dll")

#Control script operation by changing the following values :
#=====================================================================
VideoFile           = "E:\Documents\Dnload\UNPACK\Rollaine_Noise_Sample_Pass1_huffy.avi"
global badthreshold = 1.2              # 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()

script = """Subtitle("\nPrevious Ratio = " + String( YDifferenceFromPrevious(source) /
         \ Max(YDifferenceFromPrevious( selectevery(source, 1, -1)),0.00001) ) + 
         \ "\nNext Ratio        = " + String( YDifferenceToNext(source) /
         \ Max(YDifferenceToNext(selectevery(source, 1, 1)),0.00001)), lsp=0)"""
MetClip = Scriptclip(source, script)

FileFixed = (FILEWRITE)
    \ ? WriteFileIf(source, filename, "
    \ YDifferenceFromPrevious() / Max(YDifferenceFromPrevious( selectevery(1, -1)),0.00001) 
    \ > badthreshold && YDifferenceToNext() / Max(YDifferenceToNext(selectevery(1, 1)),0.00001)
    \ > badthreshold", "current_frame", append = false) : Source

output = (METRICS) ? MetClip : (REPLACE) ? ReplaceBadI(FileFixed,showdot) : FileFixed
return output

#------------------------------

function ReplaceBadI (clip c, bool SHOWDOT)
{
  even        = c.SeparateFields().SelectEven()
  super_even  = SHOWDOT ? even.subtitle("***").MSuper(pel=2) : even.MSuper(pel=2) 
  vfe         = manalyse(super_even,truemotion=true,isb=false,delta=2)
  vbe         = manalyse(super_even,truemotion=true,isb=true,delta=2)
  filldrops_e = mflowinter(even,super_even,vbe,vfe,time=50)

  odd         = c.SeparateFields().SelectOdd()
  super_odd   = SHOWDOT ? odd.subtitle("***").MSuper(pel=2) : odd.MSuper(pel=2) 
  vfo         = manalyse(super_odd,truemotion=true,isb=false,delta=2)
  vbo         = manalyse(super_odd,truemotion=true,isb=true,delta=2)
  filldrops_o = mflowinter(odd,super_odd,vbo,vfo,time=50)

  Interleave(filldrops_e,filldrops_o)
  Replacement = Weave()

  fixed       = ConditionalSelect(c, "
                Prev  = YDifferenceFromPrevious()
                Prev1 = Max(YDifferenceFromPrevious(SelectEvery(1,-1)),0.00001)
                Next  = YDifferenceToNext()
                Next1 = Max(YDifferenceToNext(SelectEvery(1,1)),0.00001)
                Prev/Prev1 < badthreshold && Next/Next1 < badthreshold ? 0 : 1", \
                c, selectevery(Replacement,1,-1))

  return fixed
}

Last edited by johnmeyer; 3rd August 2018 at 23:21. Reason: added code
johnmeyer is offline   Reply With Quote
Old 3rd August 2018, 23:16   #4  |  Link
greymouse
Registered User
 
Join Date: Aug 2007
Posts: 36
I'll give it ago, this noise is running through the whole 3 hour tape, I've tried to re-record it but the noise is still in the same place on the time line
greymouse is offline   Reply With Quote
Old 3rd August 2018, 23:23   #5  |  Link
johnmeyer
Registered User
 
Join Date: Feb 2002
Location: California
Posts: 2,184
Note that I edited my post above after you posted. You might want to re-read it.
johnmeyer is offline   Reply With Quote
Old 3rd August 2018, 23:42   #6  |  Link
greymouse
Registered User
 
Join Date: Aug 2007
Posts: 36
Quote:
Originally Posted by johnmeyer View Post
Note that I edited my post above after you posted. You might want to re-read it.
ah! thanks will read again
greymouse is offline   Reply With Quote
Old 4th August 2018, 00:03   #7  |  Link
greymouse
Registered User
 
Join Date: Aug 2007
Posts: 36
thank you very much! i'll have tinker

Last edited by greymouse; 4th August 2018 at 00:22.
greymouse is offline   Reply With Quote
Old 4th August 2018, 10:09   #8  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 7,086
Greymouse, Post result of your tinker ['result'=success/failure].
Bit busy at the mo, but may be able to take a peek in a few days.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 4th August 2018 at 10:15.
StainlessS is offline   Reply With Quote
Old 5th August 2018, 10:07   #9  |  Link
Mounir
Registered User
 
Join Date: Nov 2006
Posts: 716
For the automation part i don't know but to interpolate frames i always found svpflow work better than morph in most cases, see below

Quote:
LoadPlugin("C:\Program Files (x86)\AviSynth 2.6\plugins\svpflow-1.0.6\svpflow1.dll")
LoadPlugin("C:\Program Files (x86)\AviSynth 2.6\plugins\svpflow-1.0.6\svpflow2.dll")
AVISource("Rollaine_Noise_Sample_Pass1_huffy.avi")
assumetff()
converttoyv12(interlaced=true)

# syntax: ReplaceFramesSVPFlow(number of the frame, duration 1 frame or more)
# Replacing frames below:
ReplaceFramesSVPFlow(88,1)
ReplaceFramesSVPFlow(116,1)
ReplaceFramesSVPFlow(152,1)
ReplaceFramesSVPFlow(166,2) # 2 frames here !


function ReplaceFramesSVPFlow(clip Source, int N, int X)
{
# N is number of the 1st frame in Source that needs replacing.
# X is total number of frames to replace
#e.g. ReplaceFramesSVPFLow(101, 5) would replace 101,102,103,104,105 , by using 100 and 106 as reference points for SVPFlow interpolation

start=Source.trim(N-1,-1) #one good frame before, used for interpolation reference point
end=Source.trim(N+X,-1) #one good frame after, used for interpolation reference point

start+end
AssumeFPS(1) #temporarily FPS=1 to use mflowfps

super=SVSuper("{gpu:1}")
vectors=SVAnalyse(super, "{}")
SVSmoothFps(super, vectors, "{rate:{num:"+String(X+1)+", den:1}}", url="www.svp-team.com", mt=1).Subtitle("SVPFlow")

AssumeFPS(FrameRate(Source)) #return back to normal source framerate for joining
Trim(1, framecount-1) #trim ends, leaving replacement frames

Source.trim(0,-N) ++ last ++ Source.trim(N+X+1,0)
}
Mounir is offline   Reply With Quote
Old 5th August 2018, 10:43   #10  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 7,086
GreyMouse,
I thought 118 MB for an 8 seconds clip of 720x576@25 was a bit high, seems is HuffYUV RGB.

Assuming source was YUV then suggest next time in VDub2,
Video/Fast Recompress/
Video/Compression/HuffYUV/Configure/RGB Compression Method/ = Convert To YUY2
Video/Compression/HuffYUV/Configure/YUY2 Compression Method/ = Predict Median(Best)

Should be somewhat smaller and without YUV to RGB conversion. [EDIT: Or without even YUV -> RGB -> YUV conversion]


EDIT: John,
Maybe below a little bit simpler to understand (just format change really of part of your script [EDIT: but inside 'script' changed source to Last])
original
Code:
script = """Subtitle("\nPrevious Ratio = " + String( YDifferenceFromPrevious(source) /
         \ Max(YDifferenceFromPrevious( selectevery(source, 1, -1)),0.00001) ) + 
         \ "\nNext Ratio        = " + String( YDifferenceToNext(source) /
         \ Max(YDifferenceToNext(selectevery(source, 1, 1)),0.00001)), lsp=0)"""
MetClip = Scriptclip(source, script)

FileFixed = (FILEWRITE)
    \ ? WriteFileIf(source, filename, "
    \ YDifferenceFromPrevious() / Max(YDifferenceFromPrevious( selectevery(1, -1)),0.00001) 
    \ > badthreshold && YDifferenceToNext() / Max(YDifferenceToNext(selectevery(1, 1)),0.00001)
    \ > badthreshold", "current_frame", append = false) : Source
mod
Code:
INTERLACED          = FALSE          # You decide
filename            = "E:\Bad.txt"   # Set to name and location where you want the frame numbers stored
#=====================================================================

source = AVISource(VideoFile).convertTOYV12(Interlaced=INTERLACED).killaudio()

script = """
    PrevRatio = YDifferenceFromPrevious / Max(YDifferenceFromPrevious( selectevery(1, -1)),0.00001)
    NextRatio = YDifferenceToNext       / Max(YDifferenceToNext      ( selectevery(1, 1 )),0.00001)
    ScriptDot = (PrevRatio > badthreshold && NextRatio > badthreshold) ? "***" : ""
    Subtitle(ScriptDot+"\nPrevious Ratio = " + String(PrevRatio) + "\nNext Ratio        = " + String(NextRatio), lsp=0)
"""

MetClip = Scriptclip(source, script)

FileFixed = (FILEWRITE)
    \ ? WriteFileIf(source, filename,
        \ "
            \ YDifferenceFromPrevious() / Max(YDifferenceFromPrevious( selectevery(1, -1)),0.00001) > badthreshold &&
            \ YDifferenceToNext()       / Max(YDifferenceToNext      ( selectevery(1, 1 )),0.00001) > badthreshold
        \ "
        \ , "current_frame", append = false)
    \ : Source

output = (METRICS) ? MetClip : (REPLACE) ? ReplaceBadI(FileFixed,showdot) : FileFixed
return output#.StackVertical(Source)
EDIT: Also, the ConvertToYV12 might want an Interlaced=True if appropriate.
eg
Code:
INTERLACED          = FALSE          # You decide
filename            = "E:\Bad.txt"   # Set to name and location where you want the frame numbers stored
#=====================================================================

source = AVISource(VideoFile).convertTOYV12(Interlaced=INTERLACED).killaudio()
EDIT: Modified scipt a bit more. Added ScriptDot
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 5th August 2018 at 12:37.
StainlessS is offline   Reply With Quote
Old 5th August 2018, 15:40   #11  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 7,086
John, Spotted a pretty bad error in your script, as was a little 'messy' prior to above suggested mods, was difficult for anyone to spot it,
(probably just assumed that logic was correct without examining too closely).

Relates to detection logic
Code:
FileFixed = (FILEWRITE)
    \ ? WriteFileIf(source, filename, "
    \ YDifferenceFromPrevious() / Max(YDifferenceFromPrevious( selectevery(1, -1)),0.00001) 
    \ > badthreshold && YDifferenceToNext() / Max(YDifferenceToNext(selectevery(1, 1)),0.00001)
    \ > badthreshold", "current_frame", append = false) : Source
and this (does not produce same results as per above)
Code:
 fixed       = ConditionalSelect(c, "
                Prev  = YDifferenceFromPrevious()
                Prev1 = Max(YDifferenceFromPrevious(SelectEvery(1,-1)),0.00001)
                Next  = YDifferenceToNext()
                Next1 = Max(YDifferenceToNext(SelectEvery(1,1)),0.00001)
                Prev/Prev1 < badthreshold && Next/Next1 < badthreshold ? 0 : 1", \
                c, selectevery(Replacement,1,-1))
WriteFile stuff is like this
Code:
BADFRAME =  (A > badthresh && B > badthresh) # both have to be greater than badthresh to be bad (if either is smaller or equal to badthresh then NOT bad)
Whereas in ReplaceBadI is not same logic
Code:
GOODFRAME =  (A < badthresh && B < badthresh) # ie selects source frame if good else interpolates
Assuming that Writefile stuff is correct then ReplaceBadI should be [EDIT: Have not yet figured out which is correct]
Code:
GOODFRAME =  (A <= badthresh || B <= badthresh) # ie selects source frame if good else interpolates
Tis a bit dangerous reversing logic, (invert conditions ie > to <=) and invert logic operator (ie && to ||),
a lot safer in this case to use exact same logic and ConditionalSelect return '? 1 : 0' instead of '? 0 : 1'.

EDIT: Think this is the guy, Augustus De Morgan:- https://en.wikipedia.org/wiki/De_Morgan%27s_laws



EDIT: I really should brush up on this stuff, List of Boolean algebra topics:- https://en.wikipedia.org/wiki/List_o...algebra_topics

EDIT: Which one is as intended, WriteFileIf, or ReplaceBadI ???
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 5th August 2018 at 17:05.
StainlessS is offline   Reply With Quote
Old 5th August 2018, 17:12   #12  |  Link
johnmeyer
Registered User
 
Join Date: Feb 2002
Location: California
Posts: 2,184
StainlessS,

Thanks for taking such a detailed look at my script. As you can see from the comments in my script and also the link I provided to the thread where I initially developed this, you looked at it quite a bit back then.

I like the easier-to-understand versions, but I'm not sure all the changes are going to work (I'm not in my office right now). First, I don't see any logic to turn "showdot" on and off. I had a SHOWDOT true/false variable at the beginning of my script and, when set to FALSE, no dots were shown. The whole idea of having the dots is to be able to study those frames that are now interpolated, and take action if you see too many frames which contain motion estimation artifacts. You obviously do not want the dots in the final rendered output.

So you have to be able to turn off the dots.

The "interlaced=true" addition is a good one, and something I need to remember, since color conversions can get screwed up without it.

The replace logic bug has me scratching my head, however. I've used this script on multiple occasions and I am pretty sure the ReplaceBadI function works correctly, even if my script formatting is a little crude. So I think my "less than" and "greater than" logic is OK, as is the "AND" vs. "OR" logic (and of course Boolean logic lets you get the same result if you negate and simultaneously change from AND to OR). Thus, if there is an error, it must be in the WriteFile logic. I'm not sure I have saved frame numbers (which is what the WriteFile section does) since I first developed the script. So, when I get back to my office computer, I'll check that and see if it is indeed backwards, as you say.

Thanks!
johnmeyer is offline   Reply With Quote
Old 5th August 2018, 17:26   #13  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 7,086
The added Showdot stuff is only in the Metrics display, your showdots is for ReplaceBadI only,
Not really necessary to switch it on/off in metrics.

When you can, tell which is the correct one (I suspect that I assumed wrong and ReplaceBadI was actually correct).

Quote:
I'll check that and see if it is indeed backwards, as you say.
Guaranteed, although dont know for sure which is correct. (I stopped as soon as I saw the error).
EDIT:
Quote:
if there is an error, it must be in the WriteFile
OK, I'll continue with that assumption, however I shall mod to detect BADFRAMES as detecting GOODFRAMES dont feel right.

Currently attempting to make a much more understandable version of the entire script, with more differences available eg n-1 <-> n+1
so script can be hacked much more easily for some specific requirment.

EDIT: Question, Do you does, or do you doesn't use Avs+, GScript, Grunt ???
EDIT: "Is you is or is you ain't my baby ..."

EDIT: If you use above mentioned avs+, GScript, Grunt, then could make contained functions, less problems interfering between them
eg Local and private args courtesy of Grunt [EDIT: and without globals].

EDIT:
Quote:
As you can see from the comments in my script and also the link I provided to the thread where I initially developed this, you looked at it quite a bit back then.
Yep, and so did Gavino, so that probably vindicates/mitigates me a lil bit [Big G will probably pop up soon with some similar excuse ]
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 5th August 2018 at 18:36.
StainlessS is offline   Reply With Quote
Old 5th August 2018, 22:50   #14  |  Link
johnmeyer
Registered User
 
Join Date: Feb 2002
Location: California
Posts: 2,184
StainlessS,

I won't be able to look at this until tomorrow, but I can say with certainty that the ReplaceBadI function works as intended because I used that yesterday on the OP's video and it worked. And, it worked not only when I originally posted the script, but also when I've used it since I created it a few years ago.

Even though I included the logic to write the frame numbers to a file, I haven't used that since I did the testing when I originally wrote the script. So if there is a problem, it is probably there. In my defense, I may have wanted to write the numbers of the good frames rather than the bad ones, but I can't remember at this point. If that was my intent, I certainly failed to document it correctly.

Quote:
EDIT: Question, Do you does, or do you doesn't use Avs+, GScript, Grunt ???
EDIT: "Is you is or is you ain't my baby ..."
I am, of course, a StainlessS acolyte, so yes I do have all of those and, if you remember the NFL "kinescope" film beat bars that you helped me with, it was the functions in GScript that let me create a mask from the overexposure created by the noise bars, and then correct the exposure, a restoration result of which I am quite proud and which I could not have done without both your excellent functions, and also your help:

1955 NFL Football "Kinescope"

The only reason I brought your name up in this thread is that I thought perhaps you would have a more clever, or at least a more effective way to detect the noise bars. YDifference should have nailed it, but it didn't catch all of them, and didn't produce large, obvious metrics as I thought it would. The noise is pretty massive and should be easy to detect, but my approach isn't good enough.

A better comparison between the the two adjacent frames should be able to catch them all.

Your idea for handling two frame glitches would be very welcome (see my original post for the problems dealing with still photographer's "pre-flashes"), but the logic for doing motion estimation from frames which are more distant would be mildly complicated and therefore not a ten-minute exercise.

Last edited by johnmeyer; 5th August 2018 at 22:59. Reason: clarity
johnmeyer is offline   Reply With Quote
Old 5th August 2018, 23:18   #15  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 7,086
What I got so far.

Code:
#loadplugin("C:\Program Files\AviSynth 2.5\plugins\MVTools\mvtools2.dll")

#Control script operation by changing the following values :
#=====================================================================
VideoFile           = "E:\Documents\Dnload\UNPACK\Rollaine_Noise_Sample_Pass1_huffy.avi"
VideoFile           = ".\GreyMouse_Rollaine_Noise_Sample_Pass1_huffy.avi"

INTERLACED          = FALSE          # Source is Interlaced, You decide.
BADTHRESHOLD        = 1.3            # Set METRICS=TRUE to determine best value
METRICS             = TRUE           # TRUE will show Metrics ONLY (i.e., TRUE overrides all other selections)
REPLACE             = TRUE           # TRUE will replace each bad frame with a one that is interpolated from adjacent frames
SHOWDOT             = TRUE           # TRUE will add "***" to each replacment frame (for troubleshooting)
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(Interlaced=INTERLACED).killaudio()

Met_Script = """                                    # Where n = current_frame
        ###################
        P1C       = selectevery(1, -1)                  # Clip where n-1 Frame shifted to frame n
        N1C       = selectevery(1, +1)                  # Clip where n+1 Frame shifted to frame n
        P2C       = selectevery(1, -2)                  # Clip where n-2 Frame shifted to frame n
        N2C       = selectevery(1, +2)                  # Clip where n+2 Frame shifted to frame n
        P3C       = selectevery(1, -3)                  # Clip where n-3 Frame shifted to frame n
        N3C       = selectevery(1, +3)                  # Clip where n+3 Frame shifted to frame n
        ###
        P3Ave     = AverageLuma(P3C)                    # AverageLuma(n-3)
        N3Ave     = AverageLuma(N3C)                    # AverageLuma(n+3)
        P2Ave     = AverageLuma(P2C)                    # AverageLuma(n-2)
        N2Ave     = AverageLuma(N2C)                    # AverageLuma(n+2)
        P1Ave     = AverageLuma(P1C)                    # AverageLuma(n-1)
        N1Ave     = AverageLuma(N1C)                    # AverageLuma(n+1)
        Ave       = AverageLuma                         # AverageLuma(n+0)
        ###
        P3P2Dif   = LumaDifference(P3C,P2C)             # Dif(n-3, n-2)
        N2N3Dif   = LumaDifference(N2C,N3C)             # Dif(n+2, n+3)
        ##
        P2P1Dif   = YDifferenceFromPrevious(P1C)        # Dif(n-2, n-1)
        N1N2Dif   = YDifferenceToNext(N1C)              # Dif(n+1, n+2)
        P1Dif     = YDifferenceFromPrevious             # Dif(n-1, n+0)
        N1Dif     = YDifferenceToNext                   # Dif(n+0, n+1)
        P1Alt     = Lumadifference(P2C)                 # Dif(n-2, n+0)  # Difference between frames either side of n - 1
        N1Alt     = Lumadifference(N2C)                 # Dif(n+0, n+2)  # Difference between frames either side of n + 1
        Alt       = Lumadifference(P1C,N1C)             # Dif(n-1, n+1)  # Difference between frames either side of n
        PRatio    = P1Dif / Max(P2P1Dif,0.00001)        # Dif(n-1, n+0) / Max(Dif(n-2,n-1),0.00001)
        NRatio    = N1Dif / Max(N1N2Dif,0.00001)        # Dif(n+0, n+1) / Max(Dif(n+1,n+2),0.00001)

#       P1P2Rat    = P1Dif / Max(P2P1Dif,0.00001)       # Dif(n-1, n+0) / Max(Dif(n-2,n-1),0.00001)
#       N1N2Rat    = N1Dif / Max(N1N2Dif,0.00001)       # Dif(n+0, n+1) / Max(Dif(n-2,n-1),0.00001)
# EDIT: Should not be here, stumbling over good unique names at the moment

        ###
        FoundBad  = (PRatio >= badthreshold || NRatio >= badthreshold)      # True if FoundBad (bad if either is bad)
        ###################

        ScriptDot = (FoundBad) ? "***" : ""
        Met_Script_S  =
            \ ScriptDot                         +
            \ String(P3Ave,   "\nP3Ave   = %f") +
            \ String(N3Ave,   "\nN3Ave   = %f") +
            \ String(P2Ave,   "\nP2Ave   = %f") +
            \ String(N2Ave,   "\nN2Ave   = %f") +
            \ String(P1Ave,   "\nP1Ave   = %f") +
            \ String(N1Ave,   "\nN1Ave   = %f") +
            \ String(Ave,     "\nAve     = %f") +
            \ String(P3P2Dif, "\nP3P2Dif = %f") +
            \ String(N2N3Dif, "\nN2N3Dif = %f") +
            \ String(P2P1Dif, "\nP2P1Dif = %f") +
            \ String(N1N2Dif, "\nN1N2Dif = %f") +
            \ String(P1Dif,   "\nP1Dif   = %f") +
            \ String(N1Dif,   "\nN1Dif   = %f") +
            \ String(P1Alt,   "\nP1Alt   = %f") +
            \ String(N1Alt,   "\nN1Alt   = %f") +
            \ String(Alt,     "\nAlt     = %f") +
            \ String(PRatio,  "\nPRatio  = %f") +
            \ String(NRatio,  "\nNRatio  = %f")

        Return Subtitle(Met_Script_S, lsp=0,Font="Courier New",Size=28)
"""

MetClip = Scriptclip(source, Met_Script)
return MetClip
The 1st bit can have some lines commented out, same with subtitle metrics part.

If I can use GSCript/avs+, Grunt, and RT_Stats (older v1.43 should be fine), then I can make functions that can take a USER expression that returns
bool (final probably return int, above returns clip rather than bool or int, but that is sort of incidental).
Expression will have to use Standardised names (as in 1st part of above script, [not finalized at all yet]),
and function could create an eval string that implements only the user used variables eg P1Dif etc . Same type of thing for above Subtitle part.
In essence, user supplies a Script using named variables, and utility function returns a script string to ascertain eg dif(n-1,n+0) [for P1Dif], etc,
similar setup to create subtitle string. Depending upon some args, will concatenate scripts producing final funtionality for whatever required.

Thats the idea anyways. Question remains, do you use Gscript/avs+ Grunt ? [EDIT: Already answered]

User Supplied script might look something like
Code:
(PRatio >= Thresh1 || NRatio >= Thresh1)
and then together with some user supplied args (like ShowSubtitle, or whatever) will create function that behaves as required.

Above snippet works ok with Greymouse clip, all it does is show subtitled variables.

EDIT: Well then WriteFile stuff broken

if replace stuff,
Code:
GOODFRAME =  (A < badthresh && B < badthresh) # ie selects source frame if good else interpolates
Return (GOODFRAME) ? 0 : 1
Then below should be correct for WriteFile
Code:
BADFRAME =  (A >= badthresh || B >= badthresh)  # was, BADFRAME =  (A > badthresh && B > badthresh)
EDIT: My lil idea at start of this post is a bit hazy just now, but we will get it working just fine with
conditions that can be user knocked up reasonably easily.

EDIT:
Quote:
Thats the idea anyways. Question remains, do you use Gscript/avs+ Grunt ?
Sorry, I saw your answer now.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 6th August 2018 at 00:21.
StainlessS is offline   Reply With Quote
Old 6th August 2018, 04:37   #16  |  Link
johnmeyer
Registered User
 
Join Date: Feb 2002
Location: California
Posts: 2,184
I had to go to my office computer this evening, so I spent a few minutes on this. As I surmised, my ReplaceBadI function works as expected, although because of my poor detection logic, it is not as reliable as I'd like with this test clip. However you are correct that the WriteFileIf is dodgy. But, I don't think it is for the reasons you think. The logic itself actually works as written, and if I change the ">" to "<" it outputs almost every frame number, meaning that it is saving the good frame numbers.

I then tried changing ">" to ">=", and this made a big difference. What?? This makes absolutely no sense to me because the chances of two metrics actually being equal are virtually zero, unless you have a perfect duplicate. Therefore, I should have not seen any difference whatsoever.

So, I think my WriteIf problems are far deeper than just a mistake in boolean logic and are probably related to some of the mysteries of how conditional logic in AVISynth works.

If GScript or GRunT can solve these problems, I'm willing to try it out, although we should remember that it is the OP who asked for help, not me.
johnmeyer is offline   Reply With Quote
Old 6th August 2018, 12:26   #17  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 7,086
Quote:
BADFRAME = (A >= badthresh || B >= badthresh) # was, BADFRAME = (A > badthresh && B > badthresh)
Was not just > oposed to >= that was wrong, also the logic operator, in red above.
(and no matter how remote a possibility, >= is opposite <).
EDIT: And opposite of != is not != (as == is unlikely to happen)

Quote:
it is the OP who asked for help
Yep, and the demo metrics thing could help spot what is required for OP problem. [which is what started me on it]

A lot of the problem is that the clip pans erratically, with periods where stationary, so its hard to detect the crap.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 6th August 2018 at 12:35.
StainlessS is offline   Reply With Quote
Old 6th August 2018, 15:58   #18  |  Link
johnmeyer
Registered User
 
Join Date: Feb 2002
Location: California
Posts: 2,184
Quote:
Originally Posted by StainlessS View Post
A lot of the problem is that the clip pans erratically, with periods where stationary, so its hard to detect the crap.
One idea that has worked for me with other similar situations is to create a moving average of the metric and then scale the difference metrics according to the moving average. This makes it easier to detect anomalies that happen during fast panning.
johnmeyer is offline   Reply With Quote
Old 6th August 2018, 17:21   #19  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 7,086
Wanna play with this anybody, (not really attempted to tweak thresh), additional errors within 2 frames of current will affect result.
the MC ratios, maybe could be replaced with comparison source(n-1)->Mc(n) and source(n+1)->Mc(n)
Code:
AVISource("D:\GreyMouse_Rollaine_Noise_Sample_Pass1_huffy.avi").ConvertToYV12
ORG=Last

SelectEvery(1,-1) # Shift Forward 1
super=MSuper()
prefilt    = RemoveGrain(22)
super      = MSuper(hpad=16,vpad=16,levels=1,sharp=1,rfilter=4)   # One level is enough for MRecalculate
superfilt  = prefilt.MSuper(hpad=16,vpad=16,sharp=1,rfilter=4)      # All levels for MAnalyse
bv        = superfilt.MAnalyse(isb=true, blksize=16,overlap=4,search=3,delta=2)
fv        = superfilt.MAnalyse(isb=false,blksize=16,overlap=4,search=3,delta=2)
bv        = super.MRecalculate(bv,blksize=8,overlap=2,thSAD=100)
fv        = super.MRecalculate(fv,blksize=8,overlap=2,thSAD=100)
MFlowInter(super,bv,fv,time=50,ml=200)
MC=Last
ORG

BadThreshold=1.3
GoodThreshold=BadThreshold
SHOWSUBS=true
ShowDot=true
STACK=true

Met_Script = """                                                               # Where n = current_frame
        ###################
        P1C       = selectevery(1, -1)                                         # Clip where n-1 Frame shifted to frame n
        N1C       = selectevery(1, +1)                                         # Clip where n+1 Frame shifted to frame n
        P2C       = selectevery(1, -2)                                         # Clip where n-2 Frame shifted to frame n
        N2C       = selectevery(1, +2)                                         # Clip where n+2 Frame shifted to frame n
        P2P1Dif   = YDifferenceFromPrevious(P1C)                               # Dif(n-2, n-1)
        N1N2Dif   = YDifferenceToNext(N1C)                                     # Dif(n+1, n+2)
        P1Dif     = YDifferenceFromPrevious                                    # Dif(n-1, n+0)
        N1Dif     = YDifferenceToNext                                          # Dif(n+0, n+1)
        P1Alt     = Lumadifference(P2C)                                        # Dif(n-2, n+0)  # Difference between frames either side of n - 1
        N1Alt     = Lumadifference(N2C)                                        # Dif(n+0, n+2)  # Difference between frames either side of n + 1
        Alt       = Lumadifference(P1C,N1C)                                    # Dif(n-1, n+1)  # Difference between frames either side of n
        PRatio    = P1Dif / Max(P2P1Dif,0.00001)                               # Dif(n-1, n+0) / Max(Dif(n-2,n-1),0.00001)
        NRatio    = N1Dif / Max(N1N2Dif,0.00001)                               # Dif(n+0, n+1) / Max(Dif(n+1,n+2),0.00001)
        ###
        MC_P1Dif    = Lumadifference(P1C,MC)                                   # Dif(n-1,    MC(n+0))
        MC_N1Dif    = Lumadifference(MC,N1C)                                   # Dif(MC(n+0),n+1)
        MC_PRatio   = MC_P1Dif / Max(P2P1Dif,0.00001)                          # Dif(n-1, MC(n+0)) / Max(Dif(n-2,n-1),0.00001)
        MC_NRatio   = MC_N1Dif / Max(N1N2Dif,0.00001)                          # Dif(MC(n+0), n+1) / Max(Dif(n+1,n+2),0.00001)
        SrcIsBad    = (PRatio >= badthreshold || NRatio >= badthreshold)       # True if Source frame bad (bad if either is bad)
        MCIsGood    = (MC_PRatio < GoodThreshold && MC_NRatio < GoodThreshold) # True if MC frame Good (good only if both good)
        UseMC       = SrcIsBad && MCIsGood
        ###
        ScriptDot = String(SrcIsBad) + " " + String(MCIsGood) + " " + String(UseMC)
        Met_Script_S  =
            \ ScriptDot                             +
            \ String(P2P1Dif,   "\nP2P1Dif   = %f") +
            \ String(N1N2Dif,   "\nN1N2Dif   = %f") +
            \ String(P1Dif,     "\nP1Dif     = %f") +
            \ String(N1Dif,     "\nN1Dif     = %f") +
            \ String(P1Alt,     "\nP1Alt     = %f") +
            \ String(N1Alt,     "\nN1Alt     = %f") +
            \ String(Alt,       "\nAlt       = %f") +
            \ String(PRatio,    "\nPRatio    = %f") +
            \ String(NRatio,    "\nNRatio    = %f") +
            \ String(MC_P1Dif,  "\nMC_P1Dif  = %f") +
            \ String(MC_N1Dif,  "\nMC_N1Dif  = %f") +
            \ String(MC_PRatio, "\nMC_PRatio = %f") +
            \ String(MC_NRatio, "\nMC_NRatio = %f")

        Return SHOWSUBS ? Subtitle(Met_Script_S, lsp=0,Font="Courier New",Size=28) : !UseMC ? Last : ShowDot ? MC.Subtitle("***") : MC
"""

Scriptclip(Met_Script)
return STACK ? StackVertical(Last,(SHOWDOT&&!SHOWSUBS)?ORG.Subtitle("Source"):MC.Subtitle("MC")) : Last
I've left some non used vars available, maybe nudge into better solution.
Not perfect, but it does work to some degree (sometimes replaces non bad frames, but results dont look much different to the non bad).
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 6th August 2018 at 17:41.
StainlessS is offline   Reply With Quote
Old 6th August 2018, 19:48   #20  |  Link
johnmeyer
Registered User
 
Join Date: Feb 2002
Location: California
Posts: 2,184
The good news is that I simply copied the script and it worked. The bad news is that it doesn't seem to do anything. The lower screen seems to be nothing more than the upper screen offset by one frame, with some of the noise removed, but not much, and in many cases no noise removed at all.

Also, in looking at all the metrics, the four main "ratio" metrics, which appear to be the heart of the detection logic, don't seem to change all that much for the frames containing lots of noise.

johnmeyer is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 14:30.


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