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 4th April 2021, 21:01   #21  |  Link
Dogway
Registered User
 
Join Date: Nov 2009
Posts: 1,226
I would test with no mod borders, in my case it crops more than 4 pixels anyway. I also did a second test with more strict settings to proof myself wrong but I get both mentioned issues.
It easily fails on dark scenes, yours is well lit at borders I think.

Code:
RC_IGNORE    = 0.00
RC_WMOD      = 2     # Width multiple of this
RC_HMOD      = 2     # Height multiple of this
RC_LEFTSKIP  = 0     # Crop at least these
RC_TOPSKIP   = 0
RC_RIGHTSKIP = 0
RC_BOTSKIP   = 0
Dogway is offline   Reply With Quote
Old 4th April 2021, 21:56   #22  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 9,365
If your borders are SOLID single color, the yes RC_IGNORE=0.0 sounds good.

I'm gonna go play with FredAverage, and add mask like I said earlier today.
__________________
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 22nd April 2021, 21:31   #23  |  Link
Dogway
Registered User
 
Join Date: Nov 2009
Posts: 1,226
I have been trying to come up with solutions for longer variable lifetime set at runtime functions, like inside scriptclip, the next is a proof of concept:

Code:
function MatteCrop2(clip c, int "width", int "height", float "thr", bool "CropMore", bool "Moving", int "ScanW", int "ScanH", int "mode", string "kernel", float "SC_thr") {

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

sisphbd = AvsPlusVersionNumber > 2294
bdpth   = sisphbd ? pow(256.,c.BitsPerComponent()/8.)/256. : 1.
contoy  = sisphbd ? !isy() : !isy8()
fullchr = contoy ? sisphbd ? ExtractU().width() == w : UToY8().width() == w : true

nw     = Default(width,w)
nh     = Default(height,h)
addw   = Default(ScanW,int(round((w/5))))
addh   = Default(ScanH,int(round((h/4))))
Mot    = Default(Moving, False)                             # If the matte is moving (sliding) this enables pixel level accuracy.
CM     = Default(CropMore, Mot || fullchr ? True : False)  # In case of odd cropping, either crop 1 pixel out or leave 1 pixel of the border
thr    = Default(thr, Mot ? 16.3 : 16.0)                    # Threshold, pixel values above this will be considered borders
mode   = Default(mode, 2)                                   # 0: center+pad 1: crop to minimum (WIP) 2: resize to maximum
SC_thr = Default(SC_thr, 3.5)
kernel = Default(kernel, "spline36")                        # Kernel to use when resizing (mode=2)

thr    = thr*bdpth

avg  = contoy ? sisphbd ? converttoy() : converttoy8() : last

avg  = avg.RatioResize(640.0,"adjust2w",kernel="bicubic")

blk_b  = avg.blankclip(pixel_type="Y8",fps=framerate(c),color=$000000).killaudio()
blk_w  = avg.blankclip(pixel_type="Y8",fps=framerate(c),color=$FFFFFF).killaudio()

avg  = avg.TemporalSoften(10,255,255,10,2)
avg  = avg.TemporalSoften(10,255,255,10,2)
avgsc= RatioResize(float(w),"adjust2w",kernel="bicubic").converttoyv12()
SC   = SCSelect_HBD(avg,blk_w,blk_b,blk_b,dfactor=SC_thr,mindif=1.0)

ScriptClip("""

isSC=YPlaneMax(SC)>128

# Obviously Defined() doesn't work here
Defined(x1) || Defined(y1) ? Eval("
for (LB=0, 1440, 1) {
  if (YPlaneMax(trim(SC,current_frame-LB,current_frame-LB))>128) {
    LBF=current_frame-LB
    LB=1440
   }
}
") : nop()

trim(avgsc,LBF,LBF)


x1=0 x2=0
y1=0 y2=0

step = Mot ? 1 : 2

addw != 0 ? Eval("
for (li=step, addw, step) {
  if (AverageLuma(crop(li-step,0,-w+li,0))>thr) {
    global x1= CM ? li : li-step
    li=addw
   }
}

for (ri=step, addw, step) {
  if (AverageLuma(crop(w-ri,0,-ri+step,0))>thr) {
    global x2= CM ? ri : ri-step
    ri=addw
  }
}") : nop()


addh != 0 ? Eval("
for (ti=step, addh, step) {
  if (AverageLuma(crop(0,ti-step,0,-h+ti))>thr) {
    global y1= CM ? ti : ti-step
    ti=addh
  }
}

for (bi=step, addh, step) {
  if (AverageLuma(crop(0,h-bi,0 ,-bi+step))>thr) {
    global y2= CM ? bi : bi-step
    bi=addh
  }
}") : nop()

#subtitle(string(y2),x=30,y=10,align=5)

MotW = Mot ? round(w-x1-x2) : nop()
MotH = Mot ? round(h-y1-y2) : nop()
Mot ? spline36resizeMT(c,fullchr?MotW:MotW+MotW%2,fullchr?MotH:MotH+MotH%2,src_left=x1,src_width=-x2,src_top=y1,src_height=-y2) : \
      crop(c,x1,y1,-x2,-y2)

mode == 0 ? padresize(w,h) : \
mode == 1 ? padresize(w,h) : \
            RatioResize(float(w),"adjust2w", kernel=kernel).padresize(w,h,mirror=false)

""",args="c,SC,avgsc,addw,addh,w,h,thr,CM,Mot,w,h,fullchr,kernel,mode",local=true, after_frame=false)


padresize(nw,nh)
(!CM || Mot) && mode==2 ? ContinuityFixer(left=addw>0?2:0, top=addh>0?2:0, right=addw>0?2:0, bottom=addh>0?2:0, radius=CM && w>720?0:1) : last 
}
I'm having a hard time setting and holding x1,x2,y1 and y2 variables available as long as there's no a new scene change. Indeed Global doesn't cut it, so for the time being I'm shifting frames in a for loop until a scene change is detected but this is very slow. I tried Gavino's solution here without success though.

