Skip to content

Commit

Permalink
Cdeblend(): alternative sequential processing based on prerolling
Browse files Browse the repository at this point in the history
proposed by @myrsloik (#48 (comment))
  • Loading branch information
WolframRhodium committed Nov 5, 2023
1 parent 8a1e7e9 commit 698dae3
Showing 1 changed file with 59 additions and 56 deletions.
115 changes: 59 additions & 56 deletions muvsfunc.py
Original file line number Diff line number Diff line change
Expand Up @@ -5284,7 +5284,8 @@ def YAHRmask(clp: vs.VideoNode, expand: float = 5, warpdepth: int = 32, blur: in
def Cdeblend(input: vs.VideoNode, omode: int = 0, bthresh: float = 0.1, mthresh: float = 0.6,
xr: float = 1.5, yr: float = 2.0, fnr: bool = False,
dclip: Optional[vs.VideoNode] = None,
sequential: Optional[bool] = None
sequential: Optional[bool] = None,
preroll: int = 14
) -> vs.VideoNode:
"""A simple blend replacing function like unblend or removeblend
Expand Down Expand Up @@ -5331,6 +5332,11 @@ def Cdeblend(input: vs.VideoNode, omode: int = 0, bthresh: float = 0.1, mthresh:
sequential: (bool) Experimental support for sequential processing.
Default: False
preroll: (int) How many frames before the current one metrics are computed for.
Alternative to true sequential processing.
Must be 1 or bigger, consistent results start around 14.
Default: 14.
"""

funcName = 'Cdeblend'
Expand All @@ -5352,63 +5358,55 @@ def Cdeblend(input: vs.VideoNode, omode: int = 0, bthresh: float = 0.1, mthresh:
if sequential is None:
sequential = False

if not sequential:
import warnings
warnings.warn("this function may produce visible incorrect output")

# coefficients
# Cbp3 = 128.0 if bthresh > 0 else 2.0
Cbp2 = 128.0 if bthresh > 0 else 2.0
Cbp1 = 128.0 if bthresh > 0 else 2.0
Cbc0 = 128.0 if bthresh > 0 else 2.0
Cbn1 = 128.0 if bthresh > 0 else 2.0
Cbn2 = 128.0 if bthresh > 0 else 2.0

# Cdp3 = mthresh * 0.5
# Cdp2 = mthresh * 0.5
Cdp1 = mthresh * 0.5
Cdc0 = mthresh * 0.5
Cdn1 = mthresh * 0.5

current = 0

preproc = {i: input[0:2] + input[2+i:] for i in range(-2, 3)}

def evaluate(n: int, f: List[vs.VideoFrame], clip: vs.VideoNode, core: vs.Core) -> vs.VideoNode:
# nonlocal Cdp3, Cdp2, Cbp3
nonlocal Cdp1, Cdc0, Cdn1, Cbp2, Cbp1, Cbc0, Cbn1, Cbn2, current

Cdiff = f[0].props["PlaneMAE"] * 255 # type: ignore
Cbval = f[1].props["PlaneMean"] * 255 # type: ignore

# Cdp3 = Cdp2
# Cdp2 = Cdp1
Cdp1 = Cdc0
Cdc0 = Cdn1 if omode > 1 else Cdiff # type: ignore
Cdn1 = Cdiff # type: ignore

# Cbp3 = Cbp2
Cbp2 = Cbp1
Cbp1 = Cbc0
Cbc0 = Cbn1 if omode > 1 else (0.0 if Cdc0 < mthresh else (Cbval - Cbn2) / ((max(Cdc0, Cdp1) + mthresh) ** 0.8)) # type: ignore
Cbn1 = 0.0 if (Cdc0 < mthresh or Cdn1 < mthresh) else (Cbval - Cbn2) / ((max(Cdc0, Cdp1) + mthresh) ** 0.8) # type: ignore
Cbn2 = Cbval # type: ignore

current = (1 if ((Cbn1 < -bthresh and Cbc0 > bthresh) or (Cbn1 < 0 and Cbc0 > 0 and Cbc0 + Cbp1 > 0 and Cbc0 + Cbp1 + Cbp2 > 0)) else
0 if ((Cbc0 < -bthresh and Cbp1 > bthresh) or (Cbc0 < 0 and Cbc0 + Cbn1 < 0 and Cbp1 > 0 and Cbp1 + Cbp2 > 0)) else
(2 if Cbn1 > 0 else 1) if current == -2 else
current - 1)

if omode == 2:
current = (-1 if min(-Cbp1, Cbc0 + Cbn1) > bthresh and abs(Cbn1) > abs(Cbc0) else
1 if min(-Cbp2 - Cbp1, Cbc0) > bthresh and abs(Cbp2) > abs(Cbp1) else
-1 if min(-Cbp1, Cbc0) > bthresh else
0)

if omode <= 1:
current = (0 if min(-Cbp1, Cbc0) < bthresh else
-1 if omode == 0 else
1)
# coefficients
Cbp2 = 128.0 if bthresh > 0 else 2.0
Cbp1 = 128.0 if bthresh > 0 else 2.0
Cbc0 = 128.0 if bthresh > 0 else 2.0
Cbn1 = 128.0 if bthresh > 0 else 2.0
Cbn2 = 128.0 if bthresh > 0 else 2.0

Cdp1 = mthresh * 0.5
Cdc0 = mthresh * 0.5
Cdn1 = mthresh * 0.5

current = 0

def computestate(Cdiff: float, Cbval: float):
nonlocal Cdp1, Cdc0, Cdn1, Cbp2, Cbp1, Cbc0, Cbn1, Cbn2, current

Cdp1 = Cdc0
Cdc0 = Cdn1 if omode > 1 else Cdiff # type: ignore
Cdn1 = Cdiff # type: ignore

Cbp2 = Cbp1
Cbp1 = Cbc0
Cbc0 = Cbn1 if omode > 1 else (0.0 if Cdc0 < mthresh else (Cbval - Cbn2) / ((max(Cdc0, Cdp1) + mthresh) ** 0.8)) # type: ignore
Cbn1 = 0.0 if (Cdc0 < mthresh or Cdn1 < mthresh) else (Cbval - Cbn2) / ((max(Cdc0, Cdp1) + mthresh) ** 0.8) # type: ignore
Cbn2 = Cbval # type: ignore

current = (1 if ((Cbn1 < -bthresh and Cbc0 > bthresh) or (Cbn1 < 0 and Cbc0 > 0 and Cbc0 + Cbp1 > 0 and Cbc0 + Cbp1 + Cbp2 > 0)) else
0 if ((Cbc0 < -bthresh and Cbp1 > bthresh) or (Cbc0 < 0 and Cbc0 + Cbn1 < 0 and Cbp1 > 0 and Cbp1 + Cbp2 > 0)) else
(2 if Cbn1 > 0 else 1) if current == -2 else
current - 1)

if omode == 2:
current = (-1 if min(-Cbp1, Cbc0 + Cbn1) > bthresh and abs(Cbn1) > abs(Cbc0) else
1 if min(-Cbp2 - Cbp1, Cbc0) > bthresh and abs(Cbp2) > abs(Cbp1) else
-1 if min(-Cbp1, Cbc0) > bthresh else
0)

if omode <= 1:
current = (0 if min(-Cbp1, Cbc0) < bthresh else
-1 if omode == 0 else
1)

for i in range(max(0, preroll - n), preroll + 1):
Cdiff = f[i * 2 + 0].props["PlaneMAE"] * 255 # type: ignore
Cbval = f[i * 2 + 1].props["PlaneMean"] * 255 # type: ignore
computestate(Cdiff, Cbval)

if omode != 4:
return preproc[current]
Expand Down Expand Up @@ -5557,7 +5555,12 @@ def evaluate_seq(
states.append(state)
last = core.std.Splice(states)
else:
last = core.std.FrameEval(input, functools.partial(evaluate, clip=input, core=core), prop_src=[Cdiff, Cbval])
prop_src = []
for i in range(preroll, 0, -1):
prop_src.extend([Cdiff[0] * i + Cdiff, Cbval[0] * i + Cbval])
prop_src.extend([Cdiff, Cbval])

last = core.std.FrameEval(input, functools.partial(evaluate, clip=input, core=core), prop_src=prop_src)

recl = haf_ChangeFPS(haf_ChangeFPS(last, last.fps_num * 2, last.fps_den * 2), last.fps_num, last.fps_den)

Expand Down

0 comments on commit 698dae3

Please sign in to comment.