Log in

View Full Version : dropped frames DarkFrames()


greymouse
4th January 2018, 04:35
hi,

i'm working on some video where I would like to remove a previous frame and say 4 or 5 frames afterwards, but i can't seem to get my head around adding those addition frames to the deleted frames list and how to delete 1 frame prior frame here's my script so far




AviSource("F:\Work\Latest\First Day At School 24\Black_drops_sample_huffy.avi").converttoYV12() # change this to your video filename


threshold = 100# change this value to suit requirements

#ScriptClip(""" Subtitle(string(current_frame) + " - " + String(AverageLuma())) """) # uncomment this line to display frame numbers and averageluma values.

# now remove all frames darker than your set threshold from your video
offset = 0

ScriptClip("""
offset = offset + DarkFrames(Trim(offset, 0), current_frame, threshold) #offset contains number of frames to be cut
Trim(offset, 0) #0 pad audio

""")



# now cut out additional frames after offset
#create another function with different AvergeLuma(c) conditions


function DarkFrames(clip c, int current_frame, int thresh) {
# this function returns the number of consecutive 'dark' frames at the current frame
AverageLuma(c) > thresh ? 0
\ : (current_frame >= c.frameCount-1) ? 1
\ : 1 + DarkFrames(c.Trim(1,0), current_frame, thresh) #add one frame at a time to list using trim(1,0) with padding

}

any help please

:thanks:

greymouse
4th January 2018, 04:46
so on my avi captures, one frame prior to the drop out is bad and averageluma doesn't detect it, and after the function DarkFrames() does its job about 4 or 5 frames are bad and I would like to remove those as well

StainlessS
4th January 2018, 15:41
Post a sample.

Some links:

Delete frames satisfying user-defined condition:- https://forum.doom9.org/showthread.php?t=163107

Gavino's: Delete frames satisfying user-defined condition :- https://forum.doom9.org/showthread.php?t=172904

Blend duplicate frames? :- https://forum.doom9.org/showthread.php?p=1764486#post1764486

Another frame duplication function :- https://forum.doom9.org/showthread.php?p=1716968#post1716968

Auto drop dark frames:- https://forum.doom9.org/showthread.php?t=140999

Automatically fix dups followed (eventually) by drops :- https://forum.doom9.org/showthread.php?t=161758

Filter to remove duplicate frames:- https://forum.doom9.org/showthread.php?p=1493435#post1493435

automated framedrop filler script :):- https://forum.doom9.org/showthread.php?p=753779#post753779

greymouse
4th January 2018, 20:18
thanks!

okay uploading a sample clip


Gordon

greymouse
4th January 2018, 20:56
this is the one im working off

Auto drop dark frames:- https://forum.doom9.org/showthread.php?t=140999

Single_Frame_Previous_sample.avi


previous_frame_to_delete1.bmp

previous frame to delete
in my capture most of the time I get this frame before a frame drop, which averageluma() doesn't pick up because its set to a different threshold


then after the darkframe() function i'm left with these junk frames I would also like to delete,

i've tried modifying the script but i've had no luck in adding code to automatically delete the previous frame and he 3,4 junk frames left over

example files

Black_drops_sample.avi

after_filter_delete_frames0.bmp - after_filter_delete_frames8.mp


sample videos:


Pictures:

greymouse
4th January 2018, 21:00
the DarkFrames() works as it should its just I would like to add to the function to also delete the 1 previous frame and and left over frames afterwards

greymouse
7th January 2018, 00:23
in regard to previous frame 1.bmp or Single_Frame_Previous_Sample.avi, how do I remove that automatically? it the moment im doing frame by frame editing in VirtrualdubMod but I would like these frames deleted also automatically any help would be appreciated

StainlessS
7th January 2018, 00:40
Here:


