View Single Post
Old 26th April 2017, 00:11   #175  |  Link
MysteryX
Soul Architect
 
MysteryX's Avatar
 
Join Date: Apr 2014
Posts: 2,559
I've done plenty of changes to the artifact removal by tweaking MMask's arguments.

MMask's ml is unecessary because it simply sets to 255 values above that treshold -- which is exactly what mt_binarize is for; thus I set that to 255 and removed MaskSAD parameter.

MMask has a gamma property, which removes the need for another call to Levels. The mask level adjustment function has been removed.

MMask also has ysc which says what to do on scene changes: set everything to 255. Thus, I no longer need MSCDetection.

Mask adjustment settings are now MaskGam (gamma, applied during MMask) and MaskTrh (treshold, applied during mt_binarize).

MaskGam affects SkipOver -- and I believe I've found the right gamma value. If we find no need to change it, I might remove that property.

Because SkipOver now operate on a gamma-adjusted mask, it alters SkipOver behaviors.

After plenty of testing, I've set default to MaskGam=.6, MaskTrh=90, SkipOver=15

I removed Median and "slower" preset, went back to RemoveGrain(22) until someone can prove benefits of doing more than that.

To please manolito, I changed the arguments order for simplicity. First parameters are now: NewNum, NewDen, Preset, BlkSize

Again, settings are tweaked for YV24, and YV12 produces a different mask strength so settings will need to be adjusted.

Because now I know what I'm doing (instead of randomly using old code), the mask now both covers artifacts more precisely and leaves out more areas. I found it to be better in almost every cases.

Code:
# Frame Rate Converter
# Version: 25-Apr-2017
# By Etienne Charland
# Based on Oleg Yushko's YFRC artifact masking,
# johnmeyer's frame interpolation code, and
# raffriff42's "weak mask" and output options.
# Special thanks to Pinterf for adding 16-bit support to MvTools2 and MaskTools2
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
# http:#www.gnu.org/copyleft/gpl.html.