Last edited by Dogway; 22nd April 2021 at 22:03.
Dogway is offline   Reply With Quote
Old 23rd April 2021, 16:08   #24  |  Link
Dogway
Registered User
 
Join Date: Nov 2009
Posts: 1,226
Unfortunately I still don't know how to manage variable lifetime of runtime functions, but needed to finish the script for some projects so I went down the rabbit hole and found a method, it does the same and it's very fast, false positives are reduced to a minimum. I still need to do some slight fine tuning but this is pretty much the script done. I even added a hybrid method where IMAX scenes would center in -mode 0- (so content is not cropped) but 2.40 scenes are upscaled to fit -mode 2-.


Code:
function MatteCrop(clip c, int "width", int "height", float "thr", bool "CropMore", bool "Moving", int "ScanW", int "ScanH", int "mode", string "kernel", float "SC_thr") {

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

sisphbd = AvsPlusVersionNumber > 2294
bdpth   = sisphbd ? pow(256.,c.BitsPerComponent()/8.)/256. : 1.
contoy  = sisphbd ? !isy() : !isy8()
fullchr = contoy ? sisphbd ? ExtractU().width() == w : UToY8().width() == w : true

nw     = Default(width,w)
nh     = Default(height,h)
addw   = Default(ScanW,int(round((w/8))))
addh   = Default(ScanH,int(round((h/4))))
Mot    = Default(Moving, False)                             # If the matte is moving (sliding) this enables pixel level accuracy.
CM     = Default(CropMore, Mot || fullchr ? True : False)  # In case of odd cropping, either crop 1 pixel out or leave 1 pixel of the border
thr    = Default(thr, Mot ? 16.3 : 16.0)                    # Threshold, pixel values same or below this will be considered borders
mode   = Default(mode, 2)                                   # 0: center+pad 1: crop to minimum (WIP) 2: resize to maximum 3:hybrid 0-2 (auto)
SC_thr = Default(SC_thr, 3.5)
kernel = Default(kernel, "spline36")                        # Kernel to use when resizing (mode=2)

addw==0 ? Assert( addh>0, "You need to scan borders for at least one of the dimension") : nop()
addh==0 ? Assert( addw>0, "You need to scan borders for at least one of the dimension") : nop()

thr    = thr*bdpth

avg  = contoy ? sisphbd ? converttoy() : converttoy8() : last

avg  = avg.RatioResize(320.0,"adjust2w",kernel="bicubic")

blk_b  = avg.blankclip(width=16,height=16,pixel_type="Y8",fps=framerate(c),color=$000000).killaudio()
blk_w  = avg.blankclip(width=16,height=16,pixel_type="Y8",fps=framerate(c),color=$FFFFFF).killaudio()

avg  = avg.TemporalSoften(10,255,255,10,2)
avg  = avg.TemporalSoften(10,255,255,10,2)
# need to turn converttoyv12 into other formats as source
avg  = avg.RatioResize(float(w),"adjust2w",kernel="bicubic").MatchColorFormat(c)
avgsc= Overlay(c.greyscale(),avg,mask=BoxMaskf(addw,w-addw,addh,h-addh,show=true),greymask=true, mode="blend", opacity=1.0)

SC   = SCSelect_HBD(avg,blk_w,blk_b,blk_b,dfactor=SC_thr,mindif=1.0)

ScriptClip("""

step = Mot ? 1 : 2
LBF=current_frame
x1=0 x2=0
y1=0 y2=0

# 1440 frames -1 min on 24fps- lookback
YPlaneMax(SC)<128 ? Eval("
for (LB=0, 1440, 1) {
  if (YPlaneMax(trim(SC,current_frame-LB,-1))>128) {
    LBF=current_frame-LB
    LB=1440
   }
}") : nop()


trim(avgsc,LBF+10,-1)


addw > 0 ? Eval("
for (li=step, addw, step) {
  if (AverageLuma(crop(li-step,0,-w+li,0,align=true))>thr) {
	x1= CM ? li : li-step
	li=addw
   }
}

for (ri=step, addw, step) {
  if (AverageLuma(crop(w-ri,0,-ri+step,0,align=true))>thr) {
	x2= CM ? ri : ri-step
	ri=addw
  }
}") : nop()


addh > 0 ? Eval("
for (ti=step, addh, step) {
  if (AverageLuma(crop(0,ti-step,0,-h+ti,align=true))>thr) {
	y1= CM ? ti : ti-step
	ti=addh
  }
}

for (bi=step, addh, step) {
  if (AverageLuma(crop(0,h-bi,0 ,-bi+step,align=true))>thr) {
	y2= CM ? bi : bi-step
	bi=addh
  }
}") : nop()


MotW = Mot ? round(w-x1-x2) : nop()
MotH = Mot ? round(h-y1-y2) : nop()
Mot ? spline36resizeMT(c,fullchr?MotW:MotW+MotW%2,fullchr?MotH:MotH+MotH%2,src_left=x1,src_width=-x2,src_top=y1,src_height=-y2) : \
      crop(c,x1,y1,-x2,-y2,align=true)

mode == 0 ? padresize(w,h) : \
mode == 1 ? padresize(w,h) : \
mode == 2 ? RatioResize(float(w),"adjust2w", kernel=kernel).padresize(w,h,mirror=false) : \
            YPlaneMax(crop( addh > 0 ? width()-16 : 0,0,0, addw > 0 ? -height()+16 : 0)) <= thr ? \
            RatioResize(float(w),"adjust2w", kernel=kernel).padresize(w,h,mirror=false) : padresize(w,h)

""",args="c,SC,avgsc,addw,addh,w,h,thr,CM,Mot,fullchr,kernel,mode",local=true)


padresize(nw,nh)
(!CM || Mot) && mode==2 ? ContinuityFixer(left=addw>0?2:0, top=addh>0?2:0, right=addw>0?2:0, bottom=addh>0?2:0, radius=CM && w>720?0:1) : last
}
I plan to fix nnedi3_resize16() to simplify it and remove the dither dependency so borders are upscaled sharply without subpixel blending. The filter is designed towards blurays/UHDs, you can still use it with garbage borders found in DVDs/VHSs but YMMV.