Function DarkGreyMouse(clip c, Float "Th",Int "delPre",Int "delPost",String "FramesFile") {
# DarkGreyMouse(), (c) StainlessS, https://forum.doom9.org/showthread.php?t=175158
# Create a frames command file to delete dark ranges(<=Th) with optional deletion of preceding and postceding frames.
# Afterwards, use RejectRanges(Cmd="FrameFile.txt") to actually delete the dark frames.
# Does NOT return until FramesFile created.
# Req RT_Stats, GScript(c) Gavino.
c
Th = Float(Default(Th, 64.0)) # AverageLuma <= Th ==== DARK
delPre = Default(delPre, 0) # Number of frames to drop before first dark one
delPost = Default(delPost, 0) # Number of frames to drop after last dark one
FramesFile = Default(FramesFile, "Frames.txt") # Output file
FramesFile = RT_GetFullPathName(FramesFile)
RT_FileDelete(FramesFile)
GSCript("""
FC=FrameCount WrE = -1
for(i=0,FC-1) {
if(RT_AverageLuma(n=i) <= Th) { # Found starting dark frame
sLight=FC # Preset Starting light frame at last frame + 1
for(j=i+1,FC-1) { # look for light frame (ie last dark + 1)
if(RT_AverageLuma(n=j) > Th) {
sLight = j # Found starting light frame
j = FC # Break
}
}
WrS = Max(WrE+1,i-delPre)
WrE = Min(sLight-1+delPost,FC-1)
RT_WriteFile(FramesFile,"%d,%d",WrS,WrE,Append=True) # write dark range to framesfile (incl delpre and delpost)
i=WrE # Next i iteration continue at WrE + 1
}
}
""")
#return c
Return MessageClip(Chr(10)+"FrameFile Created"+Chr(10)+Chr(10)+Chr(10))
}


My test script

Colorbars.ConvertToYV12.killAudio

A=Trim(0,-100)
B=A.Levels(16,1.0,235,16,63,Coring=false)
A++B++A

DarkGreyMouse(Last,Th=64.0,delPre=10,delPost=20) # delete range 90,219

EDITED:

And the script to actually delete the frames

avisource("...") # whatever
return RejectRanges(Cmd="Frames.txt")


Also need RejectRanges() from Prune or FrameSel (included with both plugins, and requires both plugs).

Prune:- https://forum.doom9.org/showthread.php?t=162446
FrameSel:- https://forum.doom9.org/showthread.php?t=167971
Also requires RT_Stats:- https://forum.doom9.org/showthread.php?t=165479
and GScript if not using avs+:- https://forum.doom9.org/showthread.php?t=147846

Not much tested, but should be ok I think.

EDIT: Here what RejectRanges looks like

Function RejectRanges(clip c,String "SCmd",String "Cmd",Bool "TrimAudio",Float "FadeMS") {
# RejectRanges() by StainlessS. Required:- FrameSel, Prune, RT_Stats
# Wrapper to delete frames/ranges along with audio, can supply frames/ranges in SCmd string And/Or Cmd file.
# The wrapper makes for easier usage of Prune() which supports up to 256 input clips, but requires a clip index,
# eg '3, 100,200' would specify clip 3, range 100 to 200. The wrapper does away with the necessity for the clip index as we
# are only using a single clip here. Prune also does not have a 'reject' arg to delete specified frames rather than select them,
# this wrapper also converts a list of frames to delete into a list of frames to select so that we can use Prune and its audio
# capability.
#
# SCmd: Frames/Ranges specified in String (Frames/Ranges either Chr(10) or ';' separated, infix ',' specifies range, eg 'start,end').
# Cmd: Frames/Ranges specified in file (one frame/range per line, comments also allowed, see FrameSel for Further info).
# TrimAudio:
# True(default), deletes audio belonging to deleted frames
# False, returns original audio, probably out of sync.
# FadeMS: (default 1.0 millisec). Linear Audio Fade duration at splices when TrimAudio==true, 0 = dont fade (might result in audio 'clicks/cracks').
c
TrimAudio=Default(TrimAudio,True) # default true trims audio, false returns original audio (audiodubbed, as Framesel returns no audio)
FadeMS=Float(Default(FadeMS,1.0)) # 1 millisecond linear fadeout/fadein at splices
PruneCmd = (TrimAudio) ? "~Prune_"+RT_LocalTimeString+".txt" : ""
(!TrimAudio)
\ ? FrameSel(scmd=SCmd,cmd=Cmd,reject=true)
\ : FrameSel_CmdReWrite(PruneCmd,scmd=SCmd,cmd=Cmd,reject=true,Prune=True,range=true)
(TrimAudio) ? Prune(Cmd=PruneCmd,FadeIn=True,FadeSplice=True,FadeOut=True,Fade=FadeMS) : NOP
# If TrimAudio==true then delete Prune temp file, Else restore original Audio to the now audio-less clip
(TrimAudio)
\ ? RT_FileDelete(PruneCmd)
\ : (c.HasAudio) ? AudioDub(c) : NOP
Return Last
}

