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. |
|
|
#1 | Link |
|
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,392
|
DBSC v0.051, Scene Change Detection - Work-in-Progress
Post #1 of Many.
Updated: v0.051 http://www.mediafire.com/download/c9...BSC-v0.051.zip Basic Info Code:
/*
DBSC.avs v0.04, by StainlessS @ Doom9
A Scene Change Detection Tool set/kit/box. (Work In Progress - guinea pigs required)
Currently Implemented: (to some degree):-
Scenechange detection:-
DBSC_CreateInfo(), creates fast scan RT_Stats INFO DBase.
For each frame stores RT_YPlaneMin, RT_YPlaneMax, RT_YPlaneMinMaxDifference, RT_YPlaneMedian, RT_AverageLuma, RT_YPlaneStdev
and RT_FrameDifference(n<->n+1). Could also be useful for other purposes.
DBSC_Scan(), Using INFO DBase, creates a second SCAN DBase containing Scene Change detection data.
Single Flash frame tolerant.
Fade-To-Black Scene changes detected.
DBSC_Override(), Using SCAN DBase and Overrides.txt, allows user to set additional Scene Change or remove erroneous ones
from the SCAN DBase. Additional overrides set/unset without re-creating ScanDB.
Scenechange Utility:-
DBSC_WriteFiles(), Using SCAN DBase, Writes Start, End, Mid, And/Or Range Files for Scene Changes.
Also writes a ClipClop command file for Start (ClipClop clip 1) and End (clip 2) frames, used by DBSC_Select().
DBSC_SubsClip(), Returns clip optionally subtitled (metrics And/Or START OF SCENE / END OF SCENE / SINGLE FRAME SCENE subtitles)
DBSC_StackSceneChanges(), Returns clip, End frame of a scene together with Stacked Start frame of following scene.
(Check detections).
DBSC_Select(), Similar-ish to SCSelect.
Dynamically Changing Borders:-
DBSC_DynaCrop(), Detect Dyanamically changing borders using ScanDB and create a SpliceDB for DBSC_DynaSplice().
DBSC_DynaSplice(), Trim, Crop, Resize and Splice, dynamically changing borders. Option to call user defined function
on each trim, after it has been cropped and resized, and before splicing back together again.
DBSC_Levels(), Function to DEMO a User Function as called by DBSC_DynaSplice().
TODO:-
Improve detection.
Blended Scene Change Detection (Well I can dream cant I, anybody any ideas ? )
+ whatver else I (or you) can think of.
Required:-
Frame Accurate seekable source clip.
RT_Stats, http://forum.doom9.org/showthread.php?t=165479
GSCript, http://forum.doom9.org/showthread.php?t=147846
Grunt, http://forum.doom9.org/showthread.php?t=139337
FrameSel, http://forum.doom9.org/showthread.php?t=167971
ClipClop, http://forum.doom9.org/showthread.php?t=162266
RoboCrop http://forum.doom9.org/showthread.php?t=168053
DebugView http://technet.microsoft.com/en-gb/sysinternals/bb896647.aspx (viewing Debug Output in real time)
*/
(both worked fine a few days ago)
__________________
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; 14th February 2015 at 12:05. Reason: Update |
|
|
|
|
|
#2 | Link |
|
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,392
|
Post #2 of many
Internal Use Functions Code:
####################################################
### INTERNAL USE ONLY FUNCTIONS ***
####################################################
Function DBSC_Str2ID(String IDS) {
Assert(Strlen(IDS)==4,RT_String("%sMust be 4 character string('%s')","DBSC_Str2ID: ",IDS))
Return(((RT_Ord(IDS,4)*256+RT_Ord(IDS,3))*256 + RT_Ord(IDS,2))*256) +RT_Ord(IDS,1)
}
Function DBSC_ColorSpaceIx(clip c) {
cs=c.IsRGB24?0:c.IsRGB32?1:c.IsYUY2?2:c.IsYV12?3:-1
return(cs>=0||VersionNumber<2.6)?cs:c.IsY8?4:c.IsYV16?5:c.IsYV24?6:c.IsYV411?7:-1
}
Function DBSC_InfoValidate(String InfoDB,Bool "MustExist",String "name") {
/*
DBSC_InfoValidate(), Returns InfoDB valid status True/False.
True return signifies that the InfoDB exists and is of type InfoDB.
If InfoDB does not exist and MustExist==True(Default), then throws error alert.
Name, allows display of client function name instead of this function name in error alerts.
*/
myName=Default(name,"DBSC_InfoValidate: ")
Assert(InfoDB!="",RT_String("%sMust provide an InfoDB filename",myName))
Valid = Exist(InfoDB)
GSCript("""
if(Valid) {
Valid = RT_DBaseFields(InfoDB)==7 && RT_VarIsSame(RT_DBaseGetID(InfoDB,0),DBSC_Str2ID("DBSC")) &&
\ RT_VarIsSame(RT_DBaseGetID(InfoDB,1),DBSC_Str2ID("INFO"))
if(!Valid) {
RT_DebugF("InfoDB failed Basic validation",name=myName)
!Valid?Assert(RT_DBaseGetID(InfoDB,1)!=DBSC_Str2ID("SCAN"),RT_String("%sWe Require the InfoDB, not the ScanDB",myName)):NOP
}
} Else {Assert(!Default(MustExist,True),RT_String("%sInfoDB does NOT exist\n'%s'",myName,InfoDB))}
""")
Return Valid
}
Function DBSC_ScanValidate(String ScanDB,Bool "MustExist",String "name") {
/*
DBSC_ScanValidate(), Returns ScanDB valid status True/False.
True return signifies that the ScanDB exists and is of type ScanDB.
If ScanDB does not exist and MustExist==True(Default), then throws error alert.
Name, allows display of client function name instead of this function name in error alerts.
No Check on whether ScanDB scene changes have been user overridden.
*/
myName=Default(name,"DBSC_ScanValidate: ")
Assert(ScanDB!="",RT_String("%sMust provide a ScanDB filename",myName))
Valid = Exist(ScanDB)
GSCript("""
if(Valid) {
Valid = RT_DBaseFields(ScanDB)==5 && RT_VarIsSame(RT_DBaseGetID(ScanDB,0),DBSC_Str2ID("DBSC")) &&
\ RT_VarIsSame(RT_DBaseGetID(ScanDB,1),DBSC_Str2ID("SCAN"))
if(!Valid) {
RT_DebugF("ScanDB failed Basic validation",name=myName)
!Valid?Assert(RT_DBaseGetID(ScanDB,1)!=DBSC_Str2ID("INFO"),RT_String("%sWe Require the ScanDB, not the InfoDB",myName)):NOP
}
} Else {Assert(!Default(MustExist,True),RT_String("%sScanDB does NOT exist\n'%s'",myName,ScanDB))}
""")
Return Valid
}
Function DBSC_QueryOveridden(String ScanDB) {
/*
DBSC_QueryOveridden(), Returns TOTAL number of Overides set on a ScanDB.
Uses third last RT_DBase attribute to store the number of user set Overrides (User attribute count currently 1024).
*/
myName="DBSC_QueryOveridden: "
Assert(DBSC_ScanValidate(ScanDB,MustExist=True,name=myName),RT_String("%sScanDB Invalid\n'%s'",myName,ScanDB))
nAttribs=RT_DBaseGetAttrib(ScanDB,-1)
Return RT_DBaseGetAttrib(ScanDB,nAttribs-4)
}
__________________
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 February 2015 at 07:49. Reason: Update |
|
|
|
|
|
#3 | Link |
|
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,392
|
Post #3 of many
User Functions: Create INFO DBase Code:
####################################################
### USER FUNCTIONS ***
####################################################
Function DBSC_CreateInfo(clip c,String InfoDB,int "Matrix",Float "ChromaWeight",Float "Thresh",Bool "RecycleDB",Bool "DEBUG") {
/*
DBSC_CreateInfo()
Create DBase to assist in scanning clip to extract various data.
c source clip.
InfoDB, DBase Filename to create.
Matrix: Conversion matrix for conversion of RGB to YUV-Y Luma. 0=REC601 : 1=REC709 : 2 = PC601 : 3 = PC709,
Default = (Width > 1100 OR Height>600) then 3(PC709) else 2(PC601). YUV not used
ChromaWeight, Default 0.333333 ChromaWeight range 0.0->1.0. Default gives twice as much weight to luma as combined chroma. (YUV Only).
Thresh, Default 0.2.
RecycleDB, Default True. False, recreate DBase even if already exists. True, Try to re-use existing DBase where possible.
*/
c
myName="DBSC_CreateInfo: "
START_TIME = RT_TimerHP
Assert(RT_FunctionExist("GScript"),myName+"Essential GScript plugin installed, http://forum.doom9.org/showthread.php?t=147846")
Matrix = Default(Matrix,(Width>1100||Height>600)?3:2)
ChromaWeight = Float(Default(ChromaWeight,1.0/3.0)) # Weighting for combined U + V Channels. Suggest about 1.0/3.0 -> 1.0/2.0
Thresh = Float(Default(Thresh,0.2))
RecycleDB=Default(RecycleDB,True)
DEBUG=Default(DEBUG,True)
Assert(Matrix>=0&&Matrix<=3,RT_String("%sMatrix 0->3",myName))
Assert(ChromaWeight>=0.0 && ChromaWeight<=1.0,RT_String("%sChromaWeight 0.0->1.0",myName))
Assert(Thresh>=0.0 && Thresh<=1.0,RT_String("%sThresh 0.0->1.0",myName))
InfoDB = RT_GetFullPathName(InfoDB) # FullPath name, convert '/' to '\'
FC = FrameCount
#
GScript("""
InfoValid = DBSC_InfoValidate(InfoDB,MustExist=False,name=myName) ? RecycleDB : False
if(InfoValid&&RecycleDB) {
InfoValid =
\ RT_VarIsSame(RT_DBaseGetID(InfoDB,2),Width) && RT_VarIsSame(RT_DBaseGetID(InfoDB,3),Height) &&
\ RT_VarIsSame(RT_DBaseGetID(InfoDB,4),DBSC_ColorSpaceIx(c)) &&
\ RT_VarIsSame(RT_DBaseRecords(InfoDB),FrameCount)
if(!InfoValid) {
(DEBUG) ? RT_DebugF("InfoDB failed Match To Clip validation\n'%s'",InfoDB,name=myName) : NOP
} Else {
InfoValid = RT_VarIsSame(RT_DBaseGetID(InfoDB,5),Matrix) &&
\ RT_VarIsSame(RT_DBaseGetID(InfoDB,6),ChromaWeight) &&
\ RT_VarIsSame(RT_DBaseGetID(InfoDB,7),Thresh)
if(!InfoValid) {
(DEBUG) ? RT_DebugF("InfoDB failed Match Matrix/ChromaWeight/Thresh validation\n'%s'",InfoDB,name=myName) : NOP
}
}
}
if(!RecycleDB||!InfoValid) {
(DEBUG) ? RT_DebugF("Initializing INFO DBase %s",InfoDB,name=myName) : NOP
RT_DBaseAlloc(InfoDB,FC,"iiiifff")
# Info for Frame Number n ie record number
# INT YStats Flags Full name Local Var Range
# 0 1($01) RT_YPlaneMin() "yMin" (0->255)
# 1 2($02) RT_YPlaneMax() "yMax" (0->255)
# 2 4($04) RT_YPlaneMinMaxDifference() "yMinMaxDiff" (0->255)
# 3 8($08) RT_YPlaneMedian() "yMed" (0->255)
# FLOAT
# 4 16($10) RT_AverageLuma() "yAve" (0.0->255.0)
# 5 32($20) RT_YPlaneStdev() "yStdev" (0.0->255.0)
# -
# 6 RT_FrameDifference(n <-> n+1) (0.0->255.0)
pcf = FC / 20.0
nxtn = Round(pcf)
FMT="%d ] %.0f%% Complete"
for(n=0,FC-1) {
# Flgs = YPlaneMin=1,YPlaneMax=2,YPlaneMinMaxDifference=4,YPlaneMedian=8,AverageLuma=16,YPlaneStdev=32
RT_Ystats(Last,n,flgs=$3F,Threshold=Thresh,Matrix=Matrix)
FD=RT_FrameDifference(Last,Last,n,n+1,ChromaWeight)
RT_DBaseSet(InfoDB,n,YS_yMin,YS_yMax,YS_yMinMaxDiff,YS_yMed,YS_yAve,YS_yStdev,FD)
if(DEBUG && n>=nxtn) {
RT_DebugF(FMT,n,Round((n+1)*100.0/FC),name=myName)
nxtn=Round(n+pcf)
}
}
RT_DBaseSetID(InfoDB,0,DBSC_Str2ID("DBSC"))
RT_DBaseSetID(InfoDB,1,DBSC_Str2ID("INFO"))
RT_DBaseSetID(InfoDB,2,Width)
RT_DBaseSetID(InfoDB,3,Height)
RT_DBaseSetID(InfoDB,4,DBSC_ColorSpaceIx(c))
RT_DBaseSetID(InfoDB,5,Matrix)
RT_DBaseSetID(InfoDB,6,ChromaWeight)
RT_DBaseSetID(InfoDB,7,Thresh)
} Else {
(DEBUG) ? RT_DebugF("INFO DBase Recycled '%s'",InfoDB,name=myName) : NOP
}
T = RT_TimerHP - START_TIME
(DEBUG) ? RT_DebugF("Total Time taken = %.2f Seconds (%.2f Mins)",T,T/60.0,name=myName) : NOP
""")
return RecycleDB
}
__________________
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 February 2015 at 07:50. Reason: Update |
|
|
|
|
|
#4 | Link |
|
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,392
|
Post #4 of many
Create SCAN DBase {PART_1, (too big)} Code:
Function DBSC_Scan(clip c,String InfoDB,String ScanDB,Float "dFact",Float "dMinim",Int "dMinLen",Float "dCorr",Float "DupTh",Float "POV",
\ Int "dFlashFrames", Bool "RecycleDB",Bool "DEBUG") {
/*
DBSC_Scan().
InfoDB, EXISTING INFO DBSC_CreateInfo created DBase
ScanDB, Name of Scene Change SCAN DBase, created by this function.
dFact, Default 1.5 (greater than 1.0)
dMinim, Default 8.0, (greater than 0.1) dFact and dMinim , Control how much bigger difference between Curr->Next has to be compared
to Prev->Curr and Next->Next+1, to detect scene change.
Curr->Next has to be greater than (dFact * 'Prev->Curr' + dMinim), and also greater than (dFact * 'Next->Next+1' + dMinim)
Dfact=1.4, works pretty good but is on a hair trigger ie very sensitive, dMinim=8.0 reduces/controls that sensitivity.
If clip is anime, then is quite likely that some frame differences are 0.0, so even a small difference next to 0.0 diff frames
will be infinitely greater than 0.0, in this situation dMinim will be the sole govenor of scene detection and so should be of
reasonable value, maybe about 8.0 -> 12.0 would be good choices.
dMinLen, Default 12. Minimum frame length of current scene that qualifies for scene change detection.
DupTh, Default 0.5.
POV, Default 60.0.
RecycleDB, Default True. False, recreate DBase even if already exists. True, Try to re-use existing DBase where possible.
Created ScanDB SCAN DBase Fields
0 ) SOSix, Start Of Scene frame(record)
1 ) EOSix, End Of Scene frame(record)
2 ) Type(1=SOS,2=EOS,3=SOS and EOS(single frame scene),0=none)
3 ) SceneNo(Zero Rel)
4 ) FLGS, Detection Reason code
*/
c
myName="DBSC_Scan: "
START_TIME = RT_TimerHP
Assert(RT_FunctionExist("GScript"),myName+"Essential GScript plugin installed, http://forum.doom9.org/showthread.php?t=147846")
dFact = Float(Default(dFact,1.25)) # Lower more false +ve's, Higher fewer scene changes (Dfact=1.5 dMinim=8.0 works pretty good)
dMinim = Float(Default(dMinim,6.0)) # Scene Change, avoid silly numbers (very small) on static scenes causing false +ve
dMinLen = Default(dMinLen,6) # Minimum length of scene for scene change detection to be valid (ignore short scenes)
dCorr = Float(Default(dCorr,0.75))
DupTh = Float(Default(DupTh,0.5)) #
POV = Float(Default(POV,60.0)) #
dFlashFrames = Default(dFlashFrames,dMinLen-1)
RecycleDB=Default(RecycleDB,True)
DEBUG=Default(DEBUG,True)
Assert(dFact>1.0 ,RT_String("%sdFact MUST be greater than 1.0",myName))
Assert(dMinim>=1.0,RT_String("%sdMinim MUST be greater or equal to 1.0",myName))
Assert(dMinLen>=2,RT_String("%sdMinLen MUST be greater or equal to 2",myName)) # Cannot detect single frame scene.
Assert(dCorr>=0.6,RT_String("%sdCorr 0.6 -> 1.0",myName))
Assert(DupTh>0.0&&DupTh<=1.0,RT_String("%sdDupTh 0.0 -> 1.0",myName))
Assert(POV>=0.0&&POV<=100.0,RT_String("%sPOV 0.0 -> 100.0",myName))
Assert(dFlashFrames>=1&&dFlashFrames<dMinLen,RT_String("%sdFlashFrames 1 -> dMinLen-1 (%d)",myName,dMinLen-1))
InfoDB = RT_GetFullPathName(InfoDB) # FullPath name, convert '/' to '\'
ScanDB = RT_GetFullPathName(ScanDB)
FC = FrameCount
#
GScript("""
InfoValid = DBSC_InfoValidate(InfoDB,MustExist=True,name=myName)
Assert(InfoValid,RT_String("%sInfoDB failed Basic validation\n'%s'",myName,InfoDB))
InfoValid =
\ RT_VarIsSame(RT_DBaseGetID(InfoDB,2),Width) && RT_VarIsSame(RT_DBaseGetID(InfoDB,3),Height) &&
\ RT_VarIsSame(RT_DBaseGetID(InfoDB,4),DBSC_ColorSpaceIx(c)) &&
\ RT_VarIsSame(RT_DBaseRecords(InfoDB),FC)
Assert(InfoValid,RT_String("%sInfoDB failed Match To Clip validation\n'%s'",myName,InfoDB))
Matrix = RT_DBaseGetID(InfoDB,5)
ChromaWeight = RT_DBaseGetID(InfoDB,6)
Thresh = RT_DBaseGetID(InfoDB,7)
#
ScanValid = DBSC_ScanValidate(ScanDB,MustExist=False,name=myName) ? RecycleDB : False
if(ScanValid&&RecycleDB) {
ScanValid =
\ RT_VarIsSame(RT_DBaseGetID(ScanDB,2),Width) && RT_VarIsSame(RT_DBaseGetID(ScanDB,3),Height) &&
\ RT_VarIsSame(RT_DBaseGetID(ScanDB,4),DBSC_ColorSpaceIx(c)) &&
\ RT_VarIsSame(RT_DBaseRecords(ScanDB),FC)
if(!ScanValid) {
(DEBUG) ? RT_DebugF("ScanDB failed Match To Clip validation\n'%s'",ScanDB,name=myName) : NOP
} Else {
nAttribs=RT_DBaseGetAttrib(ScanDB,-1)
ScanValid = RT_VarIsSame(RT_DBaseGetAttrib(ScanDB,nAttribs-1),Matrix) &&
\ RT_VarIsSame(RT_DBaseGetAttrib(ScanDB,nAttribs-2),ChromaWeight) &&
\ RT_VarIsSame(RT_DBaseGetAttrib(ScanDB,nAttribs-3),Thresh)
if(!ScanValid) {
(DEBUG) ? RT_DebugF("ScanDB failed Match Matrix/ChromaWeight/Thresh to InfoDB\n'%s'",ScanDB,name=myName) : NOP
} else {
ScanValid =
\ RT_VarIsSame(RT_DBaseGetID(ScanDB,5),dFact) &&
\ RT_VarIsSame(RT_DBaseGetID(ScanDB,6),dMinim) &&
\ RT_VarIsSame(RT_DBaseGetID(ScanDB,7),dMinLen) &&
\ RT_VarIsSame(RT_DBaseGetID(ScanDB,8),dCorr) &&
\ RT_VarIsSame(RT_DBaseGetID(ScanDB,9),DupTh) &&
\ RT_VarIsSame(RT_DBaseGetID(ScanDB,10),POV) &&
\ RT_VarIsSame(RT_DBaseGetID(ScanDB,11),dFlashFrames)
if(!ScanValid) {
(DEBUG) ? RT_DebugF("ScanDB failed Match Argument validation\n'%s'",ScanDB,name=myName) : NOP
}
}
}
}
if(!RecycleDB||!ScanValid) {
(DEBUG) ? RT_DebugF("Initializing Scenechange Scan DBase %s",ScanDB,name=myName) : NOP
RT_DBaseAlloc(ScanDB,FC,"iiiii") # SOSix, EOSix, Type(1=SOS,2=EOS,0=non), SceneNo(Zero Rel), FLGS
(DEBUG) ? RT_DebugF("Creating Scan DBase",name=myName) : NOP
Start=0 B=0.0 C=0.0
# Find scene changes, marking EOSix(End Of Scene) of scene start frame(record). (ie set EOSix at SOS record)
# Also set FLGS field at EOS (End frame record).
# A=Diff(n-1<->n) B=Diff(n<->n+1), C=Diff(n+1<->n+2)
# We are detecting scene change between current and next frames, ie when n at End Of Scene
# (@ EOS we already know current SOS, and also next scene SOS is EOS + 1).
#
# For Anime, if Diff(n-1,n) < DupTh, we assume duplicate frame and instead use n-2 in comparisons [same for Diff(n+1,n+2)]
#
dPOV = POV *255.0 / 100.0 # Convert range [0.0,100.0] to [0.0,255.0]
C = RT_DBaseGetField(InfoDB,-1 + 1, 6) # Prep
NextPossEnd = dMinLen - 1
for(n=0,FC-2) {
A=B B=C C=RT_DBaseGetField(InfoDB,Min(n+1,FC-1),6) # Re-use B and C from previous iteration, new C = Diff(n+1 <-> n+2)
if(n >= NextPossEnd) {
Cx = (C<DupTh)?Max(RT_FrameDifference(Last,Last,n+1,n+3,ChromaWeight),C): C # If Diff(n+1,n+2) too low, use Diff(n+1,n+3)
if((dFact*Cx+dMinim) < B) { # sufficiently bigger than 'Next->Next+1' (RHS) ?
# Here, RHS STANDARD DETECT SCENE CHANGE: n+1 CANNOT be a single flash frame
# If fewer than dPOV luma pixels changed by at least 1 luma level, then NOT a scene change
PxDf=RT_LumaPixelsDifferent(Last,Last,n=n,n2=n+1,Thresh=1)
if(PxDf >= dPOV) { # Here, Possible RHS scene change
PxDf2 = RT_LumaPixelsDifferent(Last,Last,n=n,n2=n-1,Thresh=1)
if(PxDf2 < PxDf) { # WOULD LHS be Pixlcount Overridden ? (at previous frame)
C_DR = RT_DBaseGetField(InfoDB,n,2) # MinMaxDifY(n)
N_DR = RT_DBaseGetField(InfoDB,Min(n+1,FC-1),2) # MinMaxDifY(n+1) : ie FROM NEXT FRAME/RECORD
if(Abs(N_DR-C_DR)>4) {
# Look for Flash frames, if found disable detect until reached flash frame,
# can then redetect incl flash frames again from that point.
FlashLim = Min(n+dFlashFrames,FC-2) # MUST HALT on or before last frame where valid n+1 scene is dMinLen
for(i=FlashLim,n+2,-1) {
mfpdf=RT_LumaPixelsDifferent(Last,Last,n=n,n2=i,Thresh=16)
mfcorr=RT_LumaCorrelation(Last,Last,n=n,n2=i)
if(mfpdf<64.0 && mfcorr>dCorr) {
(DEBUG) ? RT_DebugF("%d ] MULTIFLASH: @ %d LumaPixdifCnt=%.2f%% LumaCorr=%.2f",
\ n,i,mfpdf*100.0/255.0,mfcorr,name=myName) : NOP
NextPossEnd = i # No more detections until detected flash frame
RT_DBaseSetField(ScanDB,n,4,$20001)# FLGS reason to Standard detect Override by Multiflash
i = -1 # BREAK
}
}
}
if(n >= NextPossEnd) {
RT_DBaseSetField(ScanDB,n,4,1) # FLGS reason to Standard detect
RT_DBaseSetField(ScanDB,Start,1,n) # Set Start of scene frame/Record EOSix(End OF Scene) to this frame.
NextPossEnd = n + dMinLen
Start = n + 1 # Next frame, SOS follows this EOS
}
} else { # HERE, decide not detected, OR Reason PixelCount overriden
# sufficiently bigger than 'Prev->Curr' (LHS) ? : # If Diff(n,n-1) too low, use Diff(n,n-2)
Ax = (A<DupTh)?Max(RT_FrameDifference(Last,Last,n,n-2,ChromaWeight),A): A
if((dFact*Ax+dMinim) < B) {
RT_DBaseSetField(ScanDB,n,4,$10001) # FLGS reason to Standard detect Overridden by Pixel count
(DEBUG) ? RT_DebugF("%d ] n-1->n Luma Pixel Diff Count OVERRIDE(too low) = %.2f%%",
\ n,PxDf2*100/255.0,name=myName) : NOP
}
}
} else {
RT_DBaseSetField(ScanDB,n,4,$10001) # FLGS reason to Standard detect Overridden by Pixel count
(DEBUG) ? RT_DebugF("%d ] n->n+1 Luma Pixel Diff Count OVERRIDE(too low) = %.2f%%",
\ n,PxDf*100/255.0,name=myName) : NOP
}
}
}
}
# Do the last frame (n = FC-1, moved out of above loop to avoid conditional branch
RT_DBaseSetField(ScanDB,Start,1,FC-1) # Set Start of scene frame/Record EOSix to this last frame.
#
__________________
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 February 2015 at 07:53. Reason: Update |
|
|
|
|
|
#5 | Link |
|
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,392
|
Post #5 of many
Create SCAN DBase {PART_2, (too big)} Code:
# Rescan to do Fadeout->FadeIn Scene Changes : Set only EOSix @ Start frame/record of Scene Change, and ALSO FLGS
(DEBUG) ? RT_DebugF("ReScan for Fade-to-Black SceneChanges:",name=myName) : NOP
for(n=0,FC-1) {
Start = n # SOSix for this scene
End = RT_DBaseGetField(ScanDB,Start,1) # EOSix for this scene
Len = End-Start+1
if(Len >= Max(dMinLen*2,24)) {
# Start and End with YPlaneMinMaxDifference >= 16
if(RT_DBaseGetField(InfoDB,Start,2) >= 16 && RT_DBaseGetField(InfoDB,End,2) >= 16) {
for(j=Start+dMinLen,End - dMinLen) {
mnmxdf=RT_DBaseGetField(InfoDB,j,2)
if(mnmxdf <= 6-2) { # 4 or below FADEOUT, 4->6 no mans land (still faded)
je=j
for(k=j+1,End-dMinlen) { # Hunt fade end, No mans land(4->6), remains faded
mnmxdf=RT_DBaseGetField(InfoDB,k,2) # YMinMaxDiff
if(mnmxdf <= 6-0) {
je=k # still fade
} else {
k=End # Not faded any more
}
}
m = (j + je) / 2 # middle faded frame (approx)
if(m < End - dMinLen) {
RT_DebugF("%d ] FADE SCENECHANGE @ %d",n,M,name=myName)
FLGS=RT_DBaseGetField(ScanDB,m-1,4)
RT_DBaseSetField(ScanDB,m-1,4,RT_BitOR(FLGS,$00008000)) # EOSix of prev scene FLGS set to Reason=Fade-To-Black
RT_DBaseSetField(ScanDB,Start,1,m-1) # Adjust EOSix @ Start Frame
Start=m # New Start frame
RT_DBaseSetField(ScanDB,Start,1,End) # Adjust End @ NEW Start Frame
}
# Retry for another FADE SceneChange in original scene
je = Max(m+dMinLen,je)
for(k=je+1,End-dMinLen) { # Scan till MinMaxDif(je+1) is above 16+Leeway
mnmxdf=RT_DBaseGetField(InfoDB,k,2)
if(mnmxdf >=16+8) {
(DEBUG) ? RT_DebugF("%d ] FADE SCENECHANGE RETRY SCAN @ %d",n,je+1,name=myName) : NOP
k=End
} else {
je=k
}
}
j = je # j = je + 1 at next iteration, next frame RETRY scan
}
}
}
}
n = End # End + 1 at next iteration
}
# At this point only EOSix at start of scene frame set, AND ALSO reason FLGS for Last frame of scene
(DEBUG) ? RT_DebugF("Writing Full SceneChange DBase Data",name=myName) : NOP
SceneNo=-1 # Write Scene Number (Zero Relative)
FLGS = 0
for(n=0,FC-1) {
Start = n
End = RT_DBaseGetField(ScanDB,Start,1)
SceneNo = SceneNo + 1
(DEBUG) ? RT_DebugF("%d] START=%d End=%d SceneNo=%d",n,Start,End,SceneNo,name=myName) : NOP
# SOSix, EOSix, Type(1=SOS,2=EOS,3=SOS+EOS,0=non), SceneNo(Zero Rel), FLGS
for(j=Start,End) { # Leave Reason FLGS intact
RT_DBaseSetField(ScanDB,j,0,Start)
RT_DBaseSetField(ScanDB,j,1,End)
RT_DBaseSetField(ScanDB,j,2,0)
RT_DBaseSetField(ScanDB,j,3,SceneNo)
}
RT_DBaseSetField(ScanDB,Start,4,FLGS) # Rewrite FLGS from previous EOS
RT_DBaseSetField(ScanDB,Start,2,1) # Rewrite Type, Start Of Scene
Type = (Start==End) ? 3 : 2 # Single frame scene at last frame ? (SOS & EOS)
RT_DBaseSetField(ScanDB,End ,2,Type) # ReWrite Type, End Of Scene
FLGS = RT_DBaseGetField(ScanDB,End,4) # Current scene FLGS, next time Prev scene FLGS
n = End # Next iteration n = End + 1
}
RT_DBaseSetID(ScanDB,0,DBSC_Str2ID("DBSC"))
RT_DBaseSetID(ScanDB,1,DBSC_Str2ID("SCAN"))
RT_DBaseSetID(ScanDB,2,Width)
RT_DBaseSetID(ScanDB,3,Height)
RT_DBaseSetID(ScanDB,4,DBSC_ColorSpaceIx())
nAttribs=RT_DBaseGetAttrib(ScanDB,-1)
RT_DBaseSetAttrib(ScanDB,nAttribs-1,Matrix)
RT_DBaseSetAttrib(ScanDB,nAttribs-2,ChromaWeight)
RT_DBaseSetAttrib(ScanDB,nAttribs-3,Thresh)
RT_DBaseSetID(ScanDB,5,dFact)
RT_DBaseSetID(ScanDB,6,dMinim)
RT_DBaseSetID(ScanDB,7,dMinLen)
RT_DBaseSetID(ScanDB,8,dCorr)
RT_DBaseSetID(ScanDB,9,DupTh)
RT_DBaseSetID(ScanDB,10,POV)
RT_DBaseSetID(ScanDB,11,dFlashFrames)
} Else {
(DEBUG) ? RT_DebugF("SCScan DBase Recycled '%s'",ScanDB,name=myName) : NOP
}
T = RT_TimerHP - START_TIME
(DEBUG) ? RT_DebugF("Total Time taken = %.2f Seconds (%.2f Mins)",T,T/60.0,name=myName) : NOP
""")
}
__________________
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 February 2015 at 07:54. Reason: Update |
|
|
|
|
|
#6 | Link |
|
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,392
|
Post #6 of many
Scene Change Utility funcs, Part 1 Code:
##################
# UTILITY
##################
Function DBSC_Override(String ScanDB,String Override_Fn,Bool "DEBUG") {
/*
DBSC_Override(), Using SCAN DBase and Overrides.txt, allows user to set additional Scene Change or remove erroneous ones
from the SCAN DBase.
ScanDB, INFO DBase created by DBSC_Scan.
Override_fn filename: If first character == '*' then uses text in the Override_fn string and does not load file.
When using Override_fn as string, then each override should be on separate line (same format as file).
FORMAT: One frame numer command on each line.
Any +ve frame number sets START Of Scene Change frame.
Any -ve frame number REMOVES a scene change at that frame (START or END).
*/
myName="DBSC_Override: "
START_TIME = RT_TimerHP
DEBUG=Default(DEBUG,True)
Assert(Override_Fn!="",RT_String("%sMust provide a Override filename",myName))
GSCript("""
Assert(DBSC_ScanValidate(ScanDB,MustExist=True,name=myName),RT_String("%sScanDB Invalid\n'%s'",myName,ScanDB))
if(RT_Ord(Override_Fn)!=RT_Ord("*")) {
Assert(Exist(Override_Fn),RT_String("%sOverride_Fn Does NOT exist\n'%s'",myName,Override_Fn))
(DEBUG) ? RT_DebugF("Reading Override File '%s'",Override_Fn,name=myName) : NOP
OVS = RT_ReadTxtFromFile(Override_Fn)
} Else {
OVS = MidStr(Override_Fn,2)
}
OVS=(RT_Ord(OVS)==0) ? "#" : OVS # Avoid error in RT_StrReplaceMulti for Empty string ""
Fnd_S=RT_String("\t\n \n") # Replace TAB and double SPACE with Single SPACE
Rep_S=RT_String(" \n \n")
OVS=RT_StrReplaceMulti(OVS,Fnd_S,Rep_S)
NLINES = RT_TxtQueryLines(OVS) # Lines of text in OVS
(DEBUG) ? RT_DebugF("Scanning Overrides",name=myName) : NOP
FC=RT_DBaseRecords(ScanDB)
INSERTED=0
DELETED =0
RT_DBaseSetID(ScanDB,1,-1) # Disable ScanDB validity until finished without error
for(i=0,NLINES-1) {
STR = RT_TxtGetLine(OVS,i) # Without trailing n/l
While(RT_Ord(STR)==32) { STR=MidStr(STR,2) } # Eat White
S=STR
if(RT_Ord(S)!=RT_Ord("#")&&RT_Ord(S)!=0) { # Ignore comment ONLY or Empty lines
Neg=False
n=-1
if(RT_Ord(S)==RT_Ord("-")) {
Neg=True
S=MidStr(S,2)
While(RT_Ord(S)==32) { S=MidStr(S,2) } # Eat White
} Else if(RT_Ord(S)==RT_Ord("+")) {
S=MidStr(S,2)
While(RT_Ord(S)==32) { S=MidStr(S,2) } # Eat White
}
if(RT_Ord(S)>=RT_Ord("0") && RT_Ord(S)<=RT_Ord("9")) {
n=RT_NumberValue(S)
While(RT_Ord(S)>=RT_Ord("0") && RT_Ord(S)<=RT_Ord("9")) { S=MidStr(S,2) } # Eat Digits
While(RT_Ord(S)==32) { S=MidStr(S,2) } # Eat White
if(RT_Ord(S)==RT_Ord("#")) {S=""} # Eat remaining Comment
}
Assert(S=="",RT_String("%sLINE %d : Non Parse @'%s'\n'%s'",myName,i+1,S,STR))
Assert(n>=0 && n<FC,RT_String("%sLINE %d : Frame %d Does Not Exist @'%s'\n'%s'",myName,i+1,n,S,STR))
Assert(n!=0 && n!=FC-1,RT_String("%sLINE %d : Cannot Override First or Last frame %d @'%s'\n'%s'",myName,i+1,n,S,STR))
# ScanDB Fields: SOSix, EOSix, Type(1=SOS,2=EOS,0=non), SceneNo(Zero Rel), FLGS
Start=RT_DBaseGetField(ScanDB,n,0)
End =RT_DBaseGetField(ScanDB,n,1)
Type =RT_DBaseGetField(ScanDB,n,2)
Single=(Start==End && Start == n && Type==3)
if(Neg) {
if(n!=Start && n != End) {
(DEBUG||Type!=0) ? RT_DebugF("LINE %d : DEL SC, Frame %d Neither Start nor End Of Scene, Ignoring",i+1,n,name=myName) : NOP
Assert(Type==0,RT_String("%sLINE %d : INTERNAL ERROR, Frame %d Type non-zero(%d)",myName,i+1,n,Type))
} Else {
if(Single) {
# Single Frame Scene is melded with previous scene
(DEBUG) ? RT_DebugF("LINE %d : DEL SC, Frame %d Removing Single Frame Scene",i+1,n,name=myName) : NOP
NewStart = RT_DBaseGetField(ScanDB,n-1,0) # SOSix from previous scene
NewEnd = End # EOSix from current scene (ie n)
NewType=(NewStart==n-1)?1:0 # Previous is single frame scene
RT_DBaseSetField(ScanDB,n-1,2,NewType) # Change n-1 to Type NewType (SOS OR none)
FLGS=RT_DBaseGetField(ScanDB,n-1,4) # n-1 FLGS
RT_DBaseSetField(ScanDB,n-1,4,RT_BitOR(FLGS,$40000000)) # FLGS User Deleted
FLGS=RT_DBaseGetField(ScanDB,n,4) # n FLGS
RT_DBaseSetField(ScanDB,n,4,RT_BitOR(FLGS,$40000000)) # FLGS User Deleted
} Else if(Start==n) {
(DEBUG||Type!=1) ? RT_DebugF("LINE %d : DEL SC, Frame %d Removing Start Of Scene",i+1,n,name=myName) : NOP
Assert(Type==1,RT_String("%sLINE %d : INTERNAL ERROR, Frame %d Type non-1(%d)",myName,i+1,n,Type))
NewStart = RT_DBaseGetField(ScanDB,n-1,0) # SOSix from previous scene
NewEnd = End # EOSix from current scene
RT_DBaseSetField(ScanDB,n-1,2,0) # Change n-1 to Type=None
FLGS=RT_DBaseGetField(ScanDB,n-1,4) # n-1 FLGS
RT_DBaseSetField(ScanDB,n-1,4,RT_BitOR(FLGS,$40000000)) # FLGS User Deleted
FLGS=RT_DBaseGetField(ScanDB,n,4) # n FLGS
RT_DBaseSetField(ScanDB,n,4,RT_BitOR(FLGS,$40000000)) # FLGS User Deleted
} Else {
(DEBUG||Type!=2) ? RT_DebugF("LINE %d : DEL SC, Frame %d Removing End Of Scene",i+1,n,name=myName) : NOP
Assert(Type==2,RT_String("%sLINE %d : INTERNAL ERROR, Frame %d Type non-2(%d)",myName,i+1,n,Type))
NewStart = Start # SOSis from current scene
NewEnd = RT_DBaseGetField(ScanDB,n+1,1) # EOSix from next scene
RT_DBaseSetField(ScanDB,n+1,2,0) # Change n+1 to Type=None
FLGS=RT_DBaseGetField(ScanDB,n,4) # n FLGS
RT_DBaseSetField(ScanDB,n,4,RT_BitOR(FLGS,$40000000)) # FLGS User Deleted
FLGS=RT_DBaseGetField(ScanDB,n+1,4) # n+1 FLGS
RT_DBaseSetField(ScanDB,n+1,4,RT_BitOR(FLGS,$40000000)) # FLGS User Deleted
}
for(j=NewStart,NewEnd) {
RT_DBaseSetField(ScanDB,j,0,NewStart) # Change all of scene SOSix to new Start
RT_DBaseSetField(ScanDB,j,1,NewEnd) # Change all of scene EOSix to new End
}
NewType=(Single)?2:0
RT_DBaseSetField(ScanDB,n,2,NewType) # Change n to Type=None OR EOS if Single Frame Scene
DELETED = DELETED + 1 # Removed a scene
}
} Else {
If(Single) {
(DEBUG) ? RT_DebugF("LINE %d : INS SC, Frame %d already Single Frame Scene, Ignoring",i+1,n,name=myName) : NOP
} Else if(Start==n) {
(DEBUG||Type!=1) ? RT_DebugF("LINE %d : INS SC, Frame %d already Start Of Scene, Ignoring",i+1,n,name=myName) : NOP
Assert(Type==1,RT_String("%sLINE %d : INTERNAL ERROR, Frame %d Type non-1(%d)",myName,i+1,n,Type))
} Else {
if(End==n) {
(DEBUG||Type!=2) ? RT_DebugF("LINE %d : INS SC, Frame %d Changing End Of Scene to Single Frame Scene",i+1,n,name=myName) : NOP
Assert(Type==2,RT_String("%sLINE %d : INTERNAL ERROR, Frame %d Type non-2(%d)",myName,i+1,n,Type))
} Else {
(DEBUG||Type!=0) ? RT_DebugF("LINE %d : INS SC, Frame %d Changing Mid Scene to Start Of Scene",i+1,n,name=myName) : NOP
Assert(Type==0,RT_String("%sLINE %d : INTERNAL ERROR, Frame %d Type non-0(%d)",myName,i+1,n,Type))
}
for(j=Start,n-1) {
RT_DBaseSetField(ScanDB,j,1,n-1) # Change all of scene EOSix to new end
}
NewType=(Start==n-1)?3:2
RT_DBaseSetField(ScanDB,n-1,2,NewType) # Change n-1 to Type=Single Frame Scene OR End Of Scene
for(j=n,End) {
RT_DBaseSetField(ScanDB,j,0,n) # Change all of scene SOSix to new start
}
NewType=(End==n)?3:1
RT_DBaseSetField(ScanDB,n,2,NewType) # Change n to Type= Single Frame Scene OR Start Of Scene
FLGS=RT_DBaseGetField(ScanDB,n,4) # n FLGS
RT_DBaseSetField(ScanDB,n,4,RT_BitOR(FLGS,$80000000)) # FLGS User INSERTED START
FLGS=RT_DBaseGetField(ScanDB,n-1,4) # n-1 FLGS
RT_DBaseSetField(ScanDB,n-1,4,RT_BitOR(FLGS,$80000000)) # FLGS User INSERTED END (or Single Frame Scene)
INSERTED = INSERTED + 1 # Added new scene
}
}
}
}
if(INSERTED!=0 || DELETED!=0) {
(DEBUG) ? RT_DebugF("%d Overrides Processed",INSERTED+DELETED,name=myName) : NOP
(DEBUG) ? RT_DebugF("ReScan to update SCAN DBase SceneNo",name=myName) : NOP
SceneNo = -1
for(n=0,FC-1) {
S=n
SceneNo = SceneNo + 1
Start=RT_DBaseGetField(ScanDB,n,0)
End =RT_DBaseGetField(ScanDB,n,1)
Type =RT_DBaseGetField(ScanDB,n,2)
Single=(Start==End && Start == n && Type==3)
Assert(S==Start,RT_String("%s%d ] UPDATE INTERNAL ERROR : Start SOSix Mismatch(%d,%d)",myName,n,S,Start))
(!Single)?Assert(Type==1 ,RT_String("%s%d ] UPDATE INTERNAL ERROR : Start Type non-1(%d)",myName,n,Type)):NOP
EStart=RT_DBaseGetField(ScanDB,End,0)
EEnd =RT_DBaseGetField(ScanDB,End,1)
EType =RT_DBaseGetField(ScanDB,End,2)
Assert(S==EStart,RT_String("%s%d ] UPDATE INTERNAL ERROR : End SOSix Mismatch(%d,%d)",myName,n,S,EStart))
Assert(End==EEnd,RT_String("%s%d ] UPDATE INTERNAL ERROR : End MisMatch(%d,%d)",myName,n,End,EEnd))
(!Single)?Assert(EType==2 ,RT_String("%s%d ] UPDATE INTERNAL ERROR : End Type non-2(%d)",myName,n,EType)):NOP
(Single) ?Assert(EType==3 ,RT_String("%s%d ] UPDATE INTERNAL ERROR : End Type non-3(%d)",myName,n,EType)):NOP
RT_DBaseSetField(ScanDB,Start,3,SceneNo)
RT_DBaseSetField(ScanDB,End ,3,SceneNo)
for(i=Start+1,End-1) {
SOSix=RT_DBaseGetField(ScanDB,i,0)
EOSix=RT_DBaseGetField(ScanDB,i,1)
Type =RT_DBaseGetField(ScanDB,i,2)
Assert(Start==SOSix,RT_String("%s%d ] UPDATE INTERNAL ERROR : Start SOSix Mismatch(%d,%d)",myName,n,Start,SOSix))
Assert(End==EOSix ,RT_String("%s%d ] UPDATE INTERNAL ERROR : End MisMatch(%d,%d)",myName,n,End,EOSix))
Assert(Type==0 ,RT_String("%s%d ] UPDATE INTERNAL ERROR : Start Type non-1(%d)",myName,n,Type))
RT_DBaseSetField(ScanDB,i,3,SceneNo)
}
n = End # Next iteration n = End + 1
}
nAttribs=RT_DBaseGetAttrib(ScanDB,-1)
OVERRIDDEN = RT_DBaseGetAttrib(ScanDB,nAttribs-4)
TotOVR = OVERRIDDEN+INSERTED+DELETED
RT_DBaseSetAttrib(ScanDB,nAttribs-4,TotOVR) # Count of Overridden
(DEBUG) ? RT_DebugF("Total Accumulated Overrides = %d",TotOVR,name=myName) : NOP
}
RT_DBaseSetID(ScanDB,1,DBSC_Str2ID("SCAN")) # Re-enable ScanDB validity
T = RT_TimerHP - START_TIME
(DEBUG) ? RT_DebugF("Total Time taken = %.2f Seconds (%.2f Mins)",T,T/60.0,name=myName) : NOP
""")
Return 0
}
__________________
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 February 2015 at 07:56. Reason: Update |
|
|
|
|
|
#7 | Link |
|
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,392
|
Post #7 of many
Scene Change Utility funcs, Part 2 Code:
Function DBSC_WriteFiles(String ScanDB,String "Start_Fn",String "End_Fn",String "Range_Fn",String "Mid_Fn",String "ClipClopCmd_Fn",
\ Bool "Comment",Bool "Comma",String "VideoFileName") {
/*
Write Scene info to output files:- Start, End, Mid Frame and Range.
Also writes a ClipClop command file for Start (clip 1) and End (clip 2) frames, used by DBSC_Select().
ScanDB, SCAN DBase file created via DBSC_Scan.
Comment, Default True writes additional Hash (#) separated info to file. False, omits extra info.
Comma, Default True, use Comma (,) range separator, Else False uses SPACE range separator.
VideoFilename, can supply clip name, added to Comment Header.
*/
myName="DBSC_WriteFiles: "
START_TIME = RT_TimerHP
Start_Fn=Default(Start_Fn,"") End_Fn=Default(End_Fn,"") Range_Fn=Default(Range_Fn,"")
Mid_Fn=Default(Mid_Fn,"") ClipClopCmd_Fn=Default(ClipClopCmd_Fn,"")
Comment=Default(Comment,True)
Comma=Default(Comma,True)
VideoFileName=Default(VideoFileName,"")
VideoFileName=(VideoFileName!="") ? RT_FilenameSplit(VideoFileName,12) : ""
SEP = RT_Ord((Comma) ? "," : " ")
GSCript("""
DBSC_ScanValidate(ScanDB,MustExist=True,name=myName)
(Start_Fn !="" && Exist(Start_Fn)) ? RT_FileDelete(Start_Fn) : NOP
(End_Fn !="" && Exist(End_Fn)) ? RT_FileDelete(End_Fn) : NOP
(Range_Fn !="" && Exist(Range_Fn)) ? RT_FileDelete(Range_Fn) : NOP
(Mid_Fn !="" && Exist(Mid_Fn)) ? RT_FileDelete(Mid_Fn) : NOP
(ClipClopCmd_Fn!="" && Exist(ClipClopCmd_Fn)) ? RT_FileDelete(ClipClopCmd_Fn) : NOP
(Start_Fn !="") ? RT_DebugF("Writing Start_Fn File '%s'",Start_Fn,name=myName) : NOP
(End_Fn !="") ? RT_DebugF("Writing End_Fn File '%s'", End_Fn, name=myName) : NOP
(Range_Fn !="") ? RT_DebugF("Writing Range_Fn File '%s'",Range_Fn,name=myName) : NOP
(Mid_Fn !="") ? RT_DebugF("Writing Mid_Fn File '%s'", Mid_Fn,name=myName) : NOP
(ClipClopCmd_Fn!="") ? RT_DebugF("Writing ClipClopCmd_Fn File '%s'", ClipClopCmd_Fn,name=myName) : NOP
if(Comment) {
nAttribs = RT_DBaseGetAttrib(ScanDB,-1)
Matrix = RT_DBaseGetAttrib(ScanDB,nAttribs-1)
ChromaWeight= RT_DBaseGetAttrib(ScanDB,nAttribs-2)
Thresh = RT_DBaseGetAttrib(ScanDB,nAttribs-3)
OVrCnt = RT_DBaseGetAttrib(ScanDB,nAttribs-4)
dFact = RT_DBaseGetID(ScanDB,5)
dMinim = RT_DBaseGetID(ScanDB,6)
dMinLen = RT_DBaseGetID(ScanDB,7)
dCorr = RT_DBaseGetID(ScanDB,8)
DupTh = RT_DBaseGetID(ScanDB,9)
POV = RT_DBaseGetID(ScanDB,10)
dFlashFrames= RT_DBaseGetID(ScanDB,11)
BAR =RT_StrPad("",86,"#")+Chr(10)
HEAD=RT_String("#\n# DBSC: Scene Change @@@ Frames file : @ %s\n#\n",RT_LocalTimeString(File=False))
VSTR=(VideoFileName=="") ? "" : RT_String("# SourceFile:- '%s'\n#\n",VideoFileName)
ARG =RT_String("# dFact =%.2f : dMinim =%.2f : dMinLen =%d : dCorr = %.2f\n# DupTh=%.2f : POV=%.2f : dFlashFrames=%d\n# Matrix=%d : ChromaW=%.2f : Thresh = %.2f : Overides=%d\n#\n",
\ dFact,dMinim,dMinLen,dCorr,DupTh,POV,dFlashFrames,Matrix,ChromaWeight,Thresh,OvrCnt)
LAB=RT_StrPad("# # SceneNo : Start : Mid : End : Length",85)+"#"
Z=RT_String("%s%s%s%s%s%s",BAR,HEAD,VSTR,ARG,BAR,LAB)
Z=RT_StrReplace(Z,"@@@","%s")
(Start_Fn !="") ? RT_WriteFile(Start_Fn, Z,"START" ,Append=True) : NOP
(End_Fn !="") ? RT_WriteFile(End_Fn, Z,"END" ,Append=True) : NOP
(Range_Fn !="") ? RT_WriteFile(Range_Fn, Z,"RANGE" ,Append=True) : NOP
(Mid_Fn !="") ? RT_WriteFile(Mid_Fn, Z,"MID" ,Append=True) : NOP
(ClipClopCmd_Fn!="") ? RT_WriteFile(ClipClopCmd_Fn,Z,"CLIPCLOP_CMD",Append=True) : NOP
}
for(n=0,RT_DBaseRecords(ScanDB)-1) {
Start=RT_DBaseGetField(ScanDB,n,0) End =RT_DBaseGetField(ScanDB,n,1) SceneNo=RT_DBaseGetField(ScanDB,n,3)+1
Mid = (Start + End)/ 2 Len = End-Start + 1
if(!Comment) {
(Start_Fn!="") ? RT_WriteFile(Start_Fn,"%d" ,Start ,Append=True) : NOP
(End_Fn!="") ? RT_WriteFile(End_Fn, "%d" ,End ,Append=True) : NOP
(Range_Fn!="") ? RT_WriteFile(Range_Fn,"%d%c%d" ,Start,SEP,End,Append=True) : NOP
(Mid_Fn!="") ? RT_WriteFile(Mid_Fn, "%d" ,Mid ,Append=True) : NOP
if(ClipClopCmd_Fn!="") {
RT_WriteFile(ClipClopCmd_Fn, "%d%c%d",(Start==End)?3:1,SEP,Start,Append=True)
(Start!=End) ? RT_WriteFile(ClipClopCmd_Fn, "2%c%d",SEP,End,Append=True) : NOP
}
} Else {
Com = RT_String(" # %6d : %6d : %6d : %6d : %6d",SceneNo,Start,Mid,End,Len)
(Start_Fn!="") ? RT_WriteFile(Start_Fn,"%-13d%s", Start,Com,Append=True) : NOP
(End_Fn!="") ? RT_WriteFile(End_Fn ,"%-13d%s", End, Com,Append=True) : NOP
(Range_Fn!="") ? RT_WriteFile(Range_Fn,"%s%s",RT_StrPad(RT_String("%d%c%d",Start,SEP,End),13),Com,Append=True) : NOP
(Mid_Fn!="") ? RT_WriteFile(Mid_Fn ,"%-13d%s", Mid, Com,Append=True) : NOP
if(ClipClopCmd_Fn!="") {
RT_WriteFile(ClipClopCmd_Fn,RT_String("%s%s",RT_StrPad(RT_String("%d%c%d",(Start==End)?3:1,SEP,Start),13),com),Append=True)
(Start!=End)?RT_WriteFile(ClipClopCmd_Fn,RT_String("%s%s",RT_StrPad(RT_String("%d%c%d",2,SEP,End),13),com),Append=True):NOP
}
}
n = End # Next iteration n = End + 1, ie Start of Next Scene
}
T = RT_TimerHP - START_TIME
RT_DebugF("Total Time taken = %.2f Seconds (%.2f Mins)",T,T/60.0,name=myName)
""")
}
__________________
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 February 2015 at 07:57. Reason: Update |
|
|
|
|
|
#8 | Link |
|
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,392
|
Post #8 of many
Clip Display funcs Code:
Function DBSC_SubsClip(clip c,String InfoDB,String ScanDB,Bool "Subs",Bool "Metrics",Bool "Metrics2",String "name") {
/*
DBSC_SubsClip(), Return clip optionally subtitled (metrics And/Or START OF SCENE : END OF SCENE Subtitles)
InfoDB, INFO DBase file created via DBSC_CreateInfo().
ScanDB, SCAN DBase as created via DBSC_Scan().
Metrics, Default True. Write RT_Subtitle Metrics to frame.
Metrics2, Default True. Write RT_Subtitle Metrics2 to frame.
Subs, Default True. Write Subtitles to frame, "START OF SCENE" and "END OF SCENE".
*/
myName=Default(name,"DBSC_SubsClip: ")
c
FC=FrameCount
Subs=Default(Subs,True)
Metrics=Default(Metrics,True)
Metrics2=Default(Metrics2,True)
#
InfoValid = DBSC_InfoValidate(InfoDB,MustExist=True,name=myName)
Assert(InfoValid,RT_String("%sInfoDB failed Basic validation\n'%s'",myName,InfoDB))
InfoValid =
\ RT_VarIsSame(RT_DBaseGetID(InfoDB,2),Width) && RT_VarIsSame(RT_DBaseGetID(InfoDB,3),Height) &&
\ RT_VarIsSame(RT_DBaseGetID(InfoDB,4),DBSC_ColorSpaceIx(c)) &&
\ RT_VarIsSame(RT_DBaseRecords(InfoDB),FC)
Assert(InfoValid,RT_String("%sInfoDB failed Match To Clip validation\n'%s'",myName,InfoDB))
Matrix = RT_DBaseGetID(InfoDB,5)
ChromaWeight= RT_DBaseGetID(InfoDB,6)
Thresh = RT_DBaseGetID(InfoDB,7)
#
ScanValid = DBSC_ScanValidate(ScanDB,MustExist=True,name=myName)
Assert(ScanValid,RT_String("%sScanDB failed Basic validation\n'%s'",myName,ScanDB))
ScanValid =
\ RT_VarIsSame(RT_DBaseGetID(ScanDB,2),Width) && RT_VarIsSame(RT_DBaseGetID(ScanDB,3),Height) &&
\ RT_VarIsSame(RT_DBaseGetID(ScanDB,4),DBSC_ColorSpaceIx(c)) &&
\ RT_VarIsSame(RT_DBaseRecords(ScanDB),FC)
Assert(ScanValid,RT_String("%sScanDB failed Match To Clip validation\n'%s'",myName,ScanDB))
nAttribs=RT_DBaseGetAttrib(ScanDB,-1)
ScanValid = RT_VarIsSame(RT_DBaseGetAttrib(ScanDB,nAttribs-1),Matrix) &&
\ RT_VarIsSame(RT_DBaseGetAttrib(ScanDB,nAttribs-2),ChromaWeight) &&
\ RT_VarIsSame(RT_DBaseGetAttrib(ScanDB,nAttribs-3),Thresh)
Assert(ScanValid,RT_String("%sScanDB failed Match Matrix/ChromaWeight/Thresh to InfoDB\n'%s'",myName,ScanDB))
RT_Script = """
n = current_frame
SC = RT_DBaseGetField(ScanDB,n,2)
@@
@@@
@@@@
@@@@@
@@@@@@
Return Last
"""
RT_Met1 = """
FC = Framecount
SOS = RT_DBaseGetField(ScanDB,n,0)
EOS = RT_DBaseGetField(ScanDB,n,1)
SceneNo = RT_DBaseGetField(ScanDB,n,3)+1
FLGS = RT_DBaseGetField(ScanDB,n,4)
A = RT_DBaseGetField(InfoDB,Max(n-1,0),6)
B = RT_DBaseGetField(InfoDB,n,6)
C = RT_DBaseGetField(InfoDB,Min(n+1,FC-1),6)
Ax = (A<DupTh)?Max(RT_FrameDifference(Last,Last,n,n-2,ChromaWeight),A): A
Cx = (C<DupTh)?Max(RT_FrameDifference(Last,Last,n+1,n+3,ChromaWeight),C): C # If Diff(n+1,n+2) too low, use Diff(n+1,n+3)
PxDif = RT_LumaPixelsDifferent(Last,Last,delta2=1,Thresh=1) * 100.0 / 255.0
FLGS = RT_DBaseGetField(ScanDB,n,4)
CorrY = RT_Lumacorrelation(Last,Last,n=n,n2=n+1)
FS=(RT_BitAnd(FLGS,$C0000000)!=0)?"USER OVERRIDE":(RT_BitTst(FLGS,16))?"PIXELCOUNT OVERRIDE":
\ RT_BitTst(FLGS,17)?"MULTIFLASH OVERRIDE" : (RT_BitTst(FLGS,15))?"FADE-TO-BLACK":""
"""
RT_Met2="""
Mn = RT_DBaseGetField(InfoDB,n,0)
Mx = RT_DBaseGetField(InfoDB,n,1)
MnMx = RT_DBaseGetField(InfoDB,n,2)
Med = RT_DBaseGetField(InfoDB,n,3)
AveY = RT_DBaseGetField(InfoDB,n,4)
StdY = RT_DBaseGetField(InfoDB,n,5)
"""
RT_Met1_Fn="""RT_Subtitle(FMT, n,SC,SceneNo,SceneCnt,n-SOS,SOS,EOS,EOS-SOS+1,Ax,B,Cx,PxDif,CorrY,OVR,FLGS,FS)"""
RT_Met2_Fn="""RT_Subtitle(FMT2,mn,mx,MnMx,Med,AveY,StdY,align=1)"""
INSERT_Script="""Last = (SC==1) ? STARTCLIP : (SC==2) ? ENDCLIP : (SC==3) ? SINGLECLIP : Last"""
SUBS_Script="""
SC = RT_DBaseGetField(ScanDB,current_frame,2)
Last = (SC==1) ? STARTCLIP : (SC==2) ? ENDCLIP : (SC==3) ? SINGLECLIP : Last
Return Last
"""
GScript("""
If(Metrics || Metrics2 || Subs) {
SIZE = Round(Height/8.0)
STARTCLIP = SUBS?SubTitle("START OF SCENE",Align=5,size=SIZE,y=(Height+SIZE)/2,text_color=$C080FF) : Last
ENDCLIP = SUBS?SubTitle("END OF SCENE" ,Align=5,size=SIZE,y=(Height-SIZE)/2,text_color=$FF80C0) : Last
SINGLECLIP=SUBS?SubTitle("START OF SCENE\nEND OF SCENE",Align=5,size=SIZE,y=(Height-SIZE)/2,text_color=$C0FF80,lsp=0):Last
if(Metrics||Metrics2) {
FMT="%d ]\nSC=%d#%d/%d:%d{S%d:E%d:L%d}\nPrv=%.2f Cur=%.2f Nxt=%.2f\nPxDif=%.2f%% : Corr=%.2f\nOvrCnt=%d : $%08X %s"
FMT2="Mn=%d Mx=%d MMDf=%d Med=%d\nAve=%.2f Std=%.2f"
nAttribs = RT_DBaseGetAttrib(ScanDB,-1)
OVR = RT_DBaseGetAttrib(ScanDB,nAttribs-4)
SceneCnt=RT_DBaseGetField(ScanDB,RT_DBaseRecords(ScanDB)-1,3)+1
DupTh = RT_DBaseGetID(ScanDB,8)
Script = RT_StrReplace(RT_Script,"@@@@@@" ,(Metrics2?RT_Met2_Fn:""))
Script = RT_StrReplace(Script ,"@@@@@" ,(Metrics?RT_Met1_Fn:""))
Script = RT_StrReplace(Script ,"@@@@" ,(SUBS?INSERT_SCRIPT:""))
Script = RT_StrReplace(Script ,"@@@" ,(Metrics2?RT_Met2:""))
Script = RT_StrReplace(Script ,"@@" ,(Metrics||Metrics2?RT_Met1:""))
Last.ScriptClip(Script,Args="InfoDB,ScanDB,FMT,FMT2,SceneCnt,STARTCLIP,ENDCLIP,SINGLECLIP,OVR,DupTh,ChromaWeight")
} Else {
Last.ScriptClip(SUBS_Script,Args="ScanDB,STARTCLIP,ENDCLIP,SINGLECLIP")
}
}
""")
return Last
}
Function DBSC_StackSceneChanges(clip c,String InfoDB,String ScanDB,Bool "Subs",Bool "Metrics") {
/*
DBSC_StackSceneChanges(), Return clip, End frame of a scene together with Stacked Start frame of following scene.
InfoDB, INFO DBase file created via DBSC_CreateInfo().
ScanDB, SCAN DBase as created via DBSC_Scan().
Metrics, Default True. Write RT_Subtitle Metrics to frame.
Subs, Default True. Write Subtitles to frame, eg "START OF SCENE" and "END OF SCENE", Single frame scene has both written.
Returns NO AUDIO.
*/
myName="DBSC_StackSceneChanges: "
Subs=Default(Subs,True)
Metrics=Default(Metrics,True)
DBSC_SubsClip(c,InfoDB,ScanDB,Metrics,Subs,name=myName)
LT=RT_LocalTimeString Start_Fn=LT+"_Start.txt" End_Fn =LT+"_End.txt"
DBSC_WriteFiles(ScanDB,Start_Fn,End_Fn) S=FrameSel(Last,cmd=Start_fn) E=FrameSel(Last,cmd=End_fn)
RT_FileDelete(Start_Fn) RT_FileDelete(End_Fn)
S=S.Trim(1,0) E=E.Trim(0,E.FrameCount-2)
(Width>=Height) ? StackVertical(E,S) : StackHorizontal(E,S)
return Last.KillAudio
}
__________________
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 February 2015 at 07:59. Reason: Update |
|
|
|
|
|
#9 | Link |
|
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,392
|
Post #9 of many
SCSelect equivalent Code:
Function DBSC_Select(clip Motion,String ScanDB,clip "StartClip", clip "EndClip",Clip "SingleClip") {
/*
DBSC_Select(), Similar-ish to SCSelect()
Motion, frames used where not Start nor End of scene, nor Single Frame scene,
Start/End/Single clips default to Motion clip if not supplied.
ScanDB, SCAN DBase as created via DBSC_Scan().
StartClip, Frames used for Start Of Scene Frames, Default Motion clip.
EndClip, Frames used for End Of Scene Frames, Default Motion clip.
SingleClip, Frames used for Single frame Scene, Default Motion clip.
Clip FrameCount's must be same as the ScanDB detection clip, (no other similarities to detection clip enforced).
Returns NO AUDIO.
*/
myName="DBSC_Select: "
Motion StartClip=Default(StartClip,Last) EndClip=Default(EndClip,Last) SingleClip=Default(SingleClip,Last)
Assert(RT_VarIsSame(Last,StartClip,Sig=False),RT_String("%sDissimilar StartClip dimensions OR ColorSpace",myName))
Assert(StartClip.FrameCount==FrameCount,RT_String("%sDissimilar StartClip FrameCount",myName))
Assert(RT_VarIsSame(Last,EndClip,Sig=False),RT_String("%sDissimilar EndClip dimensions OR ColorSpace",myName))
Assert(EndClip.FrameCount==FrameCount,RT_String("%sDissimilar EndClip FrameCount",myName))
Assert(RT_VarIsSame(Last,SingleClip,Sig=False),RT_String("%sDissimilar SingleClip dimensions OR ColorSpace",myName))
Assert(SingleClip.FrameCount==FrameCount,RT_String("%sDissimilar SingleClip FrameCount",myName))
Valid=DBSC_ScanValidate(ScanDB,MustExist=True,name=myName)
Assert(Valid,RT_String("%sInvalid ScanDB",myName))
Assert(RT_DBaseRecords(ScanDB)==FrameCount,RT_String("%sScanDB Records != FrameCount",myName))
ClipClopCmd_Fn=RT_LocalTimeString+".Txt"
DBSC_WriteFiles(ScanDB,ClipClopCmd_Fn=ClipClopCmd_Fn,Comment=False)
Last.ClipClop(StartClip,EndClip,SingleClip,cmd=ClipClopCmd_Fn)
RT_FileDelete(ClipClopCmd_Fn)
return Last.KillAudio
}
__________________
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 February 2015 at 08:01. Reason: Update |
|
|
|
|
|
#10 | Link |
|
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,392
|
Post #10 of many
Dynamically changing borders detector (PART 1) Code:
#######################################################
### DYNAMICALLY CHANGING BORDERS CROPPING FUNCTIONS ***
#######################################################
Function DBSC_DynaCrop(clip c,String ScanDB,String "SpliceDB",int "W",int "H",String "Resizer",
\ Int "CropLimit",Int "CropLimit_Left",Int "CropLimit_Top",Int "CropLimit_Right",Int "CropLimit_Bot",
\ int "RLBT",int "LeftAdd",int "TopAdd",int "RightAdd",int "BotAdd",
\ int "DissolveSkip",
\ String "LogFn",String "LogTMPT",
\ Float "CropThresh",Float "ATM",
\ bool "Show",bool "Debug") {
/*
DBSC_DynaCrop(). With Input SCanDB, Creates output SpliceDB and log, to crop dynamically changing borders from PROGRESSIVE clip.
Requires RoboCrop v0.21+ for RoboCrop output LogFile, to get crop coords.
As well as output SpliceDB, also outputs a user configurable log file (always outputs the log file).
ScanDB, DBase as created via DBSC_Scan().
SpliceDB filename, Optional default "", default "" produces no output DBase, only a LogFn log file.
Where provided with an output SpliceDB filename, will:-
If SpliceDB DOES NOT already Exist, Create zero record SpliceDB in STANDARD format.
If SpliceDB DOES already Exist, Create SpliceDB in SAME format as existing DBase, but first initialled to zero Records.
STANDARD Format SpliceDB consists of 12 Int fields and 1 string[256] field, ie to create zero record STANDARD format DB,
use eg, RT_DBaseAlloc(SpliceDB,0,"iiiiiiiiiiiis")
FieldNumber Type Contents
0 Int Start of Scene frame
1 Int End of Scene frame
2 Int Input clip Width (same for all DB).
3 Int Input clip Height (same for all DB).
4 Int Output clip resize Width (same for all DB).
5 Int Output clip resize Height (same for all DB).
6 Int Scene Crop left (X) offset
7 Int Scene Crop left (Y) offset
8 Int Scene Abs Crop Width
9 Int Scene Abs Crop Heigth
10 Int Scene signed crop width (width relative)
11 Int Scene signed crop width (height relative)
12 String Resizer String (256 chars], Same for all DB
You could provide an EXISTING SpliceDB with additional (to STANDARD) fields, where DBSC_DynaCrop() would 1st re-allocate with
zero records (previous contents lost, but will have same number, type and size fields), and then the STANDARD fields are filled
with the dynacrop data, any additional fields will be zeroed, ie Float==0.0, String=="".
You could later fill your addional (to STANDARD) fields in some fashion, with whatever you want via some other function of your
own making. These additional user added fields could be accessed later via a DBSC_DynaSplice() 'Func' user function.
W,H, Output resize dimensions, Defaults to same size as input clip.
Resizer, String, <Default = "Spline64Resize(_W_,_H_)">. Where '_W_' and '_H_' are replaced with output width and height in the function.
CropLimit, Default 16, Default for all below Crop edges limits if not otherwise set below.
CropLimit_Left, Default CropLimit. Maximum allowed border size on Left edge of clip.
CropLimit_Top, Default CropLimit. Maximum allowed border size on Top edge of clip.
CropLimit_Right, Default CropLimit. Maximum allowed border size on Right edge of clip.
CropLimit_Bot, Default CropLimit. Maximum allowed border size on Bottom edge of clip.
RLBT, Default 15($F). bit flags of edges to crop. 1=Top, 2=Bot, 4=Left, 8=Right. (1+2+4+8=15 = all sides)
LeftAdd, Default 0. Amount to add to detected Left edge, and before CropLimit enforced.
TopAdd, Default 0. Amount to add to detected Top edge, and before CropLimit enforced.
RightAdd, Default 0. Amount to add to detected Right edge, and before CropLimit enforced.
BotAdd, Default 0. Amount to add to detected Bottom edge, and before CropLimit enforced.
DissolveSkip, default 5. Number of frames to skip at either end of scene when detecting borders (try to avoid dissolves and wipes
playing havoc with detections). Current scene must be at least 4 * DissolveSkip otherwise DissolveSkip ignored.
LogFn default "DynaCrop.log". User configurable output log file name.
LogTMPT Log Template, Default="V_NNNN_ = Trim(_S_,_E_).Crop(_CX_,_CY_,_-CW_,_-CH_)._RSZ_"+Chr(9)+Chr(9)+"# Crop_W= _CW_ Crop_H= _CH_"
Default produces eg "V0000 = Trim(0,215).Crop(2,4,-14,-6).Spline64Resize(640,400) # Crop_W= 624 Crop_H= 390"
###
Log TEMPLATE Replacements
"_NNNN_" = trim/scene number, 0 relative
"_S_" = Start frame Number, "_E_" = End frame number
"_CX_", "_CY_", "_CW_","_CH_", Crop x,y,w,h, "_-CW_" and "_-CH_" are -ve crop width and height relative
"_IW_", "_IH_" = Input clip width and height.
"_W_", "_H_" = Resize width and height.
"_RSZ_" = The resizer, defaulted or otherwise.
Example:- Usage of DEFAULT output Log to Trim, Crop, Resize, and Splice [instead of DBSC_DynaSplice()].
Function SpliceTrimsString(String VideoString,int maxim,int "Wid",String "Func") {
Func=Default(Func,"")
HasFunc=(Func!="")
Wid=Default(Wid,4)
GSCript("""
S=""
for(i =0,maxim) {
S=(S!="" && HasFunc) ? RT_StrAddStr(S,".",Func) : S
if(S!="") {S=RT_StrAddStr(S,"+")}
S=RT_StrAddStr(S,VideoString+RT_NumberString(i,width=wid)) # RT_StrAddStr, Avoid v2.58 bug
}
""")
return S
}
AviSource("Test.avi")
FUNC="DBSC_Levels(Show=True)" # DEMO user Func for DBSC_DynaSplice
TRIMS=RT_ReadTxtFromFile("DynaCrop.log")
Lines=RT_TxtQueryLines(TRIMS) # Total lines in text file
Eval(TRIMS) # Trim, Crop, Resize
Eval(SpliceTrimsString("V",Lines-1,Func=Func)) # Splice trims
Return last
###
CropThresh is RoboCrop thresh, Default -32 (RoboCrop DEFAULTED AUTOTHRESH). Best leave alone, will auto adapt.
ATM, RoboCrop ATM, Default 16.0. Best leave alone, will auto adapt.
RETURN:- Returns clip that has been trimmed, cropped, resized and spliced, with optional info if SHOW=true.
*/
__________________
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; 12th February 2015 at 14:50. Reason: Updated |
|
|
|
|
|
#11 | Link |
|
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,392
|
Dynamically changing borders detector (PART 2)
Code:
ROBOCROP_DEBUG=False
DBUG=FALSE
c
myName="DBSC_DynaCrop: "
Valid=DBSC_ScanValidate(ScanDB,MustExist=True,name=myName)
Assert(Valid,RT_String("%sInvalid ScanDB\n%s",myName,ScanDB))
Records=RT_DBaseRecords(ScanDB)
Assert(Records==FrameCount,RT_String("%sScanDB Records != FrameCount",myName))
SpliceDB=Default(SpliceDB,"")
c2 = 0
_W_=Default(W,width) _H_=Default(H,height)
Resizer=Default(Resizer,"Spline64Resize(_W_,_H_)") # Resizer to use
TResizer="t."+Resizer
CropThresh=Float(Default(CropThresh,-32.0)) # Absolute Thresh
ATM=Float(Default(ATM,16.0)) # ATM Switched almost OFF
RLBT=Default(RLBT,15)
Assert(RLBT>=1 && RLBT<=15,RT_String("%sRLBT 1->15 Only",myName))
LeftAdd=Default(LeftAdd,0) TopAdd=Default(TopAdd,0) RightAdd=Default(RightAdd,0) BotAdd=Default(BotAdd,0)
CSX=RT_ColorSpaceXMod(c) CSY=RT_ColorSpaceYMod(c,laced=False)
CropLimit=Default(CropLimit,16)
CropLimit_Left = (Default(CropLimit_Left,CropLimit) + CSX/2) / CSX * CSX
CropLimit_Top = (Default(CropLimit_Top,CropLimit) + CSY/2) / CSY * CSY
CropLimit_Right= (Default(CropLimit_Right,CropLimit)+ CSX/2) / CSX * CSX
CropLimit_Bot = (Default(CropLimit_bot,CropLimit) + CSY/2) / CSY * CSY
DissolveSkip=Default(DissolveSkip,5)
Assert(DissolveSkip>=0 && DissolveSkip<=10,RT_String("%sDissolveSkip 0->10 only",myName))
LogFn=Default(LogFn,"DBSC_DynaCrop.log")
LogTMPT=Default(LogTMPT,RT_String("V_NNNN_ = Trim(_S_,_E_).Crop(_CX_,_CY_,_-CW_,_-CH_)._RSZ_\t\t# Crop_W= _CW_ Crop_H= _CH_"))
Show=Default(Show,False) Debug=Default(Debug,false)
(Exist(LogFn)) ? RT_FileDelete(LogFn) : NOP # Delete existing Log
EOL=Chr(10)
FND=RT_String("_RSZ_\n_NNNN_\n_S_\n_E_\n_CX_\n_CY_\n_CW_\n_CH_\n_-CW_\n_-CH_\n_W_\n_H_\n_IW_\n_IH_\n")
TmpLog="~DynaCropTmp_"+RT_LocalTimeString+".log"
(Exist(TmpLog)) ? RT_FileDelete(TmpLog) : NOP # Delete existing TmpLog
GScript("""
if(SpliceDB!="") {
if(Exist(SpliceDB)) {
Fields=RT_DBaseFields(SpliceDB)
Assert(Fields>=13,RT_String("%sInvalid SpliceDB, at least 12 Int fields and 1 String[256] field\n%s",myName,SpliceDB))
for(i=0,11) {
Assert(RT_DBaseFieldType(SpliceDB,i)==1,RT_String("%sSpliceDB field %d is NOT type Int\n%s",myName,i,SpliceDB))
}
Assert(RT_DBaseFieldType(SpliceDB,12)==3,RT_String("%sSpliceDB field 12 is NOT type String\n%s",myName,SpliceDB))
if(RT_DBaseRecords(SpliceDB) != 0) {
TypeString="iiiiiiiiiiiis"
if(Fields>13) {
for(i=13,Fields-1) {
Type=RT_DBaseFieldType(SpliceDB,i)
sz=RT_DBaseFieldSize(SpliceDB,i)
TypeString=TypeString+Select(Type,"b","i","f",RT_String("s%d",sz),"b","f")
}
}
(DEBUG)?RT_DebugF("Re-Alloc zero record SpliceDB, TypeString=%s",TypeString,name=myName):NOP
RT_DBaseAlloc(SpliceDB,0,TypeString)
} else {
(DEBUG)?RT_DebugF("Using existing zero record SpliceDB:- %s",SpliceDB,name=myName):NOP
}
} else {
(DEBUG)?RT_DebugF("Allocating Default format SpliceDB:- %s",SpliceDB,name=myName):NOP
RT_DBaseAlloc(SpliceDB,0,"iiiiiiiiiiiis")
}
}
RoboCrop(SAMPLES=Max(Round(Records/100.0),32),ignore=0.2,laced=False,rlbt=RLBT,LogFn=TmpLog,LogAppend=false,Debug=ROBOCROP_DEBUG)
Wid=Width Hit=Height
ts=RT_ReadTxtFromFile(TmpLog) Outer_x=RT_NumberValue(ts)
ts=MidStr(ts,FindStr(ts," ")+1) Outer_y=RT_NumberValue(ts)
ts=MidStr(ts,FindStr(ts," ")+1) Outer_w=RT_NumberValue(ts)
ts=MidStr(ts,FindStr(ts," ")+1) Outer_h=RT_NumberValue(ts)
Outer_XR=c.Width-Outer_x-Outer_w Outer_YB=c.Height-Outer_y-Outer_h
(DEBUG)?RT_DebugF("Outermost crop Coords = %d,%d,%d,%d (%dx%d)",Outer_x,Outer_y,Outer_XR,Outer_YB,Outer_w,Outer_h,name=myName):NOP
Start=0 End=-1 SceneNo=0 SceneCount=RT_DBaseGetField(ScanDB,Records-1,3)+1
for(n=0,Records-1) {
Start=n End=RT_DBaseGetField(ScanDB,n,1)
if(End-Start+1 >= DissolveSkip*4) {
DStart=Start+DissolveSkip DEnd=End-DissolveSkip
} Else {
DStart=Start DEnd=End
}
IGNORE=2.0 # Allow for significant CGI text
CropC = RoboCrop(thresh=CROPTHRESH,atm=ATM,ignore=IGNORE,laced=False,rlbt=RLBT,start=DStart,end=DEnd,
\ LogFn=TmpLog,LogAppend=false,Debug=ROBOCROP_DEBUG,LeftAdd=LeftAdd,TopAdd=TopAdd,RightAdd=RightAdd,BotAdd=BotAdd)
ts=RT_ReadTxtFromFile(TmpLog) XL=RT_NumberValue(ts)
ts=MidStr(ts,FindStr(ts," ")+1) YT=RT_NumberValue(ts)
ts=MidStr(ts,FindStr(ts," ")+1) CW=RT_NumberValue(ts)
ts=MidStr(ts,FindStr(ts," ")+1) CH=RT_NumberValue(ts)
XR=(Wid-XL-CW) YB=(Hit-YT-CH)
(DBUG)?RT_DebugF("XL=%d YT=%d XR=%d YB=%d",XL,YT,XR,YB,name=myName):NOP
if(XL>CropLimit_Left || YT>CropLimit_Top || XR>CropLimit_Right || YB>CropLimit_Bot) {
RT_DebugF("*** Trim(%d,%d) Scene #%d, %d,%d,%d,%d",Start,End,SceneNo+1,XL,YT,XR,YB,name=myName)
(DEBUG)?RT_DebugF("*** RoboCrop, CROP LIMIT EXCEEDED, Repeating Call with RoboCrop Default AutoThresh & ATM & Ignore=1.0",name=myName):NOP
IGNORE=1.0 # Allow for lil bit CGI text
CropC = RoboCrop(ignore=IGNORE,laced=False,rlbt=RLBT,start=DStart,end=DEnd,
\ LogFn=TmpLog,LogAppend=false,Debug=ROBOCROP_DEBUG,LeftAdd=LeftAdd,TopAdd=TopAdd,RightAdd=RightAdd,BotAdd=BotAdd)
ts=RT_ReadTxtFromFile(TmpLog) TXL=RT_NumberValue(ts)
ts=MidStr(ts,FindStr(ts," ")+1) TYT=RT_NumberValue(ts)
ts=MidStr(ts,FindStr(ts," ")+1) TCW=RT_NumberValue(ts)
ts=MidStr(ts,FindStr(ts," ")+1) TCH=RT_NumberValue(ts)
TXR=(Wid-TXL-TCW) TYB=(Hit-TYT-CH)
(DBUG)?RT_DebugF("TMP: XL=%d YT=%d XR=%d YB=%d",TXL,TYT,TXR,TYB,name=myName):NOP
XL=(XL<=CropLimit_Left) ? XL : (TXL<=CropLimit_Left) ? TXL : Min(XL,TXL)
YT=(YT<=CropLimit_Top) ? YT : (TYT<=CropLimit_Top) ? TYT : Min(YT,TYT)
XR=(XR<=CropLimit_Right)? XR : (TXR<=CropLimit_Right)? TXR : Min(XR,TXR)
YB=(YB<=CropLimit_Bot) ? YB : (TYB<=CropLimit_Bot) ? TYB : Min(YB,TYB)
(DBUG)?RT_DebugF("XL=%d YT=%d XR=%d YB=%d",XL,YT,XR,YB,name=myName):NOP
if(XL>CropLimit_Left || YT>CropLimit_Top || XR>CropLimit_Right || YB>CropLimit_Bot) {
(DEBUG)?RT_DebugF("**** RoboCrop, LIMIT EXCEEDED, Repeating Call with RoboCrop Default AutoThresh & ATM=1.0 & Ingore=0.2",name=myName):NOP
IGNORE=0.2 # No CGI text
CropC = RoboCrop(ignore=IGNORE,laced=False,rlbt=RLBT,start=DStart,end=DEnd,ATM=1.0,
\ LogFn=TmpLog,LogAppend=false,Debug=ROBOCROP_DEBUG,LeftAdd=LeftAdd,TopAdd=TopAdd,RightAdd=RightAdd,BotAdd=BotAdd)
ts=RT_ReadTxtFromFile(TmpLog) TXL=RT_NumberValue(ts)
ts=MidStr(ts,FindStr(ts," ")+1) TYT=RT_NumberValue(ts)
ts=MidStr(ts,FindStr(ts," ")+1) TCW=RT_NumberValue(ts)
ts=MidStr(ts,FindStr(ts," ")+1) TCH=RT_NumberValue(ts)
TXR=(Wid-TXL-TCW) TYB=(Hit-TYT-CH)
(DBUG)?RT_DebugF("TMP: XL=%d YT=%d XR=%d YB=%d",TXL,TYT,TXR,TYB,name=myName):NOP
XL=(XL<=CropLimit_Left) ? XL : (TXL<=CropLimit_Left) ? TXL : CropLimit_Left
YT=(YT<=CropLimit_Top) ? YT : (TYT<=CropLimit_Top) ? TYT : CropLimit_Top
XR=(XR<=CropLimit_Right)? XR : (TXR<=CropLimit_Right)? TXR : CropLimit_Right
YB=(YB<=CropLimit_Bot) ? YB : (TYB<=CropLimit_Bot) ? TYB : CropLimit_Bot
(DBUG)?RT_DebugF("XL=%d YT=%d XR=%d YB=%d",XL,YT,XR,YB,name=myName):NOP
}
}
Curr_w=Wid-XL-XR Curr_h=Hit-YT-YB
(DEBUG)?RT_DebugF("Trim(%d,%d) Scene #%d, %d,%d,%d,%d (W=%d,H=%d)",Start,End,SceneNo+1,XL,YT,-XR,-YB,Curr_w,Curr_h,name=myName):NOP
XX=Outer_x+XL YY=Outer_y+YT WW=Curr_w -(c.Width -Outer_x-XL) HH=Curr_h -(c.Height-Outer_y-YT)
REP =
\ Resizer + EOL +
\ RT_NumberString(SceneNo,width=4) + EOL +
\ RT_NumberString(Start) + EOL +
\ RT_NumberString(End) + EOL +
\ RT_NumberString(XX) + EOL +
\ RT_NumberString(YY) + EOL +
\ RT_NumberString(Curr_w) + EOL +
\ RT_NumberString(Curr_h) + EOL +
\ RT_NumberString(WW) + EOL +
\ RT_NumberString(HH) + EOL +
\ RT_NumberString(_W_) + EOL +
\ RT_NumberString(_H_) + EOL +
\ RT_NumberString(c.Width) + EOL +
\ RT_NumberString(c.Height) + EOL
LOG=RT_StrReplaceMulti(LogTMPT,FND,REP)
RT_WriteFile(LogFn,"%s",LOG,append=True)
if(SpliceDB!="") {
RT_DBaseExtend(SpliceDB) # Add a single record to DBase
RT_DBaseSetField(SpliceDB,SceneNo,0,Start) # Scene start frame
RT_DBaseSetField(SpliceDB,SceneNo,1,End) # Scene End frame
RT_DBaseSetField(SpliceDB,SceneNo,2,c.Width) # Input clip width (same for all DB).
RT_DBaseSetField(SpliceDB,SceneNo,3,c.Height) # Input clip Height (same for all DB).
RT_DBaseSetField(SpliceDB,SceneNo,4,_W_) # Output clip resize width (same for all DB).
RT_DBaseSetField(SpliceDB,SceneNo,5,_H_) # Output clip resize height (same for all DB).
RT_DBaseSetField(SpliceDB,SceneNo,6,XX) # Scene Crop left offset
RT_DBaseSetField(SpliceDB,SceneNo,7,YY) # Scene Crop top offset
RT_DBaseSetField(SpliceDB,SceneNo,8,Curr_w) # Scene Abs Crop width
RT_DBaseSetField(SpliceDB,SceneNo,9,Curr_h) # Scene Abs Crop height
RT_DBaseSetField(SpliceDB,SceneNo,10,WW) # Scene signed crop width (width relative)
RT_DBaseSetField(SpliceDB,SceneNo,11,HH) # Scene signed crop Height (height relative)
RT_DBaseSetField(SpliceDB,SceneNo,12,Resizer) # Resizer String, Same for all DB
}
t=c.Trim(Start,End).Crop(XX,YY,WW,HH)
t=Eval(TResizer) # Resize using optional resizer
t = (Show) ? t.RT_Subtitle("#%d/%d S=%d E=%d L=%d\nCrop(\aQ%d+\a-%d,\aQ%d+\a-%d,\aQ-%d\a--%d,\aQ-%d\a--%d) : %dx%d",
\ SceneNo+1,SceneCount,Start,End,End-Start+1,Outer_x,XL,Outer_y,YT,Outer_XR,XR,Outer_YB,YB,Curr_w,Curr_h,align=5) : t
c2 = (c2.IsClip()) ? c2++t : t # Splice
SceneNo=SceneNo+1
n = End # Next iteration n = End + 1, ie Start of Next Scene
}
RT_DBaseSetID(SpliceDB,0,DBSC_Str2ID("DYNS"))
(Exist(TmpLog)) ? RT_FileDelete(TmpLog) : NOP # Delete temp Log
""")
return c2
}
__________________
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 February 2015 at 08:04. Reason: Update |
|
|
|
|
|
#12 | Link |
|
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,392
|
Dynamic Changing Borders Splicer
Code:
Function DBSC_DynaSplice(clip c,String SpliceDB,String "Func",Bool "DEBUG") {
/*
DBSC_DynaSplice(), Function to trim, crop, resize and splice trims in SpliceDB DBase [as created via DBSC_DynaCrop()].
Optionally can call user function 'Func' on each cropped and resized trim, prior to splicing.
The Func arg must (if used) supply all required args (excluding initial clip) and parenthesis to call the required user function.
Eg, Func="MyFunc(Show=True)", where will be called with explicit OOP style clip as 1st arg (ie DONT INCLUDE clip as first arg in
Func string), called as in ClipName.MyFunc(Show=True) from within DBSC_DynaSplice().
See below DBSC_Levels() for example usage.
After viewing output of this function, might like to create OVERRIDE.TXT file and use DBSC_Override() to insert additional
scene changes into ScanDB (it is easlier to find problem areas with remaining borders once this has been processed, also easier to
spot blended scene transitions and force a scene change there).
*/
c
myName="DBSC_DynaSplice: "
Func=Default(Func,"")
DEBUG=Default(DEBUG,TRUE)
Assert(SpliceDB!="",RT_String("%sNeed SpliceDB name",myName))
Assert(Exist(SpliceDB),RT_String("%sSpliceDB Does not exist\n%s",myName,SpliceDB))
Assert(RT_DBaseGetID(SpliceDB,0)==DBSC_Str2ID("DYNS"),RT_String("%sNot a SpliceDB\n%s",myName,SpliceDB))
Records=RT_DBaseRecords(SpliceDB) Fields=RT_DBaseFields(SpliceDB)
Assert(Records>0,RT_String("%sInvalid SpliceDB, Zero records\n%s",myName,SpliceDB))
Assert(Fields>=13,RT_String("%sInvalid SpliceDB, at least 12 Int fields and 1 String[256] field\n%s",myName,SpliceDB))
oc=0
GScript("""
for(i=0,11) {Assert(RT_DBaseFieldType(SpliceDB,i)==1,RT_String("%sSpliceDB field %d is NOT type Int\n%s",myName,i,SpliceDB))}
Assert(RT_DBaseFieldType(SpliceDB,12)==3,RT_String("%sSpliceDB field 12 is NOT type String\n%s",myName,SpliceDB))
Resizer=RT_DBaseGetField(SpliceDB,0,12) # Resizer String, "_W_" and "_H_" are width and Height
OutW=RT_DBaseGetField(SpliceDB,0,4)
OutH=RT_DBaseGetField(SpliceDB,0,5)
FND_S=RT_String("_W_\n_H_\n")
REP_S=RT_String("%d\n%d\n",OutW,OutH)
Resizer="c.trim(Start,End).Crop(XX,YY,WW,HH)."+RT_StrReplaceMulti(Resizer,FND_S,REP_S)
HasFunc=(Func!="")
Func=(HasFunc)?"tmpc."+Func:Func
for(SceneNo=0,Records-1) {
Start = RT_DBaseGetField(SpliceDB,SceneNo,0)
End = RT_DBaseGetField(SpliceDB,SceneNo,1)
Length = End-Start+1
XX = RT_DBaseGetField(SpliceDB,SceneNo,6)
YY = RT_DBaseGetField(SpliceDB,SceneNo,7)
WW = RT_DBaseGetField(SpliceDB,SceneNo,8)
HH = RT_DBaseGetField(SpliceDB,SceneNo,9)
(DEBUG)?RT_DebugF("#%d Start=%d End=%d Length=%d Crop(%d,%d,%d,%d)",SceneNo,Start,End,Length,XX,YY,WW,HH,name=myName):NOP
tmpc=Eval(Resizer)
tmpc=(HasFunc)?Eval(Func):tmpc
oc = (oc.IsClip()) ? oc++tmpc : tmpc # Splice
}
""")
Return oc
}
__________________
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 February 2015 at 08:05. |
|
|
|
|
|
#13 | Link |
|
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,392
|
DEMO User function
Code:
Function DBSC_Levels(clip c,Float "Strength",Float "Gamma",Float "MinRngPerc",int "MinLen",Bool "Show",String "SpliceDB",Int "SceneNo") {
/*
DBSC_Levels(), Function to DEMO calling of user function on each trim of Dynamic border cropped clip.
This function can be called via DBSC_DynaSplice(func=FUNC) where FUNC argument string is eg
Func="DBSC_Levels(Strength=0.5,Show=True,SpliceDB=SpliceDB,SceneNo=SceneNo)".
Where, SpliceDB is a DBase as created via DBSC_DynaCrop and SceneNo is record number in that DBase.
Where using SpliceDB and SceneNo args then MUST be supplied exactly as "SpliceDB=SpliceDB,SceneNo=SceneNo" in the Func string.
NOTE, the user function MUST have an initial clip argument, in this case clip c as above. Any other args would best be optional.
NOTE, DBSC_DynaSplice() User functions MUST return clip of same attributes as supplied (size colorspace etc).
See DBSC_DynaCrop() and DBSC_DynaSplice().
*/
c
myName="DBSC_Levels: "
Strength=Max(Min(Float(Default(Strength,0.5)),1.0),0.0)
Gamma=Float(Default(Gamma,1.0))
MinRngPerc=Max(Min(Float(Default(MinRngPerc,33.3)),100.0),0.0)
MinLen=Default(MinLen,25) # If less than MinLen frames, then ignore
Show=Default(Show,False)
SpliceDB=Default(SpliceDB,"")
SceneNo=Default(SceneNo,-1)
DBUG=FALSE # Set TRUE to Demo DBase and SceneNo Usage
GScript("""
Valid = (SpliceDB!="" && SceneNo!= -1) # Basic Validity test
if(DBUG && Show && Valid) {
Assert(RT_DBaseGetID(SpliceDB,0)==DBSC_Str2ID("DYNS"),RT_String("%sNot a SpliceDB\n%s",myName,SpliceDB))
Start = RT_DBaseGetField(SpliceDB,SceneNo,0) # SpliceDB Start Of Scene frame (0 relative)
End = RT_DBaseGetField(SpliceDB,SceneNo,1) # SpliceDB End Of Scene frame (0 relative)
Length = End-Start+1
RT_DebugF("#%d Start=%d End=%d Len=%d",SceneNo+1,Start,End,Length,name=myName) # Show SceneNo as 1 relative
}
if(MinLen<=Framecount && STRENGTH>0.0) { # Auto Luma Levelling
Eval(RT_QueryLumaMinMax(X=8,Y=8,W=-8,H=-8)) # Ignore possible remaining borders
if(IsRGB()) { CSMin = 0 CSMax = 255 }
else { CSMin = 16 CSMax = 235 }
QLRng=QLMMMax-QLMMMin+1
CSRng=CSMax-CSMin+1
CSRngMin=CSRng*MinRngPerc/100.0
if(QLRng >= CSRngMin) { # Ignore if < MinRngPerc of CS range
ALMin = Int(CSMin - ((CSMin - QLMMMin) * STRENGTH) + 0.5) # Round Up
ALMax = Int(CSMax - ((CSMax - QLMMMax) * STRENGTH)) # Round down
if(ALMin!=CSMin || ALMax != CSMax) {
(Show)?RT_DebugF("Levels(%3d,%.2f,%3d,%d,%d,Coring=False)",ALMin,Gamma,ALMax,CSMin,CSMax,name=myName):NOP
Levels(ALMin,Gamma,ALMax,CSMin,CSMax,Coring=False)
(Show) ?RT_Subtitle("%sLevels(%3d,%.2f,%3d,%d,%d,Coring=False)",myName,ALMin,Gamma,ALMax,CSMin,CSMax) :NOP
}
} Else if(Show){
RT_DebugF("Skip %3d,%3d Range=%d %.2f%%",QLMMMin,QLMMMax,QLRng,QLRng*100.0/CSRng,name=myName)
RT_Subtitle("%sSkip %3d,%3d Range=%d %.2f%%",myName,QLMMMin,QLMMMax,QLRng,QLRng*100.0/CSRng)
}
}
""")
Return Last
}
__________________
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; 12th February 2015 at 14:58. Reason: Update |
|
|
|
|
|
#14 | Link |
|
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,392
|
Scan Client Script
Code:
# Start DebugView before script to view output
Import("DBSC.avs")
VideoFileName = "AP10_Out.avi"
Start_Fn = "Start_Frames.Txt"
End_Fn = "End_Frames.Txt"
Range_Fn = "Range_Frames.Txt"
Mid_Fn = "Mid_Frames.Txt"
ClipClop_Fn = "ClipClop_Frames.Txt"
InfoDB = VideoFileName+"_Info.DB" # INFO DBase
ScanDB = VideoFileName+"_Scan.DB" # SCAN DBase
Avisource(VideoFileName)
RECYCLE_INFO_DB= True
RECYCLE_SCAN_DB= True
OVERRIDE = "Override.txt" # Override as Filename
DBSC_CreateInfo(InfoDB,RecycleDB=RECYCLE_INFO_DB) # Create INFO DB (REQUIRED), for fast scanning
DBSC_Scan(InfoDB,ScanDB,RecycleDB=RECYCLE_SCAN_DB) # Detect Scene Changes and store in ScanDB
#DBSC_Override(ScanDB,OVERRIDE)
#DBSC_WriteFiles(ScanDB,Start_Fn,End_Fn,Range_fn,Mid_Fn,ClipClop_Fn,VideoFilename=VideoFileName,comment=True)
#Return Last
Return DBSC_SubsClip(InfoDB,ScanDB,Subs=True,Metrics=true,Metrics2=true) # View detections
#Return DBSC_StackSceneChanges(Last,InfoDB,ScanDB) # Check detections START/END of scene STACKED.
# Or Drop through to below to demo DBSC_Select()
#BilinearResize(Width*2,Height*2) # DBSC_Select clips need only be same number of frames as ScanDB detection clip.
SIZE = Round(Height/8.0)
MOTIONCLIP = SubTitle("MOTION",Align=5,size=SIZE,text_color=$80FFC0)
STARTCLIP = SubTitle("START OF SCENE",Align=5,size=SIZE,y=(Height+SIZE)/2,text_color=$C080FF)
ENDCLIP = SubTitle("END OF SCENE" ,Align=5,size=SIZE,y=(Height-SIZE)/2,text_color=$FF80C0)
SINGLECLIP = SubTitle("START OF SCENE\nEND OF SCENE",Align=5,size=SIZE,y=(Height-SIZE)/2,text_color=$C0FF80,lsp=0)
Return DBSC_Select(MOTIONCLIP,ScanDB,STARTCLIP,ENDCLIP,SINGLECLIP)
__________________
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 February 2015 at 08:39. |
|
|
|
|
|
#15 | Link |
|
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,392
|
Dynamic Changing Borders Client script
Code:
Import("DBSC.avs")
VideoFileName = "AP10_Out.avi"
InfoDB = VideoFileName+"_Info.DB" # INFO DBase
ScanDB = VideoFileName+"_Scan.DB" # SCAN DBase
LogFn = VideoFileName+"_User.Log"
SpliceDB = VideoFileName+"_Splice.DB"
RECYCLE_INFO_DB= True
RECYCLE_SCAN_DB= True
OVERRIDE = "Override.txt" # Override as Filename
Avisource(VideoFileName)
DBSC_CreateInfo(InfoDB,RecycleDB=RECYCLE_INFO_DB) # Create INFO DB (REQUIRED), for fast scanning
DBSC_Scan(InfoDB,ScanDB,RecycleDB=RECYCLE_SCAN_DB) # Detect Scene Changes and store in ScanDB
#DBSC_Override(ScanDB,OVERRIDE)
RLBT=$C # Left and Right only
# Return one of two below funcs, DBSC_DynaCrop MUST have been called (at some time) before DBSC_DynaSplice
Return DBSC_DynaCrop(ScanDB,SpliceDB=SpliceDB,rlbt=RLBT,LeftAdd=0,RightAdd=0,TopAdd=1,BotAdd=1,LogFn=LogFn,Show=True,Debug=True)
######################
######################
######################
# This one is best done is separate script when DBSC_DynaCrop() has already created Splice DBase, OR call DBSC_DynaCrop first
# and then comment out DBSC_DynaCrop line.
#FUNC="DBSC_Levels(Show=True,SpliceDB=SpliceDB,SceneNo=SceneNo)" # DEMO user Func for DBSC_DynaSplice
#FUNC="DBSC_Levels(Show=False)"
FUNC=RT_Undefined # Dont call user Func
#Return DBSC_DynaSplice(SpliceDB,Func)
######################
######################
######################
# Or Even below if comment out both DBSC_DynaCrop and DBSC_DynaSplice, but with no user Func.
TRIMS=RT_ReadTxtFromFile(LogFn)
Lines=RT_TxtQueryLines(TRIMS) # Total lines in text file (Or RT_FileQueryLines)
Eval(TRIMS) # Eval trims,crop,resize
Eval(SpliceTrimsString("V",Lines-1,Func=Func)) # Splice trims
Return last
Function SpliceTrimsString(String VideoString,int maxim,int "Wid",String "Func") {
Func=Default(Func,"")
HasFunc=(Func!="")
Wid=Default(Wid,4)
GSCript("""
S=""
for(i =0,maxim) {
S=(S!="" && HasFunc) ? RT_StrAddStr(S,".",Func) : S
if(S!="") {S=RT_StrAddStr(S,"+")}
S=RT_StrAddStr(S,VideoString+RT_NumberString(i,width=wid)) # RT_StrAddStr, Avoid v2.58 bug
}
""")
return S
}
__________________
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; 12th February 2015 at 14:51. |
|
|
|
|
|
#16 | Link |
|
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,392
|
DBSC Update to v0.04, zip in 1st post.
__________________
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 February 2015 at 10:49. |
|
|
|
|
|
#17 | Link |
|
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,392
|
Post #10 updated (FIXED): Oops, Managed to insert an old pre-DEMO version of script [EDIT: Added Func related stuff].
Example:- Usage of DEFAULT output Log to Trim, Crop, Resize, and Splice [instead of DBSC_DynaSplice()]. Code:
Function SpliceTrimsString(String VideoString,int maxim,int "Wid",String "Func") {
Func=Default(Func,"")
HasFunc=(Func!="")
Wid=Default(Wid,4)
GSCript("""
S=""
for(i =0,maxim) {
S=(S!="" && HasFunc) ? RT_StrAddStr(S,".",Func) : S
if(S!="") {S=RT_StrAddStr(S,"+")}
S=RT_StrAddStr(S,VideoString+RT_NumberString(i,width=wid)) # RT_StrAddStr, Avoid v2.58 bug
}
""")
return S
}
AviSource("Test.avi")
FUNC="DBSC_Levels(Show=True)" # DEMO user Func for DBSC_DynaSplice
TRIMS=RT_ReadTxtFromFile("DynaCrop.log")
Lines=RT_TxtQueryLines(TRIMS) # Total lines in text file
Eval(TRIMS) # Trim, Crop, Resize
Eval(SpliceTrimsString("V",Lines-1,Func=Func)) # Splice trims
Return last
Code:
TRIMS=RT_ReadTxtFromFile(LogFn)
Lines=RT_TxtQueryLines(TRIMS) # Total lines in text file (Or RT_FileQueryLines)
Eval(TRIMS) # Eval trims,crop,resize
Eval(SpliceTrimsString("V",Lines-1,Func=Func)) # Splice trims
Return last
Function SpliceTrimsString(String VideoString,int maxim,int "Wid",String "Func") {
Func=Default(Func,"")
HasFunc=(Func!="")
Wid=Default(Wid,4)
GSCript("""
S=""
for(i =0,maxim) {
S=(S!="" && HasFunc) ? RT_StrAddStr(S,".",Func) : S
if(S!="") {S=RT_StrAddStr(S,"+")}
S=RT_StrAddStr(S,VideoString+RT_NumberString(i,width=wid)) # RT_StrAddStr, Avoid v2.58 bug
}
""")
return S
}
Code:
Function DBSC_Levels(clip c,Float "Strength",Float "Gamma",Float "MinRngPerc",int "MinLen",Bool "Show",String "SpliceDB",Int "SceneNo") {
/*
DBSC_Levels(), Function to DEMO calling of user function on each trim of Dynamic border cropped clip.
This function can be called via DBSC_DynaSplice(func=FUNC) where FUNC argument string is eg
Func="DBSC_Levels(Strength=0.5,Show=True,SpliceDB=SpliceDB,SceneNo=SceneNo)".
Where, SpliceDB is a DBase as created via DBSC_DynaCrop and SceneNo is record number in that DBase.
Where using SpliceDB and SceneNo args then MUST be supplied exactly as "SpliceDB=SpliceDB,SceneNo=SceneNo" in the Func string.
NOTE, the user function MUST have an initial clip argument, in this case clip c as above. Any other args would best be optional.
NOTE, DBSC_DynaSplice() User functions MUST return clip of same attributes as supplied (size colorspace etc).
See DBSC_DynaCrop() and DBSC_DynaSplice().
*/
c
myName="DBSC_Levels: "
Strength=Max(Min(Float(Default(Strength,0.5)),1.0),0.0)
Gamma=Float(Default(Gamma,1.0))
MinRngPerc=Max(Min(Float(Default(MinRngPerc,33.3)),100.0),0.0)
MinLen=Default(MinLen,25) # If less than MinLen frames, then ignore
Show=Default(Show,False)
SpliceDB=Default(SpliceDB,"")
SceneNo=Default(SceneNo,-1)
DBUG=FALSE # Set TRUE to Demo DBase and SceneNo Usage
GScript("""
Valid = (SpliceDB!="" && SceneNo!= -1) # Basic Validity test
if(DBUG && Show && Valid) {
Assert(RT_DBaseGetID(SpliceDB,0)==DBSC_Str2ID("DYNS"),RT_String("%sNot a SpliceDB\n%s",myName,SpliceDB))
Start = RT_DBaseGetField(SpliceDB,SceneNo,0) # SpliceDB Start Of Scene frame (0 relative)
End = RT_DBaseGetField(SpliceDB,SceneNo,1) # SpliceDB End Of Scene frame (0 relative)
Length = End-Start+1
RT_DebugF("#%d Start=%d End=%d Len=%d",SceneNo+1,Start,End,Length,name=myName) # Show SceneNo as 1 relative
}
if(MinLen<=Framecount && STRENGTH>0.0) { # Auto Luma Levelling
Eval(RT_QueryLumaMinMax(X=8,Y=8,W=-8,H=-8)) # Ignore possible remaining borders
if(IsRGB()) { CSMin = 0 CSMax = 255 }
else { CSMin = 16 CSMax = 235 }
QLRng=QLMMMax-QLMMMin+1
CSRng=CSMax-CSMin+1
CSRngMin=CSRng*MinRngPerc/100.0
if(QLRng >= CSRngMin) { # Ignore if < MinRngPerc of CS range
ALMin = Int(CSMin - ((CSMin - QLMMMin) * STRENGTH) + 0.5) # Round Up
ALMax = Int(CSMax - ((CSMax - QLMMMax) * STRENGTH)) # Round down
if(ALMin!=CSMin || ALMax != CSMax) {
(Show)?RT_DebugF("Levels(%3d,%.2f,%3d,%d,%d,Coring=False)",ALMin,Gamma,ALMax,CSMin,CSMax,name=myName):NOP
Levels(ALMin,Gamma,ALMax,CSMin,CSMax,Coring=False)
(Show) ?RT_Subtitle("%sLevels(%3d,%.2f,%3d,%d,%d,Coring=False)",myName,ALMin,Gamma,ALMax,CSMin,CSMax) :NOP
}
} Else if(Show){
RT_DebugF("Skip %3d,%3d Range=%d %.2f%%",QLMMMin,QLMMMax,QLRng,QLRng*100.0/CSRng,name=myName)
RT_Subtitle("%sSkip %3d,%3d Range=%d %.2f%%",myName,QLMMMin,QLMMMax,QLRng,QLRng*100.0/CSRng)
}
}
""")
Return Last
}
__________________
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; 12th February 2015 at 18:35. |
|
|
|
|
|
#18 | Link |
|
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,392
|
v0.051, see first post for zip.
Added a DBSC_DynaSplice User function to the DBSC.avs script, DBSC_ProcessByDAR. Code:
Function DBSC_ProcessByDAR(clip c,String "SpliceDB",Int "SceneNo",Float "FDAR",
\ Float "AR1",Float "AR2",Float "AR3",Float "AR4",Float "AR5",Float "AR6",Float "AR7",Float "AR8",
\ String "FN",Bool "Show") {
/*
DBSC_DynaSplice() User function (called by DBSC_DynaSplice on each scene).
Creates ClipClop command text file based on letterbox cropped Display Aspect Ratio of each scene, enables selective
processing based on a scenes Display Aspect Ratio where DAR changes within a clip.
FDAR = Full Frame Display Aspect Ratio of Source clip (incl letterboxing).
ARx Display Aspect Ratio of image area only (Excluding letterboxing)
Always chooses one of the given ARx clip index numbers (ie never uses source clip ie clipclop clip 0
unless all ARx Aspect ratios supplied as 0.0.)
You can switch off ARx by setting to zero, however, you need to supply ClipClop Replacement clips up
to the maximum ARx number that may be non zero. Suggest always supply Source + 8 replacment clips to clipclop,
and just use dummy clip where unused (ARx==0.0).
Set Eg
FUNC="DBSC_ProcessByDar(SpliceDB=SpliceDB,SceneNo=SceneNo,FDAR=4.0/3.0,Show=True)"
And use in Dynacrop client script eg
Return DBSC_DynaSplice(SpliceDB,func=FUNC)
Use avs script eg (where ARx are processed clips for chosen AR)
ClipClop(SourceClip,AR1,AR2,AR3,AR4,AR5,AR6,AR7,AR8,cmd="ClipClopCmd.txt",Show=True)
*/
myName="DBSC_ProcessByDar: "
c
Assert(Defined(SpliceDB),RT_String("%sSpliceDB Not Supplied",myName))
Assert(Defined(SceneNo),RT_String("%sSceneNo Not Supplied",myName))
FDAR = Float(Default(FDAR,16.0/9.0))
###
AR1 = Float(Default(AR1,2.40)) # If nearest to this, then use ClipClop clip 1
AR2 = Float(Default(AR2,2.35))
AR3 = Float(Default(AR3,1.85))
AR4 = Float(Default(AR4,16.0/9.0))
AR5 = Float(Default(AR5,1.66))
AR6 = Float(Default(AR6,16.0/10.0))
AR7 = Float(Default(AR7,1.5))
AR8 = Float(Default(AR8,4.0/3.0)) # If nearest to this, then use ClipClop clip 8
###
FN=Default(FN,"ClipClopCmd.txt")
Show=Default(Show,False)
GScript("""
Valid = (SpliceDB!="" && SceneNo>= 0) # Basic Validity test, DO NOTHING if bad
if(Valid) {
(SceneNo==0) ? RT_FileDelete(FN) : NOP
Start = RT_DBaseGetField(SpliceDB,SceneNo,0) # SpliceDB Start Of Scene frame (0 relative)
End = RT_DBaseGetField(SpliceDB,SceneNo,1) # SpliceDB End Of Scene frame (0 relative)
Length = End-Start+1
IWID = RT_DBaseGetField(SpliceDB,SceneNo,2) # Source Clip Width
IHIT = RT_DBaseGetField(SpliceDB,SceneNo,3) # Source Clip Height
XX = RT_DBaseGetField(SpliceDB,SceneNo,6) # Left Crop
YY = RT_DBaseGetField(SpliceDB,SceneNo,7) # Top Crop
WW = RT_DBaseGetField(SpliceDB,SceneNo,8) # Width
HH = RT_DBaseGetField(SpliceDB,SceneNo,9) # Height
SAR = (FDAR * IHIT)/ IWID # Sample (pixel) Aspect ratio from source clip
AR = (SAR * WW) / HH # Display Aspect Ratio of cropped scene
AR0 = 99.9 BestAR = AR0 BestARix = 0 BestARdif=AR0 # If ALL ARx 0.0, Cause ClipCLop to choose source clip 0.
TmpDif = Abs(AR-AR1) If(AR1>0.0 && TmpDif<BestARdif) {BestAR = AR1 BestARix = 1 BestARdif=TmpDif}
TmpDif = Abs(AR-AR2) If(AR2>0.0 && TmpDif<BestARdif) {BestAR = AR2 BestARix = 2 BestARdif=TmpDif}
TmpDif = Abs(AR-AR3) If(AR3>0.0 && TmpDif<BestARdif) {BestAR = AR3 BestARix = 3 BestARdif=TmpDif}
TmpDif = Abs(AR-AR4) If(AR4>0.0 && TmpDif<BestARdif) {BestAR = AR4 BestARix = 4 BestARdif=TmpDif}
TmpDif = Abs(AR-AR5) If(AR5>0.0 && TmpDif<BestARdif) {BestAR = AR5 BestARix = 5 BestARdif=TmpDif}
TmpDif = Abs(AR-AR6) If(AR6>0.0 && TmpDif<BestARdif) {BestAR = AR6 BestARix = 6 BestARdif=TmpDif}
TmpDif = Abs(AR-AR7) If(AR7>0.0 && TmpDif<BestARdif) {BestAR = AR7 BestARix = 7 BestARdif=TmpDif}
TmpDif = Abs(AR-AR8) If(AR8>0.0 && TmpDif<BestARdif) {BestAR = AR8 BestARix = 8 BestARdif=TmpDif}
RT_WriteFile(FN,"%d %d,%d # SceneNo=%d Crop(%d,%d,%d,%d) CropAR=%.2f BestAR=%.2f",
\ BestARix,Start,End,SceneNo+1,XX,YY,WW,HH,AR,BestAR,Append=True)
RT_DebugF("#%d Start=%d End=%d Len=%d CropAR=%.2f BestAR=%.2f Clip=AR%d",
\ SceneNo+1,Start,End,Length,AR,BestAR,BestARix,
\ name=myName)
if(Show) {
RT_Subtitle("#%d Start=%d End=%d Len=%d CropAR=%.2f BestAR=%.2f Clip=AR%d",
\ SceneNo+1,Start,End,Length,AR,BestAR,BestARix)
}
}
""")
Return Last # Return Clip Unchanged # EDIT: Unless Show=True
}
Previous posts not updated. EDIT: Function above added due to this post: http://forum.doom9.org/showthread.php?t=171777 EDIT: Produces ClipClop command file, eg Code:
5 0,254 # SceneNo=1 Crop(18,2,692,572) CropAR=1.29 BestAR=1.33 5 255,332 # SceneNo=2 Crop(16,2,694,572) CropAR=1.29 BestAR=1.33 5 333,347 # SceneNo=3 Crop(20,2,688,572) CropAR=1.28 BestAR=1.33 5 348,355 # SceneNo=4 Crop(10,2,698,572) CropAR=1.30 BestAR=1.33 5 356,390 # SceneNo=5 Crop(10,2,698,572) CropAR=1.30 BestAR=1.33 5 391,455 # SceneNo=6 Crop(12,2,690,572) CropAR=1.29 BestAR=1.33 5 456,468 # SceneNo=7 Crop(10,2,700,572) CropAR=1.31 BestAR=1.33 5 469,476 # SceneNo=8 Crop(8,2,702,572) CropAR=1.31 BestAR=1.33 5 477,488 # SceneNo=9 Crop(12,2,698,572) CropAR=1.30 BestAR=1.33 5 489,548 # SceneNo=10 Crop(10,2,700,572) CropAR=1.31 BestAR=1.33 5 549,569 # SceneNo=11 Crop(10,2,700,572) CropAR=1.31 BestAR=1.33 EDIT: In above changed script, would have always returned clip 8. EDIT: Purpose, to create a ClipClop command file that selects clip based on scene Display Aspect Ratio of the image only area (ie without letter boxing).
__________________
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; 17th February 2015 at 04:27. |
|
|
|
|
|
#19 | Link |
|
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,392
|
Updated previous post, and zip updated to v0.051 in 1st post.
Changed slightly, and had a name change to DBSC_ProcessByDAR() [So much nicer than DBSC_Lyris() ]
__________________
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 ??? |
|
|
|
|
|
#20 | Link |
|
Registered User
Join Date: Feb 2002
Location: California
Posts: 2,783
|
I have a huge analog video transfer project (dozens of hours of home video) and I want to cut it into scenes. So, I finally have a reason to put this wonderful technology through the ringer.
My video is interlaced NTSC DV video, captured via Firewire. Scene detection works well most of the time, but I am having some failures that don't make sense. At the moment, I am using the default, using your "demo" script to drive the process. Here is a two-second clip where the scene detection fails: Scene Detect Fail.avi As you can see, the scene change actually happens in the middle of a frame, where one field in the frame is from the previous frame, and the other field is from the next frame. If I bob the video, the scene is detected correctly. Before I start playing around with all the detection parameters, I thought I'd ask whether I need to change something when dealing with interlaced video. I searched this thread and also the documentation for "interlaced," but didn't find anything. Of course I can just simply bob the video and then divide the frame detect numbers by 2, but I thought I'd ask first. |
|
|
|
![]() |
| Tags |
| scene change detection |
| Thread Tools | |
| Display Modes | |
|
|