Code:
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
}