greymouse
7th January 2018, 01:37
not working properly yet, i'm not sure what im doing wrong

i'm uploading the processed video atm

here's the script so far:

#Setmemorymax(512)

###############################################################################
LoadPlugin("C:\Video-tools\avisynth 2.5\plugins\FrameSel.dll")
LoadPlugin("C:\Video-tools\avisynth 2.5\plugins\Prune.dll")
LoadPlugin("C:\Video-tools\avisynth 2.5\plugins\RT_Stats.dll")
LoadPlugin("C:\Video-tools\avisynth 2.5\plugins\GScript.dll")

###############################################################################


#DirectShowSource("F:\Video-Capture\First Day At School 24.avi").converttoYV12() #for Win64
AVISource("D:\Temp\Video-edit2\Dropped Frames\Question\Black_drops_sample.avi").converttoYV12().killaudio


#Colorbars.ConvertToYV12.killAudio

A=Trim(0,-100)
B=A.Levels(16,1.0,235,16,50,Coring=false)
A++B++A

GreyMouse(Last,DelPre=10,delPost=20)



Function GreyMouse(clip c, Float "Th",Int "delPre",Int "delPost",String "FramesFile") {
# Does NOT return until FramesFile created.
# Req RT_Stats, GScript(c) Gavino.
c
Th = Float(Default(Th, 64.0)) # AverageLuma <= Th ==== DARK
delPre = Default(delPre, 0) # Number of frames to drop before first dark one
delPost = Default(delPost, 0) # Number of frames to drop after last dark one
FramesFile = Default(FramesFile, "Frames.txt") # Output file
RT_GetFullPathName(FramesFile)
RT_FileDelete(FramesFile)
GSCript("""
c FC=FrameCount WrE = -1
for(i=0,FC-1) {
if(RT_AverageLuma(n=i) <= Th) {
sLight=FC
for(j=i+1,FC-1) {
if(RT_AverageLuma(n=j) > Th) {
sLight = j
j = FC # Break
}
}
WrS = Max(WrE+1,i-delPre)
WrE = Min(sLight-1+delPost,FC-1)
RT_WriteFile(FramesFile,"%d,%d",WrS,WrE,Append=True)
i=WrE # Next i iteration continue at WrE + 1
}
}
""")
return c
#Return MessageClip("FrameFile Created")
}