Last edited by Dogway; 23rd April 2021 at 16:37.
Dogway is offline   Reply With Quote
Old 23rd April 2021, 16:46   #25  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 9,365
Doggy, can you supply a short testclip and client script, thanks.
[I've found your ResizersPack4.7.4.avsi]

EDIT: As a very temporary hack for global survival, you could use RT_Stats DBase or array,
and preset fields/elements with eg -1, not set. Then you only need to use a fixed DBase name
to read or write, vars can even survive a reboot.

EDIT:
Code:
DB = "My.DB".RT_GetFullPathName

X1_FLD = 0
Y1_FLD = 1
X2_FLD = 2
Y2_FLD = 3

RECORD_0 = 0

TypeString="iiii"   # 4 fields of type int

RT_DBaseAlloc(DB,1,TypeString)   # Single pre-existing record [int field defaults are set to 0]

RT_DBaseSet(DB,RECORD_0,-1,-1,-1,-1)    # PreSet all vars -1

X1 = RT_DBaseGetField(DB, RECORD_0, X1_FLD)
Y1 = RT_DBaseGetField(DB, RECORD_0, Y1_FLD)
X2 = RT_DBaseGetField(DB, RECORD_0, X2_FLD)
Y2 = RT_DBaseGetField(DB, RECORD_0, Y2_FLD)


# ...

RT_DBaseSetField(DB, RECORD_0, X1_FLD, X1)
RT_DBaseSetField(DB, RECORD_0, Y1_FLD, Y1)
RT_DBaseSetField(DB, RECORD_0, X2_FLD, X2)
RT_DBaseSetField(DB, RECORD_0, Y2_FLD, Y2)

# OR

RT_DBaseSet(DB, RECORD_0, X1,Y1,X2,Y2)
EDIT: Even though file based, DBase is fast from harddrive, certainly faster than Global access on v2.60, not sure about Avs+ as
Avs+ implemented hash table for Globals access.

EDIT: DBase is also a way to return multiple results from a function, supply the function with DBase name, and function
returns results in DB, with perhaps success status as actual function return.
__________________
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; 23rd April 2021 at 17:19.
StainlessS is offline   Reply With Quote
Old 23rd April 2021, 17:22   #26  |  Link
Dogway
Registered User
 
Join Date: Nov 2009
Posts: 1,226
I sent you a PM. I still need to refine code for sliding mattes, repurpose width and height arguments depending on mode (pad or resize)

Code:
ffvideosource("title_t00_trans1.mkv")

MatteCrop(1920,1080,thr=17.0,cropmore=true,scanH=0,scanW=50,mode=3,kernel="spline36",moving=false)
Use the function from my post, as I still haven't updated ResizersPack.


As for variable lifetime, I'm precisely trying to avoid creating intermediary files or analysis passes, but I will have a look deeper in case it helps.
Dogway is offline   Reply With Quote
Old 23rd April 2021, 17:41   #27  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 9,365
Thanks Dog, I got the clip.
I wanted the resize pack for the other functions, RatioResize, PadResize and PadMirror.

EDIT:
The DBase thing could be used in realtime, not multiple pass thingy, and you can even delete the Dbase on clip closure using CallCmd().
EDIT: This part would be done before entering scriptclip, ie create and preset DBase,
And supply DB name as arg to scriptclip,
Code:
DB = "My.DB".RT_GetFullPathName

X1_FLD = 0
Y1_FLD = 1
X2_FLD = 2
Y2_FLD = 3

RECORD_0 = 0

TypeString="iiii"   # 4 fields of type int

RT_DBaseAlloc(DB,1,TypeString)   # Single pre-existing record [int field defaults are set to 0]

RT_DBaseSet(DB,RECORD_0,-1,-1,-1,-1)    # PreSet all vars -1
Using the RT_DBaseSet and RT_DBaseGet within Scriptclip.
The RECORD_0 and X1_FLD stuff is just for self documentation, you would likely use constants instead of variables.
During script developement, it is sometimes useful to use vars like X1_FLD etc so things eg field order can be changed around
without changing entire script. When completed, then can simply do a mass text Replace of eg X1_FLD with
the final chosen constant.
__________________
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; 23rd April 2021 at 17:59.
StainlessS is offline   Reply With Quote
Old 23rd April 2021, 17:57   #28  |  Link
Dogway
Registered User
 
Join Date: Nov 2009
Posts: 1,226
I will try to play with RT_DBaseSet() soon when I recover from yesterday lol, at first sight it looks promising although currently the biggest help would be from finding a method to average ranges of frames based on SCSelect_HBD. Currently I'm doing a convoluted method of stacking TemporalSoften() (with its own SC) and shifting the parsing frame 10 frames into the future from SC for better consistency.

EDIT: just updated ResizersPack.

Last edited by Dogway; 23rd April 2021 at 18:02.
Dogway is offline   Reply With Quote
Old 23rd April 2021, 18:06   #29  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 9,365
Quote:
finding a method to average ranges of frames
Yeah, what you want is tricky.
If you can find range then below might be useful.
ClipBlend() :- https://forum.doom9.org/showthread.p...ight=clipblend
__________________
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
Reply

Tags
align, automatic, crop, reframe

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 13:11.


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