View Single Post
Old 4th November 2016, 03:30   #19  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Small mod for use with RT_Stats v2.0 Beta 3
RT_QwikScan changed to using Arrays instead of DBase's, RT_QwickScanCreate args PrevDB, NextDB changed to Prev and Next only.

Code:
# SpatialAlign.avs

Function SpatialAlign(clip Fix,clip Src,Int "MatchLen",Int "Rad",Float "LdTh",String "Prefix") {
/*
    SpatialAlign v1.01: By StainlessS.     http://forum.doom9.org/showthread.php?p=1722142#post1722142
    Fix spatial alignment between two clips containing similar scenes (dont have to be temporally aligned).
      Could take a Long time for long clips where they contain no common sequences.
      Spatial mis-alignment should not be too great or may not find temporal (and therefore spatial) alignment.

    Requires:- GScript, RT_stats v2.0 BETA 3, RoboCrop'ed before calling. DebugView for viewing debug info.
               Frame Accurate Progressive sources of same Size, FrameRate, Colorspace.

    Fix, clip to align with Src.
    Src, clip that Fix clip will be spatially aligned to.
    MatchLen, Default 50 frames. Number of frames that have to match when finding temporal alignment.
    Rad, Default 4 (1 -> 6). Maxiumum number of pixels (H and V) that fix clip may be shifted by.
    LdTh, Default 3.0 * Rad (ie 12.0 when Rad=Default 4), LumaDifference has to be less than or equal to this to detect temporal alignment.
    Prefix, Default "SA_Crop_". Default sets Global Variables with "SA_Crop_" Prefix.
        Sets variables "L", "T", "R" and "B", prefixed by the Prefix string, eg 'SA_Crop_L'.
     Can be used to crop off gunk remaining around clip edges after fixing a shifted clip.
     Prefix, allows you to change the prefix to the names of the variables.
       eg if Prefix == "My_Crop_", then set Global variables 'My_Crop_L' as Global Int.
*/
    myName      = "SpatialAlign: "
    MatchLen    = Default(MatchLen,50)
    Rad         = Default(Rad,4)
    AutoLDTh    = !Defined(LdTh)
    LdTh        = Float(Default(LdTh,3.0*Rad))
    Prefix      = Default(Prefix,"SA_Crop_")
    Assert(Src.Width==Fix.Width,RT_String("%sClip Width mismatch",myName))
    Assert(Src.Height==Src.Height,RT_String("%sClip Height mismatch",myName))
    Assert(RT_VarIsSame(Src,Fix,sig=false),RT_String("%sClip ColorSpace mismatch",myName))
    Assert(MatchLen>0,RT_String("%sInvalid MatchLen, Must be greater than 0(%d)",myName,MatchLen))
    Assert(Rad>=1 && Rad<=6,RT_String("%sInvalid Rad, 1 -> 6(%d)",myName,Rad))
    SrcMax = Src.FrameCount - MatchLen
    FixMax = Fix.FrameCount - MatchLen
    Assert(SrcMax>=0,RT_String("%sInvalid MatchLen, Src too short",myName))
    Assert(FixMax>=0,RT_String("%sInvalid MatchLen, Fix too short",myName))
    GScript("""
        FixMatchFrame  = -1  SrcMatchFrame  = -1    # Match frames not yet found
        # Test already temporally aligned
        mnlen  = Min(FixMax,SrcMAx) + 1
        nTests = Min(mnlen,10)
        tstMul = (nTests<=1) ? 0.0 : (mnlen-1) / (nTests-1.0)
        WorstOfAllDf = -1.0
        For(Test = 1, nTests) {
            tStart = int((Test - 1) * tstMul + 0.5)
            if(RT_YPlaneMinMaxDifference(Fix,n=tStart,x=rad,y=rad,w=-rad,h=-rad,Threshold=1.0) >= 32) {   # Reliable frame ?
                worstDf= -1.0
                for(j = 0, Matchlen-1) {
                    df = RT_LumaDifference(Fix,Src,n=tStart+j,n2=tStart+j,x=rad,y=rad,w=-rad,h=-rad)
                    worstDf = (df>worstDf) ? df : worstDf
                    if(df > LdTh) {
                        j = Matchlen + 1                    # Break, MatchLen, not found
                    }
                }
                if(j==MatchLen) {
                    RT_DebugF("Already temporally aligned @ frame %d (Worst LumaDif of %d frames =%.3f)",tStart,Matchlen,worstDf,name=myName)
                    FixMatchFrame  = tStart  SrcMatchFrame  = tStart
                    Test = nTests                           # Break Test
                }
                WorstOfAllDf = (worstDf>WorstOfAllDf) ? worstDf : WorstOfAllDf
            }
        }
        if(FixMatchFrame<0) {
            RT_DebugF("Not already temporally aligned (Worst LumaDif of all tested frames=%.3f)",WorstOfAllDf,name=myName)
            RT_DebugF("Searching for temporal alignment",name=myName)
            Tim = RT_LocalTimeString(File=True)
            QDB = RT_String("~QDB_%s.DB",Tim)  NDB = RT_String("~NDB_%s.DB",Tim)
            RT_QwikScanCreate(Src,QDB,prev="",next=NDB,debug=True)
            LumaTolStart = 5    LumaTolStep = 3 LumaTolEnd=17  ScanPerc = 0.5 / 2.0
            for(LT = LumaTolStart,17,LumaTolStep) {
                ScanPerc = ScanPerc * 2.0
                LumaTol = Float(min(LT,16))
                Testlen = FixMax + 1
                nTests  = Min(Testlen,Max(Round(ScanPerc*TestLen/100.0),50))
                tstMul  = (nTests<=1) ? 0.0 : (TestLen-1) / (nTests-1.0)
                If(LT != LumaTolStart) {
                    RT_DebugF("Scan failed @ LumaTol==%d, LdTh=%.2f retrying",LT-LumaTolStep,LdTh,name=myName)
                    LdTh = (AutoLdTh) ? LdTh + 1.0 : LdTh
                }
                RT_DebugF("Scanning %d frames (%.1f%%) of Fix clip @ LumaTol==%d LdTh=%.2f",
                    \ nTests,nTests*100.0/Fix.Framecount,LT,LdTh,name=myName)
                for(Test = 1,nTests) {
                    Fi = int((Test - 1) * tstMul + 0.5)
                    if(RT_YPlaneMinMaxDifference(Fix,n=Fi,x=rad,y=rad,w=-rad,h=-rad,Threshold=1.0) >= 32) {   # Reliable frame ?
                        # Best match LumaDifference scan, Only exit early on EXACT match
                        Result=RT_QwikScan(Src,0,Fix,Fi,QDB,NDB,lumatol=LumaTol,Flags=2,ld=0.0,maxdistance=SrcMax,XP=0)
                        if(Result < 0 && QWKS_BM_COUNT > 0 && QWKS_BM_LD <= LdTh) {
                            Result = QWKS_BM_LD_FRM                                 # Best match to Fix[Fi] in entire Src
                        }
                        if(Result>=0) {
                            mxdif = QWKS_BM_LD           # Best or EXACT exit condition match for LumaDifference
                            for(j=1,MatchLen-1) {
                                df=RT_LumaDifference(Fix,Src,n=Fi+j,n2=Result+j)
                                mxdif = (df>mxdif) ? df : mxdif
                                if(df > LdTh) {
                                    j = Matchlen + 1     # Break MatchLen, not found
                                }
                            }
                            if(j == MatchLen) {          # completed normally ?
                                SrcMatchFrame = Result
                                FixMatchFrame = Fi
                                RT_DebugF("Fix[%d] Match Frame found at Src[%d] MaxLumaDif=%.3f (over %d frames)",
                                        \ FixMatchFrame,SrcMatchFrame,mxdif,MatchLen,name=myName)
                                Test = nTests            # Break Tests
                            }
                        }
                    }
                }
                if(FixMatchFrame != -1) {
                    LT = LumaTolEnd                      # Break LT
                }
            }
            RT_FileDelete(QDB)  RT_FileDelete(NDB)
        }
        Crop_L=0 Crop_T=0 Crop_R=0 Crop_B=0
        if(FixMatchFrame>=0) {
            X   =   rad*2
            Y   =   rad*2
            W   =   - X             # As in crop(), clip width relative, same as c.width - X - (RADIUS * 2)
            H   =   - Y             # clip height relative, same as c.height - Y -  (RADIUS * 2)
            HDir = 0
            VDir = 0
            corr  = -1.0
            for(i= - rad, rad) {
                for (j= - rad, rad) {
                    cor = RT_LumaCorrelation(Fix, Src,n=FixMatchFrame, x=X,y=Y,w=W,h=H,n2=SrcMatchFrame, x2=X+i, y2=Y+j)
                    if(cor>corr) {
                        corr=cor
                        HDir = i
                        VDir = j
                    }
                }
            }
            Org_corr = RT_LumaCorrelation(Fix, Src,n=FixMatchFrame, x=X,y=Y,w=W,h=H,n2=SrcMatchFrame, x2=X, y2=Y)
            RT_DebugF("Shifting clip HDir=%d VDir=%d (orig correlation=%f shifted=%f",HDir,VDir,Org_corr,corr,name=myName)
            LCrop   = (HDir<0) ? -HDir : 0    RCrop = (HDir>0) ?  HDir : 0
            TCrop   = (VDir<0) ? -VDir : 0    BCrop = (VDir>0) ?  VDir : 0
            Wid = Fix.Width  Hit = Fix.Height
            XM  = Fix.RT_ColorSpaceXMod()          YM = Fix.RT_ColorSpaceYMod(Laced=False)   # NOT for Interlaced
            Fix = Fix.PointResize(Wid*XM,Hit*YM)
            Fix = Fix.Crop(LCrop*XM,TCrop*YM,-RCrop*XM,-BCrop*YM).Addborders(RCrop*XM,BCrop*YM,LCrop*XM,TCrop*YM)
            Fix = Fix.PointResize(Wid,Hit)
            SA_x = (Abs(HDir) + XM - 1) / XM * XM
            SA_y = (Abs(VDir) + YM - 1) / YM * YM
            Crop_L = (HDir<0) ? 0    : SA_x     Crop_T = (VDir<0) ? 0    : SA_y
            Crop_R = (HDir<0) ? SA_x : 0        Crop_B = (VDir<0) ? SA_y : 0
        } Else {
            RT_DebugF("Cannot temporally align frames",name=myName)
        }
        SS = RT_String("Global %sL=%d Global %sT=%d Global %sR=%d Global %sB=%d",
                \ Prefix,Crop_L,Prefix,Crop_T,Prefix,Crop_R,Prefix,Crop_B)
        Eval(SS)    RT_DebugF("%s",SS,name=myName)
    """) # End Of GScript
    return Fix
}
__________________
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 November 2016 at 03:35.
StainlessS is offline   Reply With Quote