Function RejectRanges(clip c,String "SCmd",String "Cmd",Bool "TrimAudio",Float "FadeMS") {
# RejectRanges() by StainlessS. Required:- FrameSel, Prune, RT_Stats
# Wrapper to delete frames/ranges along with audio, can supply frames/ranges in SCmd string And/Or Cmd file.
# The wrapper makes for easier usage of Prune() which supports up to 256 input clips, but requires a clip index,
# eg '3, 100,200' would specify clip 3, range 100 to 200. The wrapper does away with the necessity for the clip index as we
# are only using a single clip here. Prune also does not have a 'reject' arg to delete specified frames rather than select them,
# this wrapper also converts a list of frames to delete into a list of frames to select so that we can use Prune and its audio
# capability.
#
# SCmd: Frames/Ranges specified in String (Frames/Ranges either Chr(10) or ';' separated, infix ',' specifies range, eg 'start,end').
# Cmd: Frames/Ranges specified in file (one frame/range per line, comments also allowed, see FrameSel for Further info).
# TrimAudio:
# True(default), deletes audio belonging to deleted frames
# False, returns original audio, probably out of sync.
# FadeMS: (default 1.0 millisec). Linear Audio Fade duration at splices when TrimAudio==true, 0 = dont fade (might result in audio 'clicks/cracks').
c
TrimAudio=Default(TrimAudio,True) # default true trims audio, false returns original audio (audiodubbed, as Framesel returns no audio)
FadeMS=Float(Default(FadeMS,1.0)) # 1 millisecond linear fadeout/fadein at splices
PruneCmd = (TrimAudio) ? "~Prune_"+RT_LocalTimeString+".txt" : ""
(!TrimAudio)
\ ? FrameSel(scmd=SCmd,cmd=Cmd,reject=true)
\ : FrameSel_CmdReWrite(PruneCmd,scmd=SCmd,cmd=Cmd,reject=true,Prune=True,range=true)
(TrimAudio) ? Prune(Cmd=PruneCmd,FadeIn=True,FadeSplice=True,FadeOut=True,Fade=FadeMS) : NOP
# If TrimAudio==true then delete Prune temp file, Else restore original Audio to the now audio-less clip
(TrimAudio)
\ ? RT_FileDelete(PruneCmd)
\ : (c.HasAudio) ? AudioDub(c) : NOP
Return Last
}

greymouse
7th January 2018, 01:38
it does create frames.txt as well

frames.txt has
58,219
258,299

in it

StainlessS
7th January 2018, 01:51
Yeh, you need to decide and set args to the function, whatever you decided when viewing your original ScriptClip thing.

EDIT: Your original scriptclip thing to get best averageluma Th, and you decide however many delPre and delPost frames you want deleted.

#ScriptClip(""" Subtitle(string(current_frame) + " - " + String(AverageLuma())) """) # uncomment this line to display frame numbers and averageluma values.



The args I used were just dummies, for a quick test.

Later in another script, you use the RejectRanges function.
eg

avisource("...") # whatever
return RejectRanges(Cmd="Frames.txt")

Try not to use DirectShowSource unless absolutely necessary, not frame accurate.

EDIT:
This is all my test dummy stuff, you DONT need it

#Colorbars.ConvertToYV12.killAudio

A=Trim(0,-100)
B=A.Levels(16,1.0,235,16,50,Coring=false)
A++B++A


Set below args to whatever you want

DarkGreyMouse(Last,Th=64.0,DelPre=10,delPost=20)

The original script has changed a bit.

greymouse
7th January 2018, 02:20
okay i'll have a play around and tweak things, will post finished script, thank you StainLess

StainlessS
7th January 2018, 02:39
I've changed DarkGreyMouse a little to return c clip instead of Messageclip (choose whatever you prefer),
so as to use in a single script. [EDIT: will scan entire clip before playing deleted ranges clip]

Try this on my test clip, so you can see it working before mod to your clip.
entire script here (I have all plugs in my plugins, so I dont need load them)
I've also added ShowFrameNumber, so you can see that the frames have indeed been deleted.
Good luck.


