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.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Usage

Reply
 
Thread Tools Search this Thread Display Modes
Old 15th May 2015, 00:32   #1  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,648
SpatialAlign v1.0 : Spatial Alignment of clips

Code:
Function SpatialAlign(clip Fix,clip Src,Int "MatchLen",Int "Rad",Float "LdTh",String "Prefix") {
/*
SpatialAlign.avs v1.0
    SpatialAlign v1.0: 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).
      Can take 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, 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.txt",Tim)  NDB = RT_String("~NDB_%s.txt",Tim) 
            RT_QwikScanCreate(Src,QDB,prevdb="",nextdb=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 = -1.0
                            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
}
Utility for demo only
Code:
Function ShiftClip(clip c,Int "HDir",Int "VDir",Int "BordCol") {
    c
    HDir = Default(HDir,0)            VDir = Default(VDir,0)        BordCol = Default(BordCol,0)
    LCrop   = (HDir<0) ? -HDir : 0    RCrop = (HDir>0) ?  HDir : 0
    TCrop   = (VDir<0) ? -VDir : 0    BCrop = (VDir>0) ?  VDir : 0
    XM = RT_ColorSpaceXMod()          YM = RT_ColorSpaceYMod(Laced=False)   # NOT for Interlaced
    PointResize(c.Width*XM,c.Height*YM)    
    Crop(LCrop*XM,TCrop*YM,-RCrop*XM,-BCrop*YM)
    Addborders(RCrop*XM,BCrop*YM,LCrop*XM,TCrop*YM,BordCol)
    PointResize(c.Width,c.Height)    
    Return Last
}
# Return Clip Difference of input clips (amp==true = Amplified, show==true = show background)
Function ClipDelta(clip clip1,clip clip2,bool "amp",bool "show") {
    amp=Default(amp,false)
    show=Default(show,false)
    c2=clip1.levels(128-32,1.0,128+32,128-32,128+32).greyscale()
    c1=clip1.subtract(clip2)
    c1=(amp)?c1.levels(127,1.0,129,0,255):c1
    return (show)?c1.Merge(c2):c1
}

Function Stack4Delta(clip c1,clip c2,bool "gray") {
    Gray =Default(gray,false)
    c1=(gray) ? c1.GrayScale:c1
    c2=(gray) ? c2.GrayScale:c2
    L=StackVertical(c1,c2)
    D1=ClipDelta(c1,c2)
    D2=ClipDelta(c1,c2,AMP=True)
    R=StackVertical(D1,D2)
    StackHorizontal(L,R)
    Return Last
}
Demo client script
Code:
DOFIX    = True    # Fix the shift ?
FIXGUNK  = True    # crop off gunk after shift fix ?

ColorBars.ConvertToYV12.Trim(0,-500).ShowFrameNumber
shifted = ShiftClip(2,4)        # Mis-aligned test clip. Multiple of X/Y Mod so as not to mess up chroma
SRC=Last

# Fix shifted clip
Result = (DOFIX) ? SpatialAlign(Shifted,Rad=4,SRC,Prefix="Crop_") : Shifted
# Crop off rubbish from edges
Result = (DOFIX&&FIXGUNK) ? Result.Crop(Crop_L,Crop_T,-Crop_R,-Crop_B) : Result
SRC    = (DOFIX&&FIXGUNK) ? SRC.Crop(Crop_L,Crop_T,-Crop_R,-Crop_B)    : SRC

Return Stack4Delta(SRC,Result)
__________________
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; 30th May 2015 at 11:04. Reason: Update
StainlessS is offline   Reply With Quote
Old 16th May 2015, 19:56   #2  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,648
Post #1 update to v1.0, working pretty good.

Hi there Jmac, wondered when you would be visiting here.
__________________
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 ???
StainlessS is offline   Reply With Quote
Old 29th May 2015, 02:04   #3  |  Link
chawl
Registered User
 
chawl's Avatar
 
Join Date: Feb 2012
Posts: 3
Your script needs something like this
Code:
Function SpatialAlign(clip Fix, clip "Src", int "Matchlen", int "Rad", float "LdTh", string "Prefix") {
/*

Last edited by chawl; 29th May 2015 at 02:28.
chawl is offline   Reply With Quote
Old 29th May 2015, 06:57   #4  |  Link
foxyshadis
ангел смерти
 
foxyshadis's Avatar
 
Join Date: Nov 2004
Location: Lost
Posts: 9,314
I'd love to see what you could come up with for a Stab/Deshaker script, StainlessS. You know how to handle this kind of video quite well.
__________________
There are four boxes to be used in defense of liberty: soap, ballot, jury, and ammo. Please use in that order. ~ Ed Howdershelt
foxyshadis is offline   Reply With Quote
Old 30th May 2015, 11:15   #5  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,648
@chawl, oops yes, fixed. Musta done that during a post edit.

Foxy, as well as RT_LumaCorrelation, I want to use RT_FrameDifference (which currently supports only full frame, awaits RT_ update).
I want to examine two horizontal strips at top and bottom of frame, and two vertical strips @ left and right of frame, and a block
in middle (maybe about 16x16), then could probably better estimate zoom as well as pan, guess that Stab/Deshaker already does something like that.
I have two 80's movies, one is about 20 mins longer than the other, frame contents can be both zoomed in and out compared with the other clip, and
scenes are in totally different order, one is in German, the other French, with different movie names but more or less the same storyline.
I shall be trying to do something that can automate alignment and cutting of these two difficult clips. (EDIT: This could be a little over ambitious)
__________________
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; 30th May 2015 at 12:01.
StainlessS is offline   Reply With Quote
Old 31st May 2015, 06:35   #6  |  Link
chawl
Registered User
 
chawl's Avatar
 
Join Date: Feb 2012
Posts: 3
How about merging spatial alignment logic into your brilliant MatchFrames script? I guess It might boost its efficiency quite dramatically especially if sources of the two clips are very different like VHS capture versus DVD. So it would be easier to reconstruct your old but lovely VHS cut (English?) of a title by replacing its crumbling frames with the ones from a remastered DVD (German?) which is cut, cropped and/or panned differently. This might be the holy grail of poor man's remastering

I'm sorry if I've said something silly but I'm just a hobbyist
chawl is offline   Reply With Quote
Old 31st May 2015, 15:25   #7  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,648
Quote:
How about merging spatial alignment logic into your
Something to consider for the future, but not just yet.

Quote:
but I'm just a hobbyist
Me too
__________________
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 ???
StainlessS is offline   Reply With Quote
Old 6th June 2015, 08:34   #8  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,860
Hey there S

This is awesome. There are uses for this in various versions of movies, for example full frame laserdisc version and 16x9 cropped dvd version.

Between cuts, spatial alignment, the last piece of the puzzle to me in terms of matching sources is colour.

There's the histogram, but I was thinking of a solver that finds the best match in terms of YUV referenced hue and saturation, as this more closely models physically the differences in capture settings and colour adjustments that were possible in early video editing.

I used the FFT based plugin to match widescreen to scan and pan version, it didn't follow so well, but it was neat to see the director moving a box around basically to focus on certain faces. You can also combine these to make better resolution; for example my copy wasn't anamorphic and the pan/scan version had dramatically better resolution in it's region, for a 2.35:1 film.

I'd like to see a script to combine two resolutions like that and spit out an ideal sized combined version.
jmac698 is offline   Reply With Quote
Old 6th June 2015, 11:15   #9  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,648
Hi there JMac,

I'm well snowed under with stuff at the mo, trying not to get into any other projects and I would actually like to get away from AVS
and into Android apps, but its hard to let go.
This and the sequence replacement (in another thread a bit earlier), and perhaps deshaking, color matching, could all be good additions
to the DBSC thing (which already is a bit of a monster). My guess is that my maths are just not up to the color matching thing, I remember mg262
saying something like "I am not completely happy with it" about his ColorLike plug, and if he could not get it working well, not sure I could
even come close to anything useful.
I've recently started using Martin53 AWB() [auto white balance], its really pretty good and a lot faster than I thought it would be, I spotted a couple
of possible problem areas that could be tweaked, hope he comes back soon and continues work on it.

Got to dash, be good.
__________________
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 ???
StainlessS is offline   Reply With Quote
Old 6th June 2015, 18:55   #10  |  Link
mandarinka
Registered User
 
mandarinka's Avatar
 
Join Date: Jan 2007
Posts: 666
Would it be possible to somehow adapt this for luma<->chroma matching?

One of the big problems that I never found solution for is sources in which chroma doesn't match luma temporally. The problem happens with telecined video where the pattern for chroma fields is broken, so that after IVTC, you will have chroma that has one of its fields from non-matching frame (combed ghost, basically).

Those sources could probably be handled if we had a function or script that would be able to match chroma to luma (basically something like seperately IVTCing chroma and then picking frame that matches luma IVTCed clip).

Sadly, I never found a way to do such luma/chroma matching
mandarinka is offline   Reply With Quote
Old 7th June 2015, 00:59   #11  |  Link
foxyshadis
ангел смерти
 
foxyshadis's Avatar
 
Join Date: Nov 2004
Location: Lost
Posts: 9,314
Quote:
Originally Posted by StainlessS View Post
@chawl, oops yes, fixed. Musta done that during a post edit.

Foxy, as well as RT_LumaCorrelation, I want to use RT_FrameDifference (which currently supports only full frame, awaits RT_ update).
I want to examine two horizontal strips at top and bottom of frame, and two vertical strips @ left and right of frame, and a block
in middle (maybe about 16x16), then could probably better estimate zoom as well as pan, guess that Stab/Deshaker already does something like that.
I have two 80's movies, one is about 20 mins longer than the other, frame contents can be both zoomed in and out compared with the other clip, and
scenes are in totally different order, one is in German, the other French, with different movie names but more or less the same storyline.
I shall be trying to do something that can automate alignment and cutting of these two difficult clips. (EDIT: This could be a little over ambitious)
Thank you for the great work you have done in the meantime, though! I have a movie that I have a good 4:3 pan-n-scan dvd of and a less detailed 16:9 dvd of with a different cut, so I'm in a similar boat. Your functions will definitely cut down the work required to "remaster" them into one good one.
__________________
There are four boxes to be used in defense of liberty: soap, ballot, jury, and ammo. Please use in that order. ~ Ed Howdershelt
foxyshadis is offline   Reply With Quote
Old 8th June 2015, 08:01   #12  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,648
Quote:
Originally Posted by mandarinka View Post
Sadly, I never found a way to do such luma/chroma matching
Best I can suggest is to find scene changes separately for both Luma & Chroma, eg using RT_FrameDifference(ChromaWeight=0.0) [Luma Only] and RT_FrameDifference(ChromaWeight=1.0) [Chroma Only]. I did at one point try detecting scene changes with chroma only, just to see if it worked ok, and it did.

EDIT: Added 'RT_' to FrameDifference.
EDIT: OR probably better, find Luma Scene change, and then check against chroma SC a couple of frames either side of detected scene change.
__________________
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; 8th June 2015 at 09:18.
StainlessS is offline   Reply With Quote
Old 8th August 2015, 15:36   #13  |  Link
Dogway
Registered User
 
Join Date: Nov 2009
Posts: 949
Can this output matching metrics? It can work good for detecting tilts and pans, along zooms they trigger some false-positives in my FilmGateFix() function (as in deshakers as well). I guess you can make a better job at it than I did, I always struggle with ScriptClip (updating the function today so you can have a glance of the hacky code).

Last edited by Dogway; 8th August 2015 at 16:12.
Dogway is offline   Reply With Quote
Old 8th August 2015, 17:35   #14  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,648
I'll see what I can do when I get time (not soon sorry).

Here, did search on FilmgateFix (save me searching again):- http://forum.videohelp.com/threads/3...409&viewfull=1

and also, Jmac posted somewhere about Shiftclip(), did not find it and so wrote function in 1st post, [was actually called Shift()], found it here:- http://forum.doom9.org/showthread.ph...80#post1518480
__________________
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 ???
StainlessS is offline   Reply With Quote
Old 8th August 2015, 18:01   #15  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,648
Further to previous post:

Doggy, perhaps could use Letterbox() instead of PadInwards().

Also for others, Stabilization Tools Pack v1.8 in full here (from above link):

Code:
###                                                      #
###                                                      #
### Stabilization Tools Pack 1.8 by Dogway (08-08-2015)  #
###                                                      #
##########################################################
###
### FilmGateFix()
###
### Function to fix frames ( by means of FreezeFrame() ) with film gate issues after a scene change.
### This is aimed at animation, for live footage frame interpolation should be desired.
###
### Rationale:
### Film Gate is about non-linear vertical stretching, thus we compare
### current and next frames in two blocks, a 1/5 block of top and bottom.
### The difference in both should be very high for film gate artifacts
### between the 2nd and 3rd frame after a Scene Change (also 1st and 2nd are compared).
### We mask this through a Scene Detection filter, motion masks, etc.
###
###  (http://forum.videohelp.com/threads/371336)
###
###
### Dependencies:
###
### Required:
### ------------
###
###   MVTools       (v2.5.11.3 or higher)               (http://avisynth.org.ru/mvtools/mvtools2.html)
###   masktools     (v2a48 or higher)                   (http://forum.doom9.org/showthread.php?t=98985)
###   Average       (v0.92 or higher)                   (http://forum.doom9.org/showthread.php?t=169832)
###   GRunT         (v1.0.1 or higher)                  (http://forum.doom9.org/showthread.php?t=139337)
###
####################################

function FilmGateFix(clip c,  float "thr", int "window", int "thSCD1", int "thSCD2", bool "debug") {

thr     = Default(thr,1.0)      # Main tweak setting, use debug and tweak according 2nd frame after Scene Change
window  = Default(window,5)     # Enlarges/reduces detection area, "height()/window"
thSCD1  = Default(thSCD1,500)   # Increase to reduce number of scenes detected
thSCD2  = Default(thSCD2,145)   # Increase to reduce number of scenes detected
Debug   = Default(Debug,false)  # Check what frames will be fixed and the difference value of frames for tweaking "thr"
thr2    = 5.0                   # central part of frame must change less than this to consider static scene to fix.

c
w=width()
h=height()

# Block for Scene Change detection and Motion Mask
kind   = 0
gam    = 1.2 # Could probably be exposed
mvthr  = 30  # Threshold, heavily dependent on gamma value above
super  = MSuper  (pel=1, sharp=0,vpad=0,hpad=0)
b1v    = MAnalyse(super,isb=true, blksize=16,overlap=8,search=0)
f1v    = MAnalyse(super,isb=false, blksize=16,overlap=8,search=0)
SADbv1 = MMask   (b1v,kind=kind,gamma=gam,thSCD1=thSCD1,thSCD2=thSCD2)
SADfv1 = MMask   (f1v,kind=kind,gamma=gam,thSCD1=thSCD1,thSCD2=thSCD2)

SceneChange = MSCDetection (f1v,thSCD1=thSCD1,thSCD2=thSCD2)
mvmask      = Average(SADbv1,1./2,SADfv1,1./2)


# Film Gate happens commonly between 2nd and 3rd frame after SC
# 1st frame is commonly garbage
add = round(w/(window*1.0))
T   = crop(0,0,0,((-h+add)/8)*8)
B   = crop(0,((h-add)/8)*8,0,0)

L   = crop(0,0,((-w+add)/8)*8,0)
R   = crop(((w-add)/8)*8,0,0,0)

CTB  = crop(0,((add)/8)*8,0,-((add)/8)*8)
CLR  = crop(round(((add*1.5)/8)*8),0,round(-((add*1.5)/8)*8),0)

SC2 = mt_logic(SceneChange,selectevery(SceneChange,1,-1),"max",U=3,V=3)

# Here, if after SC top area changes more than "thr" compared to bottom area
# then apply one FreezeFrame() for first SC frame, and another FreezeFrame() for the 2nd one,
# they (1st and 2nd) compute individually. There is a motionmask on top to rule out false positives.
scriptclip("""(abs(YDifferenceToNext(T)-YDifferenceToNext(B))>"""+string(thr)+""" && abs(YDifferenceToNext(CTB))<"""+
            \ string(thr2)+""") || (abs(YDifferenceToNext(L)-YDifferenceToNext(R))>"""+string(thr)+
            \ """ && abs(YDifferenceToNext(CLR))<"""+string(thr2)+""") ?"""+\
            \ """(YplaneMax(SC2)>254?(YDifferenceFromPrevious(SC2)>250?(AverageLuma(mvmask)<"""+string(mvthr)+
            \ """?(YDifferenceToNext(1)<9.0?freezeframe(current_frame,current_frame,current_frame+2):c):c):"""+\
            \ """(AverageLuma(mvmask)<"""+string(mvthr)+"""?freezeframe(current_frame,current_frame,current_frame+1):c)):c):c""",
            \ args="T,B,L,R,c,SC2,CTB,CLR,mvmask")

# Debug block
debug ? +\
eval("""stackhorizontal(scriptclip("Subtitle(c,"+Chr(34)+" Top & Bottom:"+Chr(34)+"+String(YDifferenceToNext(T)-YDifferenceToNext(B))+\
       "+Chr(34)+"\n Left & Right:  "+Chr(34)+"+String(YDifferenceToNext(L)-YDifferenceToNext(R))+\
       "+Chr(34)+"\n Center Horiz:  "+Chr(34)+"+String(YDifferenceToNext(CTB))+\
       "+Chr(34)+"\n Center Vert:    "+Chr(34)+"+String(YDifferenceToNext(CLR)),
       z align=7,size=30,lsp=10)",args="T,B,L,R,c,CTB,CLR"),+\
       scriptclip("AverageLuma(mvmask)<"""+string(mvthr)+"""?((abs(YDifferenceToNext(T)-YDifferenceToNext(B))>"+string(thr)+
           \ " && abs(YDifferenceToNext(CTB))<"+string(thr2)+") || (abs(YDifferenceToNext(L)-YDifferenceToNext(R))>"+
           \ string(thr)+" && abs(YDifferenceToNext(CLR))<"+string(thr2)+") ? "+\
           \ "(YplaneMax(SC2)>254&&YDifferenceToNext(1)<9.0?mt_lut(c,"+Chr(34)+"255"+Chr(34)+",U=128,V=128):mt_lut(c,"+Chr(34)+"0"+Chr(34)+
           \ ",U=128,V=128)):mt_lut(c,"+Chr(34)+"0"+Chr(34)+",U=128,V=128)):mt_lut(c,"+Chr(34)+"0"+
           \ Chr(34)+",U=128,V=128)",args="T,B,L,R,c,CTB,CLR,SC2,mvmask"))
           \ crop(0,0,-(round(w/1.1)/2)*2,0).Subtitle("Frame to Freeze",align=9,size=40)""") : last }





####################################
###
### FillBorders()
###
### Function to fill dark (use threshold) borders, in the vein of old FillMargins() function.
### But instead of mirroring or other approaches like resizing, this function fills/interpolates
### missing data from surrounding pixels.
### Useful to use as a clean pass after stab() and crop(x1,y1,x2,y2)
### for the remaining thin black borders (up to 3px)
###
### For borders of 4px and more you can enable FixFalPos, there you supply a clip
### without black borders (ie. before stab() ). It automatically replaces the offended frames.
### Some thick black borders aren't "0" black at all, they show garbage and the 3+1 pixel border
### may not average to 0, so a "thr2" setting is added as threshold, default 7 should be enough.
###
### Below you can still use the the FindBlackBorders() function for manual handling of thick black borders.
### Use ClipClop() for the stab() results according to the statistics file of FindBlackBorders()
###
### Mind you, for FillBorders() you need to manually load the AVSInpaint plugin:
### LoadCPlugin("AVSInpaint.dll")
###
###  (http://forum.videohelp.com/threads/371336)
###
###
### Dependencies:
###
###   masktools     (v2a48 or higher)                   (http://forum.doom9.org/showthread.php?t=98985)
###   GRunT         (v1.0.1 or higher)                  (http://forum.doom9.org/showthread.php?t=139337)
###   AVSInpaint    (v2008.02.23 or higher)             (http://forum.doom9.org/showthread.php?t=133682)
###
####################################

function FillBorders(clip c, int "thr", int "pad", bool "blur", bool "debug", clip "FixFalPos", int "thr2") {

thr      = Default(thr, 1)      # Threshold, pixel values below this will be considered borders
pad      = Default(pad, 0)      # Pixels, you can expand the replacement area adding more pixels 
                                # (to deal with dirty borders) (use "1" to deal with 1px b/w chroma, due to the chroma subsampling nature of video)
blur     = Default(blur ,false) # Blurs the masking for the replacement area. Currently not supported for InpaintLogo()
debug    = Default(debug,false) # Show the borders that are going to be filled
FalPos   = Defined(FixFalPos) ? true : false # If you supply a reference clip borders with 4 or more
                                # average thr2 pixels will be replaced with the clip's frame
thr2     = Default(thr2, 7)     # Threshold for FalPos, FalPos frames sometimes have garbage borders so you need to increase 
                                # threshold

c
converttoy8()
y8=last
w=width()
h=height()

# 4px or greater
L4=FalPos ? crop(0,0,-w+4,0) : nop()
R4=FalPos ? crop(w-4,0,0 ,0) : nop()
T4=FalPos ? crop(0,0,0,-h+4) : nop()
B4=FalPos ? crop(0,h-4,0 ,0) : nop()
# 3px
L3=crop(0,0,-w+3,0)
R3=crop(w-3,0,0 ,0)
T3=crop(0,0,0,-h+3)
B3=crop(0,h-3,0 ,0)
# 2px
L2=crop(L3,0,0,-1, 0)
R2=crop(R3,1,0,0 , 0)
T2=crop(T3,0,0,0 ,-1)
B2=crop(B3,0,1,0 , 0)
# 1px
L1=crop(L3,0,0,-2,0 )
R1=crop(R3,2,0,0 ,0 )
T1=crop(T3,0,0,0 ,-2)
B1=crop(B3,0,2,0 ,0 )

c
Fill = ScriptClip("""
y8
pad= blur ? pad+2 : pad

x1 = AverageLuma(L1) < thr ? (AverageLuma(L2) < thr ? (AverageLuma(L3) < thr ? 3+pad : 2+pad) : 1+pad) : 0
x2 = AverageLuma(R1) < thr ? (AverageLuma(R2) < thr ? (AverageLuma(R3) < thr ? 3+pad : 2+pad) : 1+pad) : 0
y1 = AverageLuma(T1) < thr ? (AverageLuma(T2) < thr ? (AverageLuma(T3) < thr ? 3+pad : 2+pad) : 1+pad) : 0
y2 = AverageLuma(B1) < thr ? (AverageLuma(B2) < thr ? (AverageLuma(B3) < thr ? 3+pad : 2+pad) : 1+pad) : 0

FalPos = FalPos ? ((x1-pad > 2 || x2-pad > 2 || y1-pad > 2 || y2-pad > 2 )
              \ ? ((AverageLuma(L4) < thr2) || (AverageLuma(R4) < thr2) || (AverageLuma(T4) < thr2) || (AverageLuma(B4) < thr2)
              \ ? true : false) : false) : false

ter = !FalPos && (x1+y1+x2+y2>0) ? true : false

msk  = PadInwards(mt_lut("0"),x1,y1,x2,y2,$ffffff).trim(0,-1).FreezeFrame(0, FrameCount(last)-1, 0).mt_lut("x 128 > 255 x ?")
msk  = blur ? msk.mt_convolution("1 1 1 1 1", "1 1 1 1 1").converttoyv12() : msk.converttoyv12()

fill = FalPos ? trim(c,0,current_frame-1)++trim(FixFalPos,current_frame,-1)++trim(c,current_frame+1,0) : \
         (ter ? InpaintLogo(c, radius=max(x1,y1,x2,y2)+max(2,pad), mask=msk) : c)
sub  = debug  ? subtitle(msk,"Bordered",align=3,size=round(h/20.0)) : nop()

debug ? (ter?sub:msk) : fill
""",args="y8,c,w,h,thr,thr2,L4,R4,T4,B4,L3,R3,T3,B3,L2,R2,T2,B2,L1,R1,T1,B1,pad,blur,debug,FalPos,FixFalPos")

!debug ? Fill : \
eval("""
 box    = h/4.0
 m      = 2

 corner = crop(mt_lut("255"),round((w-box)/m)*m,round((h-box)/m)*m,0,0)
 corner = corner.addborders(0,0,round((w/2.0-box)/m)*m,round(box/m)*m).mt_lut("x 255 < 0 255 ?")

 horiz  = stackhorizontal(corner,corner.fliphorizontal())
 verti  = stackvertical(horiz,horiz.flipvertical())

 mt_merge(c,Fill.pointresize(w,h),verti,luma=true)""") }


####################################
###
### FindBlackBorders()
###
### Script to find sources with black borders for example as a result of bad deshaking, run on analysis pass
### The output file is formatted to be imported to avspmod as bookmarks
### use ClipClop() afterwards on a scene by scene basis to fix this.
###
### "width" is border thickness for detection
### "thr" is threshold, pixel values below this will be considered borders
### "path" is the path to store the statistics file, with end backslash. Default is "C:"
### "filename" is the statistics file name. In case you don't want to overwrite old ones
###
###  (http://forum.videohelp.com/threads/371336)
###
### Dependencies:
###
### Required:
### ------------
###
###   masktools     (v2a48 or higher)                   (http://forum.doom9.org/showthread.php?t=98985)
###   Dither        (v1.26.5 or higher)                 (http://forum.doom9.org/showthread.php?p=1386559#post1386559)
###
####################################

function FindBlackBorders(clip c, int "width", int "thr", string "path", string "filename") {

add      = Default(width,1)     # Width for detection, normally 1 should suffix to most situations
thr      = Default(thr,1)       # Threshold for detection, pixels lower than this value will be considered a border
path     = Default(path, "C:")  # This is the path to store the statistics file
filename = Default(filename, "FindBlackBorders - Statistics.log") # Filename of the statistics file

c
converttoy8()
w=width()
h=height()

L1=crop(0,0,-w+add,0)
R1=crop(w-add,0,0 ,0)
T1=crop(0,0,0,-h+add)
B1=crop(0,h-add,0 ,0)

ScriptClip("""
x1 = AverageLuma(L1) < thr ? true : false
x2 = AverageLuma(R1) < thr ? true : false
y1 = AverageLuma(T1) < thr ? true : false
y2 = AverageLuma(B1) < thr ? true : false
function IsBorder(clip c, bool x1, bool x2, bool y1, bool y2) {return (x1||y1||x2||y2)?true:false}

q = chr(34)chr(34)chr(34)
WriteFileIf(""+path+"\"+filename+"", " "+string(IsBorder(x1,y1,x2,y2))+" ", q+"CHAPTER00="+q,
        \ "FFFormatTime(round((current_frame * 1000) / framerate()))", "", "")
""",args="thr,L1,R1,T1,B1,path,filename")

converttoyv12()

# Bug or limitations of 8-bit masktools with Overlay or...
# mt_merge (masking PC Range masks) so use Dither tools
Dither_merge16_8(Dither_convert_8_to_16(),Dither_convert_8_to_16(c),mt_lut("255"),luma=true)
ditherpost(mode=-1) }


######### HELPER FUNCTIONS #########

# Helper function for FindBlackBorders() from FFMS2.avsi
function FFFormatTime(int ms) {
    s = ms / 1000
    ms = ms % 1000
    m = s / 60
    s = s % 60
    h = m / 60
    m = m % 60
    return string(h) + ":" + string(m,"%02.0f") + ":" + string(s,"%02.0f") + "." + string(ms,"%03.0f")}


# Helper function for FillBorders() and FindBlackBorders()
function PadInwards(clip clp, int "left", int "top", int "right", int "bottom", int "color") {

l = default( left,  0 )
t = default( top,   0 )
r = default( right, 0 )
b = default( bottom,0 )
color = default( color, 000000 )

clp
crop      (l,t,-r,-b)
addborders(l,t, r, b,color) }
EDIT: reformatted long lines a little to fit page.
__________________
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; 9th August 2015 at 15:44.
StainlessS is offline   Reply With Quote
Old 9th August 2015, 14:03   #16  |  Link
Dogway
Registered User
 
Join Date: Nov 2009
Posts: 949
Thanks, you reposted my script? didn't change anything?

Why letterbox? PadInwards is only a crop() and addborders() line.

I added another check to avoid evaluating borders of 4 pixels for every frame, I will keep updating in its original thread.
Code:
FalPos = FalPos ? ((x1-pad > 2 || x2-pad > 2 || y1-pad > 2 || y2-pad > 2 )
              \ ? ((AverageLuma(L4) < thr2) || (AverageLuma(R4) < thr2) || (AverageLuma(T4) < thr2) || (AverageLuma(B4) < thr2)
              \ ? true : false) : false) : false
Dogway is offline   Reply With Quote
Old 9th August 2015, 15:40   #17  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,648
Quote:
Originally Posted by Dogway View Post
Thanks, you reposted my script? didn't change anything?

Why letterbox? PadInwards is only a crop() and addborders() line.
I did not change anything (only re-formatted for very long lines), just posted so others did not have to search D9 and then internet for the script.

LetterBox is only a crop and AddBorders too (but different arg order), from docs.

Quote:
Letterbox
Letterbox (clip, int top, int bottom, [int left], [int right], int "color")

Letterbox simply blackens out the top top and the bottom bottom, and optionally left and right side of each frame. This has a couple of uses: one, it can eliminate stray video noise from the existing black bands in an image that's already letterboxed; two, it can eliminate the garbage lines that often appear at the bottom of the frame in captures from VHS tape.

The functionality of Letterbox can be duplicated with a combination of Crop and AddBorders, but Letterbox is faster and easier.
EDIT: Added FalPos Mod.
__________________
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; 9th August 2015 at 15:46.
StainlessS is offline   Reply With Quote
Old 9th August 2015, 15:55   #18  |  Link
Dogway
Registered User
 
Join Date: Nov 2009
Posts: 949
I see, internal function much better.
Dogway is offline   Reply With Quote
Old 4th November 2016, 03:30   #19  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,648
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
Reply

Tags
spatial alignment

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 09:49.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2018, vBulletin Solutions Inc.