#######################################################################################
### Frame Rate Converter
### Increases the frame rate with interpolation and strong artifact removal.
##
## YV12/YV24/Y8/YUY2
## Requires: MaskTools2, MvTools2, rgtools
##
## @ NewNum      - The new framerate numerator (if FrameDouble = false, default = 60)
##
## @ NewDen      - The new framerate denominator (if FrameDouble = false, default = 1)
##
## @ Preset      - The speed/quality preset [slow|normal|fast|faster]. (default=normal)
##
## @ BlkSize     - The horizontal block size (default = Width>1200||Height>900 ? 32 : Width>720||C.Height>480 ? 16 : 8)
## 
## @ BlkSizeV    - The vertical block size (default = BlkSize)
##
## @ FrameDouble - Whether to double the frame rate and preserve original frames (default = true)
##
## @ Output      - Output mode [auto|inter|none|mask|over] (default=auto)
##                 auto=normal artifact masking; flow=interpolation only
##                 none=ConvertFPS only; mask=mask only; over=mask as cyan overlay for debugging
##
## @ MaskGam     - A gamma to be applied to the raw mask, between 0 and 1. 
##                 Higher value means stronger mask. (Default=.6)
##
## @ MaskTrh     - The treshold where a block is considered bad, between 0 and 255. 0 to disable artifact masking.
##                 Higher value means stronger mask. (Default=90)
##
## @ SkipOver    - Skip interpolation of frames when artifacts cover more than specified treshold, 
##                 0 to disable. Does not work in Avisynth+ MT mode. (Default=48)
##          
function FrameRateConverter(clip C, int "NewNum", int "NewDen", string "Preset", int "BlkSize", int "BlkSizeV", 
\ bool "FrameDouble", string "Output", float "MaskGam", int "MaskTrh", int "SkipOver")
{
    Output     = Default(Output, "auto")
    FrameDouble= Default(FrameDouble, Defined(NewNum) ? false : true)
    NewNum     = FrameDouble ? C.FrameRateNumerator * 2 : Default(NewNum, 60)
    NewDen     = FrameDouble ? C.FrameRateDenominator : Default(NewDen, 1)
    Preset     = Default(Preset, "normal")
    BlkSize    = Default(BlkSize, C.Width>1200||C.Height>900 ? 32 : C.Width>720||C.Height>480 ? 16 : 8)
    BlkSizeV   = Default(BlkSizeV, BlkSize)
    blkmin     = BlkSize > BlkSizeV ? BlkSizeV : BlkSize
    MaskGam    = Default(MaskGam, .6)
    MaskTrh    = Default(MaskTrh, 90)
    SkipOver   = Default(SkipOver, 15)

    Assert(Preset == "slow" || Preset == "normal" || Preset == "fast" || Preset == "faster", 
    \      "FrameRateConverter: Preset must be slow, normal, fast or faster")
    Assert(BlkSize == 8 || BlkSize == 16 || BlkSize == 32, "FrameRateConverter: BlkSize must be 8, 16 or 32")
    Assert(BlkSizeV == 8 || BlkSizeV == 16 || BlkSizeV == 32, "FrameRateConverter: BlkSizeV must be 8, 16 or 32")
    Assert(MaskGam > 0 && MaskGam <= 1, "FrameRateConverter: MaskGam must be between 0 and 1")
    Assert(MaskTrh >= 0 && MaskTrh <= 255, "FrameRateConverter: MaskTrh must be between 0 and 255")
    Assert(SkipOver >= 0 && SkipOver <= 255, "FrameRateConverter: SkipOver must be between 0 and 255")

    # Performance settings: slow, normal, fast, faster
    Recalculate = preset == "normal"
    prefilter = preset != "faster"
    DCT = preset == "slower" ? 1 : 0

    ## "B" - Blending, "BHard" - No blending
    BHard = C.ChangeFPS(NewNum, NewDen)
    B  = C.ConvertFPS(NewNum, NewDen)
    B  = FrameDouble ? SelectOdd(B) : B

    ## jm_fps interpolation
    prefiltered = Prefilter ? C.RemoveGrain(22) : C
    superfilt = MSuper(prefiltered, hpad = 16, vpad = 16) # all levels for MAnalyse
    super = Prefilter ? MSuper(C, hpad = 16, vpad = 16, levels = 1) : superfilt # one level is enough for MRecalculate
    bak = MAnalyse(superfilt, isb=true, blksize=BlkSize, blksizeV=BlkSizeV, overlap = blkmin>8?4:blkmin>4?2:0, search=3, dct=DCT)
    fwd = MAnalyse(superfilt, isb=false, blksize=BlkSize, blksizeV=BlkSizeV, overlap = blkmin>8?4:blkmin>4?2:0, search=3, dct=DCT)
    fwd = Recalculate ? MRecalculate(super, fwd, blksize=BlkSize/2, blksizeV=BlkSizeV/2, overlap = blkmin>8?2:0, thSAD=100) : fwd
    bak = Recalculate ? MRecalculate(super, bak, blksize=BlkSize/2, blksizeV=BlkSizeV/2, overlap = blkmin>8?2:0, thSAD=100) : bak
    Flow = MFlowFps(C, super, bak, fwd, num = NewNum, den = NewDen, blend = false, ml = 200, mask = 2)

    ## "EM" - error or artifact mask
    EM = MaskTrh > 0 ? C.MMask(bak, ml=255, kind=1, ysc=255, gamma=1.0/MaskGam) : BlankClip(C)   # kind=SAD
    EMfwd = MaskTrh > 0 ? C.MMask(fwd, ml=255, kind=1, gamma=1.0/MaskGam) : EM           # kind=temporal blending
    EMfwd = FrameDouble ? EMfwd.DeleteFrame(0) : EMfwd
    EM = MaskTrh > 0 ? EM.Overlay(EMfwd, opacity=0.5, mode="lighten") : EM
    SkipEM = EM
    
    EM = EM.BicubicResize(Round(C.Width/BlkSize/4.0)*4, Round(C.Height/BlkSizeV/4.0)*4)
    \       .mt_expand(mode= mt_circle(zero=true, radius=1))
    \       .mt_binarize(255-MaskTrh)
    \       .Blur(.6)
    \       .BicubicResize(C.Width, C.Height)
    
    ## "Sc" - scene detection / SkipOver
    Sc = SkipOver > 0 ? ConditionalFilter(SkipEM, BlankClip(EM, color=color_white), BlankClip(EM), 
    \                    "AverageLuma()", ">", string(SkipOver)) : BlankClip(EM)

    ## Convert masks to desired frame rate
    EM = EM.ChangeFPS(NewNum, NewDen)
    Sc = Sc.ChangeFPS(NewNum, NewDen)

    ## the FrameRateConverter magic happens
    M = mt_merge(FrameDouble ? SelectOdd(Flow) : Flow, B, EM, luma=true)
    M = SkipOver > 0 ? mt_merge(M, BHard, Sc, luma=true) : M

    R = (StrCmpi(Output, "auto")==0)        [** auto:  artifact masking     *] 
    \     ? (FrameDouble ? Interleave(C, M) : M)
    \ : (StrCmpi(Output, "flow")==0)        [** flow: interpolation only   *] 
    \     ? Flow
    \ : (StrCmpi(Output, "none")==0)        [** none: ConvertFPS only       *] 
    \     ? B
    \ : (StrCmpi(Output, "mask")==0)        [** mask:  mask only            *] 
    \     ? EM
    \ : (StrCmpi(Output, "over")==0)        [** over:  mask as cyan overlay *] 
    \     ? mt_merge(
    \         Flow.Overlay(MergeRGB(BlankClip(EM), EM, EM), mode="Add", opacity=0.40, pc_range=true),
    \         BlankClip(EM, color=color_darkgoldenrod), Sc.mt_lut("x 2 / "), luma=true)
    \ : Assert(false, "FrameRateConverter: 'Output' not one of (auto|flow|none|mask|over)")
    return R
}

Last edited by MysteryX; 26th April 2017 at 02:16.
MysteryX is offline   Reply With Quote