View Full Version : RoboCrop, v1.13 - 07 Feb 2020


StainlessS
12th June 2013, 13:46
RoboCrop v1.13, v2.58, avs/+ v2.60, x86 and x64 dll's.
Requires VS2008 CPP Runtimes.

V1.13 Docs overflow 16kb limit, so left at v1.0 docs below.
See post #37 for v1.13 Docs over two posts. Here: http://forum.doom9.org/showthread.php?p=1696703#post1696703

RoboCrop()

To Protect And Serve - by StainlessS @ Doom9:- http://forum.doom9.org/showthread.php?t=168053

VIDEO: Planar, YUY2, RGB.
AUDIO: No change.

Plugin's for both Avisynth v2.5 and v2.6.

RoboCrop is an automatic cropping solution to crop black borders from video clips, loosely based on (but using no code from)
Autocrop by Glenn Bussell.

For the most part, you can just call it with RoboCrop(clip) and not bother with any other arguements, it is intended to be pretty
much autonomous in its decisions. You might however want to alter eg WMod and HMod if your encoder has special requirements, and
perhaps Laced if your source is likely to be fully progressive.

Borders are detected by sampling at Samples frames, at scanlines (h/v) using AverageLuma (RGB is converted to Luma Y at either TV or
PC levels, See Matrix). This sampling is done on all 4 sides of the frame.
If a scanline Average luma is below or equal to Thresh, then is considered possible black border, above considered possible image,
if Baffle [default=4] adjacent scanlines above Thresh, then it IS image.

Function RoboCrop(clip c,int "Samples"=32,Float "Thresh"=-32,bool "Laced"=true,int "WMod",int "HMod",int "RLBT"=15,bool "Debug"=false, \
float "Ignore"=0.2,int "Matrix"=(c.width<=720?2:3), int "Baffle"=4, bool "ScaleAutoThreshRGB"=true,bool "ScaleAutoThreshYUV"=false, \
int "CropMode"=2,bool "Blank"=false,bool "BlankPC"=false,bool "Align"=false,bool "Show"=false,String "LogFn"="",bool "LogAppend"=false, \
Float "ATM"=4.0)


Args:-

Samples=32, Number of frames to sample from source clip c.
As an observation, most clips have good border recogition within the 1st 2 sampled frames using the default -32.0 AUTOTHRESH
although have noticed some dark clips that required ~8 samples (maybe more) for full recognition @ default Thresh = -32.0
We use a default Samples=32, because we are intrinsically paranoid.
If clip more than 250 frames, will ignore the first 5% and last 10% of frames when both auto-thresholding and crop sampling to
try to negate effects of artificial black in titles and end credits. (Even without this feature, it always skips beginning and end
where possible like this "00100100100" where 1 represents sampled frames when sampling 3 frames from 11).

Thresh: Default= -32.0 (==DEFAULT AUTOTHRESH, any -ve Thresh is AUTOTHRESH where Thresh adjustments are automatic).

Thresh > 0: (Explicit Threshold)
A user supplied +ve Thresh should be at correct TV/PC levels for the the clip being worked on ie 16->235 for TV levels and
0->255 for PC Levels (RGB, as appropriate for matrix being used).

Thresh <= 0: (AUTOTHRESH)
When Thresh <= 0, the clip will be sampled over Samples frames to find the minimum YPlaneMin (using Matrix if RGB) which
we will call MINLUMA and an Explicit Threshold calculated by adding MINLUMA to abs(Thresh), after that it is processed
as for Thresh > 0: (Explicit Threshold) as noted above, but, before adding MINLUMA, some AUTOTHRESH massaging occurs.

Here AUTOTHRESH Thresh massaging occurs in sequence:-
1 ) if (Thresh == DEFAULT AUTOTHRESH && ATM < 32.0) (DEFAULT AUTOTHRESH = -32.0, defaulted OR user supplied):
Let FrameRange = FrameEnd-FrameStart+1 (after skipping titles and end Credits, also Samples limited to FrameRange).
Samples_massage = (Samples>=16) ? 1.0 : (Samples-1) * (1.0/(16-1))
Range_massage =(Float(frmend-frmstart+1)/samples >= 250) ? 1.0 :(Float(frmend-frmstart)/samples * (1.0/(250-1)))
Thresh = -(((Samples_massage * Range_massage) * (32.0 -ATM)) + ATM)
The adjustment to Auto Thresh is to reduce the possibility of overcropping on eg a dark low 'Samples' clip, or where
source FrameRange (ie temporal frame set) is too small to take a reliable sample from.
Resulting massaged Thresh will range between -ATM and -32.0.
Although massaging is intended to reduce overcropping, it could result in not cropping enough border (less disastrous),
its a bit of a balancing act really. See also ATM.
2 ) If RGB AND PC matrix(default) AND ScaleAutoThreshRGB==True(default) then
Thresh= Thresh*(255.0/(235-16))
3 ) If YUV AND ScaleAutoThreshYUV==True(default=false) then
Thresh= Thresh*(255.0/(235-16))

Steps 2) and 3) above, by default treat a -ve AUTOTHRESH as being @ TV Levels and so Scale RGB Thresh to PC levels but not YUV.
If you want to supply a PC levels AUTOTHRESH Thresh for RGB, then simply set ScaleAutoThreshRGB=false to inhibit scaling.
Note, if a TV levels Matrix is supplied for RGB, then scaling will always be inhibited.
If your clip is YUV at PC levels and you want to use eg DEFAULT AUTOTHRESH (-32.0, which is considered to be @ TV levels),
then set ScaleAutoThreshYUV=True to enable Thresh scaling.
If your clip is YUV at PC levels and you want to use a PC levels AUTOTHRESH (-ve) then leave ScaleAutoThreshYUV at default false
which does not scale Thresh.
After any scaling, MINLUMA is then added to abs(Thresh) and processed as for +ve Explicit Threshold as noted above.
NOTE, RoboCrop 'massages' DEFAULT THRESH (exactly -32.0) if low samples count or if short clip. Reason being to avoid
overcropping when insufficient data available for reliable cropping. It is considered better to not crop enough or at all, than
to overcrop. You can override by simply setting an explicit threshold (+ve) of eg 40.0, or setting a NON-DEFAULT auto thresh (-ve)
eg -16.0 or -32.1, where YPlaneMin is established for the sampled frames and then abs(thresh) is added to that value which is
then used as an explicit thresh.

Laced:, Default=true, true for Interlaced.
RoboCrop automatically deduces colorspace cropping restrictions and sets internal XMod and YMod,
eg XMod and YMod would both be set to 2 for YV12, for YUY2 Xmod=2, YMod=1, etc.
If Laced==true, then internal YMod is doubled so as not to destroy chroma.
Below WMod and HMod are both defaulted to internal XMod and YMod respectively after the Laced hint is applied to YMod.

WMod:, Default=The natural chroma cropping restriction of the colorspace concerned, eg 2 for YV12.
HMod:, Default=The natural chroma cropping restriction of the colorspace concerned, BUT, doubled if laced=true.
The above WMod,HMod sets rounding for legal cropping coords for colorspace concerned.
WMod MUST be a multiple of internal XMod as described under Laced above, or it will throw an error.
HMod MUST be a multiple of internal YMod as described under Laced above, or it will throw an error. If eg colorspace is
YV12 then YMod would be set to 2, and if Laced, then YMod would be doubled to 4, so HMod MUST be a multiple of 4.
Some encoders may require an WMod/HMod of eg 8 or 16, and if set thus, would crop off more or less depending upon
which CropMode is set, if later resizing will be done, then encoder requirements can be satisfied during the resize.
NOTE, Some players and VirtualDubMod (Helix YV12 decoder) dont like WMOD less than 4 (Vdub latest, OK, internal decoder).

RLBT:=15=All Borders, Bitflags of edges to crop, 15 ($0F) crops all four. Each letter in the name 'RLBT' represents an edge and bit position
starting with 'R' in bit 3 representing the value 8 (2^3=8). 'L' = bit 2=4 (2^2=4), 'B' = bit 1=2 (2^1=2), 'T' = bit 0=1 (2^0=1).
To calculate the RLBT bitflags, for 'R'(Right) add 8, for 'L'(Left) add 4, for 'B'(Bottom) add 2, and for 'T'(Top) add 1.
Add all of the bit flags together 8+4+2+1 (=15) crops all four edges, 8+4 crops only Right & Left, and 2+1 crops only Bottom & Top.

DEBUG:=False=No Debug. Set True for debugging info, need DebugView: http://technet.microsoft.com/en-gb/sysinternals/bb545027

Ignore:=0.2, Percentage of darkest pixels to ignore during AutoThresh scan to detect minimum luma pixel of all sampled frames.
(ignores noise, as Threshold in YPlaneMin).

Matrix:, RGB ONLY. For conversion of RGB to YUV-Y, 0 = Rec601, 1 = Rec709, 2 = PC601, 3 = PC709
Default for RGB is 2(PC601) if clip width <= 720 else 3(PC709) : YUV not used
The defaults are for PC601 & PC709 range 0-255.
So as to not require different AutoThresh for RGB, if clip c is RGB AND matrix is PC Levels AND Thresh < 0.0 and ScaleAutoThreshRGB=true,
then Thresh will be scaled to RGB full range ie Thresh = Thresh * (255.0/(235.0-16.0)) ONLY when AutoThresh (ie Thresh < 0.0,
YPlaneMin relative).
When +ve Thresh is explicitly supplied (Thresh > 0.0) it is not scaled and assumed to be already correct range TV or PC levels.

Baffle:=4, Number of scanlines (h/v) that must break threshold to be considered image (avoids noise). Does not usually need changing.

ScaleAutoThreshRGB: bool default True. If true and RGB and Matrix at PC levels, and Thresh -ve (autothresh) then thresh will (after any low
samples count scaling) be scaled to PC levels. By default, -ve Auto Thresh is considered to be at TV levels, and so will be scaled to
to PC levels to match the matrix setting. If ScaleAutoThreshRGB is False Then autothresh is considered to be at PC levels and not scaled.

ScaleAutoThreshYUV: bool default False. If true and YUV and Thresh -ve (autothresh) then thresh will (after any low samples count scaling)
be scaled to PC levels. By default, -ve Auto Thresh is considered to be at TV levels, this allows you to change that assumption when
source clips are at PC levels. If supplying PC levels clip and PC levels autothresh then leave this setting at false (no scaling).
The above seemingly awkward settings are due to having to deal with YUV @ TV levels and RGB @ PC levels with the possibility of
YUV @ PC levels.

Cropmode: default=2 == CropMore. 1 = CropLess. Range 1 -> 2.
1 (CropLess) crops a little less border if the exact cropping coords do not comply with XMod/YMod/WMod/HMod as
described earlier. May leave a little border edge.
2 Default, (CropMore) crops a little extra where exact coords do not comply XMod/YMod/WMod/HMod requirements.
You may lose a little of the image edges.

Blank: Default False. If true, then Blanks the borders, ie sets border to RGB(0,0,0) or YUV(16,128,128) instead of cropping.
Is overridden if Show == true.

BlankPC: default false. If Blanking then blanks to YUV(0,128,128) instead of default YUV(16,128,128).

Align: Default false. If true, then aligns frames in memory when cropping, for eg SSE2 16-byte alignment required by some
filters, particularly smoothing filters (filters following after RoboCrop). See Docs for Crop().
Only Applies if Cropping, ie Blank==false AND Show==false.

Show: Default false. If true, then does no cropping, just shows a little info on frame. Overrides both Blank and Align.

LogFn: Default "". Filename of Log file. Will output crop coords eg "10 16 700 544". Crop coords will be output whether
cropping or not (Blank/Show).

LogAppend: Default false. If true then appends log to any existing log file.

ATM: Float default 4.0 (0.5 -> 32.0). Silently limited to valid range.
ATM allows user to set the DEFAULT AUTOTHRESH massaging minimum. When eg samples = 1, then auto thresholding is of course quite
unreliable and so auto thresh would be 'massaged' to -ve(ATM), other values of Samples below 16 will likewise have auto thresh
massaged but to a lesser degree, linearly between -ve(ATM) for Samples == 1 and -ve(32.0) for Samples == 16.
Previous (Fixed) default for ATM was 0.5, for maximum safety so that a single Samples scan would NOT overcrop. The new ATM arg default
of 4.0 is a less paranoid safety setting which should in most cases work well but with a very short clip or eg single image then
user might be better off giving the minimum ATM of 0.5. An ATM of 32.0 will switch OFF default auto thresh massaging.
So long as your clips are about 6 mins or more (and Samples == default 32) then there will be no auto thresh massaging and current
default is unlikely to need changed, with very short clips or reduced Samples count, then you might want to reduce ATM, for maximum
paranoia, set ATM=0.5. See Thresh.


Cropping will likely fail on END CREDITS ONLY clips, where on black background, and will probably crop off the sides that are no
different in average luma to any letterbox borders, if you cannot see the borders, then neither can RoboCrop(), even setting the
auto Thresh to eg -1.0 or 0.0 is quite likely to fail. (See RLBT edge bitflags).

If cropping too much border, then increase Samples or reduce Thresh or lower ATM if short clip.
If not cropping enough border then border is being seen as image, increase Thresh.
To speed up, you may want to leave Auto-Thresh alone and reduce samples, but there is danger that it will not detect all borders (overcrop).
NOTE, The plugin AutoCrop() uses a Thresh of 40.0 and samples == 5 by default (No AutoThresh), but the base logic is not too dissimilar.

Final NOTE, the args to especially note are:- WMod, you might want to supply WMod=4 if using VDubMod (some players might try to download codec),
And Laced=False if you always process progressive or deinterlaced, And ATM set between 0.5 and 4.0 if very short clips/single-image.

StainlessS


Show=true v1.06
https://s20.postimg.cc/vk7jwv799/robo0_zpsfzfpfakr.jpg (https://postimg.cc/image/sq4ejf52x/)
Show=true v1.10+
https://s20.postimg.cc/b7qcuw2gt/cab2_zpsjgrrflzt.png (https://postimg.cc/image/vf3sn6zy1/)
Bottom image above: Left edge, single dots line, other edges a bit wiggly ie cropping moved inwards [CROPMORE] to adhere to X/Y/W/H Mod requirements.

See Mediafire in sig.

mastrboy
12th June 2013, 15:40
very interesting plugin.
I usually use applyrange to fix cropping in sources when it's not a static value, like:
ApplyRange(25760,26183,"c_bottom")
ApplyRange(26220,27286,"c_bottom")
ApplyRange(27394,27605,"c_bottom")
ApplyRange(27702,28529,"c_top")

function c_top (clip c) {
c
return crop(0,2,0,0).Spline36Resize(width,height)
}

function c_bottom (clip c) {
c
return crop(0,0,0,-4).Spline36Resize(width,height)
}

function c_top_right (clip c) {
c
return crop(0,2,-4,0).Spline36Resize(width,height)
}

function c_right (clip c) {
c
return crop(0,0,-4,0).Spline36Resize(width,height)
}


Could this plugin replace that tedious work?
And if yes, is there a way to log in a file all the frames/ranges which where cropped by RoboCrop?

StainlessS
12th June 2013, 16:16
Sorry Mastrboy, No.

RoboCrop is a sort of drop in replacement for AutoCrop. Where croppings differ, will pick the outermost cropping (EDIT: that it finds, by default it only samples 24 frames).

I did do a little script using GScript and RT_Stats a few months back to fix dynamically changing borders on some anime.
I got it working to do the job, but would not say it was complete (I got sick of it, especially as I have zero interest in cartoons).
Perhaps you can make use of parts of it, search on "BorderTorture", I think you should get a hit on that (it was a test clip generator,
cant remember what I called the actual cropping func).
EDIT: See Here:- http://forum.doom9.org/showthread.php?t=167531&highlight=bordertorture

As I remember, it produced a file of crop coords and a sister fuinc, read them in and did the cropping.

EDIT: It might make an interesting little project though, I'll have to think about that for a little while.
The previously mentioned anime was interlaced, you got same prob ?
I dont really have any source like that, that I can think of, except for one, and that one has scene blends
which cause additional problems. hard to tell where the scene change is and where to alter cropping, also, that source
is a tube flv file so lousy quality to begin with.

creaothceann
12th June 2013, 19:34
This looks very useful! :)

Definitely going to come in handy with my anime.

mastrboy
13th June 2013, 15:49
Sorry Mastrboy, No.
The previously mentioned anime was interlaced, you got same prob?


It's related to anime indeed, but not specifically interlaced anime, I have noticed it on different anime's usually created around 2000-2003. Usually it's only about 2-4px borders, so not very noticeable. But when noticed, you can't "un-notice" it :P

StainlessS
13th June 2013, 23:37
This world is plagued by perfectionists.

I personally miss the days when you could accuse someone of being witch, and next day you could burn them.
Good times.

EDIT: I'll see what I can do with a plugin to generate list of crops.

mastrboy
14th June 2013, 18:22
Indeed, I blame this forum for making me into one, a perfectionist that is :P .
If such a plugin arises, just let me know. I would be happy to test it out.

StainlessS
14th June 2013, 20:56
From the link previously given, perhaps of some use. Just need to give clip trims, will auto crop and resize.

EDIT:- SCRIPT REMOVED, See Next post.

Perhaps use ConvertToYV24() beforehand.

StainlessS
17th June 2013, 01:48
Mastrboy,

Perhaps handy for Dynamic cropping of Progressive stuff.

Script removed, see posts #14 to #16

StainlessS
17th June 2013, 18:36
Previous post script updated.

StainlessS
18th June 2013, 04:42
RoboCrop v0.10, update. see 1st post.

Small mod for Auto Thresh Massaging


Here AUTOTHRESH Thresh massaging occurs in sequence:-
1 ) if Thresh == DEFAULT AUTOTHRESH (-32.0, defaulted OR user supplied):
Let FrameRange = FrameEnd-FrameStart+1 (after skipping titles and end Credits, also Samples limited to FrameRange).
Samples_massage = (Samples>=12) ? 1.0 : (Samples-1) * (1.0/(12-1))
Range_massage = (FrameRange >= 1000) ? 1.0 : (FrameRange-1) * (1.0/(1000-1))
Thresh = -(((Samples_massage * Range_massage) * 31.5) + 0.5)
The adjustment to Auto Thresh is to reduce the possibility of overcropping on eg a dark low 'Samples' clip, or where
source FrameRange (ie temporal frame set) is too small to take a reliable sample from.
Resulting massaged Thresh will range between -0.5 and -32.0.
Although massaging is intended to reduce overcropping, it could result in not cropping enough border (less disastrous),
its a bit of a balancing act really.
2 ) If RGB AND PC matrix(default) AND ScaleAutoThreshRGB==True(default) then
Thresh= Thresh*(255.0/(235-16))
3 ) If YUV AND ScaleAutoThreshYUV==True(default=false) then
Thresh= Thresh*(255.0/(235-16))


Blue text describes (badly) the mod, Much safer now in eg DynaCrop script in earlier post.
On synthetic BorderTorture created clip, source had several 18 frame scenes which did not
previously crop well, now crops spot on. clip was a sort of photo shoot with black backdrops
which made it difficult to find cropping on an 18 frame scene. Also, scene change in DynaCrop
script does not get fooled by single white frame flash photography (was already flash proof).

Really happy how it is performing. :)

Now I would like to know how DynaCrop (and by extension RoboCrop) performs on non synthetic dynamic borders.

EDIT: Mastrboy, I'll add a crop log to DynaCrop(), perhaps in form

"Trim(s,e).Crop(x,y,-w,-h)"

or maybe

"Vnnn=Trim(s,e).Crop(x,y,-w,-h)"

Or other, Any preference ?

mastrboy
18th June 2013, 21:54
A lot happened in this thread when I wasn't looking. :)

Only preference I have is that it logs by ranges, and not single frames, unless of course there is a single frame which needs cropping.

Now I only have to find those sources which had these issues and test...

StainlessS
19th June 2013, 09:09
Change of mind, Ill implement user configured log, something like


"V_NNN_=Trim(_S_,_E_).Crop(_X_,_Y_,_-W_,_-H_)"

or

"V_NNN_=Trim(_S_,_E_).Crop(_X_,_Y_,_W_,_H_)"


where '_z_' replaced by numbers.

StainlessS
19th June 2013, 16:46
Update to RoboCrop v0.20 see first post.

Added args, BlankPC, LogFn, LogAppend.

Changed, range massage switch on frames to below 1500 (from 1000).

Range_massage = (FrameRange >= 1500) ? 1.0 : (FrameRange-1) * (1.0/(1500-1))


Split post as overflows 16kb limit

MakeBorderTortureClip.avs

# MakeBorderTortureClip.avs

Function MakeBorderTortureClip(clip c,String "fn") {
# TESTING ONLY
# Make a torture test clip using trims file made by SC_MakeTrimFile() {MUST USE SAME SOURCE FILE AS SC_MakeTrimFile}.
# Use resulting clip as input to DynaCrop().
# Input clip should have plenty of scene changes WITHOUT Blended Scene Transitions.
# Edges will be cropped and synthetic borders added to original size.
# Requires RT_Stats v1.18 for RT_ColorSpaceXMod/YMod.
c
myName="MakeBorderTortureClip: "
fn=Default(fn,"TrimFile.Txt") # input filename
Assert(Exist(fn),myName+"File Not Found "+fn)
c2=0 oldcx=0 oldcy=0 oldcw=0 oldch=0
XMod=RT_ColorSpaceXMod() YMod=RT_ColorSpaceYMod(Laced=false) MX=32/XMod MY=32/YMod
GSCript("""
Lines=RT_FileQueryLines(fn) # Total lines in text file
SS=RT_ReadTxtFromFile(fn) # Complete text file of trims.
For(n=0,Lines-1) {
S=RT_TxtGetLine(SS,Line=n) # Get the trim line
S=RT_StrReplace(S,Chr(9)," ") # Convert any TAB to SPACE
S=Lcase(RT_StrReplaceDeep(S," "," ")) # Convert Multiple SPACE to single SPACE
Start=RT_NumberValue(S) # trim start
S=MidStr(S,FindStr(S," ")+1)
End=RT_NumberValue(S) # trim end
t=Trim(Start,End)
b=true
while(b || (cx==oldcx && cy==oldcy && cw==oldcw && ch==oldch)) { # Make sure some change at every trim
cx=Rand(MX+1)*XMod cy=Rand(MY+1)*YMOD cw=Rand(MX+1)*XMod ch=Rand(MY+1)*YMod
b=false
}
t=t.Crop(cx,cy,-cw,-ch).AddBorders(cx,cy,cw,ch) # create fake borders
c2 = (c2.isClip) ? c2++t : t
old_cx=cx oldcy=cy oldcw=cw oldch=ch # REM for next time
}
""")
return c2
}