Function RejectRanges(clip c,String "SCmd",String "Cmd",Bool "TrimAudio",Float "FadeMS") {
# RejectRanges() by StainlessS. Required:- FrameSel, Prune, RT_Stats
# Wrapper to delete frames/ranges along with audio, can supply frames/ranges in SCmd string And/Or Cmd file.
# The wrapper makes for easier usage of Prune() which supports up to 256 input clips, but requires a clip index,
# eg '3, 100,200' would specify clip 3, range 100 to 200. The wrapper does away with the necessity for the clip index as we
# are only using a single clip here. Prune also does not have a 'reject' arg to delete specified frames rather than select them,
# this wrapper also converts a list of frames to delete into a list of frames to select so that we can use Prune and its audio
# capability.
#
# SCmd: Frames/Ranges specified in String (Frames/Ranges either Chr(10) or ';' separated, infix ',' specifies range, eg 'start,end').
# Cmd: Frames/Ranges specified in file (one frame/range per line, comments also allowed, see FrameSel for Further info).
# TrimAudio:
# True(default), deletes audio belonging to deleted frames
# False, returns original audio, probably out of sync.
# FadeMS: (default 1.0 millisec). Linear Audio Fade duration at splices when TrimAudio==true, 0 = dont fade (might result in audio 'clicks/cracks').
c
TrimAudio=Default(TrimAudio,True) # default true trims audio, false returns original audio (audiodubbed, as Framesel returns no audio)
FadeMS=Float(Default(FadeMS,1.0)) # 1 millisecond linear fadeout/fadein at splices
PruneCmd = (TrimAudio) ? "~Prune_"+RT_LocalTimeString+".txt" : ""
(!TrimAudio)
\ ? FrameSel(scmd=SCmd,cmd=Cmd,reject=true)
\ : FrameSel_CmdReWrite(PruneCmd,scmd=SCmd,cmd=Cmd,reject=true,Prune=True,range=true)
(TrimAudio) ? Prune(Cmd=PruneCmd,FadeIn=True,FadeSplice=True,FadeOut=True,Fade=FadeMS) : NOP
# If TrimAudio==true then delete Prune temp file, Else restore original Audio to the now audio-less clip
(TrimAudio)
\ ? RT_FileDelete(PruneCmd)
\ : (c.HasAudio) ? AudioDub(c) : NOP
Return Last
}

Function DarkGreyMouse(clip c, Float "Th",Int "delPre",Int "delPost",String "FramesFile") {
# DarkGreyMouse(), (c) StainlessS, https://forum.doom9.org/showthread.php?t=175158
# Create a frames command file to delete dark ranges(<=Th) with optional deletion of preceding and postceding frames.
# Afterwards, use RejectRanges(Cmd="FrameFile.txt") to actually delete the dark frames.
# Does NOT return until FramesFile created.
# Req RT_Stats, GScript(c) Gavino.
c
Th = Float(Default(Th, 64.0)) # AverageLuma <= Th ==== DARK
delPre = Default(delPre, 0) # Number of frames to drop before first dark one
delPost = Default(delPost, 0) # Number of frames to drop after last dark one
FramesFile = Default(FramesFile, "Frames.txt") # Output file
FramesFile = RT_GetFullPathName(FramesFile)
RT_FileDelete(FramesFile)
GSCript(""" # COMMENT out if AVS+
FC=FrameCount WrE = -1
for(i=0,FC-1) {
if(RT_AverageLuma(n=i) <= Th) { # Found starting dark frame
sLight=FC # Preset Starting light frame at last frame + 1
for(j=i+1,FC-1) { # look for light frame (ie last dark + 1)
if(RT_AverageLuma(n=j) > Th) {
sLight = j # Found starting light frame
j = FC # Break
}
}
WrS = Max(WrE+1,i-delPre)
WrE = Min(sLight-1+delPost,FC-1)
RT_WriteFile(FramesFile,"%d,%d",WrS,WrE,Append=True) # write dark range to framesfile (incl delpre and delpost)
i=WrE # Next i iteration continue at WrE + 1
}
}
""") # COMMENT out if AVS+
return c
#Return MessageClip(Chr(10)+"FrameFile Created"+Chr(10)+Chr(10)+Chr(10))
}

Colorbars.ConvertToYV12.killAudio

A=Trim(0,-100) # 100 frame
B=A.Levels(16,1.0,235,16,63,Coring=false) # 100 dark frames
A++B++A++B++A # 100 light, 100 dark, 100 light, 100 dark, 100 light, total 500 frames.
ShowFrameNumber

DarkGreyMouse(Last,Th=64.0,delPre=10,delPost=20,FramesFile="Frames.txt") # delete ranges 90,219(100-10, 199+20) and 290,419(300-10, 399+20)

