View Full Version : Video of lightning storm - cutting lightnings
Drayden
19th September 2015, 21:37
Hello!
I have a video of storm with several lightnings in it. I want to
1) make a better, shorter video with all "unfun" parts cut out and only lightnings left.
2) make a gallery of lightnings. As pictures.
First part can be done manually with Virtual Dub. But its a boring task and I do not want to do it every time when I make a video like that. I made manual editing on the part of video. It is uploaded here (http://www.youtube.com/watch?v=SRqJbtL9EdE). I want to finish editing with some configurable automated solution.
I tried script from that topic but it doesnt seem to work for me
http://forum.doom9.org/showthread.php?t=166974
Can someone help me or give some advice?
StainlessS
19th September 2015, 22:10
Hi there.
I'm a little busy at the moment but will probably find a little time (maybe tomorrow) to have a play with your clip (have DL'ed sample).
Think I should be able to do something with it.
johnmeyer
20th September 2015, 03:12
Search for "flash frames." StainlessS created some tools to detect photographer strobe flashes as well as the flash you get at the beginning of most film scenes. I have a script, if you want some code.
StainlessS
20th September 2015, 03:35
John, I'm assuming OP wants to keep some frames either side of lightning, at least that is what I'm doing now.
johnmeyer
20th September 2015, 04:49
John, I'm assuming OP wants to keep some frames either side of lightning, at least that is what I'm doing now.You are probably right. However, having just videotaped a lightning storm a month ago, I was reminded of something that I had forgotten from the last time I did it: lightning doesn't just strike once. Most of the time the "flash" that you see is actually a series of flashes over a 200 - 1,000 millisecond interval. It is not unusual to have 3-4 flashes during that time, usually in the same location (if you can follow the stroke), but of widely varying intensity. The OP will have to decide whether to keep them all, or not.
StainlessS
20th September 2015, 12:47
Have partly got it done, scans and sets DBase with TYPE (Dark/Light based on AveLuma Thresh), also extent of D/L seq (Start and End) and also
the brightest frame in seq (TYPE=L seq only).
Will then scan DBase to output frames file for eg Brightest Lightning frame in a sequence, and also another frames file to extract lightning sequence
with user selected number of partition frames either side (closely adjacent L seqs already coalesced).
EDIT:
@ Drayden, is audio required for lightning sequences ? (not a problem if so).
Drayden
20th September 2015, 21:19
Have partly got it done, scans and sets DBase with TYPE (Dark/Light based on AveLuma Thresh), also extent of D/L seq (Start and End) and also
the brightest frame in seq (TYPE=L seq only).
Will then scan DBase to output frames file for eg Brightest Lightning frame in a sequence, and also another frames file to extract lightning sequence
with user selected number of partition frames either side (closely adjacent L seqs already coalesced).
EDIT:
@ Drayden, is audio required for lightning sequences ? (not a problem if so).
Hey, thats cool!
I think original audio is lost there so I will just add another music again.
StainlessS
21st September 2015, 03:37
OK, here is something to play with as I've gotta get some sleep.
It will only show sequences, partitions and flash frames, does not as yet extract flash frames or partitions.
A sequence is a group of adjacent frames that are either above or below the AveLuma 'THRESH', types D (below) and 'L' above.
An 'L' Partition is a group of coalesced L sequences with at most 2*'KEEPFRAMES' from any single D seq. If a D sequence is longer than
2*KEEPFRAMES, then that D sequence will become a D Partition with L partitions either side having 'KEEPFRAMES frames coalesced with them.
When done, you wil be able to extract Flash frames, L Partitions, and also the D partitions to see if anything was missed out.
Its quite fascinating to see the ShowDB output metrics preceding the flashes.
here tis:
SCRIPT REMOVED: See posts 11 and 12.
jmac698
21st September 2015, 13:52
You can also do this the other way around; if you have a Canon camera, you can load a custom firmware and then run a program that takes pictures only when it flashes. It would also be possible to take video clips starting at a flash, log flash times, etc.
http://chdk.wikia.com/wiki/UBASIC/Scripts:Lightning_script_--_Fudgey
Drayden
21st September 2015, 17:27
OK, here is something to play with as I've gotta get some sleep.
It will only show sequences, partitions and flash frames, does not as yet extract flash frames or partitions.
...
Wow, thank you very much!
Thats a freaking ton of code... Gonna test it a bit later, when im finally home...
jmac698
thank you for idea, but its inapplicable in my case :(
StainlessS
22nd September 2015, 19:43
OK here tis complete with frame, Seq and Part extraction.
CODE REMOVED
StainlessS
22nd September 2015, 19:44
And here the client (See prev post)
EDIT: Script removed.
And script from Prune/FrameSel.
SelectRanges.avs
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 SelectRanges(clip c,String "SCmd",String "Cmd",Bool "TrimAudio",Float "FadeMS",Bool "Ordered") {
# SelectRanges() by StainlessS. Required:- FrameSel, Prune, RT_Stats
# Wrapper to Select 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.
#
# 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 allowed, see FrameSel for Further info).
# *** NOTE ***, If both Cmd and SCmd supplied AND Ordered == False, then will process Cmd file and then SCmd string afterwards, ie
# Will select ranges in Cmd file and in order specified (rather than auto ordering ranges) and then append ranges specified in
# SCmd string (and in order specified).
# TrimAudio:
# True(default), selects audio belonging to selected frames/ranges
# False, returns original audio, probably out of sync (maybe totally out of whack if Ordered == false and selected ranges out of order).
# FadeMS: (default 1.0 millisec). Linear Audio Fade duration at splices when TrimAudio==true, 0 = dont fade (might result in audio 'clicks/cracks').
# Ordered:
# True(default), all frames/ranges are returned in sequencial order. Any frame specified more than once will return only 1 instance.
# False, All frames/Ranges are returned in specified order, Cmd processed first and then SCmd. Frames/ranges specified more than once
# will return multiple instances. Allows out-of-order trimming of clip, eg re-sequencing of scenes in movie.
#
# Does not make much sense to select individual frames with audio, best used with ranges.
# Will coalesce individually selected adjacent frames/ranges before any Fade, ie only audio fade where sensible to do so.
# TrimAudio==false with non Ordered selection will result in completely out of sync audio.
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
Ordered=Default(Ordered,True) # True (default) frames/ranges will be Ordered and selected only once even if specified more than once.
# False, frames/ranges returned in specified order, Cmd processed 1st and then SCmd.
PruneCmd = (TrimAudio) ? "~Prune_"+RT_LocalTimeString+".txt" : ""
(!TrimAudio)
\ ? FrameSel(scmd=SCmd,cmd=Cmd,Ordered=Ordered)
\ : FrameSel_CmdReWrite(PruneCmd,scmd=SCmd,cmd=Cmd,Ordered=Ordered,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
}
EDIT: Dont forget to COMMENT out InitDB when done, and SequenceDB when happy with Thresh, and PartitionDB when
happy with PartFrames.
Can then call any of the other Show/extraction funcs.
NOTE, ShowDB(Last,DB).GetSeqs(DB,True) will show DARK seq frames that have been Partitioned into LIGHT Partitions,
where you might catch some lightning frames that would not be caught in LIGHT only sequencing (because they are within
PartFrames distance of LIGHT seq).
Drayden
22nd September 2015, 22:10
Thank you very much!
Opened a script in Vdub and its thinking hard.
Gonna wait until it shows me some feedback...
Drayden
23rd September 2015, 20:58
Vdub is still "not responding". Is that all right?
:confused:
StainlessS
24th September 2015, 01:01
Part 1 of LightningSelectFrames.avs (Too big for post)
#LightningSelectFrames.avs # Req:- GScript, Grunt, RT_Stats, FrameSel, Prune.
Function ShowDB(clip c,String DB) {
/*
ShowDB(), Show DB Status, MUST at least call InitDB beforehand.
If not sequenced then will only show AverageLuma for each frame.
If Sequenced then shows Sequence info.
If both Sequenced and Partitioned, then shows Sequence and Partition info.
*/
c myName="ShowDB: "
Records = RT_DBaseRecords(DB) Assert(Records==FrameCount,RT_String("%sFrameCount/Records mismatch",myName))
Th = RT_DBaseGetID(DB,0) nSeqs = RT_DBaseGetID(DB,1) PartFrames= RT_DBaseGetID(DB,2) nParts = RT_DBaseGetID(DB,3)
Fmt="%d] AveY=%.2f\nSEQ:%-5d} Type='%c' Start=%-6d End=%-6d FlashFrm=%d\nPART:%4d} Type='%c' Start=%-6d End=%-6d"
Fmt2="Thresh=%.2f : nSeqs=%d : PartFrames=%d : nParts=%d"
SSS="""
n = current_frame
RT_Subtitle(Fmt,
\ n,RT_DBaseGetField(DB,n,0),RT_DBaseGetField(DB,n,1),RT_Ord("-DL",RT_DBaseGetField(DB,n,2)+2),
\ RT_DBaseGetField(DB,n,3),RT_DBaseGetField(DB,n,4),RT_DBaseGetField(DB,n,5),
\ RT_DBaseGetField(DB,n,6),RT_Ord("-DL",RT_DBaseGetField(DB,n,7)+2),RT_DBaseGetField(DB,n,8),RT_DBaseGetField(DB,n,9))
RT_SubTitle(Fmt2,Th,nSeqs,PartFrames,nParts,align=1)
Return Last
"""
Last.GScriptClip(SSS,ARGS="Fmt,Fmt2,DB,Th,nSeqs,PartFrames,nParts",Local=True)
Return Last
}
Function WriteFlashFrames(String DB,String FN) { # Write 1 frame from each sequence with highest AveLuma
myName="WriteFlashFrames: " FC = RT_DBaseRecords(DB) nSeqs = RT_DBaseGetID(DB,1) RT_FileDelete(FN)
Assert(nSeqs > 0, RT_String("%sDBase Not Sequenced, Call SequenceDB(Thresh)",myName))
GSCript("""
For(i=0,FC-1) {
SeqType = RT_DBaseGetField(DB,i,2) # 0 = DARK seq : 1= LIGHT seq
SeqEnd = RT_DBaseGetField(DB,i,4) # Seq End
if(SeqType==1) {RT_WriteFile(FN,"%d",RT_DBaseGetField(DB,i,5),Append=True)} # Frame with greatest AveLuma in seq
i=SeqEnd # next iteration SeqEnd + 1 is Start of next Seq
}
""")
Return 0
}
Function WriteFlashSeqs(String DB,String FN) { # Write all L type sequences
myName="WriteFlashseqs: " FC = RT_DBaseRecords(DB) nSeqs = RT_DBaseGetID(DB,1) RT_FileDelete(FN)
Assert(nSeqs > 0, RT_String("%sDBase Not Sequenced, Call SequenceDB(Thresh)",myName))
GSCript("""
For(i=0,FC-1) {
SeqType = RT_DBaseGetField(DB,i,2) # 0 = DARK seq : 1= LIGHT seq
SeqEnd = RT_DBaseGetField(DB,i,4) # Seq End
if(SeqType==1) {
SeqLen = SeqEnd - i + 1
(SeqLen==1) ? RT_WriteFile(FN,"%d",i,Append=True) : RT_WriteFile(FN,"%d,%d",i,SeqEnd,Append=True)
}
i=SeqEnd # next iteration SeqEnd + 1 is Start of next Seq
}
""")
Return 0
}
Function WriteFlashParts(String DB,String FN) { # Write all L type Partitions
myName="WriteFlashParts: " FC = RT_DBaseRecords(DB) nParts = RT_DBaseGetID(DB,3) RT_FileDelete(FN)
Assert(nParts > 0, RT_String("%sDBase Not Partitioned, Call PartitionDB(PartFrames)",myName))
GSCript("""
For(i=0,FC-1) {
PartType= RT_DBaseGetField(DB,i,7) # 0 = DARK Part : 1= LIGHT Part
PartEnd = RT_DBaseGetField(DB,i,9) # Part End
if(PartType==1) {
PartLen = PartEnd - i + 1
(PartLen==1) ? RT_WriteFile(FN,"%d",i,Append=True) : RT_WriteFile(FN,"%d,%d",i,PartEnd,Append=True)
}
i=PartEnd # next iteration PartEnd + 1 is Start of next Part
}
""")
Return 0
}
Function GetFlashFrames(clip c,String DB) {
FN="Flash_"+RT_LocalTimeString(File=True)+".txt" WriteFlashFrames(DB,FN) Flashframes=SelectRanges(c,Cmd=FN)
RT_FileDelete(FN) Return Flashframes.KillAudio
}
Function GetSeqs(clip c,String DB,Bool "Dark") {
Dark = Default(Dark,False) FN="Seqs_"+RT_LocalTimeString(File=True)+".txt"
WriteFlashSeqs(DB,FN) Seqs=(Dark) ? RejectRanges(c,Cmd=FN) : SelectRanges(c,Cmd=FN)
RT_FileDelete(FN) Return Seqs
}
Function GetParts(clip c,String DB,Bool "Dark") {
Dark = Default(Dark,False) FN="Parts_"+RT_LocalTimeString(File=True)+".txt"
WriteFlashParts(DB,FN) Parts=(Dark) ? RejectRanges(c,Cmd=FN) : SelectRanges(c,Cmd=FN)
RT_FileDelete(FN) Return Parts
}
StainlessS
24th September 2015, 01:02
Part 2
Function InitDB(clip c,String DB,Float "Thresh",Int "PartFrames",Bool "Debug") {
/*
InitDB, Writes AverageLuma to DB DBase file for each frame in clip c.
Optionally call SequenceDB(DB,Thresh) if Thresh>0.0
Optionally call PartitionDB(DB,PartFrames) if Thresh>0.0 AND PartFrames>0
DB FIELDS:-
0=AveY (Float)
1=SeqIx (0 Rel)
2=Seq Type (0=Dark, 1=Light)
3=Seq Start
4=Seq End
5=Seq Brightest Strike frame(only where seq TYPE==1)
6=PartIx (0 Rel)
7=Partition Type (0=Dark, 1=Light)
8=Partition Start
9=Partition End
DB ID's
0=Thresh (Float)
1=Number of Sequences
2=PartFrames (0 == Not Partitioned)
3=Number of Partitions
*/
c myName="InitDB: "
Thresh=Float(Default(Thresh,0.0)) PartFrames=Default(PartFrames,0) Debug=Default(Debug,False)
StartT=RT_TimerHP FC=FrameCount RT_DBaseAlloc(DB,FC,"fiiiiiiiii")
GSCript("""
for(i=0,FC-1) {
(Debug) ? RT_DebugF("%d]",i,name=myName) : NOP
RT_DBaseSet(DB,i,RT_AverageLuma(c,n=i),-1,-1,-1,-1,-1,-1,-1,-1,-1)
}
T = RT_TimerHP - StartT RT_DebugF("Completed in %.2f secs (%.2fMins) : %.2f FPS",T,T/60.0,FC/T,name=myName)
if(Thresh > 0.0) {
SequenceDB(DB,Thresh)
if(PartFrames > 0) {
PartitionDB(DB,PartFrames)
}
}
""")
Return 0
}
Function SequenceDB(String DB,Float Thresh,Bool "Debug") {
/*
Split DB into sequences of Dark and Light by Thresh (Call AFTER [or via] InitDB).
Can Re-SequenceDB without repeat call to InitDB.
*/
myName="SequenceDB: " Debug=Default(Debug,False) StartT=RT_TimerHP Records=RT_DBaseRecords(DB)
GSCript("""
nSeqs = 0
if(Thresh<=0.0) {
(DEBUG)?RT_DebugF("Removing DB Sequences and Partitions",name=myName):NOP
for(i=0,Records-1) {
RT_DBaseSet(DB,i,RT_DBaseGetField(DB,i,0),-1,-1,-1,-1,-1,-1,-1,-1,-1) # Re-Init Record (copying original AveLuma)
}
RT_DBaseSetID(DB,0,0.0) # Set Thresh = 0.0 for ShowDB
} else {
(DEBUG)?RT_DebugF("Sequencing DBase",name=myName):NOP
Old_Start = 0
AL = RT_DBaseGetField(DB,Old_Start,0)
Old_SeqT = (AL>=Thresh) ? 1 : 0 # 0=DARK, 1=LIGHT (preset, so no change detected on frame 0)
Old_LMax = AL # Brightest Strike
Old_LMax_Frm= Old_Start # Brightest strike frame
SeqT = Old_SeqT
for(i=0,Records) {
if(i != Records) { # NOT Last Frame + 1, (where RECORD/FRAME DOES NOT EXIST)
AL=RT_DBaseGetField(DB,i,0)
SeqT = (AL>=Thresh) ? 1 : 0 # Sequence Type, 0=DARK, 1=LIGHT
RT_DBaseSet(DB,i,AL,nSeqs,SeqT,-1,-1,-1,-1,-1,-1,-1) # Init Record
}
if(SeqT != Old_SeqT || i==Records) { # New TYPE (or Last frame + 1, ie seq/loop closure)
(Debug) ? RT_DebugF("%d] SeqType=%d SeqIx=%d",i,SeqT,nSeqs,name=myName) : NOP
for(j=Old_Start,i-1) {
RT_DBaseSetField(DB,j,3,Old_Start) # Start frame of sequence of Old Seq (ie previous sequence)
RT_DBaseSetField(DB,j,4,i-1) # End frame of sequence of Old Seq
if(Old_SeqT==1) { # For Lightning strikes ONLY
RT_DBaseSetField(DB,j,5,Old_LMax_Frm) # Brightest frame in Lightning seq
}
}
nSeqs = nSeqs + 1 # Incr Sequence count
Old_Start = i # Remember new Start frame and current Seq Type for Next Time.
Old_SeqT = SeqT
Old_LMax = AL # init Brightest Strike
Old_LMax_Frm = i # init Brightest strike frame
} else if(Old_SeqT==1 && AL>Old_LMax) { # Is Lightning
Old_LMax = AL
Old_LMax_Frm = i
}
}
RT_DBaseSetID(DB,0,Thresh) # Set for ShowDB (Sequences are set BUT Not yet Partitioned)
}
RT_DBaseSetID(DB,1,nSeqs) # Sequence Count
RT_DBaseSetID(DB,2,0) # PartsFrames
RT_DBaseSetID(DB,3,0) # nParts, Any previously existing partitions are invalid
T = RT_TimerHP - StartT RT_DebugF("Completed in %.2f secs (%.2fMins) : %.2f FPS",T,T/60.0,Records/T,name=myName)
""")
Return 0
}
Function PartitionDB(String DB,Int "PartFrames",bool "Debug") { # Partition DB, (ie coalesce adjacent lightning seqs and add PartFrames either side)
myName="PartitionDB: " PartFrames=Default(PartFrames,0) FC=RT_DBaseRecords(DB) nSeqs=RT_DBaseGetID(DB,1) Debug=Default(Debug,False)
Assert(nSeqs > 0, RT_String("%sDBase Not Sequenced, Call SequenceDB(Thresh)",myName))
GSCript("""
StartT=RT_TimerHP
if(RT_DBaseGetID(DB,3) > 0) { # Already Partitioned ? (nParts)
(DEBUG)?RT_DebugF("Resetting DB Partitions",name=myName):NOP
for(i=0,FC-1) { # Reset
RT_DBaseSetField(DB,i,6,-1) # Reset Part Number
RT_DBaseSetField(DB,i,7,-1) # Reset Type of Part
RT_DBaseSetField(DB,i,8,-1) # Reset Start of Part
RT_DBaseSetField(DB,i,9,-1) # Reset End of Part
}
RT_DBaseSetID(DB,2,0) # PartFrames
RT_DBaseSetID(DB,3,0) # nParts = 0
T = RT_TimerHP - StartT RT_DebugF("Reset DB Partitions in %.2f secs (%.2fMins) : %.2f FPS",T,T/60.0,FC/T,name=myName)
}
if(PartFrames > 0) {
(DEBUG)?RT_DebugF("\nPartitioning DB with PartFrames=%d\n",PartFrames,name=myName):NOP
nSeqs = RT_DBaseGetID(DB,1)
nParts = 0
P_FrmS = 0 # Partition Start Frame
P_Type = RT_DBaseGetField(DB,0,2) # SEQ type of Start Partition is same as start SEQ
if(P_Type==0 && RT_DBaseGetField(DB,0,4)+1<=PartFrames && nSeqs>=2) {
P_Type = 1 # D type and <= PartFrames, convert to L type Start ie coalesce.
(Debug)?RT_DebugF("First 'D' Part Convert to 'L' Part - coalescing",name=myName):NOP
}
False=False # Make local (faster access)
ERR=0
for(i=0,FC-1) {
Old_I = i
SeqType = RT_DBaseGetField(DB,i,2)
SeqS = RT_DBaseGetField(DB,i,3)
SeqE = RT_DBaseGetField(DB,i,4)
RemLen = SeqE-i+1 # Length of what remains in current Seq
if(DEBUG) {
(P_FrmS==i)?RT_DebugF("%6d] Opening Partition:- PartType='%c' Start=%-6d",i,RT_Ord("DL",P_Type+1),i,name=myName):NOP
RT_DebugF("%6d] SeqType='%c' SeqRel=%-6d SeqS=%-6d SeqE=%-6d SeqLen=%-6d RemLen=%-6d",
\ i,RT_Ord("DL",SeqType+1),i-SeqS,SeqS,SeqE,SeqE-SeqS+1,RemLen,name=myName)
}
Close = False
if(P_Type==0) { # DARK Part
if(SeqType==0) {
if(i==0) { # 1st PART is DARK
if(SeqE==FC-1) {
i=SeqE # Single DARK Part only
} else {
i=SeqE - PartFrames # Close current D PART and join end of this D seq to next L seq
}
Close=True
} else if(i!=SeqS) {
if(RemLen>PartFrames) {
i=SeqE - PartFrames # Close current D Partition and join end of this D seq to next L seq
Close=True
} else {
ERR=2
}
} else {
ERR=3
}
} else {
ERR=4
}
} else { # LIGHT Part (coalescing)
if(SeqType == 1) {
i=SeqE # Always coalesce L seq
} else if(i==SeqS) {
if(RemLen<=PartFrames*2) {
i=SeqE # Coalesce entire D seq if <= PartFrames*2
} else {
i=i+PartFrames-1 Close=True # coalesce Start of D seq and close for next D Part
}
} else if(RemLen<=PartFrames) {
i=SeqE # if <= PartFrames then coalesce End of D seq to next L seq
} else {
ERR=5
}
}
if(i < Old_I) {
ERR = 1
}
if(ERR != 0) {
ES = RT_String("%s*** Error = %d ***\ni=%d Old_I=%d P_FrmS=%d P_Type=%d SeqType=%d SeqS=%d SeqE=%d RemLen=%d",
\ myName,ERR,i,Old_I,P_FrmS,P_Type,SeqType,SeqS,SeqE,RemLen)
RT_DebugF("%s",ES,name=myName)
RT_WriteFile("PartitionDB_ERROR.TXT","%s",ES)
Assert(False,ES)
}
if(i==FC-1) {Close=True}
if(Close || i>=FC) {
P_FrmE = Min(i,FC-1)
(Close&&DEBUG) ? RT_DebugF("%6d] Closing Partition:- PartType='%c' Start=%-6d End=%-6d PartLen=%-6d",
\ i,RT_Ord("DL",P_Type+1),P_FrmS,P_FrmE,P_FrmE-P_FrmS+1,name=myName) : NOP
(!Close) ? RT_DebugF("*** Not Closed ***, i>=FC-1(i=%d FC-1=%d)",i,FC-1,name=myName) : NOP
for(j=P_FrmS,P_FrmE) {
RT_DBaseSetField(DB,j,6,nParts) # Part Number (0 Rel)
RT_DBaseSetField(DB,j,7,P_Type) # Partition Type (0=Dark, 1=Light)
RT_DBaseSetField(DB,j,8,P_FrmS) # Partition Start
RT_DBaseSetField(DB,j,9,P_FrmE) # Partition End
}
nParts = nParts + 1
P_Type = (P_Type==0)?1:0 # Toggle Partition Type
P_FrmS = i+1
}
}
RT_DBaseSetID(DB,3,nParts) # Flag Partition Count
(DEBUG) ? RT_DebugF("DB Partitioned with PartFrames=%d",PartFrames,name=myName) : NOP
}
RT_DBaseSetID(DB,2,PartFrames) # Flag Partition PartFrames
T=RT_TimerHP-StartT RT_DebugF("Completed in %.2f secs (%.2fMins) : %.2f FPS",T,T/60.0,FC/T,name=myName)
""")
return 0
}
StainlessS
24th September 2015, 01:06
Client
Import("SelectRanges.avs")
Import("LightningSelectFrames.avs")
###
#LightningSelectFrames_Client.avs # Req:- GScript, Grunt, RT_Stats, FrameSel, Prune.
###
#VideoFilename = "Lightning.avi"
VideoFilename = "Join3.avi"
####
DB = VideoFilename + ".DB"
THRESH = 5.0 # Lightning >= THRESH
PARTFRAMES = 10 # Frames to keep either side of lightning sequences
# If Dark Seq length between L seqs is <= 2*PARTFRAMES then will be coalesced into L seq.
####
####
Avisource(VideoFilename,Audio=False)
#### InitDB() Must be called to create DB, and write AverageLuma to DBase for each frame.
#### InitDB() can optionally call SequenceDB (when Thresh>0.0) and also PartitionDB (when Thresh>0.0 and PARTFRAMES>0)
####
#### After DB created can call SequenceDB, PartitionDB{only after SequenceDB) and ShowDB as you wish
#### SequenceDB splits DB frames into sequences of light and Dark frames based on AverageLuma Thresh, can re-sequence without repeat call to InitDB.
#### PartitionDB, coalesces 'L' sequences. Can re-partition without repeat calls the InitDB and SequenceDB.
####
DEBUG=False # In event of problems make True (Get DebugView https://technet.microsoft.com/en-us/library/bb896647.aspx)
# Comment out below 3 options when done (or repeat run will do them all again)
InitDB(Last,DB,Debug=DEBUG) # After InitDB, can comment out and call PartitionDB to change PARTFRAMES
SequenceDB(DB,THRESH,Debug=DEBUG) # Sequence if not already done by InitDB.
PartitionDB(DB,PARTFRAMES,Debug=DEBUG) # Partition if not already done by InitDB.
#### ShowDB, shows metrics, can un-comment and use together with one of the Getxxx options to show metrics with selected frames.
ShowDB(Last,DB) # View DB Sequence and Partition status (MUST call at least InitDB before use)
#### Select frames to return, un-comment one only (after DB initialised and sequenced, and Partitioned).
#GetFlashFrames(Last,DB) # Get Brightest Flash from Each Seq
#GetSeqs(Last,DB) # Get Light Seqs
#GetSeqs(Last,DB,True) # Get DARK Seqs
#GetParts(Last,DB) # Get Light Partitions
#GetParts(Last,DB,True) # Get DARK Partitions
####
return Last
UPDATED
Drayden
24th September 2015, 18:42
Oh.
I'm uploading uncut video to Google Drive now. Gonna give the link when its done.
Its ~800 mb. Is that ok?
StainlessS
24th September 2015, 19:18
Yep OK, also provide the Thresh and PartFrames that you are using.
EDIT: Little bit of info.
InitDB, I'm getting something like 250FPS on 2.4Hhz Core Duo (IIRC).
SequenceDB and PartitionDB about 590 and 550 FPS.
With a fast machine you should get something a lot faster than that.
EDIT: OK, Got your link below, gonna DL it.
OK, got it, shall have a play, soon.
Drayden
24th September 2015, 21:04
Link:
https://drive.google.com/file/d/0B3xVUmPuz-n_dUxRRV9LbmE0ZDA/view?usp=sharing
Drayden
24th September 2015, 22:25
Thresh and Partframes I did not change yet - they were as you set them initially.
johnmeyer
25th September 2015, 03:00
The following kiddiescript is nothing compared to StainlessS' professional work, but it is a simple way to get you 80% of the way there. Here's the output file containing flash frame numbers:
Flash Frame.txt (https://www.dropbox.com/s/c1tj7tptayi0es9/flash_frames.txt?dl=0)
And here's the simple script:
#Script to find flash frames
filename = "e:\flash_frames.txt"
global flashthreshold=0.8
i=AVISource("E:\Documents\Dnload\UNPACK\join3.avi")
j=trim(i,1,0) #Previous frame
# Temporarily un-comment next line to display the average luma value on screen to help determine threshold value
#ScriptClip(i,"Subtitle(String(YDifferenceToNext(i) ))" )
#This finds the FIRST frame in a series that fall below the threshold
#WriteFileIf(i, filename, "(YDifferenceToNext(i)>flashthreshold)&&YDifferenceToNext(j)<flashthreshold", "current_frame+1", append = false)
#This line below will output EVERY frame that is below threshold, which results in LOTS of frames
WriteFileIf(i, filename, "(YDifferenceToNext(i)>flashthreshold)", "current_frame+1", append = false)
#The line below finds the LAST flash frame in a series
#WriteFileIf(i, filename, "(YDifferenceToNext(i)<flashthreshold)&&YDifferenceToNext(j)>flashthreshold", "current_frame+1", append = false)
Drayden
29th September 2015, 08:50
Guys, thank you very much for your help!
I'm gonna continue playing with the task later on weekend and post some feedback.
StainlessS
1st October 2015, 17:30
Posts #15 to #17 updated.
Getting speeds on 2.4Ghz Core Duo duel core of (53:00 Join3.Avi clip):
00000002 541.76666260 [3748] InitDB: Completed in 541.21 secs (9.02Mins) : 176.31 FPS
00000003 623.11572266 [3748] SequenceDB: Completed in 81.35 secs (1.36Mins) : 1173.00 FPS
00000004 690.96984863 [3748] PartitionDB: Completed in 67.85 secs (1.13Mins) : 1406.35 FPS
Although InitDB timing previously gave me about 220FPS with debugging switched on, can only assume that my machine was doing something else
in the background during InitDB.
EDIT:
Not having a clue how to open *.webm I used below ConvertToAVI.Bat file together with ffmpeg (output UTVideo codec)
setlocal
REM Where to Find ffmpeg
set FFMPEG="C:\BIN\ffmpeg.exe"
REM Where to get input file, No terminating Backslash, "." = current directory (ie same as dir .bat file)
set INDIR="."
REM Where to place output file, No terminating Backslash. "." would be same as .bat file
set OUTDIR="D:\AVS\AVI"
FOR %%A IN (*.vob *.wmv *.mpg *.avi *.flv *.mov *.mp4 *.m4v *.RAM *.RM *.mkv *.TS *.y4m *.yuv *.webm) DO (
%FFMPEG% -i "%INDIR%\%%A" -vcodec utvideo -acodec pcm_s16le "%OUTDIR%\%%~nxA.AVI"
)
Pause
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.