MakeBorderTortureClip_Client.avs

# MakeBorderTortureClip_Client.avs

Import("DynaCrop.avs")
Import("MakeBorderTortureClip.avs")

AVISource("D:\AVS\TEST.avi") # TESTING ONLY ON GOOD CLIP WITHOUT BORDERS and NO blended Scene transitions.

#ConvertToYV24() # v2.6 optional, MOD 1 Torture clip and cropping

Return SC_ShowMetrics() # Show metrics to get best Threshold 'th'.
#Return SC_MakeTrimFile() # Make Trims file for MakeBorderTortureClip/DynaCrop, Must Play all way through.

### MUST use SC_MakeTrimFile() to make trims file BEFORE below used.

CROPTHRESH = -32.0 # AUTOMATIC Thresholding, See RoboCrop.
SHOW=True

#Return MakeBorderTortureClip().DynaCrop(CropThresh=CROPTHRESH,show=SHOW).ConvertToYV12() # Show croppings

#MakeBorderTortureClip() # MAKE A SOURCE TORTURE CLIP for DynaCrop_Client test
#ConvertToYV12()

StainlessS
19th June 2013, 16:47
Also see previous post, RoboCrop Update.

DynaCrop.AVS

######################
# DynaCrop.AVS v1.01 - Script, by StainlessS.
# Crop dynamically changing borders from PROGRESSIVE clip. Requires GScript, Grunt, RT_Stats v1.18, RoboCrop v0.20.
# Will NOT Work well with blended scene transitions.
######################

Function SC_ShowMetrics(clip c,float "th",float "th2",int "x",int "y",int "w",int "h",bool "fast") {
# For Setting th (and less often th2) for SC_MakeTrimFile().
# Above th is Scene Change (Curr->Next).
# th2 governs NOT SCENE CHANGE decisions Prev->Curr and Next->(Next+1). Should be less than th. Default 0.8 * th.
# x,y,w,h sets border to ignore crud.
# Metric used sort of like:- mt_lutxy(mt_polish("((x-y)/4)^2")).AverageLuma()
c
th=Float(Default(th,80.0)) # About 80.0 seems good for fast/slow motion
th2=Float(Default(th2,0.8*th)) # Default th2 set 0.8 * th
x=default(x,16) y=default(y,16) w=default(w,-16) h=default(h,-16) # avoid crud
Fast=Default(Fast,True)
Global SCM_B=0.0 Global SCM_C=0.0 Global SCM_sc=False Global SCM_Prev=-2 # Init vars, SCM_Prev=-2 forces initalize
ScriptClip("""
# If jumped about, get values for Previous frame, else keep same.
NotNext = (current_frame!=SCM_Prev+1)
Global SCM_A=(NotNext)? RT_LumaSceneChange(Last,Last,n=current_frame-2,n2=current_frame-1,x=x,y=y,w=w,h=h) : SCM_A
Global SCM_B=(NotNext)? RT_LumaSceneChange(Last,Last,n=current_frame-1,n2=current_frame ,x=x,y=y,w=w,h=h) : SCM_B
Global SCM_C=(NotNext)? RT_LumaSceneChange(Last,Last,n=current_frame, n2=current_frame+1,x=x,y=y,w=w,h=h) : SCM_C
psc=(NotNext) ? (SCM_A<th2 && SCM_B>=th && SCM_C<th2) : SCM_SC
# Pass the parcel
Global SCM_A=SCM_B
Global SCM_B=SCM_C
Global SCM_C=RT_LumaSceneChange(Last,Last,n=current_frame+1,n2=current_frame+2,x=x,y=y,w=w,h=h) # diff(next,next+1)
# Prev->Curr NOT Scene Change AND Curr->Next IS Scene Change AND Next->(Next+1) NOT Scene Change
Global SCM_SC=((SCM_A<th2 && SCM_B>=th && SCM_C<th2) || current_frame==FrameCount()-1) # Last frame in scene ?
Subtitle(String(current_frame)+"] "+String(SCM_A,"%6.2f")+" "+String(SCM_B,"%6.2f")+" "+String(SCM_C,"%6.2f")+\
"\nTh="+String(th,"%.1f")+" Th2="+String(th2,"%.1f"),lsp=0)
(SCM_SC) ? Subtitle("END OF SCENE", align=1,size=30) : NOP
(psc||current_frame==0) ? Subtitle("START OF SCENE",align=3,size=30) : NOP # 1st frame in scene, Previous was Last frame in scene
Global SCM_Prev=current_frame
Return Last
""",args="th,th2,x,y,w,h") # Needs Grunt for args
return ((Fast)?AssumeFPS(250.0):Last).KillAudio()
}


Function SC_MakeTrimFile(clip c,float "th",float "th2",int "x",int "y",int "w",int "h",bool "fast",String "Fn") {
# Must play all way through, no jumping about. Set th using SC_ShowMetrics()
# Creates output file, list of trims for DynaCrop() {ALSO for MakeBorderTortureClip() to create a TEST clip}
# Above th is Scene Change (Curr->Next).
# th2 governs NOT SCENE CHANGE decisions Prev->Curr and Next->(Next+1). Should be less than th. Default 0.8 * th.
# x,y,w,h sets border to ignore crud.
# Metric used sort of like:- mt_lutxy(mt_polish("((x-y)/4)^2")).AverageLuma()
c
myName="SC_MakeTrimFile: "
th=Float(Default(th,80.0)) # About 80.0 seems good for fast/slow motion
th2=Float(Default(th2,0.8*th)) # Default th2 set 0.8 * th
x=default(x,16) y=default(y,16) w=default(w,-16) h=default(h,-16) # avoid crud
Fast=Default(Fast,True)
Fn=Default(Fn,"TrimFile.Txt")
(Exist(Fn)) ? RT_FileDelete(Fn) : NOP # Delete existing
Global SCM_B=0.0 Global SCM_C=0.0 Global SCM_Prev=-1 Global SCM_Start=0 Global SCM_NotNext=false # Init vars
ScriptClip("""
Global SCM_NotNext = (current_frame!=SCM_Prev+1 || SCM_NotNext) # Lock NotNext global if error
(SCM_NotNext && Exist(Fn)) ? RT_FileDelete(Fn) : NOP # Spank user for jumping about :)
Assert(SCM_NotNext==false,myName+"Cannot seek whilst making trims file "+fn) # Message on frame ONLY, no abort
# Pass the parcel
Global SCM_A=SCM_B
Global SCM_B=SCM_C
Global SCM_C=RT_LumaSceneChange(Last,Last,n=current_frame+1,n2=current_frame+2,x=x,y=y,w=w,h=h)
# Prev->Curr NOT Scene Change AND Curr->Next IS Scene Change AND Next->(Next+1) NOT Scene Change
SC=((SCM_A<th2 && SCM_B>=th && SCM_C<th2) || current_frame==FrameCount()-1)
(SC && !SCM_NotNext) ? RT_TxtWriteFile(String(SCM_Start)+" "+String(current_frame),Fn,append=True) : NOP
Global SCM_Start = (SC) ? current_frame + 1 : SCM_Start
Global SCM_Prev=current_frame
Return Last
""",args="th,th2,x,y,w,h,fn,myName") # Needs Grunt for args
return ((Fast)?AssumeFPS(250.0):Last).KillAudio()
}


Function DynaCrop(clip c,String "fn",int "W",int "H",String "Resizer",Float "CropThresh",bool "Show",String "LogFn",String "LogTMPT",bool "Debug") {
# Auto crop list of trims in filename 'fn' and resize to WxH using 'Resizer' <Default = "Spline64Resize(_W_,_H_)">
# CropThresh is RoboCrop thresh. Show is RoboCrop Show.
# 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_"+(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"
# Requires RoboCrop v0.20 for RoboCrop output LogFile, to get crop coords.
#########################################
# Log TEMPLATE Replacements
# "_NNNN_" = trim 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.
#########################################
c
myName="DynaCrop:"
c2 = 0
fn=Default(fn,"TrimFile.Txt") # input filename
_W_=Default(W,width) _H_=Default(H,height)
Resizer=Default(Resizer,"Spline64Resize(_W_,_H_)") # Resizer to use
TResizer="t."+Resizer
LogTMPT=Default(LogTMPT,"V_NNNN_ = Trim(_S_,_E_).Crop(_CX_,_CY_,_-CW_,_-CH_)._RSZ_"+Chr(9)+Chr(9)+"# Crop_W= _CW_ Crop_H= _CH_" )
LogFn=Default(LogFn,"DynaCrop.log")
Debug=Default(Debug,false)
Assert(Exist(fn),myName+" File Not Found "+fn)
(Exist(LogFn)) ? RT_FileDelete(LogFn) : NOP # Delete existing Log
Lines=RT_FileQueryLines(fn) # Total lines in text file
SS=RT_ReadTxtFromFile(fn) # Read complete text file into string
EOL=Chr(10)
FND="_RSZ_"+EOL+"_NNNN_"+EOL+"_S_"+EOL+"_E_"+EOL+"_CX_"+EOL+"_CY_"+EOL+"_CW_"+EOL+"_CH_"+EOL+"_-CW_"+EOL+"_-CH_"+EOL+"_W_"+EOL+
\ "_H_"+EOL+"_IW_"+EOL+"_IH_"+EOL
TmpLog="DynaCropTmp~.log"
(Exist(TmpLog)) ? RT_FileDelete(TmpLog) : NOP # Delete existing TmpLog
GSCript("""
for(n=0,Lines-1) {
S=RT_TxtGetLine(SS,Line=n) # Get the trim line
S=RT_StrReplace(S,Chr(9)," ") # Convert any TAB to SPACE
S=Lcase(RT_StrReplaceDeep(S," "," ")) # Convert Multiple SPACE to single SPACE
Start=RT_NumberValue(S)
S=MidStr(S,FindStr(S," ")+1)
End=RT_NumberValue(S)
t=Trim(Start,End) # Get current trim
t=t.RoboCrop(thresh=CROPTHRESH,laced=False,show=Show,debug=Debug,LogFn=TmpLog,LogAppend=false)
if(LogFn!="" && Exist(TmpLog)) {
ts= RT_ReadTxtFromFile(TmpLog)
Crop_x=RT_NumberValue(ts)
ts=MidStr(ts,FindStr(ts," ")+1)
Crop_y=RT_NumberValue(ts)
ts=MidStr(ts,FindStr(ts," ")+1)
Crop_w=RT_NumberValue(ts)
ts=MidStr(ts,FindStr(ts," ")+1)
Crop_h=RT_NumberValue(ts)
REP =
\ Resizer + EOL +
\ RT_NumberString(n,width=4) + EOL +
\ RT_NumberString(Start) + EOL +
\ RT_NumberString(End) + EOL +
\ RT_NumberString(crop_x) + EOL +
\ RT_NumberString(crop_y) + EOL +
\ RT_NumberString(crop_w) + EOL +
\ RT_NumberString(crop_h) + EOL +
\ RT_NumberString(crop_w -(Width - crop_x)) + EOL +
\ RT_NumberString(crop_h -(Height - crop_y)) + EOL +
\ RT_NumberString(_W_) + EOL +
\ RT_NumberString(_H_) + EOL +
\ RT_NumberString(Width) + EOL +
\ RT_NumberString(Height) + EOL
LOG=RT_StrReplaceMulti(LogTMPT,FND,REP)
RT_TxtWriteFile(LOG,LogFn,append=True)
}
t=Eval(TResizer) # Resize using optional resizer
c2 = (c2.isClip) ? c2++t : t # Splice
}
(Exist(TmpLog)) ? RT_FileDelete(TmpLog) : NOP # Delete temp Log
""")
return c2
}



DynaCrop_Client.avs

# DynaCrop_Client.avs

Import("DynaCrop.avs")

#AVISource("D:\AVS\TEST.avi")
AVISource("D:\AVS\BORDERTORTURE.avi") # Pre-Prepared TORTURE test clip

#ConvertToYV24() # Optional v2.6, MOD 1 crop coords

Return SC_ShowMetrics().ConvertToYV12() # Show metrics to get best Threshold 'th', use bofore SC_MakeTrimFile().
#Return SC_MakeTrimFile().ConvertToYV12() # Make Trims file for DynaCrop(), Must Play all way through.

### MUST use SC_MakeTrimFile() to make trims file BEFORE below used.

CROPTHRESH = -32.0 # AUTOMATIC Thresholding, See RoboCrop.
SHOW=True # SHOW WHAT WHAT WILL BE CROPPED
DEBUG=False # RoboCrop Debug

#Return DynaCrop(CropThresh=CROPTHRESH,show=SHOW,debug=DEBUG).ConvertToYV12()



DynaSplice.avs

# DynaSplice.avs # Joins trims file generated as DEFAULT DynaCrop logfile.