return RejectRanges(Cmd="Frames.txt")


Generated frames.txt

90,219
290,419

greymouse
7th January 2018, 06:56
managed to mod my script its is working really well! :) :) :) :) :thanks: :thanks: :thanks:

StainlessS
7th January 2018, 15:36
Very good, glad you are a happy chappy :)

If you have a lot of similar stuff to do, perhaps this of use (change ending of previous script to this, try with my test first).

Colorbars.ConvertToYV12.killAudio
A=Trim(0,-100) # 100 frame
B=A.Levels(16,1.0,235,16,63,Coring=false) # 100 dark frames
A++B++A++B++A # 100 light, 100 dark, 100 light, 100 dark, 100 light, total 500 frames.
ShowFrameNumber

# BELOW PASS 1, Create Frames File
DarkGreyMouse(Last,Th=64.0,delPre=10,delPost=20,FramesFile="Frames.txt") # delete ranges 90,219(100-10, 199+20) and 290,419(300-10, 399+20)

# Delete Dark Ranges, Start of Pass 2
RejectRanges(Cmd="Frames.txt")

# Below To Auto Write AVI file.
FILENAME = "Result.avi"
OVERWRITE = True
FOURCC = "ULY0" # Ut_Video
# Save/Overwrite output to Lossless UT_Video, and play video as you write it.
TWriteAvi(Last,FILENAME,Overwrite=OVERWRITE,fourcc=FOURCC) # TWriteAVI:- https://forum.doom9.org/showthread.php?t=172837

# UnComment BELOW to NOT Play, just write AVI and stop on "ALL Done" message.
# ForceProcessAVI(Last) Return MessageClip("All Done"+Chr(10)+"Result written to AVI")

Return Last

greymouse
8th January 2018, 00:24
that's the idea the more I can get done automatically the better, helps speed up the whole process

StainlessS
8th January 2018, 15:17
This might be quite nice too

Function TestAveLuma(clip c,Float Th,Int "BordCol",Int "BordSz",Int "FontSz",Int "Align",Bool "Subs") {
Function TestAveLuma_LO(clip c,Float Th,Int BordCol,Int BordSz,Int FontSz,Int Align,Bool Subs) {
c Y=AverageLuma
(Y>Th) [* Maybe Change condition *]
\ ? NOP [* OK CONDITION *]
\ : LetterBox(BordSZ,BordSZ,BordSZ,BordSZ,BordCol) [* NOT OK, BordCol Border *]
Subs ? Subtitle(String(current_frame,"%.0f] ") + String(Y,"AverageLuma = %.2f"),Size=FontSz,Align=Align) : NOP
Return Last
}
c BordCol=Default(BordCol,$FF0000) BordSz=Default(BordSz,8)
FontSz=Default(FontSz,32) Align=Default(Align,7)# Subtitle Alignment
Subs=Default(Subs,True) AddBorders(BordSz,BordSz,BordSz,BordSz,$808080)
Return ScriptClip(string(TH,"TestAveLuma_LO(%f")+String(BordCol,",%.0f")+String(BordSz,",%.0f")+
\ String(FontSz,",%.0f")+String(Align,",%.0f,")+String(Subs)+")")
}


MyTest

ColorBars.ConvertToYV12.KillAudio A=Trim(0,-100) B=A.Levels(16,1,235,16,63,coring=false) A++B++A++B++A

TH = 64.0
BORDSZ = 8
FONTSZ = 32
BORDCOL = $FF0000
ALIGN = 7
SUBS = True

#TestAveLuma(TH)
TestAveLuma(TH,BordCol=BORDCOL,BordSz=BORDSZ,FontSz=FONTSZ,Align=ALIGN,Subs=SUBS)


Where dark, might look something like this (Red border instead of mid grey when Y <= Th [Can see instantly if within bounds without reading numbers])
https://s20.postimg.cc/chj54svn1/image.jpg (https://postimages.cc/)

No Reply necessary.

EDIT: Added Subs arg, default True.