Function SpliceTrimsString(String VideoString,int maxim,int "Wid") {
Wid=Default(Wid,4)
GSCript("""
S=""
for(i =0,maxim) {
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("D:\AVS\BORDERTORTURE.avi") # Pre-Prepared TORTURE test clip

#ConvertToYV24() # v2.6 optional, Mod 1 Cropping

TRIMSFILE="Dynacrop.log" # Created by DynaCrop default logging.

TRIMS=RT_ReadTxtFromFile(TRIMSFILE) # Or Import()
Lines=RT_TxtQueryLines(TRIMS) # Total lines in text file (Or RT_FileQueryLines)
SPLICE=SpliceTrimsString("V",Lines-1) # Zero Relative
Eval(TRIMS) # Eval trims,crop,resize
Eval(SPLICE) # Splice trims

ConvertToYV12()

StainlessS
19th June 2013, 16:51
Split post due to 16kb limit. See two previous posts.


Trims file Generated by SC_MakeTrimFile()

0 215
216 233
234 334
335 442
443 520
521 637
638 711
712 798
799 816
817 843
844 1018
1019 1131
1132 1298
1299 1329
1330 1450
1451 1569
1570 1744
1745 1856
1857 1917
1918 2010
2011 2055
2056 2118
2119 2236
2237 2392
2393 2473
2474 2723
2724 3410
3411 3505
3506 3608
3609 3684
3685 3769
3770 4143
4144 4212
4213 4685
4686 5202
5203 5449
5450 5791
5792 5822


Default Logfile Generated by DynaCrop() {User configurable}

V0000 = Trim(0,215).Crop(8,20,-31,-1).Spline64Resize(640,400) # Crop_W= 601 Crop_H= 379
V0001 = Trim(216,233).Crop(29,16,-27,-21).Spline64Resize(640,400) # Crop_W= 584 Crop_H= 363
V0002 = Trim(234,334).Crop(1,11,-29,-29).Spline64Resize(640,400) # Crop_W= 610 Crop_H= 360
V0003 = Trim(335,442).Crop(16,30,-28,-29).Spline64Resize(640,400) # Crop_W= 596 Crop_H= 341
V0004 = Trim(443,520).Crop(25,29,-9,-24).Spline64Resize(640,400) # Crop_W= 606 Crop_H= 347
V0005 = Trim(521,637).Crop(18,18,-8,-21).Spline64Resize(640,400) # Crop_W= 614 Crop_H= 361
V0006 = Trim(638,711).Crop(28,7,-30,-5).Spline64Resize(640,400) # Crop_W= 582 Crop_H= 388
V0007 = Trim(712,798).Crop(17,29,-2,-12).Spline64Resize(640,400) # Crop_W= 621 Crop_H= 359
V0008 = Trim(799,816).Crop(20,21,-21,-13).Spline64Resize(640,400) # Crop_W= 599 Crop_H= 366
V0009 = Trim(817,843).Crop(26,31,-7,-27).Spline64Resize(640,400) # Crop_W= 607 Crop_H= 342
V0010 = Trim(844,1018).Crop(26,18,-5,-6).Spline64Resize(640,400) # Crop_W= 609 Crop_H= 376
V0011 = Trim(1019,1131).Crop(18,11,-27,-22).Spline64Resize(640,400) # Crop_W= 595 Crop_H= 367
V0012 = Trim(1132,1298).Crop(5,4,-5,-23).Spline64Resize(640,400) # Crop_W= 630 Crop_H= 373
V0013 = Trim(1299,1329).Crop(25,21,-6,-22).Spline64Resize(640,400) # Crop_W= 609 Crop_H= 357
V0014 = Trim(1330,1450).Crop(11,6,-7,-19).Spline64Resize(640,400) # Crop_W= 622 Crop_H= 375
V0015 = Trim(1451,1569).Crop(7,32,-14,-27).Spline64Resize(640,400) # Crop_W= 619 Crop_H= 341
V0016 = Trim(1570,1744).Crop(24,10,-31,-32).Spline64Resize(640,400) # Crop_W= 585 Crop_H= 358
V0017 = Trim(1745,1856).Crop(25,10,-23,-12).Spline64Resize(640,400) # Crop_W= 592 Crop_H= 378
V0018 = Trim(1857,1917).Crop(17,30,-16,-5).Spline64Resize(640,400) # Crop_W= 607 Crop_H= 365
V0019 = Trim(1918,2010).Crop(24,15,-6,-17).Spline64Resize(640,400) # Crop_W= 610 Crop_H= 368
V0020 = Trim(2011,2055).Crop(27,17,-27,-22).Spline64Resize(640,400) # Crop_W= 586 Crop_H= 361
V0021 = Trim(2056,2118).Crop(12,26,-16,-17).Spline64Resize(640,400) # Crop_W= 612 Crop_H= 357
V0022 = Trim(2119,2236).Crop(5,7,-15,0).Spline64Resize(640,400) # Crop_W= 620 Crop_H= 393
V0023 = Trim(2237,2392).Crop(8,4,-26,-22).Spline64Resize(640,400) # Crop_W= 606 Crop_H= 374
V0024 = Trim(2393,2473).Crop(14,3,-27,-8).Spline64Resize(640,400) # Crop_W= 599 Crop_H= 389
V0025 = Trim(2474,2723).Crop(15,29,-19,-24).Spline64Resize(640,400) # Crop_W= 606 Crop_H= 347
V0026 = Trim(2724,3410).Crop(0,30,-18,-29).Spline64Resize(640,400) # Crop_W= 622 Crop_H= 341
V0027 = Trim(3411,3505).Crop(26,12,-5,-2).Spline64Resize(640,400) # Crop_W= 609 Crop_H= 386
V0028 = Trim(3506,3608).Crop(29,31,0,-21).Spline64Resize(640,400) # Crop_W= 611 Crop_H= 348
V0029 = Trim(3609,3684).Crop(14,30,-15,-12).Spline64Resize(640,400) # Crop_W= 611 Crop_H= 358
V0030 = Trim(3685,3769).Crop(28,24,-20,-24).Spline64Resize(640,400) # Crop_W= 592 Crop_H= 352
V0031 = Trim(3770,4143).Crop(14,17,-27,-31).Spline64Resize(640,400) # Crop_W= 599 Crop_H= 352
V0032 = Trim(4144,4212).Crop(5,7,-26,-28).Spline64Resize(640,400) # Crop_W= 609 Crop_H= 365
V0033 = Trim(4213,4685).Crop(12,10,-7,-31).Spline64Resize(640,400) # Crop_W= 621 Crop_H= 359
V0034 = Trim(4686,5202).Crop(21,29,-22,-18).Spline64Resize(640,400) # Crop_W= 597 Crop_H= 353
V0035 = Trim(5203,5449).Crop(13,11,0,-21).Spline64Resize(640,400) # Crop_W= 627 Crop_H= 368
V0036 = Trim(5450,5791).Crop(29,32,-1,-23).Spline64Resize(640,400) # Crop_W= 610 Crop_H= 345
V0037 = Trim(5792,5822).Crop(32,9,-20,-31).Spline64Resize(640,400) # Crop_W= 588 Crop_H= 360


EDIT:
Only preference I have is that it logs by ranges

Trims file generated by SC_MakeTrimFile() produces 1st file above.

EDIT: Found a fairly popular DVD that SC_MakeTrimFile fails on quite badly, X-Men II.
The lady in the blue rubber naked suit (forgot her name), has different cropping whenever she is on screen,
so I thought I would try the Dynacrop thing, and SC_MakeTrimFile is way off recognizing many scene changes.
Some scene changes require a th of about 16.0 (default 80.0) so is a long way off. Going to have to add chroma
to scene change detection or figure out a better way of doing it.

StainlessS
21st June 2013, 18:34
Here, just an experiment to see if we understood how SCSelect works.

Avisource("D:\avs\test.avi")

# RemoveDirt's SCSelect(clip input, clip scene_begin, clip scene_end, clip global_motion, float dfactor, bool debug, bool planar)

Function SCSelect_Like(clip dclip,clip Start,clip End,clip Motion, float "dfactor",bool "debug") {
# Start, End, Motion MUST all be same, dclip can be other colorspace/size (unlike SCSelect).
dfactor=Float(Default(dfactor,4.0))
debug=Default(debug,false)
Global SCM_A=0.0 Global SCM_B=0.0 Global SCM_SC=0 Global SCM_Prev=-1
Motion.ScriptClip("""
NotNext = (current_frame!=SCM_Prev+1)
Global SCM_A=(NotNext)? RT_LumaDifference(dclip,dclip,n=current_frame-1,n2=current_frame) : SCM_B
Global SCM_B= RT_LumaDifference(dclip,dclip,n=current_frame,n2=current_frame+1)
# 0 = Start of scene, 1 = End of scene, 2 = Global motion
Global SCM_SC=(current_frame==FrameCount-1)?1:(SCM_A>dfactor*SCM_B || current_frame==0)?0:(SCM_B>dfactor*SCM_A)?1:2
(SCM_SC==0) ? Start : (SCM_SC==1) ? End : Last # Choose Start, End or Motion(ie Last)
(debug)?RT_Subtitle("%d ] %6.2f %6.2f SC=%d",current_frame,SCM_A,SCM_B,SCM_SC):NOP
Global SCM_Prev=current_frame
Return Last
""",args="dfactor,Start,End,Dclip,debug") # Needs Grunt for args
return Last
}

Start=Subtitle("START OF SCENE",align=3,size=30)
End=Subtitle("END OF SCENE", align=1,size=30)
Motion=Subtitle("GLOBAL MOTION",align=5,size=30)
L=SCSelect_Like(Last,Start,End,Motion,debug=true)
R=SCSelect(Last,Start,End,Motion)
StackHorizontal(L,R)

EDITED:

EDIT: It's not what I could call reliable, unmatched start/end scene, completely messes up on flash photography.
I'm quite surprised that people use SCSelect at all.

StainlessS
10th July 2013, 22:54
RoboCrop v0.21, Update, see 1st post.

Changed default samples to 32, modified Thresh Massaging, generally a bit more paranoia.

StainlessS
11th September 2013, 00:04
RoboCrop v1.00, beta status removed (Atm arg added). See 1st post.

EDIT: current RT_Stats zip contains updates to previous given scripts eg DynaCrop.avs.

FredThompson
23rd November 2013, 18:45
Mediafire link is a 404. Did you intend to have an updated script set there?

I am looking for a way to autocrop frames such as the attached screenshot. Preferred method would be a scan of an entire file with the minimal crop values returned. Seems the entire stream should be checked due to the variable cropping mentioned above. Results will be used to generate encoder scripts with video bitrate a function of post-cropped frame-size. My hope is to use RoboCrop in a pre-scan to generate crop values for each file in the queue, preserving field order and block sizes so crap and frame would be the result. Output from RoboCrop would probably go into a file with a format similar to:

filename
cropx1
cropx2
cropy1
cropy2
framewidth
frameheight

or something similar which can be easily parsed by a batch file. End result of my process will be a job queue of various frame sizes, rates and source codecs which can be loaded into Hybrid encoding GUI for a "encode all in directory to a target quality/size" process.

Another example of this type of unwanted junk is at:

http://forum.doom9.org/showthread.php?p=1651430#post1651430

Notice how close the noise is to the desired video data. Perhaps a grayscale vs. chroma determination would help.

I assume this is extra junk that DirecTV uses for the guide data or extra information for a show, maybe it's the bitmap for the recorded show.

Background to this project is at:

http://forum.doom9.org/showthread.php?t=169673

StainlessS
23rd November 2013, 19:07
Sorry Fred, MediaFire problem, hopefully just temporary but till fixed try here: LINK REMOVED

StainlessS
23rd November 2013, 19:11
Sorry, even that one seems to have a problem, except for me, try again here: LINK REMOVED

EDIT:
Arh, see what you mean, the updated scripts are in RT_Stats zip here: LINK REMOVED

StainlessS
23rd November 2013, 19:17
See Above Edit Fred.

FredThompson
23rd November 2013, 19:44
Thanks. I've edited my previous post to expand on the goals of my current project. Would appreciate any help you will offer.

StainlessS
23rd November 2013, 20:11
Mediafire link is a 404. Did you intend to have an updated script set there?

I am looking for a way to autocrop frames such as the attached screenshot. Preferred method would be a scan of an entire file with the minimal crop values returned. Seems the entire stream should be checked due to the variable cropping mentioned above. Results will be used to generate encoder scripts with video bitrate a function of post-cropped frame-size. My hope is to use RoboCrop in a pre-scan to generate crop values for each file in the queue, preserving field order and block sizes so crap and frame would be the result. Output from RoboCrop would probably go into a file with a format similar to:

filename
cropx1
cropx2
cropy1
cropy2
framewidth
frameheight

or something similar which can be easily parsed by a batch file. End result of my process will be a job queue of various frame sizes, rates and source codecs which can be loaded into Hybrid encoding GUI for a "encode all in directory to a target quality/size" process.

Another example of this type of unwanted junk is at:

http://forum.doom9.org/showthread.php?p=1651430#post1651430

Notice how close the noise is to the desired video data. Perhaps a grayscale vs. chroma determination would help.

I assume this is extra junk that DirecTV uses for the guide data or extra information for a show, maybe it's the bitmap for the recorded show.

Background to this project is at:

http://forum.doom9.org/showthread.php?t=169673

I would need to disable the auto start/end credits skipping, and give alternative method of selecting samples, eg percentage of frames to scan (maybe user calc something like 100.0 / FrameRate for 1 frame per second, scanned, or 10.0 % for 1 in ten scanned). Have to think about the morse code stuff, and waiting to see attachment.

FredThompson
24th November 2013, 03:35
Yes, I was thinking about 1 frame every 15 or 30 frames through the whole file. It's a very different use than you've envisioned but a related concept.

Letterboxed source with the "morse code" is fairly easy because there will be a number of near-black lines above and below the source. Test from the bottom then use that indicate relative upper cutoff location.

Non-letterboxed source with that crap in the top few lines is the challenge. Sometimes it's one line, The sample I made is probably the most complex I've seen, four or five lines. That's a LOT of extra data. My original idea was to overwrite those lines with black to preserve aspect ratio.

The DirecTV files I have with the crap in them are all 480x480 or 544x480 SD. If there are other formats with junk, I don't know about them.

StainlessS
24th November 2013, 16:59
Having seen you attachment, think all that really is needed is avoid start/end credits skipping. You can calc samples as FrameCount / 30
or whatever and the Baffle setting would avoid the morse code anyway (can set higher than default 4), setting Blank to true would blank
out the border area. Would work best if converted to YV24 allowing blanking of individual scanlines.
Ill add something to avoid credits skipping and let you have a try with that.

EDIT:
Non-letterboxed source with that crap in the top few lines is the challenge. Sometimes it's one line,

Not sure that single line of morse could be detected if no additional lines of black. The Baffle setting controls the minimum
number of consecutive lines that have to be above Threshold, to be detected as image rather than border.
Your attachment should be no problem but baffle might need be raised if morse thicker than Baffle default of 4.

FredThompson
25th November 2013, 19:27
thanks.

StainlessS
25th November 2013, 20:31
Fred can you up a sample somewhere, think I got an idea that might work for morse without letterboxing, about two minutes should do.

FredThompson
25th November 2013, 22:11
Fantastic news! Yes, am putting one up now. Will send you a PM with a link.

StainlessS
29th November 2013, 15:27
Link to MediaFire in sig now working OK, removed temp links.

jmac698
1st December 2013, 03:49
Feature request,
Hi, it's the season for planet cropping again, and I just came up with a really clean way to do it. What I'd like is a tracking crop. What this means is that, I supply frame1 and frame100 and it computes the cropping values for each, then draws a linear line between them, and uses that for the search zone.

In the ideal case, planets move in a perfect straight line across the camera as the earth turns. But it's not exactly because of lens distortions and other things. You can speed up cropping tremendously by tracking the search area. Sometimes I'm tracking only 20x20 pixels in a 16MP image. There's also the possibility of passing by some other bright object that can fool plain luma detection.

So the parameters would be, start/end frame to find endpoint locations, initial search window w/h/x/y, and tween search window size, and all the usual detection parameters. Also the option for simple tracking with no detection at all in the tweens.

some samples here
http://imgur.com/FnbRhes,wOBrbPf,E2y7UUy,lOBJ5oT,NQOEk3y,GIBgUhD#0

StainlessS
1st December 2013, 19:24
Jmac, surely animate could be persuaded to do that.

EDIT: Also, see no real advantage to 'tracking' estimate to were planets are, the RT_YInRangeLocate fn
in PlanetCrop is really quite fast and I dont really fancy spending quite a lot of time coding to save a second
or two every now and then.

StainlessS
17th January 2014, 05:05
RoboCrop v1.03, updated 26 Dec 2013.


v0.20, Changed, range massage switch on frames to below 1500 (from 1000).
v0.21, Autothresh Massaging changed minimum to -1.5 from -0.5.
v1.00, Added ATM arg.
v1.02, Added Start & End args, Changed default rec709 switch to width > 1100 || height > 600.
v1.03, Minor mods.

Reginald0
11th October 2014, 01:58
Hi, folks! Sorry if I miss something in the doc, but is it possible to adjust specific values like in the AutoCrop plugin?

AutoCrop(mode=0, leftadd=4, rightadd=2, topadd=8, bottomadd=6)

StainlessS
11th October 2014, 17:52
Suggest trying a greater value of auto Thresh (greater being more -ve). I wish now that I had used a more -ve default AutoThresh (is -32.0),
I sometimes find that RoboCrop() does leaves a little dark line (which is perhaps about AverageLuma ~48.0 to ~56.0, but still appears as dark edge
when adjacent to lighter image). If I have a problem clip (maybe about 1 in 30 or 40, or thereabouts), I just try a Thresh of eg -50.0 sometimes takes -64.0, and the line disappears. Might also prove better with the occasional clip to raise Baffle to eg 8 from default 4. AutoCrop() would also fail with the problem clips leaving a line,
but a lot more often and with worse results, AutoCrop gets it wrong a lot more often than RoboCrop and occasionally eats up more image than it leaves intact.
I would suggest that you try the above fix (make Thresh more -ve), and if not satisfactory, then will look at adding the suggested args, (LeftAdd etc).

EDIT: I have a 10min sample VOB from Cabaret (Liza Minnelli) that AutoCrop crops about 200 pixels both left and right sides, rather than maybe about 4 pixels either side (default settings). RoboCrop gets it bang on correct with only a single sample (Default 32, although it would depend upon which frame was chosen to sample, AutoCrop and RoboCrop do not use similar methods to select sample frames).

StainlessS
13th October 2014, 01:07
v1.13 Docs, part 1 of 2 (Post #1 only has v1.0 docs due to draconian D9 post size restrictions)

RoboCrop()

To Protect And Serve - by StainlessS @ Doom9:- http://forum.doom9.org/showthread.php?t=168053
Requires VS2008 CPP Runtimes.

VIDEO: Planar, YUY2, RGB (Must be Seekable ie best not DivX or XVid).
AUDIO: No change.

Plugin's for both Avisynth v2.58 and v2.6 (avs+ x86 & x64).

RoboCrop is an automatic cropping solution to crop black borders from video clips, loosely based on (but using no code from)
Autocrop by Glenn Bussell.

For the most part, you can just call it with RoboCrop(clip) and not bother with any other arguements, it is intended to be pretty
much autonomous in its decisions. You might however want to alter eg WMod/HMod if your encoder has special requirements, and
perhaps Laced if your source is likely to be fully progressive.

Borders are detected by sampling at Samples frames, at scanlines (h/v) using AverageLuma (RGB is converted to Luma Y at either TV or
PC levels, See Matrix). This sampling is done on all 4 sides of the frame.
If a scanline Average luma is below or equal to Thresh, then is considered possible black border, above considered possible image,
if Baffle [default=4] adjacent scanlines above Thresh, then it IS image.

Function RoboCrop(clip c,int "Samples"=40,Float "Thresh"=-40.0,bool "Laced"=true,int "WMod",int "HMod",int "RLBT"=15,bool "Debug"=false, \
float "Ignore"=0.4,int "Matrix"=(c.Width>1100||c.Height>600?3:2), int "Baffle"=4, bool "ScaleAutoThreshRGB"=true,
bool "ScaleAutoThreshYUV"=false, int "CropMode"=2,bool "Blank"=false,bool "BlankPC"=false,bool "Align"=True,bool "Show"=false, \
String "LogFn"="",bool "LogAppend"=false, Float "ATM"=4.0,int "Start"=Undefined,Int "End"=Undefined, \
Int "LeftAdd"=0,Int "TopAdd"=0,Int "RightAdd"=0,Int "BotAdd"=0, \
Int "LeftSkip"=0,Int "TopSkip"=0,Int "RightSkip"=0,Int "BotSkip"=0 \
Float "ScanPerc=49.0,String "Prefix"="ROBOCROP_" )


Args:-

Samples=40, Number of frames to sample from source clip c. v1.06 changed default from 32 to 40.
As an observation, most clips have good border recogition within the 1st 2 or 3 sampled frames using the default -40.0 AUTOTHRESH
although have noticed some dark clips that required ~8 samples (maybe more) for full recognition @ default Thresh = -40.0
We use a default Samples=40, because we are intrinsically paranoid.
If number of frames between frame at 5% of framecount and frame at 90% of framecount is greater than 250 and is also greater
than Samples, will ignore the first 5% and last 10% of frames when both auto-thresholding and crop sampling to try to negate
effects of artificial black in titles and end credits. Can override the Auto Credits skipping by setting Start and/or End frame
of the range to sample.
Samples = 0, will be converted to Samples = FrameCount, ie auto credits skipping disabled and ALL FRAMES SAMPLED,
of use for very short scenes, not for general full movie clips.
Set eg Samples = Int(FrameCount * 2.0 / 100.0 + 0.5) to sample 2.0% of frames in clip.

Thresh: Default= -40.0 (==DEFAULT AUTOTHRESH, any -ve (or 0.0) Thresh is AUTOTHRESH where Thresh adjustments are automatic).
v1.06, Changed DEFAULT AUTOTHRESH from -32.0 to -40.0.
v1.07, Changed to recognise a Thresh of either -32.0 or -40.0 as DEFAULT_AUTOTHRESH (fully automatic).

Thresh > 0: (Explicit Threshold)
A user supplied +ve Thresh should be at correct TV/PC levels for the the clip being worked on ie 16->235 for TV levels and
0->255 for PC Levels (RGB, as appropriate for matrix being used).

Thresh <= 0: (AUTOTHRESH)
When Thresh <= 0, the clip will be sampled over Samples frames to find the minimum YPlaneMin (using Matrix if RGB) which
we will call MINLUMA and an Explicit Threshold calculated by adding MINLUMA to abs(Thresh), after that it is processed
as for Thresh > 0: (Explicit Threshold) as noted above, but, before adding MINLUMA, some AUTOTHRESH massaging and scaling occurs.

Here AUTOTHRESH Thresh massaging and scaling occurs in sequence:-
1 ) if (Thresh == DEFAULT AUTOTHRESH && ATM < abs(thresh))
(DEFAULT AUTOTHRESH = exactly -40.0, defaulted OR user supplied, v1.07 also recognises -32.0 as DEFAULT_AUTOTHRESH):
Let sampstart and sampend, be starting and ending frames numbers after any Auto Credits skipping and/or user set Start or End.
Let Samples be limited to sampend-sampstart+1.
Let SampRange (Sample Range) = SampEnd-SampStart+1.
samples_massage =(Samples>=20) ? 1.0 : (Samples-1) * (1.0/(20-1)) # No massaging if Samples >= 20
range_massage =(SampRange >= (250*20)) ? 1.0 : (SampRange-1) * (1.0/((250*20)-1)) # No massaging if SampRange >= 5000
Both samples_massage and range_massage will be in range 0.0 to 1.0.
Thresh = -(((samples_massage * range_massage) * (abs(Thresh) - ATM)) + ATM)
This adjustment to Auto Thresh is to reduce the possibility of overcropping on eg a dark low 'Samples' clip, or where
source SampRange (ie temporal frame set) is too small to take a reliable sample from.
Resulting massaged Thresh will range between -ATM and DEFAULT_AUTOTHRESH.
Although massaging is intended to reduce overcropping, it could result in not cropping enough border (less disastrous),
its a bit of a balancing act really. See also ATM.
2 ) If RGB AND PC matrix(default) AND ScaleAutoThreshRGB==True(default) then
Thresh= Thresh*(255.0/(235-16))
3 ) If YUV AND ScaleAutoThreshYUV==True(default=false) then
Thresh= Thresh*(255.0/(235-16))

Steps 2) and 3) above, by default treat a -ve AUTOTHRESH as being @ TV Levels and so Scale RGB Thresh to PC levels but not YUV.
If you want to supply a PC levels AUTOTHRESH Thresh for RGB, then simply set ScaleAutoThreshRGB=false to inhibit scaling.
Note, if a TV levels Matrix is supplied for RGB, then scaling will always be inhibited.
If your clip is YUV at PC levels and you want to use eg DEFAULT AUTOTHRESH (-40.0, which is considered to be @ TV levels),
then set ScaleAutoThreshYUV=True to enable Thresh scaling.
If your clip is YUV at PC levels and you want to use a PC levels AUTOTHRESH (-ve) then leave ScaleAutoThreshYUV at default false
which does not scale Thresh.
After any scaling, MINLUMA is then added to abs(Thresh) and processed as for +ve Explicit Threshold as noted above.
NOTE, Above RoboCrop step 1) 'massages' DEFAULT_AUTOTHRESH (exactly -40.0 or v1.07 exactly -32.0) if low samples count or if short clip.
Reason being to avoid overcropping when insufficient data available for reliable cropping. It is considered better to not crop enough
or at all, than to overcrop. You can override by simply setting an explicit threshold (+ve) of eg 40.0, or setting a NON-DEFAULT auto thresh
(-ve) eg -16.0 or -40.1, where YPlaneMin is established for the sampled frames and then abs(thresh) is added to that value which
is then used as an explicit thresh.
NOTE, v1.07 recognises a Thresh of either -40.0 OR -32.0 as DEFAULT_AUTOTHRESH, so user can provide either value and
DEFAULT_AUTOTHRESH massaging will be applied for low samples count and/or low frame ranges.

Laced:, Default=true, true for Interlaced.
RoboCrop automatically deduces colorspace cropping restrictions and sets internal XMod and YMod,
eg XMod and YMod would both be set to 2 for YV12, for YUY2 Xmod=2, YMod=1, etc.
If Laced==true(default), then internal YMod is doubled so as not to destroy interlaced chroma.
Below HMod is defaulted to internal YMod after the Laced hint is applied to YMod.
You can set Laced=False if your source is known Progressive, if your dont then you may lose a few scanlines.

WMod:, Default=Max(XMOD,4), Where XMOD is the natural chroma cropping restriction of the colorspace concerned, eg 2 for YV12.
WMod MUST be a multiple of internal XMOD as described above, or it will throw an error.
v1.06, Changed default from XMOD to Max(XMOD,4), this is for several reasons, some encoders, media players and VDubMod
demand WMOD==4 ie width an exact multiple of 4 (some Mpeg encoders may demand WMOD=16 which you would have to set yourself).
In addition to above, Avisynth v2.58 kicks up a fuss if any YUV colorspace clip with Width not an exact multiple of 4 is
returned as final result clip (intermediate clips only have to comply with colorspace XMOD requirment). It is not really
the job of any plugin to guess whether it's result will be the final return clip and so is not really for RoboCrop to
enforce WMOD=4 for eg YV12, BUT, combined with the other reasons above, it was decided to change default WMOD to Max(XMOD,4),
you will have to set eg WMOD=2 manually if required for eg YV12 or YUY2, or WMOD=1 for eg RGB32 if that is what you want.
Avisynth has no problem returning eg RGB32 with an odd width, but at least one player had problems when RGB32 was XMOD=2
about 12 months prior to writing this (now fixed). WMOD set to 4 [as Max(XMOD,4) will likely be] will be least problematic
choice but you know what you require and can set WMOD to suit.
Some encoders may require an WMod/HMod of eg 8 or 16, and if set thus, would crop off more or less depending upon
which CropMode is set, if later resizing will be done, then encoder requirements can be satisfied during the resize.
NOTE, Some players and VirtualDubMod (Helix YV12 decoder) dont like WMOD less than 4 (Vdub latest, OK, internal decoder).
If eg VDMod shows blank frame, OR eg player halts saying eg "No combination of filters cound be found to render frame"
then WMod needs to be a multiple of 4.
NOTE, RT_Stats has a function RT_GetProcessName() which could be used to set WMod=4 only for specific programs eg,
RoboCrop(WMod=(RT_GetProcessName=="VirtualDubMod.exe") ? 4 : Last.RT_ColorspaceXMod) # Where VDubMod opened Avisynth
v1.08, limited WMod to max 16.

HMod:, Default=The natural chroma cropping restriction of the colorspace concerned, BUT, doubled if laced=true.
HMod MUST be a multiple of internal YMod as described under Laced above, or it will throw an error. If eg colorspace is
YV12 then YMod would be set to 2, and if Laced, then YMod would be doubled to 4, so HMod MUST be a multiple of 4.
v1.08, limited HMod to max 16.

RLBT:=15=All Borders, Bitflags of borders to detect, 15 ($0F) crops all four. Each letter in the name 'RLBT' represents an edge and bit position
starting with 'R' in bit 3 representing the value 8 (2^3=8). 'L' = bit 2=4 (2^2=4), 'B' = bit 1=2 (2^1=2), 'T' = bit 0=1 (2^0=1).
To calculate the RLBT bitflags, for 'R'(Right) add 8, for 'L'(Left) add 4, for 'B'(Bottom) add 2, and for 'T'(Top) add 1.
Add all of the bit flags together 8+4+2+1 (=15) crops all four edges, 8+4 crops only Right & Left, and 2+1 crops only Bottom & Top.
RLBT affects border detection.
User Skips eg LeftSkip are applied irrespective of what RLBT is set to.
User adjustments eg LeftAdd are applied irrespective of what RLBT is set to.

DEBUG:=False=No Debug. Set True for debugging info, need DebugView: http://technet.microsoft.com/en-gb/sysinternals/bb545027
The debug info output shows eg range limiting of Samples and sample info and resultant auto set Thresh. You are encouraged
to use debug to see the eg the auto Thresh massaging in action, it may help to understand usage of the plugin. MS DebugView
can also be used to view output from other plugins and programs that can also be useful.

Ignore:=0.4, Percentage of darkest pixels to ignore during AutoThresh scan to detect minimum luma pixel of all sampled frames.
(ignores a few extreme pixel values ie noise, as for Threshold arg in YPlaneMin).
v1.05, changed default from 0.2% to 0.4%.

Matrix:, RGB ONLY. For conversion of RGB to YUV-Y, 0 = Rec601, 1 = Rec709, 2 = PC601, 3 = PC709
Default for RGB is:- If clip Width > 1100 OR clip Height > 600 Then 3(PC709) , else 2(PC601) : YUV not used
The defaults are for PC601 & PC709 range 0-255.
So as to not require different AutoThresh for RGB, if clip c is RGB AND matrix is PC Levels AND Thresh < 0.0 and ScaleAutoThreshRGB=true,
then Thresh will be scaled to RGB full range ie Thresh = Thresh * (255.0/(235.0-16.0)) ONLY when AutoThresh (ie Thresh < 0.0,
YPlaneMin relative).
When +ve Thresh is explicitly supplied (Thresh > 0.0) it is not scaled and assumed to be already correct range TV or PC levels.

StainlessS
13th October 2014, 01:07
v1.13 Docs, part 2 of 2



Baffle:=4, Number of scanlines (h/v) that must break threshold to be considered image (can avoid noise around frame edges).
Does not usually need changing but might be of use to avoid some kind of eg teletext data at top of frame in broadcast video.

ScaleAutoThreshRGB: bool default True. If true and RGB and Matrix at PC levels, and Thresh -ve (autothresh) then thresh will (after any
auto Thresh massaging) be scaled to PC levels. By default, -ve Auto Thresh is considered to be at TV levels, and so will be scaled to
to PC levels to match the matrix setting. If ScaleAutoThreshRGB is False Then autothresh is considered to be at PC levels and not scaled.

ScaleAutoThreshYUV: bool default False. If true and YUV and Thresh -ve (autothresh) then Thresh will (after any auto Thresh massaging),
be scaled to PC levels. By default, -ve Auto Thresh is considered to be at TV levels, this allows you to change that assumption when
source clips are at PC levels. If supplying PC levels clip and PC levels autothresh then leave this setting at false (no scaling).
The above seemingly awkward settings are due to having to deal with YUV @ TV levels and RGB @ PC levels with the possibility of
YUV @ PC levels.

Cropmode: default=2 == CropMore. 1 = CropLess. Range 1 -> 2.
1 (CropLess) crops a little less border if the exact cropping coords do not comply with XMod/YMod/WMod/HMod as
described earlier. May leave a little border edge.
2 Default, (CropMore) crops a little extra where exact coords do not comply XMod/YMod/WMod/HMod requirements.
You may lose a little of the image edges.
CropMode is applied AFTER any user edge adjustments via LeftAdd, TopAdd, RightAdd and BotAdd.

Blank: Default False. If true, then Blanks the borders, ie sets border to RGB(0,0,0) or YUV(16,128,128) instead of cropping.
Is overridden if Show == true.

BlankPC: default false. If Blanking then blanks to YUV(0,128,128) instead of default YUV(16,128,128).

Align: Default True. If true, then aligns frames in memory when cropping, for eg SSE2 16-byte alignment required by some
filters, particularly smoothing filters (filters following RoboCrop). See Docs for Crop().
Only Applies if Cropping, ie Blank==false AND Show==false.
v1.11, changed Default to True, avoid Avs+ problems which can put up an error if False.

Show: Default false. If true, then does no cropping, just shows a little info on frame. Overrides both Blank and Align.
Final image edge positions shown as dotted lines every fifth pixel set white, always shown. Final image edge markers show edge
after any User adjustment via Add args (LeftAdd, TopAdd, RightAdd, BotAdd), and also after Modn rounding applied (CropMore/CropLess).
Exact image edges are show if not exactly coinciding with Final Image Edge markers, Exact image edge markers shown as every 3rd pixel
plotted in white.
Where the Skip args (LeftSkip, TopSkip, RighSkip, BotSkip) are non zero, will show skip positions as dotted lines with dots
every other pixel, not plotted if exact same position at final Modn (CropMore/CropLess) position or detected exact edge position.
The Skip args preset the 'already cropped area', ie auto cropping starts with edges already considered border.
Added cross hair reticule when show=True. Larger markings are 10 pixels apart, dots are 5 pixels apart.
Perhaps of use where borders not of fixed position.

LogFn: Default "" (unset). Filename of Log file.
Will output crop coords, crop coords will be output whether cropping or not (Blank/Show), format as within quotes below.

'28 92 668 392 2 4 2 4 720 576 27 89 696 484 2 27 89 696 484 '

Where in order:
CropX CropY CropW CropH : Crop coords mod XMod, YMod, WMod, HMod.
XMod YMod WMod HMod : As used for above crop coords
Width Height : Original frame width and height
ORG_X1 ORG_Y1 ORG_X2 ORG_Y2 : Exact coords of found image, not rounded according to x/y/w/h mod (Before User Adjust)
CropMode : 1 = CropLess, 2 = CropMore(default)
X1 Y1 X2 Y2 : Coords after any User adjustments eg ORG_X1+LeftAdd etc and before applying XMod etc.
All values output are single SPACE separated.


LogAppend: Default false. If true then appends log to any existing log file.

ATM: Float default 4.0 (0.5 -> 40.0). Silently limited to valid range.
ATM allows user to set the DEFAULT_AUTOTHRESH massaging minimum. When eg samples = 1, then auto thresholding is of course quite
unreliable and so auto Thresh would be 'massaged' to -ve(ATM), other values of Samples below 20 will likewise have auto thresh
massaged but to a lesser degree, linearly between -ve(ATM) for Samples == 1 and -ve(40.0) for Samples == 20.
Auto Thresh massaging also takes into account the frame range of samples (first sampled frame to last sampled frame inclusive)
and this is mixed together with any samples massaging then applied to auto Thresh.
Previous (Fixed) default for ATM was 0.5, for maximum safety so that a single Samples scan would NOT overcrop. The new ATM arg default
of 4.0 is a less paranoid safety setting which should in most cases work well but with a very short clip or eg single image then
user might be better off giving the minimum ATM of 0.5. An ATM of 40.0 will switch OFF default auto thresh massaging.
So long as sample range is about 5000+ frames and Samples at least 20(default 40), then there will be no auto thresh massaging and
current default is unlikely to need changing, with very short clips or reduced Samples count, then you might want to reduce ATM, for
maximum paranoia, set ATM=0.5 -> 1.0, especially in an app that processes single images. See Thresh.

Start: Default Undefined. Start frame of scan area. Overrides Auto Intro credits skipping.
For Auto Intro and End Credits Skipping to be set to 5% (of FrameCount for Intro Skipping) and 90% (for End Skipping), the number of
frames between them must be greater or equal to 250 frames, and MUST also be greater than Samples, otherwise Auto skipping ignored and
the Start and End frame numbers are set to 0 and Framecount - 1. If a user supplies eg a Start frame number ONLY, then End Skipping
has to comply with the same conditions, range between End Skip frame and user supplied Start has to be at least 250 frames and greater
than Samples, otherwise End frame set to FrameCount - 1.
After either via Auto Credits skipping, or user supplied Start/End, or defaulted to 0 & FrameCount -1, we have a sample scan range.

End: Default Undefined. End frame for scan area. Overrides Auto End credits skipping. 0 will be converted to Framecount - 1.
See previous Start setting.

Int LeftAdd, TopAdd, RightAdd, BotAdd, All default 0. Valid range depends upon clip dimensions, Skip and Baffle settings.
User adjustments to Skip + Autocrop exact found coords. CropMode applied after user Add adjustments.

Int LeftSkip, TopSkip, RightSkip, BotSkip, All default 0. TopSkip/BotSkip range 0 -> Height/4. LeftSkip/RightSkip range 0 -> Width/4.
Minimum edge croppings, detection starts with these edges cropped already, and are applied whether RLBT flags (ie edge crop scanning)
are applied or not. Avoid noise eg teletext at top of frame of VHS gunk at bottom.
NOTE, The Skip and Add args eg LeftSkip and LeftAdd are processed irrespective of the relevant RLBT flags so if you just wanted to
autocrop top and botton then set RLBT=$03 and can set either LeftSkip = 16 OR LeftAdd=16 to manually crop 16 pixels from Left hand
Side, DO NOT SET BOTH are this would crop off 32 pixels. LeftSkip is applied before autocrop, and LeftAdd after autocrop, and then
results are rounded to WMOD:HMOD, dependent upon cropmode (Default CROPMORE).

Float ScanPerc, Default 49.0, Range 1.0->99.0. Percentage of clip dimensions to scan for border edges.
Default 49.0%, Starts scan from nearly the middle of frame to outer edge of frame looking for borders.
Specialist use, might use eg 99.0% when image wholly to one of other side of the middle of frame.
eg, when 99.0, starts scan for TOP edge at nearly bottom of frame, scanning upwards.
starts scan for BOT edge at nearly top of frame, scanning downwards.
starts scan for LFT edge at nearly RHS of frame, scanning leftwards.
starts scan for RGT edge at nearly LHS of frame, scanning rightwards.

String Prefix, Default "ROBOCROP_". Prefix for Local vars set by the filter, crop coordinates. Setting to "" disables Local vars.
With Prefix="ROBOCROP_" (Default)
ROBOCROP_X = X coord
ROBOCROP_Y = Y coord
ROBOCROP_W = +ve Width
ROBOCROP_H = +ve Height
ROBOCROP_W2 = -ve Width relative crop coord
ROBOCROP_H2 = -ve Height relative crop coord

Example use:
<<<<<<<<< CODE START <<<<<<<
BlankClip(Length=1,width=1024,height=768,Pixel_type="YV12")
Wid=Width
Hit=Height
BLK=Last.BlankClip(width=320,height=240,color=$FF00FF)
OverLay(BLK,x=680,y=416)
RoboCrop(ScanPerc=99,show=true,debug=true,Prefix="ROBOCROP_")
X=ROBOCROP_X # Get Local Vars as set by RoboCrop (Using Prefix, above using Prefix same as Default Prefix)
Y=ROBOCROP_Y
W=ROBOCROP_W
H=ROBOCROP_H
W2=ROBOCROP_W2
H2=ROBOCROP_H2
Subtitle("Source: Width="+String(Wid)+",Height="+String(Hit),Y=4)
Subtitle("Crop("+String(X)+","+String(Y)+","+String(W)+","+String(H)+")",Y=24)
Subtitle("Crop("+String(X)+","+String(Y)+","+String(W2)+","+String(H2)+")",Y=44)
Return Last
>>>>>>>>>> CODE END >>>>>>>





Cropping will likely fail on END CREDITS ONLY clips, where on black background, and will probably crop off the sides that are no
different in average luma to any letterbox borders, if you cannot see the borders, then neither can RoboCrop(), even setting the
auto Thresh to eg -1.0 or 0.0 is quite likely to fail. (See RLBT edge bitflags).

If cropping too much border, then increase Samples or reduce Thresh or lower ATM if short clip.
If not cropping enough border then border is being seen as image, increase Thresh (for -ve Thresh , make more -ve).

To speed up, you may want to leave Auto-Thresh alone and reduce samples, but there is danger that it will not detect all borders (overcrop).
Suggest you do not go below Samples=20, although early default for samples was 12, we use a paranoid setting of 40 by default.
However, RoboCrop is quite sprightly and you will probably not need to reduce Samples, but if you are interested in how long it takes to
do it's auto thresh scanning in the filter constructor, the time taken is output via the debug arg to DebugView. Clips that have no letter
boxing are quickest dealt with and those with largest borders take most time as it has to scan the borders of all Samples frames, looking for
bigger image. Doing a short test as I write this on a 10 mins 12 secs PAL DVD vob of Cabaret, it took 0.875secs where
borders = Crop(30,90,-24,-92) with default args except for Debug=true (RoboCrop v1.03, YV12, Core Duo, Duel Core 2.14Ghz, Sata 2).
NOTE, scans over entire range of clip and so clip must be seekable, ie not eg DIVX with only a single keyframe, would take nearly forever.

NOTE, The plugin AutoCrop() uses a Thresh of 40.0 and samples == 5 by default (No AutoThresh), but the base logic is not too dissimilar.

Final NOTE, use arg Laced=False if you always process progressive or deinterlaced, And ATM set between 0.5 and 4.0 if very short
clips/single-image.

StainlessS

StainlessS
25th February 2015, 15:37
RoboCrop new version v1.12. See 1st post. 1st post has old version of docs
(too big for 16KB post limit, see post #37 [2 posts ahead] for current docs over two posts).


v0.20, Changed, range massage switch on frames to below 1500 (from 1000).
v0.21, Autothresh Massaging changed minimum to -1.5 from -0.5.
v1.00, Added ATM arg.
v1.02, Added Start & End args, Changed default rec709 switch to width > 1100 || height > 600.
v1.03, Minor mods.
v1.04, Added User adjustments to detected border edges.
v1.05, Addef LeftSkip, RightSkip, TopSkip, BotSkip (also shown when Show). Changed default Ignore from 0.2 to 0.4.
v1.06, Changed Default WMod to 4, avoid possible problems in Avisynth v2.58, some media players and VDubMod.
Changed Default AutoThresh to -40.0, been wanting to do this for some time.
Changed default Samples to 40, paranoia.
v1.07, Changed to recognise AutoThresh of both -32.0 and -40.0 as DEFAULT AUTOTHRESH (both old and new version args).
v1.08, wmod,hmod limited max 16. Fixed crop centering.
v1.09, Added reticule when Show=true..
v1.10, Added Exact line marker when show.
v1.11, 07 Jan 2019. Added Version Resource, Move to VS2008, Added x64, Changed default Align=True.
v1.12, 06 Feb 2020. Added ScanPerc arg.


@ FredThompson, TopSkip, should assist with your morse code gunk.


Int LeftSkip, TopSkip, RightSkip, BotSkip, All default 0. Minimum edge croppings, detection starts with these edges cropped already,
avoid noise eg teletext at top of frame or VHS gunk at bottom.

StainlessS
22nd April 2015, 03:30
RoboCrop new version v1.06. See 1st post. 1st post has old version of docs
(too big for 16KB post limit, see post #37 for current docs over two posts).


v1.05, Added LeftSkip, RightSkip, TopSkip, BotSkip (also shown when Show). Changed default Ignore from 0.2 to 0.4.
v1.06, Changed Default WMod to 4, avoid possible problems in Avisynth v2.58, some media players and VDubMod.
Changed Default AutoThresh to -40.0, been wanting to do this for some time.
Changed default Samples to 40, paranoia.


Main changes


Samples=40, Number of frames to sample from source clip c. v1.06 changed default from 32 to 40.
As an observation, most clips have good border recogition within the 1st 2 or 3 sampled frames using the default -40.0 AUTOTHRESH
although have noticed some dark clips that required ~8 samples (maybe more) for full recognition @ default Thresh = -40.0
We use a default Samples=40, because we are intrinsically paranoid.
If number of frames between frame at 5% of framecount and frame at 90% of framecount is greater than 250 and is also greater
than Samples, will ignore the first 5% and last 10% of frames when both auto-thresholding and crop sampling to try to negate
effects of artificial black in titles and end credits. Can override the Auto Credits skipping by setting Start and/or End frame
of the range to sample.
Samples = 0, will be converted to Samples = FrameCount - 1, ie auto credits skipping disabled and ALL FRAMES SAMPLED,
of use for very short scenes, not for general full movie clips.
Set eg Samples = Int(FrameCount * 2.0 / 100.0 + 0.5) to sample 2.0% of frames in clip.

Thresh: Default= -40.0 (==DEFAULT AUTOTHRESH, any -ve (or 0) Thresh is AUTOTHRESH where Thresh adjustments are automatic).
v1.06, Changed DEFAULT AUTOTHRESH from -32.0 to -40.0.

Thresh > 0: (Explicit Threshold)
A user supplied +ve Thresh should be at correct TV/PC levels for the the clip being worked on ie 16->235 for TV levels and
0->255 for PC Levels (RGB, as appropriate for matrix being used).

Thresh <= 0: (AUTOTHRESH)
When Thresh <= 0, the clip will be sampled over Samples frames to find the minimum YPlaneMin (using Matrix if RGB) which
we will call MINLUMA and an Explicit Threshold calculated by adding MINLUMA to abs(Thresh), after that it is processed
as for Thresh > 0: (Explicit Threshold) as noted above, but, before adding MINLUMA, some AUTOTHRESH massaging and scaling occurs.

Here AUTOTHRESH Thresh massaging and scaling occurs in sequence:-
1 ) if (Thresh == DEFAULT AUTOTHRESH && ATM < 40.0) (DEFAULT AUTOTHRESH = exactly -40.0, defaulted OR user supplied):
Let sampstart and sampend, be starting and ending frames numbers after any Auto Credits skipping and/or user set Start or End.
Let Samples be limited to sampend-sampstart+1.
Let SampRange (Sample Range) = SampEnd-SampStart+1.
samples_massage =(Samples>=20) ? 1.0 : (Samples-1) * (1.0/(20-1)) # No massaging if Samples >= 20
range_massage =(SampRange >= (250*20)) ? 1.0 : (SampRange-1) * (1.0/((250*20)-1)) # No massaging if SampRange >= 5000
Both samples_massage and range_massage will be in range 0.0 to 1.0.
Thresh = -(((samples_massage * range_massage) * (40.0 - ATM)) + ATM)
This adjustment to Auto Thresh is to reduce the possibility of overcropping on eg a dark low 'Samples' clip, or where
source SampRange (ie temporal frame set) is too small to take a reliable sample from.
Resulting massaged Thresh will range between -ATM and -40.0.
Although massaging is intended to reduce overcropping, it could result in not cropping enough border (less disastrous),
its a bit of a balancing act really. See also ATM.
2 ) If RGB AND PC matrix(default) AND ScaleAutoThreshRGB==True(default) then
Thresh= Thresh*(255.0/(235-16))
3 ) If YUV AND ScaleAutoThreshYUV==True(default=false) then
Thresh= Thresh*(255.0/(235-16))

Steps 2) and 3) above, by default treat a -ve AUTOTHRESH as being @ TV Levels and so Scale RGB Thresh to PC levels but not YUV.
If you want to supply a PC levels AUTOTHRESH Thresh for RGB, then simply set ScaleAutoThreshRGB=false to inhibit scaling.
Note, if a TV levels Matrix is supplied for RGB, then scaling will always be inhibited.
If your clip is YUV at PC levels and you want to use eg DEFAULT AUTOTHRESH (-40.0, which is considered to be @ TV levels),
then set ScaleAutoThreshYUV=True to enable Thresh scaling.
If your clip is YUV at PC levels and you want to use a PC levels AUTOTHRESH (-ve) then leave ScaleAutoThreshYUV at default false
which does not scale Thresh.
After any scaling, MINLUMA is then added to abs(Thresh) and processed as for +ve Explicit Threshold as noted above.
NOTE, Above RoboCrop step 1) 'massages' DEFAULT AUTOTHRESH (exactly -40.0) if low samples count or if short clip. Reason being to
avoid overcropping when insufficient data available for reliable cropping. It is considered better to not crop enough or at all,
than to overcrop. You can override by simply setting an explicit threshold (+ve) of eg 40.0, or setting a NON-DEFAULT auto thresh
(-ve) eg -16.0 or -40.1, where YPlaneMin is established for the sampled frames and then abs(thresh) is added to that value which
is then used as an explicit thresh.



WMod:, Default=Max(XMOD,4), Where XMOD is the natural chroma cropping restriction of the colorspace concerned, eg 2 for YV12.
WMod MUST be a multiple of internal XMOD as described above, or it will throw an error.
v1.06, Changed default from XMOD to Max(XMOD,4), this is for several reasons, some encoders, media players and VDubMod
demand WMOD==4 ie width an exact multiple of 4 (some Mpeg encoders may demand WMOD=16 which you would have to set yourself).
In addition to above, Avisynth v2.58 kicks up a fuss if any YUV colorspace clip with Width not an exact multiple of 4 is
returned as final result clip (intermediate clips only have to comply with colorspace XMOD requirment). It is not really
the job of any plugin to guess whether it's result will be the final return clip and so is not really for RoboCrop to
enforce WMOD=4 for eg YV12, BUT, combined with the other reasons above, it was decided to change default WMOD to Max(XMOD,4),
you will have to set eg WMOD=2 manually if required for eg YV12 or YUY2, or WMOD=1 for eg RGB32 if that is what you want.
Avisynth has no problem returning eg RGB32 with an odd width, but at least one player had problems when RGB32 was WMOD=2
about 12 months prior to writing this (now fixed). WMOD set to 4 [as Max(XMOD,4) will likely be] will be least problematic
choice but you know what you require and can set WMOD to suit.

EDIT:
The Max() bit above in Magenta is just in case some future supported Planar format has requirement greater than 4.


Function RoboCrop(clip c,int "Samples"=40,Float "Thresh"=-40.0,bool "Laced"=true,int "WMod",int "HMod",int "RLBT"=15,bool "Debug"=false, \
float "Ignore"=0.4,int "Matrix"=(c.Width>1100||c.Height>600?3:2), int "Baffle"=4, bool "ScaleAutoThreshRGB"=true,
bool "ScaleAutoThreshYUV"=false, int "CropMode"=2,bool "Blank"=false,bool "BlankPC"=false,bool "Align"=false,bool "Show"=false, \
String "LogFn"="",bool "LogAppend"=false, Float "ATM"=4.0,int "Start"=Undefined,Int "End"=Undefined, \
Int "LeftAdd"=0,Int "TopAdd"=0,Int "RightAdd"=0,Int "BotAdd"=0, \
Int "LeftSkip"=0,Int "TopSkip"=0,Int "RightSkip"=0,Int "BotSkip"=0)


Laced=True,Show = true
https://s20.postimg.org/vk7jwv799/robo0_zpsfzfpfakr.jpg (https://postimg.org/image/sq4ejf52x/)

MysteryX
4th December 2015, 01:09
I'm using RoboCrop like this to get the auto-crop dimensions
RoboCrop(LogFn="Preview_Temp.txt")

then I run it with avs2yuv.exe

It takes a long time to get the result because it is processing the whole file. Is there a way to just get the coordinates to the file and then stop any further processing?

Groucho2004
4th December 2015, 01:16
I'm using RoboCrop like this to get the auto-crop dimensions
RoboCrop(LogFn="Preview_Temp.txt")

then I run it with avs2yuv.exe

It takes a long time to get the result because it is processing the whole file. Is there a way to just get the coordinates to the file and then stop any further processing?
AVSMeter script.avs -i

StainlessS
4th December 2015, 01:53
Or something like,


AviSource("Cabaret.avi")
WMOD=4
LACED=False
SHOW=True # Whatever
DEBUG=True # DebugView
RoboCrop(WMod=WMOD,Laced=LACED,Show=SHOW,LogFn="Coord.Txt",Debug=DEBUG)
Trim(0,-1) # Curtail Avs2YUV scan


EDIT:
Produces This coords.txt:

28 90 668 394 2 2 4 2 720 576 28 89 696 484 2 28 89 696 484



LogFn: Default "" (unset). Filename of Log file.
Will output crop coords, crop coords will be output whether cropping or not (Blank/Show), format as within quotes below.

'28 92 668 392 2 4 2 4 720 576 27 89 696 484 2 27 89 696 484 '

Where in order:
CropX CropY CropW CropH : Crop coords mod XMod, YMod, WMod, HMod.
XMod YMod WMod HMod : As used for above crop coords
Width Height : Original frame width and height
ORG_X1 ORG_Y1 ORG_X2 ORG_Y2 : Exact coords of found image, not rounded according to x/y/w/h mod (Before User Adjust)
CropMode : 1 = CropLess, 2 = CropMore(default)
X1 Y1 X2 Y2 : Coords after any User adjustments eg ORG_X1+LeftAdd etc and before applying XMod etc.
All values output are single SPACE separated.


https://s20.postimg.cc/9mb332s8t/Cabaret_zpsl1admor0.png (https://postimg.cc/image/7hqq1zqm1/)

Debugview

00000174 262.95639038 [2148] RoboCrop: RoboCrop: v1.06 - 22 Apr 2015 - By StainlessS
00000175 262.95642090 [2148] RoboCrop: Input: Width=720 Height=576 FrameCount=15285
00000176 262.95642090 [2148] RoboCrop:
00000177 262.95648193 [2148] RoboCrop: Thresh defaulting to DEFAULT AUTOTHRESH -40.00
00000178 262.95651245 [2148] RoboCrop: Potential Auto Credits Skip Start@5%=764 End @90%=13756 : Range=12993
00000179 262.95654297 [2148] RoboCrop: Skip Start(764) and End(13756) : Range=12993
00000180 262.95657349 [2148] RoboCrop:
00000181 262.95660400 [2148] RoboCrop: Samples=40 Thresh=-40.000 Laced=False Matrix=2
00000182 262.95663452 [2148] RoboCrop: WMod=4 HMod=2 {Colorspace/Laced Restricted XMod=2 YMod=2}
00000183 262.95666504 [2148] RoboCrop: RLBT=15 Ignore=0.400 Baffle=4
00000184 262.95669556 [2148] RoboCrop: ScaleAutoThreshRGB=Yes ScaleAutoThreshYUV=No
00000185 262.95669556 [2148] RoboCrop: CropMode=2(CropMore) Blank=No Align=No Show=Yes Log=Yes
00000186 262.95672607 [2148] RoboCrop: Atm=4.000 SampStart=764 SampEnd=13756 SampRange=12993
00000187 262.95672607 [2148] RoboCrop: LeftAdd=0 TopAdd=0 RightAdd=0 BotAdd=0
00000188 262.95675659 [2148] RoboCrop: LeftSkip=0 TopSkip=0 RightSkip=0 BotSkip=0
00000189 262.95678711 [2148] RoboCrop:
00000190 262.98403931 [2148] RoboCrop: AutoThresh 1) [ 764] YPlaneMin = 14 (14)
00000191 263.04266357 [2148] RoboCrop: AutoThresh 2) [ 1097] YPlaneMin = 14 (14)
00000192 263.07455444 [2148] RoboCrop: AutoThresh 3) [ 1430] YPlaneMin = 14 (14)
00000193 263.09149170 [2148] RoboCrop: AutoThresh 4) [ 1763] YPlaneMin = 14 (14)
00000194 263.10733032 [2148] RoboCrop: AutoThresh 5) [ 2097] YPlaneMin = 14 (14)
00000195 263.12109375 [2148] RoboCrop: AutoThresh 6) [ 2430] YPlaneMin = 15 (14)
00000196 263.13745117 [2148] RoboCrop: AutoThresh 7) [ 2763] YPlaneMin = 14 (14)
00000197 263.15515137 [2148] RoboCrop: AutoThresh 8) [ 3096] YPlaneMin = 14 (14)
00000198 263.17474365 [2148] RoboCrop: AutoThresh 9) [ 3429] YPlaneMin = 13 (13)
00000199 263.21542358 [2148] RoboCrop: AutoThresh 10) [ 3762] YPlaneMin = 14 (13)
00000200 263.24392700 [2148] RoboCrop: AutoThresh 11) [ 4095] YPlaneMin = 14 (13)
00000201 263.25967407 [2148] RoboCrop: AutoThresh 12) [ 4428] YPlaneMin = 14 (13)
00000202 263.32559204 [2148] RoboCrop: AutoThresh 13) [ 4762] YPlaneMin = 14 (13)
00000203 263.35232544 [2148] RoboCrop: AutoThresh 14) [ 5095] YPlaneMin = 14 (13)
00000204 263.38153076 [2148] RoboCrop: AutoThresh 15) [ 5428] YPlaneMin = 14 (13)
00000205 263.42202759 [2148] RoboCrop: AutoThresh 16) [ 5761] YPlaneMin = 14 (13)
00000206 263.48983765 [2148] RoboCrop: AutoThresh 17) [ 6094] YPlaneMin = 14 (13)
00000207 263.55682373 [2148] RoboCrop: AutoThresh 18) [ 6427] YPlaneMin = 14 (13)
00000208 263.59436035 [2148] RoboCrop: AutoThresh 19) [ 6760] YPlaneMin = 14 (13)
00000209 263.62008667 [2148] RoboCrop: AutoThresh 20) [ 7093] YPlaneMin = 14 (13)
00000210 263.64840698 [2148] RoboCrop: AutoThresh 21) [ 7427] YPlaneMin = 15 (13)
00000211 263.66235352 [2148] RoboCrop: AutoThresh 22) [ 7760] YPlaneMin = 14 (13)
00000212 263.67373657 [2148] RoboCrop: AutoThresh 23) [ 8093] YPlaneMin = 14 (13)
00000213 263.70022583 [2148] RoboCrop: AutoThresh 24) [ 8426] YPlaneMin = 14 (13)
00000214 263.73031616 [2148] RoboCrop: AutoThresh 25) [ 8759] YPlaneMin = 14 (13)
00000215 263.74728394 [2148] RoboCrop: AutoThresh 26) [ 9092] YPlaneMin = 14 (13)
00000216 263.75781250 [2148] RoboCrop: AutoThresh 27) [ 9425] YPlaneMin = 14 (13)
00000217 263.77706909 [2148] RoboCrop: AutoThresh 28) [ 9758] YPlaneMin = 14 (13)
00000218 263.79431152 [2148] RoboCrop: AutoThresh 29) [ 10092] YPlaneMin = 14 (13)
00000219 263.81048584 [2148] RoboCrop: AutoThresh 30) [ 10425] YPlaneMin = 14 (13)
00000220 263.83358765 [2148] RoboCrop: AutoThresh 31) [ 10758] YPlaneMin = 14 (13)
00000221 263.85678101 [2148] RoboCrop: AutoThresh 32) [ 11091] YPlaneMin = 14 (13)
00000222 263.86941528 [2148] RoboCrop: AutoThresh 33) [ 11424] YPlaneMin = 14 (13)
00000223 263.89089966 [2148] RoboCrop: AutoThresh 34) [ 11757] YPlaneMin = 14 (13)
00000224 263.90399170 [2148] RoboCrop: AutoThresh 35) [ 12090] YPlaneMin = 14 (13)
00000225 263.92401123 [2148] RoboCrop: AutoThresh 36) [ 12423] YPlaneMin = 14 (13)
00000226 263.94082642 [2148] RoboCrop: AutoThresh 37) [ 12757] YPlaneMin = 14 (13)
00000227 263.96194458 [2148] RoboCrop: AutoThresh 38) [ 13090] YPlaneMin = 14 (13)
00000228 263.98049927 [2148] RoboCrop: AutoThresh 39) [ 13423] YPlaneMin = 14 (13)
00000229 264.00881958 [2148] RoboCrop: AutoThresh 40) [ 13756] YPlaneMin = 14 (13)
00000230 264.00885010 [2148] RoboCrop:
00000231 264.00888062 [2148] RoboCrop: YPlaneMin=13 : Automatic set Thresh=53.000
00000232 264.00891113 [2148] RoboCrop:
00000233 264.01147461 [2148] RoboCrop: Top 1) [ 764] AveY= 53.14 Y1=177
00000234 264.01153564 [2148] RoboCrop: Bot 1) [ 764] AveY= 57.44 Y2=484
00000235 264.01156616 [2148] RoboCrop: Lft 1) [ 764] AveY= 54.72 X1=154
00000236 264.01162720 [2148] RoboCrop: Rgt 1) [ 764] AveY= 54.73 X2=695
00000237 264.01531982 [2148] RoboCrop: Lft 3) [ 1430] AveY= 54.32 X1= 28
00000238 264.01910400 [2148] RoboCrop: Top 5) [ 2097] AveY= 53.28 Y1=110
00000239 264.02890015 [2148] RoboCrop: Rgt 10) [ 3762] AveY= 63.56 X2=696
00000240 264.03656006 [2148] RoboCrop: Top 14) [ 5095] AveY= 54.04 Y1= 89
00000241 264.09036255 [2148] RoboCrop:
00000242 264.09039307 [2148] RoboCrop: Active Frames (where image coords first found) = 5
00000243 264.09042358 [2148] RoboCrop: Sampled ImageEdge: X1=28 Y1=89 X2=696(W=669,-23) Y2=484(H=396,-91)
00000244 264.09069824 [2148] RoboCrop:
00000245 264.09078979 [2148] RoboCrop: Crop(ModW/H): X = 28 Y = 90 W =668(-24) H =394(-92)
00000246 264.09085083 [2148] RoboCrop: Constructor Scan Total Time=1.140 secs

MysteryX
4th December 2015, 02:21
Trim(0,-1)

yeah that works.

Oddly enough, I already was using that for another script; somehow I missed that I was already doing it.

StainlessS
14th June 2016, 14:39
RoboCrop v1.07, new version.

V1.07 Docs overflow 16kb limit, so left first post docs at v1.0.
See post #37 for v1.07 Docs over two posts. Here: http://forum.doom9.org/showthread.php?p=1696703#post1696703


v0.20, Changed, range massage switch on frames to below 1500 (from 1000).
v0.21, Autothresh Massaging changed minimum to -1.5 from -0.5.
v1.00, Added ATM arg.
v1.02, Added Start & End args, Changed default rec709 switch to width > 1100 || height > 600.
v1.03, Minor mods.
v1.04, Added User adjustments to detected border edges.
v1.05, Addef LeftSkip, RightSkip, TopSkip, BotSkip (also shown when Show). Changed default Ignore from 0.2 to 0.4.
v1.06, Changed Default WMod to 4, avoid possible problems in Avisynth v2.58, some media players and VDubMod.
Changed Default AutoThresh to -40.0, been wanting to do this for some time.
Changed default Samples to 40, paranoia.
v1.07, Changed to recognise AutoThresh of both -32.0 and -40.0 as DEFAULT AUTOTHRESH (both old and new version args).


See Mediafire in sig for zip (~148.0 KB)

Katie Boundary
14th June 2016, 15:56
This reminds me of an idea that I recently had for a plugin that would auto-kill the slight pillarboxing that exists in some fullscreen sources because of overscan. Basically, you'd just give it a number (default = 16), and it would automatically select and crop the "darkest" column of pixels from either the left or right side of the screen, iterated that many times per frame. It could easily be modified to kill letterboxing as well. The easiest way to implement this might be to just give it a target resolution instead of target numbers of rows/columns to kill.

I shall call it... PillKill.

FranceBB
14th June 2016, 16:30
I tried it and it works.
I tested it with a "dodgy" source, which is HD - 2.35 LB but has a few captions appearing and disappearing sometimes at the bottom and it worked (it didn't crop them).
Well done! ;)

StainlessS
14th June 2016, 16:56
FranceBB,
With such a source, I would not recommend auto cropping of bottom, you were perhaps lucky that it just happened to sample a frame
with caption appearing just by chance (only samples 40 frames from entire clip, by default).
Perhaps best to set RLBT flags (which sides to autocrop) for eg top only, and set eg BotAdd to 64 or whatever to manually crop bottom area.
(EDIT: Above I'm assuming you mean that captions appear in bottom border)

EDIT:
@Katie, RoboCrop should deal with your problem clips no bother at all (see image a few posts ahead for all 4 sides cropped).

EDIT: The image is done with Show=True, ie did not do the actual cropping.
EDIT: To crop mod16 width, just set WMod=16 (where will center L+R cropping). Same for height, set HMod (see Laced).
CropLess mode may leave a little border to comply with W/HMod, CropMore[default] may crop a little extra to comply.
EDIT: Or mod8 as filler56789 said is OK for TmpGenc in your thread, set WMod=8.

StainlessS
14th June 2016, 17:52
Below a bit of code to show cropped DAR (Display Aspect Ratio) and also signal to MeGUI.
Req, RT_Stats.


AvisourcE("CabaretUncropped.avi")

FULLFRAME_DAR = 4.0/3.0 # Display Aspect Ratio of FULL FRAME

SAR = Last.RT_GetSAR(FULLFRAME_DAR) # Gets Sample (pixel) Aspect Ratio from full frame DAR Display Aspect Ratio.
RoboCrop(WMod=4, Laced=false, debug=true)
DAR = Last.RT_GetDAR(SAR) # Gets cropped DAR Display Aspect Ratio from SAR, Sample (pixel) Aspect Ratio.

RT_SignalDAR(DAR) # Signal DAR to MEGUI.
# Sets Global vars MeGUI_darX and MeGUI_darY which are read during MEGUI loading of AVS file.

RT_DebugF("Cropped DAR = %.3f",DAR,name="ShowDAR: ") # To DebugView

RT_Subtitle("Cropped DAR = %.3f",DAR,align=5)


NOTE, Dont miss post #45, RoboCrop is updated today.

EDIT: For Cabaret shows "Cropped DAR = 1.808".

EDIT Added explicit Last in places, might not be obvious that it is using clip to calc DAR and SAR.

EDIT: Above RT_ Aspect ratio functions converted from script, below original script

Function GetCropDAR(clip c,float DAR,float "X",float "Y",float "W",float "H") {
# Call prior to Crop/Resize with (possibly fractional) cropping to calc resultant DAR, X,Y,W,H are cropping coords
# DAR = FAR * SAR ::: FAR = DAR / SAR ::: SAR = DAR / FAR
#
X=Float(Default(X,0.0)) Y=Float(Default(Y,0.0)) W=Float(Default(W,0.0)) H=Float(Default(H,0.0))
W=W<=0.0?c.width+W-X:W H=H<=0.0?c.height+H-Y:H
# Irrespective of what various resizers in various Avisynth versions silently correct, we dont allow eg -ve X
Assert(X>=0.0&&X < c.width, "GetCropDAR: Invalid X("+String(X)+")")
Assert(Y>=0.0&&Y < c.height,"GetCropDAR: Invalid Y("+String(Y)+")")
Assert(W> 0.0&&X+W<=c.width, "GetCropDAR: Invalid W("+String(W)+")")
Assert(H> 0.0&&Y+H<=c.height,"GetCropDAR: Invalid H("+String(H)+")")
Return c.GetSAR(DAR) * W / H
}

#--------------

# From MeGUI Wiki:
Function GetDAR(clip c, float SAR) { return Float(c.width) * SAR / Float(c.height)} # Gets the DAR from the SAR
Function GetSAR(clip c, float DAR) { return DAR * Float(c.height) / Float(c.width) } # Gets the SAR from the DAR
Function SignalDAR(float DAR){ # Signal DAR for MEGUI (Name change from SetDar)
Assert(DAR>0.0, "SignalDAR: Error, DAR must be greater than zero")
Global MeGUI_darx=Round(1000*DAR) Global MeGUI_dary=1000
}
Function SignalDAR2(int DARX,int DARY){
Assert(DARX>0 && DARY>0, "SignalDAR2: Error, DARX and DARY must be greater than zero")
Global MeGUI_darx=DARX Global MeGUI_dary=DARY
}


Cropping keeps original SAR. Resizing (without crop) keeps original DAR.

Katie Boundary
14th June 2016, 18:37
@Katie, RoboCrop should deal with your problem clips no bother at all (see image a few posts ahead for all 4 sides cropped).

EDIT: The image is done with Show=True, ie did not do the actual cropping.
EDIT: To crop mod16 width, just set WMod=16 (where will center L+R cropping). Same for height, set HMod (see Laced).

If I'm interpreting the documentation correctly, that won't work. I'm talking about cropping in increments of one pixel until a target resolution is achieved. WMod and HMod seem to set the increments by which the cropping is done, with the final resolution being entirely decided by the filter...

On a side note, the hypothetical filter that I described has some serious flaws that become apparent when the pillarboxing is a few pixels wider or thinner than expected. A better version of the filter would attempt to include equal amounts of black on the edges if the borders are wider than expected, or crop equal amounts of color off the edges if the borders are thinner than expected. I've seen plenty of episodes in which the actual black area was - for example - only 7 pixels on one edge and 3 on the other, and I had to pad the crop values to 10 and 6 respectively. This crap drives me nuts.

StainlessS
14th June 2016, 19:07
Arh, so you mean whether there are borders or not, you remove columns.
Not so sure that is of any use unless only a single frame is being processed (otherwise some serious jumping about is gonna happen
if you have to do that at every frame).

Anyways, just discovered that the mentioned "where will center L+R cropping" dont work proper [dont center],
bug fix version imminent, when I can figure out how to fix it.

FranceBB
14th June 2016, 22:17
@StainslesS... Yep, they appear in the bottom line. Anyway, I usually crop sources myself, but I was curious about the filter and I wanted to try it with such a source, mainly for curiosity.
Anyway, thank you :)

Katie Boundary
14th June 2016, 22:55
Arh, so you mean whether there are borders or not, you remove columns.

I can't really imagine why anyone would apply this filter to a video without any borders :confused: If you need to crop 8 pixels from each side of an image, a simple crop(8,0,-8,-0) should work...

Not so sure that is of any use unless only a single frame is being processed (otherwise some serious jumping about is gonna happen if you have to do that at every frame).

It is intended to be applied on a frame-by-frame basis, but that's perfectly fine, because the only times when pillarboxes substantially change in thickness are when the opening credits end or the end credits start, and then you'll actually WANT the cropped area to shift a bit.

StainlessS
14th June 2016, 23:05
until a target resolution is achieved
would seem to imply that presence of real border is unimportant. (dont want an argument here).
RoboCrop crops to the outermost border.

to be applied on a frame-by-frame basis
Slowish, Would need to use ScriptClip().
Could use RT_Stats RT_AverageLuma(x=X,y=0,w=1,H=0) to scan vertical colums at X. (inside Scriptclip script).
RT_AverageLuma(n=current_frame) # is the default.

Not too difficult to code that really, go on, have a go :)

EDIT: Would of course also need GSCript.

Katie Boundary
14th June 2016, 23:20
would seem to imply that presence of real border is unimportant.

It's important when deciding whether to use Crop(8,0,-8,-0) or a "smart" cropper like Robocrop.

Otherwise, you're correct.

Slowish

LOL. Not compared to resizing, sharpening, blurring, deinterlacing, or many of the other things that AVIsynth can do...

Would need to use ScriptClip().
Could use RT_Stats RT_AverageLuma(x=X,y=0,w=1,H=0) to scan vertical colums at X. (inside Scriptclip script).
RT_AverageLuma(n=current_frame) # is the default.

Not too difficult to code that really, go on, have a go :)

EDIT: Would of course also need GSCript.

I have no idea what any of that is, does, or means...

StainlessS
14th June 2016, 23:40
Here is what you suggest (it aint good, somewhat jumpy, feel free to improve), [req RT_Stats, GScript, Grunt]


GSCript("""
Function Katie(clip c,int n,Int WKill) {
c
XMod = c.RT_ColorSpaceXMod
WKill = (WKill + XMod-1) / XMod * XMod # Round UP Will return WRONG SIZE and Error Alert of WKill not multiple of XMod.
Lft=0 Rgt=0
While(Lft+Rgt<WKill) {
LAve=RT_AverageLuma(n=n,x=Lft,y=0,w=XMod,H=0)
RAve=RT_AverageLuma(n=n,x=Width-XMod-Rgt,y=0,w=XMod,H=0)
if(LAve<RAve) {Lft = Lft + XMod}
else {Rgt = Rgt + XMod}
}
Crop(Lft,0,-Rgt,-0)
RT_Subtitle("Lft=%d Rgt=%d",Lft,Rgt,Align=5)
Return Last
}
""")

SCRIPT = "return Katie(ORG,current_frame,WKill)"

AvisourcE("CabaretUncropped.avi")
ORG = Last # Uncropped source (clip2)
WKILL = 16
Crop(WKILL,0,0,0) # Scriptclip can ONLY return same size clip as arg
Return ScriptClip(SCRIPT,Args="ORG,WKILL") # Import ORG clip into Scriptclip (req Grunt)


By the way, you would want to get this working in script before attempting to learn CPP, and implementing.

EDIT: Only left and right implemented.

Katie Boundary
14th June 2016, 23:47
I... have no idea what that is or what I'm supposed to do with it...

StainlessS
14th June 2016, 23:54
All four sides.

GSCript("""
Function Katie(clip c,int n,Int WKill,Int HKill) {
c
XMod = RT_ColorSpaceXMod # Left and Right scan Width : eg 1 for RGB, 2 for YV12 & YUY2
WKill = (WKill + XMod-1) / XMod * XMod # Round UP Will return WRONG SIZE and Error Alert of WKill not multiple of XMod.
Lft=0 Rgt=0
While(Lft+Rgt<WKill) {
LAve=RT_AverageLuma(n=n,x=Lft,y=0,w=XMod,H=0)
RAve=RT_AverageLuma(n=n,x=Width-XMod-Rgt,y=0,w=XMod,H=0)
if(LAve<RAve) {Lft = Lft + XMod} # Lft is darker than Rgt
else if(RAve<LAve) {Rgt = Rgt + XMod} # Rgt is darker than Lft
else if(Lft<Rgt) {Lft = Lft + XMod} # Lft and Rgt same AveLuma AND Lft < Rgt
else {Rgt = Rgt + XMod} # Lft and Rgt same AveLuma AND Rgt <= Lft
}
YMod = RT_ColorSpaceYMod(Laced=False) # Top and Bot Scan Height : eg 1 for RGB and YUY2, 2 for YV12
HKill = (HKill + YMod-1) / YMod * YMod # Round UP Will return WRONG SIZE and Error Alert of HKill not multiple of YMod.
Top=0 Bot=0
While(Top+bot<HKill) {
TAve=RT_AverageLuma(n=n,x=0,y=Top,w=0,H=YMod)
BAve=RT_AverageLuma(n=n,x=0,y=Height-YMod-Bot,w=0,H=YMod)
if(TAve<BAve) {Top = Top + YMod} # Top is darker than Bot
else if(BAve<TAve) {Bot = Bot + YMod} # Bot is darker than Top
else if(Top<Bot) {Top = Top + YMod} # Top and Bot same AveLuma AND Top < Bot
else {Bot = Bot + YMod} # Top and Bot same AveLuma AND Bot <= Top
}
Crop(Lft,Top,-Rgt,-Bot)
# RT_DebugF("Lft=%d Rgt=%d : Top=%d Bot=%d W=%d H=%d",Lft,Rgt,Top,Bot,Width,Height,name="Katie: ")
RT_Subtitle("Lft=%d Rgt=%d : Top=%d Bot=%d",Lft,Rgt,Top,Bot,Align=5)
Return Last
}
""")

SCRIPT = "return Katie(ORG,current_frame,WKill,HKill)" # We use ORG clip and simply discard the dummy clip (dont use it for anything)
#####################################
### Katie's Config Below
#Avisource("CabaretUncropped.avi")
mpeg2source("001.d2v")
bob(b=0,c=1)
selecteven()
#
WKILL = 16
HKILL = 0
#####################################
### Katie Hands off below
ORG = Last # Uncropped source (clip2)
Dummy=Crop(WKILL,HKILL,0,0) # Scriptclip can ONLY return same size clip as arg, so we create dummy clip
Dummy.ScriptClip(SCRIPT,Args="ORG,WKILL,HKILL") # Import ORG (full uncropped) clip into Scriptclip (req Grunt)
### Katie's Postscript
simpleresize(352,240)
###
Return Last


EDIT:
I... have no idea what that is or what I'm supposed to do with it...
Change

Avisource("CabaretUncropped.avi")

to whatever you want, it implements your suggested functionality.

WKILL and HKILL are total Width and Height pixels to crop. (Just try it and stop belly aching :) )

EDIT: Put RT_Stats, GScript and Grunt in Plugins directory, run script.

Katie Boundary
15th June 2016, 00:30
Um... okay. While I'm setting this circus up, would you mind letting me know what the script looks like when WKILL is 16 and HKILL is 0? I don't know what I'm supposed to add, or replace, or... seriously, you're breaking my brain here.

EDIT: I plan for my script to look something like this...

mpeg2source("001.d2v")

bob(b=0,c=1)

selecteven()

[big pile of gobbledygook written by StainlessS]

simpleresize(352,240)

What should "[big pile of gobbledygook written by StainlessS]" be replaced with, assuming that I plan to crop width by 16 and height by 0?

StainlessS
15th June 2016, 00:37
Katie, post #58 update.
Is more stable now (so long as WKILL and HKILL are at least total width/height of borders), but still a bit unstable.

Edit, is for Progressive ONLY (holla if Interlaced required).

Katie Boundary
15th June 2016, 00:39
Katie, post #58 update.
Is more stable now (so long as WKILL and HKILL are at least total width/height of borders), but still a bit unstable.

I'm not concerned with stability at the moment... I'm concerned with just having an actual script. Also, I was editing my previous post when you wrote this; please see edits.

Edit, is for Progressive ONLY (holla if Interlaced required).

I plan to deinterlace or IVTC before cropping, but... why would this even matter?

EDIT: oh, and I noticed that your scripts don't say anything about converting to RGB. That might be necessary if the edges are being cropped by an odd number of pixels. Or maybe the script just assumes that the colorspace is already RGB. I seriously have no idea.

StainlessS
15th June 2016, 00:59
why would this even matter?

Interlaced YV12 can only crop vertical Mod 4 (otherwise chroma damaged).

Script updated. (You would not want to use it though, too unstable).

EDIT: Script will handle any Progressive colorspace.

StainlessS
15th June 2016, 01:15
big pile of gobbledygook written by StainlessS

Hid some of the gobbledygook for you.


GSCript("""
Function Katie_Lo(clip c,int n,Int WKill,Int HKill,Bool Subs) {
c
XMod = RT_ColorSpaceXMod # Left and Right scan Width : eg 1 for RGB, 2 for YV12 & YUY2
WKill = (WKill + XMod-1) / XMod * XMod # Round UP Will return WRONG SIZE and Error Alert of WKill not multiple of XMod.
Lft=0 Rgt=0
While(Lft+Rgt<WKill) {
LAve=RT_AverageLuma(n=n,x=Lft,y=0,w=XMod,H=0)
RAve=RT_AverageLuma(n=n,x=Width-XMod-Rgt,y=0,w=XMod,H=0)
if(LAve<RAve) {Lft = Lft + XMod} # Lft is darker than Rgt
else if(RAve<LAve) {Rgt = Rgt + XMod} # Rgt is darker than Lft
else if(Lft<Rgt) {Lft = Lft + XMod} # Lft and Rgt same AveLuma AND Lft < Rgt
else {Rgt = Rgt + XMod} # Lft and Rgt same AveLuma AND Rgt <= Lft
}
YMod = RT_ColorSpaceYMod(Laced=False) # Top and Bot Scan Height : eg 1 for RGB and YUY2, 2 for YV12
HKill = (HKill + YMod-1) / YMod * YMod # Round UP Will return WRONG SIZE and Error Alert of HKill not multiple of YMod.
Top=0 Bot=0
While(Top+bot<HKill) {
TAve=RT_AverageLuma(n=n,x=0,y=Top,w=0,H=YMod)
BAve=RT_AverageLuma(n=n,x=0,y=Height-YMod-Bot,w=0,H=YMod)
if(TAve<BAve) {Top = Top + YMod} # Top is darker than Bot
else if(BAve<TAve) {Bot = Bot + YMod} # Bot is darker than Top
else if(Top<Bot) {Top = Top + YMod} # Top and Bot same AveLuma AND Top < Bot
else {Bot = Bot + YMod} # Top and Bot same AveLuma AND Bot <= Top
}
Crop(Lft,Top,-Rgt,-Bot)
(Subs)?RT_Subtitle("Lft=%d Rgt=%d : Top=%d Bot=%d",Lft,Rgt,Top,Bot,Align=5):NOP
Return Last
}
Function Katie(clip c,Int "WKill",Int "HKill",Bool "Subs") {
WKill=Default(WKill,0)
HKill=Default(HKill,0)
Subs=Default(Subs,False)
Dummy=c.Crop(WKILL,HKILL,0,0) # Scriptclip can ONLY return same size clip as arg, so we create dummy clip
SCRIPT = "return Katie_Lo(c,current_frame,WKill,HKill,Subs)" # We use c clip and simply discard the dummy clip
Return Dummy.ScriptClip(SCRIPT,Args="c,WKILL,HKILL,Subs") # Import c (full uncropped) clip into Scriptclip (req Grunt)
}
""")

#####################################
#Avisource("CabaretUncropped.avi") # My Test clip

### Katie's Config Below
mpeg2source("001.d2v")
bob(b=0,c=1)
selecteven()
#
WKILL = 16
HKILL = 0
SUBS = True
#
Katie(wkill=WKILL,hkill=HKILL,subs=SUBS)
simpleresize(352,240)
###
Return Last


EDIT: If you provide WKill/HKill less than total border thickness you will easily see the instability.

EDIT: Even if encoded in CPP, would be slowish (and unstable), a simple Crop() is considered a 'zero cost' filter, especially
if not aligning in memory (just adjusts offset within the frame descriptor), but this function would not only have to
scan each and every frame, would also need to vary the coords to copy into a new frame (no great overhead I guess).
I would not waste my time converting this to CPP but is interesting exercise in script.
RoboCrop prescans 40(default) frames in constructor (less than 1.0 second usually) before frame serving starts, after
that is little different to a zero cost crop() filter (when align=false[default]).

EDIT: Is real slow when cropping all four sides of my Cabaret test clip (Liza Minnelli) with borders about 28,90,-24,-92.
EDIT: I wonder if there is a better (hier rez) version of Cabaret, mine came as freebie on cover of tabloid newspaper.

Katie Boundary
15th June 2016, 02:08
You... you'd have me bob, selecteven, bob again, selecteven again, resize, and then resize again?

Or did you not read my post carefully enough? :p

When I have no idea how your script actually works, I can't distinguish between what you're trying to say and what you're actually saying, which makes it absolutely critical that the rest of our communication be specific and 100% accurate. When I ask you what to replace one line of my script with, and you respond with a complete script, that's a sign that we're not communicating clearly. I was able to catch this communication error, but what errors have escaped my attention?

And what the hell is "CabaretUncropped.avi"? Why is it in the script?

StainlessS
15th June 2016, 02:20
And what the hell is "CabaretUncropped.avi"? Why is it in the script?

I dont have your clip and I have to test with something. [EDIT: You can delete from your version, but I'm keeping in mine]

The last script spoon feeds you with everything. http://www.cosgan.de/images/smilie/nahrung/e035.gif

EDIT: The first ever program on UK ITV Television on 22 Sept 1955 was a childrens TV program called "Muffin the Mule".
I always thought it sounded like something you would get jail for http://www.cosgan.de/images/smilie/froehlich/r015.gif [Except in certain US states]

EDIT: Seems I'm wrong about Muffin the Mule, not even on ITV:- http://home.bt.com/news/world-news/september-22-1955-commercial-television-comes-to-britain-as-itv-starts-broadcasting-11364005683860
https://en.wikipedia.org/wiki/Muffin_the_Mule
https://www.youtube.com/watch?v=spQY2FbCUtM

Dont know where I got that from http://www.cosgan.de/images/smilie/konfus/a080.gif

Katie Boundary
17th June 2016, 05:20
BTW Stainless I'm sorry that this is taking so long. I've been sidetracked by several different things in the past few days. However, my WoW subscription expired earlier today so I should have some results to report tomorrow.

Katie Boundary
18th June 2016, 04:31
Well now, THIS is neat. Not only is the script clipping the borders pretty closely to where it should, but it's giving me some white text telling me exactly what it's clipping from each frame, thus saving me a whole LOT of trouble that I thought I'd have to go through with copying source frames to clipboards and seeing exactly what parts of the original image they corresponded to... the bad news is, it's only cropping in increments of two.

I'll do more thorough stress-testing in the next few days. For now, StainlessS, I am quite impressed with your black magic. I must learn what all this arcane jibberish means...

EDIT: adding converttorgb and replacing simpleresize with bilinear fixed the even-numbered pickiness. It's now cropping exactly where it's supposed to: 11 off the left and 5 off the right, occasionally veering into 12/4 or 10/6 when it's supposed to. If I still had a Paypal account, I would send you five bucks.

EDIT 2: The first experiment used Exo Squad episode 4, "Blitzkreig". The second run, using episode 2, "Seeds of Deception", proved far more... interesting. The black bars were somewhere in the neighborhood of 4,-7, so the results should have ranged from 7,-9 to 6,-10. Actual results were quite a bit more erratic...

https://scontent-dfw1-1.xx.fbcdn.net/v/t1.0-9/13417618_1702172123380576_7433326870192021335_n.jpg?oh=506e06b4f10f961c75f43fa9692d6579&oe=57CFCA7B

It definitely seemed like the filter wasn't very good at handling thinner-than-expected black bars, especially when one edge of the screen was a lot darker than the other. This is exactly what I expected from the first-draft version of the filter, before I figured out that this is exactly what would happen.

The good news is that I've had the time to figure out how the second-draft version might work. It requires setting an arbitrary threshold parameter and involves a much more complicated decision tree, though...

StainlessS
18th June 2016, 17:42
Yep, YV12 [from mpeg2source("001.d2v")] can only be cropped mod2 [both horiz & vert, you cannot crop a chroma sample in half],
convertToRGB24/32 as RGB can be cropped mod1.
[might be faster to, convertToYV24, Katie(...), ConvertToRGB for display <cannot normally view YV24>].

EDIT: Below inquires current colorspace min cropping increment.

XMod = RT_ColorSpaceXMod # Left and Right scan Width : eg 1 for RGB, 2 for YV12 & YUY2

StainlessS
21st June 2016, 04:46
RoboCrop v1.08, new version. See 1st post.

V1.08 Docs overflow 16kb limit, so left first post docs at v1.0.
See post #37 for v1.08 Docs over two posts. Here: http://forum.doom9.org/showthread.php?p=1696703#post1696703


v1.06, Changed Default WMod to 4, avoid possible problems in Avisynth v2.58, some media players and VDubMod.
Changed Default AutoThresh to -40.0, been wanting to do this for some time.
Changed default Samples to 40, paranoia.
v1.07, Changed to recognise AutoThresh of both -32.0 and -40.0 as DEFAULT AUTOTHRESH (both old and new version args).
v1.08, wmod,hmod limited max 16. Fixed crop centering.


zip @ mediafire or Sendspace in sig below.

EDIT:

AvisourcE("CabaretUncropped.avi")
A=RoboCrop(WMod=16,HMod=16,Laced=false, show=true,CropMode=1).Trim(13858,-1) # 1 frame CropLess
B=A.BlankClip(height=4,color=$FFFFFF) # white separator
C=RoboCrop(WMod=16,HMod=16,Laced=false, show=true,CropMode=2).Trim(13858,-1) # 1 frame CropMore
StackVertical(A,B,C)

https://s20.postimg.org/rewnay9h9/frame0_zpsuans01iu.jpg (https://postimg.org/image/mg94wf5o9/)

StainlessS
24th August 2016, 15:07
RoboCrop v1.09, new version.

Small change only.


Show: Default false. If true, then does no cropping, just shows a little info on frame. Overrides both Blank and Align.
v1.09, Added cross hair reticule when show=True. Larger markings are 10 pixels apart, dots are 5 pixels apart.
Perhaps of use where borders not of fixed position.

EDIT: RoboCrop detects the outermost borders.

See 1st post.

https://s20.postimg.cc/90m46yx6l/reticule_zpspscygvvx.png (https://postimg.cc/image/muagw0prt/)

EDIT:

Int LeftAdd, TopAdd, RightAdd, BotAdd, All default 0. Valid range depends upon clip dimensions, Skip and Baffle settings.
User adjustments to Skip + Autocrop exact found coords. CropMode applied after user Add adjustments.

Can crop a lil bit more off by using the eg LeftAdd etc args, after viewing the recticule when Show=true.

StainlessS
25th August 2016, 18:23
v1.10, new version. See 1st post or docs here:- http://forum.doom9.org/showthread.php?p=1696703#post1696703


Show: Default false. If true, then does no cropping, just shows a little info on frame. Overrides both Blank and Align.
Final image edge positions shown as dotted lines every fifth pixel set white, always shown. Final image edge markers show edge
after any User adjustment via Add args (LeftAdd, TopAdd, RightAdd, BotAdd), and also after Modn rounding applied (CropMore/CropLess).
Exact image edges are shown if not exactly coinciding with Final Image Edge markers, Exact image edge markers shown as every 3rd pixel
plotted in white.
Where the Skip args (LeftSkip, TopSkip, RighSkip, BotSkip) are non zero, will show skip positions as dotted lines with dots
every other pixel, not plotted if exact same position at final Modn (CropMore/CropLess) position or detected exact edge position.
The Skip args preset the 'already cropped area', ie auto cropping starts with edges already considered border.
Added cross hair reticule when show=True. Larger markings are 10 pixels apart, dots are 5 pixels apart.
Perhaps of use where borders not of fixed position.


https://s20.postimg.org/hwwwawnst/cab_zpsuusmfo3y.png (https://postimg.org/image/n8bsvm9vd/)

script used.

AviSource("D:\V\CabaretUnCropped.avi")
RoboCrop(laced=False,Show=True,Debug=true,LeftSkip=5,TopSkip=5,RightSkip=5,BotSkip=5,LeftAdd=4,TopAdd=4,RightAdd=4,BotAdd=4)
Return last


Added Skip args just to show skip markers (not shown if 0), and Add args for no particular reason other than to show separated from exact image markers.
Exact top edge y1, at 89, User adjustment to 93, and then rounded YMod=2 to 94 (CropMore).

EDIT: Debug output

00000004 18:25:58.937 RoboCrop: RoboCrop: v1.10 - 25 Aug2016 - By StainlessS
00000005 18:25:58.937 RoboCrop: Input: Width=720 Height=576 FrameCount=15285
00000006 18:25:58.937 RoboCrop:
00000007 18:25:58.937 RoboCrop: Thresh defaulting to DEFAULT AUTOTHRESH -40.00
00000008 18:25:58.937 RoboCrop: Thresh -40.00 recognised as DEFAULT AUTOTHRESH
00000009 18:25:58.937 RoboCrop: Potential Auto Credits Skip Start@5%=764 End @90%=13756 : Range=12993
00000010 18:25:58.937 RoboCrop: Skip Start(764) and End(13756) : Range=12993
00000011 18:25:58.937 RoboCrop:
00000012 18:25:58.937 RoboCrop: Samples=40 Thresh=-40.000 Laced=False Matrix=2
00000013 18:25:58.937 RoboCrop: WMod=4 HMod=2 {Colorspace/Laced Restricted XMod=2 YMod=2}
00000014 18:25:58.937 RoboCrop: RLBT=15 Ignore=0.400 Baffle=4
00000015 18:25:58.937 RoboCrop: ScaleAutoThreshRGB=Yes ScaleAutoThreshYUV=No
00000016 18:25:58.937 RoboCrop: CropMode=2(CropMore) Blank=No Align=No Show=Yes Log=No
00000017 18:25:58.937 RoboCrop: Atm=4.000 SampStart=764 SampEnd=13756 SampRange=12993
00000018 18:25:58.937 RoboCrop: LeftAdd=4 TopAdd=4 RightAdd=4 BotAdd=4
00000019 18:25:58.937 RoboCrop: LeftSkip=5 TopSkip=5 RightSkip=5 BotSkip=5
00000020 18:25:58.937 RoboCrop:
00000021 18:25:58.953 RoboCrop: AutoThresh 1) [ 764] YPlaneMin = 14 (14)
00000022 18:25:58.968 RoboCrop: AutoThresh 2) [ 1097] YPlaneMin = 14 (14)
00000023 18:25:58.984 RoboCrop: AutoThresh 3) [ 1430] YPlaneMin = 14 (14)
00000024 18:25:59.000 RoboCrop: AutoThresh 4) [ 1763] YPlaneMin = 14 (14)
00000025 18:25:59.015 RoboCrop: AutoThresh 5) [ 2097] YPlaneMin = 14 (14)
00000026 18:25:59.031 RoboCrop: AutoThresh 6) [ 2430] YPlaneMin = 15 (14)
00000027 18:25:59.062 RoboCrop: AutoThresh 7) [ 2763] YPlaneMin = 14 (14)
00000028 18:25:59.093 RoboCrop: AutoThresh 8) [ 3096] YPlaneMin = 14 (14)
00000029 18:25:59.125 RoboCrop: AutoThresh 9) [ 3429] YPlaneMin = 14 (14)
00000030 18:25:59.140 RoboCrop: AutoThresh 10) [ 3762] YPlaneMin = 14 (14)
00000031 18:25:59.156 RoboCrop: AutoThresh 11) [ 4095] YPlaneMin = 14 (14)
00000032 18:25:59.187 RoboCrop: AutoThresh 12) [ 4428] YPlaneMin = 14 (14)
00000033 18:25:59.203 RoboCrop: AutoThresh 13) [ 4762] YPlaneMin = 14 (14)
00000034 18:25:59.234 RoboCrop: AutoThresh 14) [ 5095] YPlaneMin = 14 (14)
00000035 18:25:59.250 RoboCrop: AutoThresh 15) [ 5428] YPlaneMin = 14 (14)
00000036 18:25:59.265 RoboCrop: AutoThresh 16) [ 5761] YPlaneMin = 14 (14)
00000037 18:25:59.281 RoboCrop: AutoThresh 17) [ 6094] YPlaneMin = 14 (14)
00000038 18:25:59.296 RoboCrop: AutoThresh 18) [ 6427] YPlaneMin = 14 (14)
00000039 18:25:59.328 RoboCrop: AutoThresh 19) [ 6760] YPlaneMin = 14 (14)
00000040 18:25:59.343 RoboCrop: AutoThresh 20) [ 7093] YPlaneMin = 14 (14)
00000041 18:25:59.359 RoboCrop: AutoThresh 21) [ 7427] YPlaneMin = 15 (14)
00000042 18:25:59.375 RoboCrop: AutoThresh 22) [ 7760] YPlaneMin = 14 (14)
00000043 18:25:59.390 RoboCrop: AutoThresh 23) [ 8093] YPlaneMin = 14 (14)
00000044 18:25:59.406 RoboCrop: AutoThresh 24) [ 8426] YPlaneMin = 14 (14)
00000045 18:25:59.421 RoboCrop: AutoThresh 25) [ 8759] YPlaneMin = 14 (14)
00000046 18:25:59.437 RoboCrop: AutoThresh 26) [ 9092] YPlaneMin = 14 (14)
00000047 18:25:59.453 RoboCrop: AutoThresh 27) [ 9425] YPlaneMin = 14 (14)
00000048 18:25:59.468 RoboCrop: AutoThresh 28) [ 9758] YPlaneMin = 14 (14)
00000049 18:25:59.484 RoboCrop: AutoThresh 29) [ 10092] YPlaneMin = 14 (14)
00000050 18:25:59.500 RoboCrop: AutoThresh 30) [ 10425] YPlaneMin = 14 (14)
00000051 18:25:59.515 RoboCrop: AutoThresh 31) [ 10758] YPlaneMin = 14 (14)
00000052 18:25:59.531 RoboCrop: AutoThresh 32) [ 11091] YPlaneMin = 14 (14)
00000053 18:25:59.546 RoboCrop: AutoThresh 33) [ 11424] YPlaneMin = 14 (14)
00000054 18:25:59.562 RoboCrop: AutoThresh 34) [ 11757] YPlaneMin = 14 (14)
00000055 18:25:59.578 RoboCrop: AutoThresh 35) [ 12090] YPlaneMin = 14 (14)
00000056 18:25:59.593 RoboCrop: AutoThresh 36) [ 12423] YPlaneMin = 14 (14)
00000057 18:25:59.609 RoboCrop: AutoThresh 37) [ 12757] YPlaneMin = 14 (14)
00000058 18:25:59.625 RoboCrop: AutoThresh 38) [ 13090] YPlaneMin = 14 (14)
00000059 18:25:59.640 RoboCrop: AutoThresh 39) [ 13423] YPlaneMin = 14 (14)
00000060 18:25:59.656 RoboCrop: AutoThresh 40) [ 13756] YPlaneMin = 14 (14)
00000061 18:25:59.656 RoboCrop:
00000062 18:25:59.656 RoboCrop: YPlaneMin=14 : Automatic set Thresh=54.000
00000063 18:25:59.656 RoboCrop:
00000064 18:25:59.656 RoboCrop: Top 1) [ 764] AveY= 54.30 Y1=178
00000065 18:25:59.656 RoboCrop: Bot 1) [ 764] AveY= 58.04 Y2=484
00000066 18:25:59.656 RoboCrop: Lft 1) [ 764] AveY= 54.79 X1=154
00000067 18:25:59.656 RoboCrop: Rgt 1) [ 764] AveY= 54.75 X2=695
00000068 18:25:59.656 RoboCrop: Lft 3) [ 1430] AveY= 54.43 X1= 28
00000069 18:25:59.671 RoboCrop: Top 9) [ 3429] AveY= 54.11 Y1=177
00000070 18:25:59.671 RoboCrop: Rgt 10) [ 3762] AveY= 69.26 X2=696
00000071 18:25:59.671 RoboCrop: Top 14) [ 5095] AveY= 54.04 Y1= 89
00000072 18:25:59.734 RoboCrop:
00000073 18:25:59.734 RoboCrop: Active Frames (where image coords first found) = 5
00000074 18:25:59.734 RoboCrop: Sampled ImageEdge: X1=28 Y1=89 X2=696(W=669,-23) Y2=484(H=396,-91)
00000075 18:25:59.734 RoboCrop:
00000076 18:25:59.734 RoboCrop: User Adjust: X1=32 Y1=93 X2=692(W=661,-27) Y2=480(H=388,-95)
00000077 18:25:59.734 RoboCrop:
00000078 18:25:59.734 RoboCrop: Crop(ModW/H): X = 32 Y = 94 W =660(-28) H =386(-96)
00000079 18:25:59.734 RoboCrop: Constructor Scan Total Time=0.812 secs


EDIT:Below, Y1 top exact image edge = 89, rounded mod 2 to 90, so where rounding (default CROPMORE), will show wiggly edge as on top,
right and bottom (adjacent dotted lines). Left edge did not need rounding.

RoboCrop(laced=False,Show=True)

https://s20.postimg.cc/b7qcuw2gt/cab2_zpsjgrrflzt.png (https://postimg.cc/image/vf3sn6zy1/)

gaak
18th January 2017, 00:21
Hello all,

Anyone know the location of a 64 bit version of RoboCrop? The only link I could find to MediaFire returns as invalid.

Thanks.

StainlessS
18th January 2017, 00:36
The is no 64 bit version of RoboCrop (leastwise not by me). what MediaFire link are you talking about that returns as 'invalid' ?

EDIT: I did try to do some filter in 64 bit (I'm on XP32) some time ago, but it did not work, cant remember what it was.

gaak
18th January 2017, 01:07
The is no 64 bit version of RoboCrop (leastwise not by me). what MediaFire link are you talking about that returns as 'invalid' ?

I used the link on this page:

http://avisynth.nl/index.php/External_filters#64-bit_filters

It's under "Borders and Cropping". It points to MediaFire.

StainlessS
18th January 2017, 02:47
You were looking in the wrong place, should have taken this link at page you linked (link marked in Blue)

64-bit filters

A comprehensive list of 64-bit filters is available in the AviSynth+ page

ie here:- http://avisynth.nl/index.php/AviSynth%2B#AviSynth.2B_x64_plugins

RoboCrop is not in the list, however AutoCrop is (but it was not that good unless improved since I last tried).

gaak
18th January 2017, 03:48
You were looking in the wrong place, ...

I can see how you would have thought that but I had looked at the page you suggested too. I was looking for and found other 64 bit filters like Colormatrix which is not on that list. I dug a little deeper and was just wondering if anyone had a copy. Yes, AutoCrop is on the list and I am using it, but I prefer to use yours over that one as I have found cases where AutoCrop fails.

Thanks.

StainlessS
18th January 2017, 05:00
I can see how you would have thought that

I'm not sure what you are saying (but it dont matter anyway), the page that you originally linked was the general external filters page,
and the 64 bit section was simply a link to the Avs+ 64 bit page, no other plugins on the original page are 64 bit.
(although they may have counterparts on the 64 bit page).

I have found cases where AutoCrop fails

Yep, not so hard to find them.

EDIT: By the way, the 32 bit RoboCrop MediaFire link should not really have been put up on the Wiki, old dll zips are deleted when a new version is uploaded, so direct links on MediaFire will be invalid, Wiki should really point links at the StainlessS folder on MediaFire or the plugin thread on D9, which will in turn point to MediaFire/StainlessS folder.

gaak
18th January 2017, 11:45
I'm not sure what you are saying (but it dont matter anyway), the page that you originally linked was the general external filters page,
and the 64 bit section was simply a link to the Avs+ 64 bit page, no other plugins on the original page are 64 bit.
(although they may have counterparts on the 64 bit page).


The words didn't come out right. I was just saying I was hunting for other sources and came across that site. I must have been punch-drunk from spending too many hours debugging and digging around. I went back to the site in question and you're right, It was for 32 bit filters. Sorry if I caused any confusion. It wasn't my intention. Anyway, I hope you get opportunity the to make a 64 bit version someday, it's a superior filter.

Groucho2004
18th January 2017, 12:50
Anyway, I hope you get opportunity the to make a 64 bit version someday, it's a superior filter.
I gave it a go, try the 64 bit RoboCrop from here (https://www.dropbox.com/s/mdum817nakt8ncm/RoboCrop64.7z?dl=0). I hope Stainless has no objections. :)

Reel.Deel
18th January 2017, 15:25
I gave it a go, try the 64 bit RoboCrop from here (https://www.dropbox.com/s/mdum817nakt8ncm/RoboCrop64.7z?dl=0). I hope Stainless has no objections. :)

Thanks, I'll add it to the list. :)

Did you compile it with ICL?

Groucho2004
18th January 2017, 16:44
Thanks, I'll add it to the list. :)

Did you compile it with ICL?
Built with VC10_64, ICL didn't yield any advantage. I only tested it very briefly but it should be working fine.

StainlessS
18th January 2017, 20:01
Thanx g2k4, no probs with that here. No surprise that ICL gives no advantage,, all work done before frame serving starts.
Mobile.

StainlessS
23rd October 2017, 18:43
By the way, I eventually found out why I was having probs installing SDK 7.1 for VS 2008 (with 64bit), seems the SDK ISO I had was corrupt, with much of it missing but still occupying blank space, it failed on accessing some html file (whose name existed), but the file contents did not exist in the ISO (so install failed and uninstalled again).

Guess I really should check MD5's :(

StainlessS
7th January 2019, 06:43
RoboCrop v1.11, new version see 1st post.
For v1.11 Docs, see post #37:- https://forum.doom9.org/showthread.php?p=1696703#post1696703


v1.09, Added reticule when Show=true..
v1.10, Added Exact line marker when show.
v1.11, 07 Jan 2019. Added Version Resource, Move to VS2008, Added x64, Changed default Align=True.



Align: Default True. If true, then aligns frames in memory when cropping, for eg SSE2 16-byte alignment required by some
filters, particularly smoothing filters (filters following RoboCrop). See Docs for Crop().
Only Applies if Cropping, ie Blank==false AND Show==false.
v1.11, changed Default to True, avoid Avs+ problems which can put up an error if False.


EDIT:
SSE2 16-byte alignment
Actually, I think AVS+ might align to either 32 or 64 bytes(think 64, not sure).

spoRv
30th January 2019, 01:06
Dear StainlessS, first of all, thanks for all your scripts!

:thanks:

Back to topic: DynaCrop (https://forum.doom9.org/showthread.php?p=1633485#post1633485)

I have a video with variable vertical borders; they are pixel perfect (no "smearing" like in analog captures).
I want to get fixed borders for the whole video, so it seems your DynaCrop is the right script.

Some questions:
Return SC_ShowMetrics().ConvertToYV12() # Show metrics to get best Threshold 'th', use before SC_MakeTrimFile()

Borders are pure black ($000000); could I skip this step?

return SC_MakeTrimFile().ConvertToYV12() # Make Trims file for DynaCrop(), Must Play all way through.

This writes actually the crop info file, right?

DynaCrop(CropThresh=CROPTHRESH,show=SHOW,debug=DEBUG).ConvertToYV12(

Then at the end this produces the script needed to crop and resize the video, right?

Now, let's say that I want the video to be resized at 1920x816, where should I set these figures?

Last thing:
x,y,w,h sets border to ignore crud
not understood, can you explain?

Thanks a lot in advance, hope to not abuse (well, not too much!) of your infinite patience! :D

StainlessS
30th January 2019, 01:57
Sorry, but I aint gonna go back to look at that, was long Superceded by DBSC:- https://forum.doom9.org/showthread.php?t=171624&highlight=DBSC

x,y,w,h sets border to ignore crud
Crud, maybe VHS with borders but also with VHS tracking crud, otherwise crud would look like NOT border, allows script to assume the crud at least is border. x,y,w,h are crop type coords.

I dont know of anything else that can do what DBSC can do, but it aint automatic.
The current version is somewhat diferent to posted, but is not really suitable for posting yet.

EDIT: You defo need DebugView, and need to use it.

Dreamject
24th April 2019, 16:45
Why is it not working or even can not detect borders? I use potplayer
https://s16.directupload.net/images/190424/c7yri5jb.png (https://s16.directupload.net/images/190424/i9ru5ef5.png)

PPcheck=1#WIDTH
PPcheck==1? eval ("""
SetFilterMTMode("ffdshow_source",3)
ffdshow_source()
ConvertToYV12()
global threads=2 #for regular player
""") : eval ("""
global threads=round(1.83 * #CPUS) #valid only for PotPlayer. You can calculate and input numbers of CPU Cores*2 manually
SetFilterMTMode("potplayer_source",3)
potplayer_source()
""")
LoadPlugin("avisynth\RoboCrop_x86.dll")
LoadPlugin("autocrop.dll")
#autocrop(mode=1)
RoboCrop(Samples=10,show=true) #RoboCrop(potplayer_source/ffdshow_source,show=true)



Potplayer does not support resizing, but I need to crop black borders for better motion interpolation
If I just use crop, it works, but still can not get why robocrop/autocrop can not even recognize black borders (i've used pc level too)
LoadPlugin("avisynth\RoboCrop_x86.dll")
crop(100,100,400,376)
RoboCrop(show=true)
https://s16.directupload.net/images/190424/a6hb9t88.png (https://s16.directupload.net/images/190424/rxml5lox.png)

StainlessS
25th April 2019, 13:12
What does the debug output tell you, post it. [ RoboCrop(show=true,debug=true) # you need DebugView, google]
Try in something other than Potplayer, I've never even heard of PotPlayer_Source, Suggest Vdub2.
Does your clip have sections without any border, if so then it is doing exactly what its supposed to do.
Absolutely no idea what is happening with your 2nd image, I would say that result is impossible.
(dont have any idea what the blue stuff says either).
Also, suggest that you do not change Samples, default 40 samples would probably take less than a second to scan.

EDIT: What is the clip length ?
RoboCrop deliberately alters thresh for short clips (when using Default autothresh, Thresh = -32.0 or thresh = -40). [to avoid overcrop on short dark clips]
If your clips are dark (and they look like they are), and also short, then set a non DEFAULT_AUTOTHRESH.


Thresh: Default= -40.0 (==DEFAULT AUTOTHRESH, any -ve (or 0.0) Thresh is AUTOTHRESH where Thresh adjustments are automatic).
v1.06, Changed DEFAULT AUTOTHRESH from -32.0 to -40.0.
v1.07, Changed to recognise a Thresh of either -32.0 or -40.0 as DEFAULT_AUTOTHRESH (fully automatic).

Thresh > 0: (Explicit Threshold)
A user supplied +ve Thresh should be at correct TV/PC levels for the the clip being worked on ie 16->235 for TV levels and
0->255 for PC Levels (RGB, as appropriate for matrix being used).

Thresh <= 0: (AUTOTHRESH)
When Thresh <= 0, the clip will be sampled over Samples frames to find the minimum YPlaneMin (using Matrix if RGB) which
we will call MINLUMA and an Explicit Threshold calculated by adding MINLUMA to abs(Thresh), after that it is processed
as for Thresh > 0: (Explicit Threshold) as noted above, but, before adding MINLUMA, some AUTOTHRESH massaging and scaling occurs.

Here AUTOTHRESH Thresh massaging and scaling occurs in sequence:-
1 ) if (Thresh == DEFAULT AUTOTHRESH && ATM < abs(thresh))
(DEFAULT AUTOTHRESH = exactly -40.0, defaulted OR user supplied, v1.07 also recognises -32.0 as DEFAULT_AUTOTHRESH):
Let sampstart and sampend, be starting and ending frames numbers after any Auto Credits skipping and/or user set Start or End.
Let Samples be limited to sampend-sampstart+1.
Let SampRange (Sample Range) = SampEnd-SampStart+1.
samples_massage =(Samples>=20) ? 1.0 : (Samples-1) * (1.0/(20-1)) # No massaging if Samples >= 20
range_massage =(SampRange >= (250*20)) ? 1.0 : (SampRange-1) * (1.0/((250*20)-1)) # No massaging if SampRange >= 5000
Both samples_massage and range_massage will be in range 0.0 to 1.0.
Thresh = -(((samples_massage * range_massage) * (abs(Thresh) - ATM)) + ATM)
This adjustment to Auto Thresh is to reduce the possibility of overcropping on eg a dark low 'Samples' clip, or where
source SampRange (ie temporal frame set) is too small to take a reliable sample from.
Resulting massaged Thresh will range between -ATM and DEFAULT_AUTOTHRESH.
Although massaging is intended to reduce overcropping, it could result in not cropping enough border (less disastrous),
its a bit of a balancing act really. See also ATM.
2 ) If RGB AND PC matrix(default) AND ScaleAutoThreshRGB==True(default) then
Thresh= Thresh*(255.0/(235-16))
3 ) If YUV AND ScaleAutoThreshYUV==True(default=false) then
Thresh= Thresh*(255.0/(235-16))

Steps 2) and 3) above, by default treat a -ve AUTOTHRESH as being @ TV Levels and so Scale RGB Thresh to PC levels but not YUV.
If you want to supply a PC levels AUTOTHRESH Thresh for RGB, then simply set ScaleAutoThreshRGB=false to inhibit scaling.
Note, if a TV levels Matrix is supplied for RGB, then scaling will always be inhibited.
If your clip is YUV at PC levels and you want to use eg DEFAULT AUTOTHRESH (-40.0, which is considered to be @ TV levels),
then set ScaleAutoThreshYUV=True to enable Thresh scaling.
If your clip is YUV at PC levels and you want to use a PC levels AUTOTHRESH (-ve) then leave ScaleAutoThreshYUV at default false
which does not scale Thresh.
After any scaling, MINLUMA is then added to abs(Thresh) and processed as for +ve Explicit Threshold as noted above.
NOTE, Above RoboCrop step 1) 'massages' DEFAULT_AUTOTHRESH (exactly -40.0 or v1.07 exactly -32.0) if low samples count or if short clip.
Reason being to avoid overcropping when insufficient data available for reliable cropping. It is considered better to not crop enough
or at all, than to overcrop. You can override by simply setting an explicit threshold (+ve) of eg 40.0, or setting a NON-DEFAULT auto thresh
(-ve) eg -16.0 or -40.1, where YPlaneMin is established for the sampled frames and then abs(thresh) is added to that value which
is then used as an explicit thresh.
NOTE, v1.07 recognises a Thresh of either -40.0 OR -32.0 as DEFAULT_AUTOTHRESH, so user can provide either value and
DEFAULT_AUTOTHRESH massaging will be applied for low samples count and/or low frame ranges.

StainlessS
6th February 2020, 19:02
RoboCrop v1.12, update, see first post.

Added ScanPerc, allows detect when image is wholly one or other side of clip center.

Function RoboCrop(clip c,int "Samples"=40,Float "Thresh"=-40.0,bool "Laced"=true,int "WMod",int "HMod",int "RLBT"=15,bool "Debug"=false, \
float "Ignore"=0.4,int "Matrix"=(c.Width>1100||c.Height>600?3:2), int "Baffle"=4, bool "ScaleAutoThreshRGB"=true,
bool "ScaleAutoThreshYUV"=false, int "CropMode"=2,bool "Blank"=false,bool "BlankPC"=false,bool "Align"=True,bool "Show"=false, \
String "LogFn"="",bool "LogAppend"=false, Float "ATM"=4.0,int "Start"=Undefined,Int "End"=Undefined, \
Int "LeftAdd"=0,Int "TopAdd"=0,Int "RightAdd"=0,Int "BotAdd"=0, \
Int "LeftSkip"=0,Int "TopSkip"=0,Int "RightSkip"=0,Int "BotSkip"=0 \
Float "ScanPerc=49.0 )



Float ScanPerc, Default 49.0, Range 1.0->99.0. Precentage of clip dimensions to scan for border edges.
Default 49.0%, Starts scan from nearly the middle of frame to outer edge of frame looking for borders.
Specialist use, might use eg 99.0% when image wholly to one of other side of the middle of frame.
eg, when 99.0, starts scan for TOP edge at nearly bottom of frame, scanning upwards.
starts scan for BOT edge at nearly top of frame, scanning downwards.
starts scan for LFT edge at nearly RHS of frame, scanning leftwards.
starts scan for RGT edge at nearly LHS of frame, scanning rightwards.




BlankClip(width=1024,height=768,Pixel_type="YV12").trim(0,-1)
W=Last.BlankClip(width=320,height=240,color=$FF00FF)
OverLay(W,x=680,y=416)
RoboCrop(Samples=1,debug=true,ScanPerc=99,show=true)
Return Last#.info


ScanPerc=99.0 [Show=True]
https://i.postimg.cc/251KvxyZ/RoboCrop.jpg (https://postimages.org/)

Show=true [from old version 1.06]
https://s20.postimg.cc/vk7jwv799/robo0_zpsfzfpfakr.jpg (https://postimg.cc/image/sq4ejf52x/)
Show=true [from old version 1.10]
https://s20.postimg.cc/b7qcuw2gt/cab2_zpsjgrrflzt.png (https://postimg.cc/image/vf3sn6zy1/)
Bottom image above: Left edge, single dots line, other edges a bit wiggly ie cropping moved inwards [CROPMORE] to adhere to X/Y/W/H Mod requirements.

EDIT: AutoCrop() fails badly [with defaults] on a 10 mins clip surrounding above frame from Cabaret. [chops off half of frame, not much image left]

Hotte
6th February 2020, 19:20
Thanks, StainlessS, for your nice support in Avs Dev-Forum and for this this new version of RoboCrop. Its great to have this option now for to crop frames away wherever they show up.
:thanks:

hello_hello
6th February 2020, 23:42
StainlessS,
Does RoboCrop only support 8 bit video? If that's the case do you have any plans?
Being all new and shiny I assumed it would support high bitdepths, so I was going to replace AutoCrop with RoboCrop in my script, but I appear to have assumed incorrectly.

I also have a feature request if it's not hard to do. For a future version would it be possible to display the cropping in human-speak in addition to the current method? ie
Crop(8,52,-16,-52)
and
Crop(8,52,1256,616)

The dimensions in human-speak would be great too. Something like:
Source Dimensions 1280x720
Cropped Dimensions 1256x616

I realise the information is already there. It's just a habit thing, or maybe I'm an idiot, but I don't see it displayed in other ways regularly, so I invariably need to down-tools for a bit while I think about it.

Cheers.

StainlessS
7th February 2020, 00:31
You are welcome Hotte :)

Hello_Hello,
Crop(8,52,-16,-52)
Look in above image, next to CROPMORE [Cabaret Image] ie
Crop(28,90,668,394) [CROPMORE]

From prev posted script for lob-sided borders (Debug=True)

00000146 23:22:07.597 RoboCrop: v1.12 - 06 Feb 2020 - By StainlessS
00000147 23:22:07.597 Input: Width=1024 Height=768 FrameCount=1
00000149 23:22:07.597 Thresh defaulting to DEFAULT AUTOTHRESH -40.00
00000150 23:22:07.597 Thresh -40.00 recognised as DEFAULT AUTOTHRESH
00000151 23:22:07.597 Potential Auto Credits Skip Start@5%=0 End @90%=0 : Range=1
00000152 23:22:07.597 No Skip Start(0), No Skip End(0) : Range=1 [Skip range < 250]
00000153 23:22:07.597 Low Samples count(1), Massaging Auto Thresh(samples scaler=0.000000)
00000154 23:22:07.597 Low Frames Range(1), Massaging Auto Thresh(range scaler=0.000000)
00000155 23:22:07.597 Combined Thresh Massage Scaler=0.000000
00000156 23:22:07.597 Auto Thresh reduced from DEFAULT -40.000000 to -4.000000
00000158 23:22:07.597 Samples=1 Thresh=-4.000 Laced=True Matrix=3
00000159 23:22:07.597 WMod=4 HMod=4 {Colorspace/Laced Restricted XMod=2 YMod=4}
00000160 23:22:07.597 RLBT=15 Ignore=0.400 Baffle=4
00000161 23:22:07.597 ScaleAutoThreshRGB=Yes ScaleAutoThreshYUV=No
00000162 23:22:07.597 CropMode=2(CropMore) Blank=No Align=Yes Show=Yes Log=No
00000163 23:22:07.597 Atm=4.000 SampStart=0 SampEnd=0 SampRange=1
00000164 23:22:07.597 LeftAdd=0 TopAdd=0 RightAdd=0 BotAdd=0
00000165 23:22:07.597 LeftSkip=0 TopSkip=0 RightSkip=0 BotSkip=0
00000166 23:22:07.597 ScanPerc=99.000000
00000168 23:22:07.597 AutoThresh 1) [ 0] YPlaneMin = 16 (16)
00000170 23:22:07.597 YPlaneMin=16 : Automatic set Thresh=20.000
00000172 23:22:07.597 Top 1) [ 0] AveY= 44.13 Y1=416
00000173 23:22:07.597 Bot 1) [ 0] AveY= 44.13 Y2=655
00000174 23:22:07.597 Lft 1) [ 0] AveY=106.00 X1=680
00000175 23:22:07.597 Rgt 1) [ 0] AveY=106.00 X2=999
00000177 23:22:07.597 Active Frames (where image coords first found) = 1
00000178 23:22:07.597 Sampled ImageEdge: X1=680 Y1=416 X2=999(W=320,-24) Y2=655(H=240,-112)
00000180 23:22:07.597 Crop(ModW/H): X =680 Y =416 W =320(-24) H =240(-112)
00000181 23:22:07.597 Constructor Scan Total Time=0.000 secs


As far as hi bit depth thing is concerned, there are not I think, many plugins that support HBD. [well some by Pinterf, and Source filters, maybe a few more].
I aint had enough play as yet to do a plug, and first one would have to be DDigit text renderer, which I would need in a lot of my plugs.
[Info.h Metrics text renderer from Avs+ source does not support HBD either, leastwise last time I looked.]

Maybe one day, but not today, sorry.

hello_hello
7th February 2020, 02:27
Look in above image, next to CROPMORE [Cabaret Image] ie
Crop(28,90,668,394) [CROPMORE]

I know it's there, but chances are some GUI users would have no idea you can crop that way, and to know what was cropped right and bottom you have to know the source dimensions, or check X,Y co-ordinates. The actual width and height might have been better than W and H there, but not to worry, it was just an idea.

Maybe one day, but not today, sorry.

I rarely work with HBD video anyway, but while I was playing with RoboCrop I thought I'd ask.

Cheers.

StainlessS
7th February 2020, 06:14
RoboCrop v1.13, update, see first post.
Full docs here:- https://forum.doom9.org/showthread.php?p=1696703#post1696703

Added Prefix Arg.

Function RoboCrop(clip c,int "Samples"=40,Float "Thresh"=-40.0,bool "Laced"=true,int "WMod",int "HMod",int "RLBT"=15,bool "Debug"=false, \
float "Ignore"=0.4,int "Matrix"=(c.Width>1100||c.Height>600?3:2), int "Baffle"=4, bool "ScaleAutoThreshRGB"=true,
bool "ScaleAutoThreshYUV"=false, int "CropMode"=2,bool "Blank"=false,bool "BlankPC"=false,bool "Align"=True,bool "Show"=false, \
String "LogFn"="",bool "LogAppend"=false, Float "ATM"=4.0,int "Start"=Undefined,Int "End"=Undefined, \
Int "LeftAdd"=0,Int "TopAdd"=0,Int "RightAdd"=0,Int "BotAdd"=0, \
Int "LeftSkip"=0,Int "TopSkip"=0,Int "RightSkip"=0,Int "BotSkip"=0 \
Float "ScanPerc=49.0,String "Prefix"="ROBOCROP_" )



String Prefix, Default "ROBOCROP_". Prefix for Local vars set by the filter, crop coordinates. Setting to "" disables Local vars.
With Prefix="ROBOCROP_" (Default)
ROBOCROP_X = X coord
ROBOCROP_Y = Y coord
ROBOCROP_W = +ve Width
ROBOCROP_H = +ve Height
ROBOCROP_W2 = -ve Width relative crop coord
ROBOCROP_H2 = -ve Height relative crop coord

Example use:
<<<<<<<<< CODE START <<<<<<<
BlankClip(Length=1,width=1024,height=768,Pixel_type="YV12")
Wid=Width
Hit=Height
BLK=Last.BlankClip(width=320,height=240,color=$FF00FF)
OverLay(BLK,x=680,y=416)
RoboCrop(ScanPerc=99,show=true,debug=true,Prefix="ROBOCROP_")
X=ROBOCROP_X # Get Local Vars as set by RoboCrop (Using Prefix, above using Prefix same as Default Prefix)
Y=ROBOCROP_Y
W=ROBOCROP_W
H=ROBOCROP_H
W2=ROBOCROP_W2
H2=ROBOCROP_H2
Subtitle("Source: Width="+String(Wid)+",Height="+String(Hit),Y=4)
Subtitle("Crop("+String(X)+","+String(Y)+","+String(W)+","+String(H)+")",Y=24)
Subtitle("Crop("+String(X)+","+String(Y)+","+String(W2)+","+String(H2)+")",Y=44)
Return Last
>>>>>>>>>> CODE END >>>>>>>


Test script

BlankClip(Length=1,width=1024,height=768,Pixel_type="YV12")
Wid=Width
Hit=Height
BLK=Last.BlankClip(width=320,height=240,color=$FF00FF)
OverLay(BLK,x=680,y=416)
RoboCrop(ScanPerc=99,show=true,debug=true,Prefix="ROBOCROP_")
X=ROBOCROP_X # Get Local Vars as set by RoboCrop (Using Prefix, above using Prefix same as Default Prefix)
Y=ROBOCROP_Y
W=ROBOCROP_W
H=ROBOCROP_H
W2=ROBOCROP_W2
H2=ROBOCROP_H2
Subtitle("Source: Width="+String(Wid)+",Height="+String(Hit),Y=4)
Subtitle("Crop("+String(X)+","+String(Y)+","+String(W)+","+String(H)+")",Y=24)
Subtitle("Crop("+String(X)+","+String(Y)+","+String(W2)+","+String(H2)+")",Y=44)
Return Last

https://i.postimg.cc/nzXhVmnv/Robo-Test-00.jpg (https://postimages.org/)

debug output

00000123 04:58:04.155 RoboCrop: v1.13 - 07 Feb 2020 - By StainlessS
00000124 04:58:04.155 Input: Width=1024 Height=768 FrameCount=1
00000126 04:58:04.155 Samples (40) limited to FrameCount(1)
00000127 04:58:04.155 Thresh defaulting to DEFAULT AUTOTHRESH -40.00
00000128 04:58:04.155 Thresh -40.00 recognised as DEFAULT AUTOTHRESH
00000129 04:58:04.155 Potential Auto Credits Skip Start@5%=0 End @90%=0 : Range=1
00000130 04:58:04.155 No Skip Start(0), No Skip End(0) : Range=1 [Skip range < 250]
00000131 04:58:04.155 Low Samples count(1), Massaging Auto Thresh(samples scaler=0.000000)
00000132 04:58:04.155 Low Frames Range(1), Massaging Auto Thresh(range scaler=0.000000)
00000133 04:58:04.155 Combined Thresh Massage Scaler=0.000000
00000134 04:58:04.155 Auto Thresh reduced from DEFAULT -40.000000 to -4.000000
00000136 04:58:04.155 Samples=1 Thresh=-4.000 Laced=True Matrix=3
00000137 04:58:04.155 WMod=4 HMod=4 {Colorspace/Laced Restricted XMod=2 YMod=4}
00000138 04:58:04.155 RLBT=15 Ignore=0.400 Baffle=4
00000139 04:58:04.155 ScaleAutoThreshRGB=Yes ScaleAutoThreshYUV=No
00000140 04:58:04.155 CropMode=2(CropMore) Blank=No Align=Yes Show=Yes Log=No
00000141 04:58:04.155 Atm=4.000 SampStart=0 SampEnd=0 SampRange=1
00000142 04:58:04.155 LeftAdd=0 TopAdd=0 RightAdd=0 BotAdd=0
00000143 04:58:04.155 LeftSkip=0 TopSkip=0 RightSkip=0 BotSkip=0
00000144 04:58:04.155 ScanPerc=99.000000
00000145 04:58:04.155 Prefix='ROBOCROP_'
00000147 04:58:04.155 AutoThresh 1) [ 0] YPlaneMin = 16 (16)
00000149 04:58:04.155 YPlaneMin=16 : Automatic set Thresh=20.000
00000151 04:58:04.155 Top 1) [ 0] AveY= 44.13 Y1=416
00000152 04:58:04.155 Bot 1) [ 0] AveY= 44.13 Y2=655
00000153 04:58:04.155 Lft 1) [ 0] AveY=106.00 X1=680
00000154 04:58:04.155 Rgt 1) [ 0] AveY=106.00 X2=999
00000156 04:58:04.155 Active Frames (where image coords first found) = 1
00000157 04:58:04.155 Sampled ImageEdge: X1=680 Y1=416 X2=999(W=320,-24) Y2=655(H=240,-112)
00000159 04:58:04.155 Crop(ModW/H): X =680 Y =416 W =320(-24) H =240(-112)
00000160 04:58:04.155 Input: Width=1024 Height=768
00000161 04:58:04.155 Crop(680,416,320,240)
00000162 04:58:04.155 Crop(680,416,-24,-112)
00000163 04:58:04.155 Constructor Scan Total Time=0.000 secs

hello_hello
8th February 2020, 05:32
That was speedy service. Thanks.
Is it always possible to get plugin variables that way, or is it something you've specifically had to configure?

"Usage" looked a bit hard, so I made a wrapper function and sexed it up a bit, although I'm not sure what font you're using normally.
I couldn't think of a better name, so it's called RoboCropped. It just calls RoboCrop with the options at their default values, but you can specify them as you can for RoboCrop, so to show the cropping preview it's Show=true as usual. The subtitles should sit in the bottom left corner. There's a link below.

Have you used RoboCrop with much h264 video? It's really, really slow to open for me with the default settings. Your example avs and mpeg2 are okay, but the 720p sources I've been playing around with take between 30 seconds to 1 minute to open. If I reduce Samples to 1 it's okay, so I guess there's a lot of decoding that needs to be done when checking lots of frames.

Cheers.

RoboCropped.avsi (https://files.videohelp.com/u/210984/RoboCropped.avsi)
(function edited 2020-02-29 to change scaling of subtitle text)

https://i.postimg.cc/g0VMGKyX/Robo-Cropped.jpg

StainlessS
8th February 2020, 06:37
or is it something you've specifically had to configure?
This is it

if(debug) {
dprintf("Crop(ModW/H): X =%3d Y =%3d W =%3d(%d) H =%3d(%d)",
crop_x,crop_y,crop_w,crop_x+crop_w-w,crop_h,crop_y+crop_h-h);
dprintf("Input: Width=%d Height=%d",w,h);
dprintf("Crop(%d,%d,%d,%d)",crop_x,crop_y,crop_w,crop_h);
dprintf("Crop(%d,%d,%d,%d)",crop_x,crop_y,crop_x+crop_w-w,crop_y+crop_h-h); // debug output
if(isplanar && crop_w % 4)
dprintf("*** WARNING *** Some players and VDubMod may require WMod=4");
double duration = (double(clock()) / double(CLOCKS_PER_SEC)) - start_time;
dprintf("Constructor Scan Total Time=%.3f secs",duration);
}
if(prefix !="") {
const char *p;
int pfixlen=int(strlen(prefix));
if(pfixlen>128)
pfixlen=128;
char bf[128+32];
memcpy(bf,prefix,pfixlen);
char *d;
AVSValue var;

d=bf+pfixlen;
for(p="X";*d++=*p++;); // strcat variable name part
var = GetVar(env,bf);
env->SetVar(var.Defined()?bf:env->SaveString(bf),crop_x);

d=bf+pfixlen;
for(p="Y";*d++=*p++;); // strcat variable name part
var = GetVar(env,bf);
env->SetVar(var.Defined()?bf:env->SaveString(bf),crop_y);

d=bf+pfixlen;
for(p="W";*d++=*p++;); // strcat variable name part
var = GetVar(env,bf);
env->SetVar(var.Defined()?bf:env->SaveString(bf),crop_w);

d=bf+pfixlen;
for(p="H";*d++=*p++;); // strcat variable name part
var = GetVar(env,bf);
env->SetVar(var.Defined()?bf:env->SaveString(bf),crop_h);

d=bf+pfixlen;
for(p="W2";*d++=*p++;); // strcat variable name part
var = GetVar(env,bf);
env->SetVar(var.Defined()?bf:env->SaveString(bf),crop_x+crop_w-w);

d=bf+pfixlen;
for(p="H2";*d++=*p++;); // strcat variable name part
var = GetVar(env,bf);
env->SetVar(var.Defined()?bf:env->SaveString(bf),crop_y+crop_h-h);
}

I did not bother to check for valid Prefix variable name, so if you provide something like "a!35434342123:'^%$", I've no idea if it will go BANG!!!.
Dont think I've ever seen anybody else check valid var name, I did it in one plug but forgot which one.

RoboCrop scans from start to end of video clip, Samples number of frames [default 40], spread evenly throughout the clip.
Is your source filter Indexing the thing, if so then that is where the pause is. [I usually use it with Ut_Video AVI, where it takes maybe less than 1.0 sec for 2 hr Movie].
LSMashVideoSource source does not index, although I dont know how well it does where seeking in big jumps through the video clip.
RoboCrop tries to get the OutMost borders, so if borders change will try to find the least crop borders.

"Usage" looked a bit hard"
I usually just call as RoboCrop(), is intended to be mostly autonomous. [might want to set WMod, HMod, and Laced].

If I reduce Samples to 1
Not a terribly good idea, dark single frame like the prev Cabaret frame might chop up your clip. [just as Autocrop with default settings of 5 samples frames (as I posted in Cabaret post)]
EDIT: AutoCrop() fails badly [with defaults] on a 10 mins clip surrounding above frame from Cabaret. [chops off half of frame, not much image left]

hello_hello
8th February 2020, 08:39
Thanks for the info.

"Usage" looked a bit hard"
I usually just call as RoboCrop(), is intended to be mostly autonomous. [might want to set WMod, HMod, and Laced].

Sorry, I meant "usage" in respect to adding the subtitles, not RoboCrop in general.

Not a terribly good idea, dark single frame like the prev Cabaret frame might chop up your clip. [just as Autocrop with default settings of 5 samples frames (as I posted in Cabaret post)]

I don't use auto cropping a lot, but I think the main reason AutoCrop's default settings might be more likely to fail isn't because it only takes 5 samples, but because the default for the first sample is the first frame, and the last sample is the second last frame. I'm not sure what the point of starting more than a few hundred frames from the beginning would be, especially for a movie and to avoid the end credits you'd probably want to finish a fair bit before the end too, but you'd no doubt know better than me.

StainlessS
8th February 2020, 12:34
Yes it normally starts at 5% and ends at 90% [below clip is only single frame so that is not gonna happen there, I said starts at beginning and ends at end, I was being economical with words.]


00000123 04:58:04.155 RoboCrop: v1.13 - 07 Feb 2020 - By StainlessS
00000124 04:58:04.155 Input: Width=1024 Height=768 FrameCount=1
00000126 04:58:04.155 Samples (40) limited to FrameCount(1)
00000127 04:58:04.155 Thresh defaulting to DEFAULT AUTOTHRESH -40.00
00000128 04:58:04.155 Thresh -40.00 recognised as DEFAULT AUTOTHRESH
00000129 04:58:04.155 Potential Auto Credits Skip Start@5%=0 End @90%=0 : Range=1
00000130 04:58:04.155 No Skip Start(0), No Skip End(0) : Range=1 [Skip range < 250]

StainlessS
12th February 2020, 15:56
HH,

Something just occurred to me, when you say RoboCrop is slow, maybe you are calling it last, after some heavy duty scripting, eg MCDegrain/QTGMC.
This would cause it to sample eg McDegrain/QTGMC'ed frames, and so slow.
I always use RoboCrop pre [nearly] everything else, just be sure to set Laced [ie interlaced, is default True] arg for interlaced sources.
Cropping first, would take borders out prior to any eg Auto Gain/Levelling, may produce less frame to process.
Deblocking might require a bit more thought, would need pad to mod 8 [usually], and done before cropping. [then remove padding] prior to autocrop]

Prev post not quite correct, finds Potential Auto Credits skip frames at 5% and 90% Framecount [where at least 250 frames],
thereafter spreads out samples frames like so

00100100

# OR

00100100100

# OR

000010000

Where first and last 0's are credit skip first and last frames, and 1's are sampled frames, if sampling single frame then would be the middle frame [if odd frames].

Also, where default SAMPLES = 40, will actually scan 80 frames, 40 sampled for YPlaneMin [to decide what Auto threshold should be], and then same 40 frames
again to detect borders usng the auto set threshold.

EDIT: I have occasionally come across clips where border color is quite a bit lighter than darkest luma in image part [maybe YPlaneMin=0, border=32], this tends to mess up
the auto thresholding somewhat, and will may cause failure where no border is cropped.

EDIT: You could also crop in YV24 for YMOD, HMod of 2.

real.finder
21st October 2020, 18:12
Hi StainlessS

is it possible to use RoboCrop to generate a mask instead of cropping? so the mask will be used in ExInpaint or AvsInpaint

and the mask changes every frame of course

StainlessS
21st October 2020, 18:28
Nope, RoboCrop is a clip global filter, clip global crop is based on sampling SAMPLES frames from complete clip with single result crop coords.
RoboCrop does NOT detect borders, it detects non borders, what is left after clip global scan of non border detection, is border.
I would say that it is not realistically possible [with or without AI] to accurately do single frame crop always without any errors,
I have many images where I cannot accurately say where the border is, or if there is a border.

real.finder
21st October 2020, 19:03
IIRC Stabilization Tools Pack by Dogway has some method to detect black borders in real time

StainlessS
21st October 2020, 19:13
I have lots of glamour/movie star type studio setting images where they have stylized black backgrounds that are NOT border, deliberate part of image.
Neither human nor AI could say for sure where or if those images have a border.

Cabaret (Minnelli/York), about 10min section start near "Prairie Oyster" scene,
AutoCrop() on default settings [5 sample frames], crops almost more image than it leaves remaining.
Stabilization Tools Pack, must be very good if it can do better than that
[RoboCrop on defaults nails it dead EDIT: default 40 sample frames, and auto thresholding].

Blankmedia
16th October 2021, 06:53
Awesome name for an awesome script.

StainlessS
16th October 2021, 07:51
Thanx Blanky :)

Blankmedia
20th October 2021, 05:16
Damn thing thing is so good, I wish it exist on vapoursynth. Nice work!

virgi
23rd January 2026, 18:24
Hi. I was wondering if this plugin could crop and realign PNG frames captured on 8mm film. Thanks.

StainlessS
23rd January 2026, 19:48
I dont think so, although some images in your own thread might prompt some assistance from others that have experience of such.
Attaching image in this forum can be slow, or not et done at all, best to embed in post yourself.
[EDIT: Perhaps Deshaker might assist, the guys will tell you if so. ]

Postimage instructions:- https://forum.doom9.org/showthread.php?p=1959414&highlight=postimage#post1959414

[ virgi thread:: avisynth 8 mm help :- https://forum.doom9.org/showthread.php?t=186803 ]