soifunc 0.10.0__py3-none-any.whl → 0.11.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- soifunc/__init__.py +1 -0
- soifunc/deband.py +3 -3
- soifunc/denoise.py +9 -11
- soifunc/interpolate.py +146 -0
- soifunc/resize.py +10 -13
- {soifunc-0.10.0.dist-info → soifunc-0.11.0.dist-info}/METADATA +2 -2
- soifunc-0.11.0.dist-info/RECORD +10 -0
- {soifunc-0.10.0.dist-info → soifunc-0.11.0.dist-info}/WHEEL +1 -1
- soifunc-0.10.0.dist-info/RECORD +0 -9
- {soifunc-0.10.0.dist-info → soifunc-0.11.0.dist-info}/LICENSE +0 -0
soifunc/__init__.py
CHANGED
soifunc/deband.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from vsdeband import
|
|
3
|
+
from vsdeband import f3k_deband
|
|
4
4
|
from vsmasktools import dre_edgemask
|
|
5
5
|
from vstools import InvalidVideoFormatError, check_variable, core, vs
|
|
6
6
|
|
|
@@ -19,7 +19,7 @@ def retinex_deband(
|
|
|
19
19
|
16 might be a more sane starting point. Increase as needed.
|
|
20
20
|
|
|
21
21
|
This function does not add grain on its own. Use another function like
|
|
22
|
-
`vsdeband.
|
|
22
|
+
`vsdeband.AddNoise` to do that.
|
|
23
23
|
"""
|
|
24
24
|
assert check_variable(clip, retinex_deband)
|
|
25
25
|
|
|
@@ -39,5 +39,5 @@ def retinex_deband(
|
|
|
39
39
|
if showmask:
|
|
40
40
|
return mask
|
|
41
41
|
|
|
42
|
-
deband =
|
|
42
|
+
deband = f3k_deband(clip, thr=(threshold << 2))
|
|
43
43
|
return core.std.MaskedMerge(deband, clip, mask)
|
soifunc/denoise.py
CHANGED
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
from typing import Callable, Optional
|
|
4
4
|
|
|
5
5
|
import vsdenoise
|
|
6
|
-
from vsdenoise import DFTTest,
|
|
6
|
+
from vsdenoise import DFTTest, bm3d, mc_degrain
|
|
7
7
|
from vstools import core, vs
|
|
8
8
|
|
|
9
9
|
__all__ = ["MCDenoise", "magic_denoise", "hqbm3d", "mc_dfttest"]
|
|
@@ -13,7 +13,7 @@ def hqbm3d(
|
|
|
13
13
|
clip: vs.VideoNode,
|
|
14
14
|
luma_str: float = 0.45,
|
|
15
15
|
chroma_str: float = 0.4,
|
|
16
|
-
profile: Profile = Profile.FAST,
|
|
16
|
+
profile: bm3d.Profile = bm3d.Profile.FAST,
|
|
17
17
|
) -> vs.VideoNode:
|
|
18
18
|
"""
|
|
19
19
|
High-quality presets for motion compensated denoising.
|
|
@@ -24,24 +24,22 @@ def hqbm3d(
|
|
|
24
24
|
blksize = select_block_size(clip)
|
|
25
25
|
mv = mc_degrain(
|
|
26
26
|
clip,
|
|
27
|
-
preset=vsdenoise.
|
|
27
|
+
preset=vsdenoise.MVToolsPreset.HQ_SAD,
|
|
28
28
|
tr=2,
|
|
29
29
|
thsad=100,
|
|
30
30
|
refine=3 if blksize > 16 else 2,
|
|
31
31
|
blksize=blksize,
|
|
32
32
|
prefilter=vsdenoise.Prefilter.DFTTEST(
|
|
33
33
|
clip,
|
|
34
|
-
|
|
34
|
+
sloc=[(0.0, 1.0), (0.2, 4.0), (0.35, 12.0), (1.0, 48.0)],
|
|
35
35
|
ssystem=1,
|
|
36
36
|
full_range=3.5,
|
|
37
37
|
planes=0,
|
|
38
38
|
),
|
|
39
39
|
planes=None,
|
|
40
40
|
)
|
|
41
|
-
bm3d =
|
|
42
|
-
|
|
43
|
-
)
|
|
44
|
-
return vsdenoise.nl_means(bm3d, strength=chroma_str, tr=1, ref=mv, planes=[1, 2])
|
|
41
|
+
out = bm3d(clip, sigma=luma_str, tr=1, ref=mv, profile=profile, planes=0)
|
|
42
|
+
return vsdenoise.nl_means(out, h=chroma_str, tr=1, ref=mv, planes=[1, 2])
|
|
45
43
|
|
|
46
44
|
|
|
47
45
|
def mc_dfttest(
|
|
@@ -62,7 +60,7 @@ def mc_dfttest(
|
|
|
62
60
|
return mc_degrain(
|
|
63
61
|
clip,
|
|
64
62
|
prefilter=vsdenoise.Prefilter.DFTTEST,
|
|
65
|
-
preset=vsdenoise.
|
|
63
|
+
preset=vsdenoise.MVToolsPreset.HQ_SAD,
|
|
66
64
|
thsad=thSAD,
|
|
67
65
|
tr=2,
|
|
68
66
|
refine=3 if blksize > 16 else 2,
|
|
@@ -201,12 +199,12 @@ def magic_denoise(clip: vs.VideoNode) -> vs.VideoNode:
|
|
|
201
199
|
thscd1=300,
|
|
202
200
|
)
|
|
203
201
|
|
|
204
|
-
return DFTTest.denoise(
|
|
202
|
+
return DFTTest().denoise(
|
|
205
203
|
clip,
|
|
206
204
|
sloc=[(0.0, 0.8), (0.06, 1.1), (0.12, 1.0), (1.0, 1.0)],
|
|
207
205
|
pmax=1000000,
|
|
208
206
|
pmin=1.25,
|
|
209
|
-
ftype=FilterType.MULT_RANGE,
|
|
207
|
+
ftype=DFTTest.FilterType.MULT_RANGE,
|
|
210
208
|
tbsize=3,
|
|
211
209
|
ssystem=1,
|
|
212
210
|
)
|
soifunc/interpolate.py
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import platform
|
|
4
|
+
|
|
5
|
+
import vstools
|
|
6
|
+
from vsmlrt import backendT
|
|
7
|
+
from vstools import vs
|
|
8
|
+
|
|
9
|
+
__all__ = ["rate_doubler", "decimation_fixer"]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def rate_doubler(
|
|
13
|
+
clip: vs.VideoNode, multi: int = 2, backend: backendT | None = None
|
|
14
|
+
) -> vs.VideoNode:
|
|
15
|
+
"""
|
|
16
|
+
A utility to scale the framerate of a video via frame interpolation.
|
|
17
|
+
|
|
18
|
+
Probably shouldn't just go spraying this everywhere,
|
|
19
|
+
it's more for fun and science than anything.
|
|
20
|
+
"""
|
|
21
|
+
import vsmlrt
|
|
22
|
+
|
|
23
|
+
width = clip.width
|
|
24
|
+
height = clip.height
|
|
25
|
+
matrix = vstools.Matrix.from_video(clip)
|
|
26
|
+
transfer = vstools.Transfer.from_video(clip)
|
|
27
|
+
primaries = vstools.Primaries.from_video(clip)
|
|
28
|
+
clip = clip.misc.SCDetect()
|
|
29
|
+
clip = clip.resize.Bicubic(
|
|
30
|
+
format=vs.RGBS,
|
|
31
|
+
width=next_multiple_of(64, width),
|
|
32
|
+
height=next_multiple_of(64, height),
|
|
33
|
+
)
|
|
34
|
+
clip = vsmlrt.RIFE(
|
|
35
|
+
clip,
|
|
36
|
+
multi=multi,
|
|
37
|
+
model=vsmlrt.RIFEModel.v4_25_heavy,
|
|
38
|
+
# Why these defaults? Because running ML stuff on AMD on Windows sucks hard.
|
|
39
|
+
# Trial and error led me to finally find that ORT_DML works.
|
|
40
|
+
backend=(
|
|
41
|
+
backend
|
|
42
|
+
if backend
|
|
43
|
+
else (
|
|
44
|
+
vsmlrt.Backend.ORT_DML()
|
|
45
|
+
if platform.system() == "Windows"
|
|
46
|
+
else vsmlrt.Backend.TRT_RTX()
|
|
47
|
+
)
|
|
48
|
+
),
|
|
49
|
+
)
|
|
50
|
+
# TODO: Handle other chroma samplings
|
|
51
|
+
clip = clip.resize.Bicubic(
|
|
52
|
+
format=vs.YUV420P16,
|
|
53
|
+
width=width,
|
|
54
|
+
height=height,
|
|
55
|
+
matrix=matrix,
|
|
56
|
+
transfer=transfer,
|
|
57
|
+
primaries=primaries,
|
|
58
|
+
)
|
|
59
|
+
return clip
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def decimation_fixer(
|
|
63
|
+
clip: vs.VideoNode, cycle: int, offset: int = 0, backend: backendT | None = None
|
|
64
|
+
) -> vs.VideoNode:
|
|
65
|
+
"""
|
|
66
|
+
Attempts to interpolate frames that were removed by bad decimation.
|
|
67
|
+
Only works with static decimation cycles.
|
|
68
|
+
`cycle` should be the output cycle, i.e. what did the idiot who decimated this
|
|
69
|
+
pass into the decimation filter to achieve this monstrosity?
|
|
70
|
+
|
|
71
|
+
Yeah, I know, "ThiS is bAd AND yOu shoUldn'T Do IT".
|
|
72
|
+
Maybe people shouldn't decimate clips that don't need decimation.
|
|
73
|
+
Sometimes you can't "just get a better source".
|
|
74
|
+
"""
|
|
75
|
+
import vsmlrt
|
|
76
|
+
|
|
77
|
+
if offset >= cycle - 1:
|
|
78
|
+
raise Exception("offset must be less than cycle - 1")
|
|
79
|
+
if cycle <= 0:
|
|
80
|
+
raise Exception("cycle must be greater than zero")
|
|
81
|
+
|
|
82
|
+
width = clip.width
|
|
83
|
+
height = clip.height
|
|
84
|
+
fps = clip.fps
|
|
85
|
+
input_cycle = cycle - 1
|
|
86
|
+
matrix = vstools.Matrix.from_video(clip)
|
|
87
|
+
transfer = vstools.Transfer.from_video(clip)
|
|
88
|
+
primaries = vstools.Primaries.from_video(clip)
|
|
89
|
+
clip = clip.misc.SCDetect()
|
|
90
|
+
clip = clip.resize.Bicubic(
|
|
91
|
+
format=vs.RGBS,
|
|
92
|
+
width=next_multiple_of(64, width),
|
|
93
|
+
height=next_multiple_of(64, height),
|
|
94
|
+
)
|
|
95
|
+
doubled = vsmlrt.RIFE(
|
|
96
|
+
clip,
|
|
97
|
+
model=vsmlrt.RIFEModel.v4_25_heavy,
|
|
98
|
+
backend=(
|
|
99
|
+
backend
|
|
100
|
+
if backend
|
|
101
|
+
else (
|
|
102
|
+
vsmlrt.Backend.ORT_DML()
|
|
103
|
+
if platform.system() == "Windows"
|
|
104
|
+
else vsmlrt.Backend.TRT_RTX()
|
|
105
|
+
)
|
|
106
|
+
),
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
out_clip = None
|
|
110
|
+
# This is the frame after our insertion point
|
|
111
|
+
src_frame = offset
|
|
112
|
+
last_src_frame = 0
|
|
113
|
+
# This is the frame we want to grab from the doubled clip
|
|
114
|
+
doub_frame = offset * 2 - 1
|
|
115
|
+
while src_frame < clip.num_frames:
|
|
116
|
+
if src_frame > 0:
|
|
117
|
+
interp = doubled[doub_frame]
|
|
118
|
+
if out_clip is None:
|
|
119
|
+
out_clip = clip[last_src_frame:src_frame] + interp
|
|
120
|
+
else:
|
|
121
|
+
out_clip = out_clip + clip[last_src_frame:src_frame] + interp
|
|
122
|
+
last_src_frame = src_frame
|
|
123
|
+
src_frame += input_cycle
|
|
124
|
+
doub_frame += input_cycle * 2
|
|
125
|
+
out_clip += clip[last_src_frame:]
|
|
126
|
+
out_clip = out_clip.std.AssumeFPS(
|
|
127
|
+
fpsnum=fps.numerator * cycle // input_cycle, fpsden=fps.denominator
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# TODO: Handle other chroma samplings
|
|
131
|
+
out_clip = out_clip.resize.Bicubic(
|
|
132
|
+
format=vs.YUV420P16,
|
|
133
|
+
width=width,
|
|
134
|
+
height=height,
|
|
135
|
+
matrix=matrix,
|
|
136
|
+
transfer=transfer,
|
|
137
|
+
primaries=primaries,
|
|
138
|
+
)
|
|
139
|
+
return out_clip
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def next_multiple_of(multiple: int, param: int) -> int:
|
|
143
|
+
rem = param % multiple
|
|
144
|
+
if rem == 0:
|
|
145
|
+
return param
|
|
146
|
+
return param + (multiple - rem)
|
soifunc/resize.py
CHANGED
|
@@ -4,18 +4,15 @@ from dataclasses import dataclass
|
|
|
4
4
|
from inspect import getfullargspec
|
|
5
5
|
from typing import Any
|
|
6
6
|
|
|
7
|
-
from vsaa.
|
|
7
|
+
from vsaa.deinterlacers import NNEDI3
|
|
8
8
|
from vskernels import (
|
|
9
|
-
Catrom,
|
|
10
|
-
EwaLanczos,
|
|
11
9
|
Hermite,
|
|
12
|
-
KeepArScaler,
|
|
13
10
|
Scaler,
|
|
14
|
-
|
|
11
|
+
ScalerLike,
|
|
15
12
|
Spline36,
|
|
16
13
|
)
|
|
17
|
-
from vsscale import SSIM, ArtCNN, GenericScaler
|
|
18
|
-
from vstools import check_variable_format, is_gpu_available, join, vs
|
|
14
|
+
from vsscale import SSIM, ArtCNN, GenericScaler
|
|
15
|
+
from vstools import check_variable_format, inject_self, is_gpu_available, join, vs
|
|
19
16
|
|
|
20
17
|
__all__ = [
|
|
21
18
|
"good_resize",
|
|
@@ -61,11 +58,11 @@ def good_resize(
|
|
|
61
58
|
if gpu:
|
|
62
59
|
luma_scaler = ArtCNN()
|
|
63
60
|
else:
|
|
64
|
-
luma_scaler =
|
|
61
|
+
luma_scaler = NNEDI3(scaler=Hermite(sigmoid=True))
|
|
65
62
|
else:
|
|
66
63
|
luma_scaler = Hermite(sigmoid=True)
|
|
67
64
|
elif is_upscale:
|
|
68
|
-
luma_scaler =
|
|
65
|
+
luma_scaler = NNEDI3(scaler=SSIM())
|
|
69
66
|
else:
|
|
70
67
|
luma_scaler = SSIM()
|
|
71
68
|
|
|
@@ -76,8 +73,8 @@ def good_resize(
|
|
|
76
73
|
|
|
77
74
|
@dataclass
|
|
78
75
|
class HybridScaler(GenericScaler):
|
|
79
|
-
luma_scaler:
|
|
80
|
-
chroma_scaler:
|
|
76
|
+
luma_scaler: ScalerLike
|
|
77
|
+
chroma_scaler: ScalerLike
|
|
81
78
|
|
|
82
79
|
def __post_init__(self) -> None:
|
|
83
80
|
super().__post_init__()
|
|
@@ -85,7 +82,7 @@ class HybridScaler(GenericScaler):
|
|
|
85
82
|
self._luma = Scaler.ensure_obj(self.luma_scaler)
|
|
86
83
|
self._chroma = Scaler.ensure_obj(self.chroma_scaler)
|
|
87
84
|
|
|
88
|
-
@
|
|
85
|
+
@Scaler.cached_property
|
|
89
86
|
def kernel_radius(self) -> int:
|
|
90
87
|
return self._luma.kernel_radius
|
|
91
88
|
|
|
@@ -109,7 +106,7 @@ class HybridScaler(GenericScaler):
|
|
|
109
106
|
return join(luma, chroma)
|
|
110
107
|
|
|
111
108
|
|
|
112
|
-
def _get_scaler(scaler:
|
|
109
|
+
def _get_scaler(scaler: ScalerLike, **kwargs: Any) -> Scaler:
|
|
113
110
|
scaler_cls = Scaler.from_param(scaler, _get_scaler)
|
|
114
111
|
|
|
115
112
|
args = getfullargspec(scaler_cls).args
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: soifunc
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.11.0
|
|
4
4
|
Summary: Soichiro's VapourSynth Functions Collection
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: Josh Holmer
|
|
@@ -11,7 +11,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.12
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.13
|
|
13
13
|
Requires-Dist: vapoursynth (>=68)
|
|
14
|
-
Requires-Dist: vsjetpack (>=0.
|
|
14
|
+
Requires-Dist: vsjetpack (>=0.5.1,<0.6.0)
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
|
|
17
17
|
## soifunc
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
soifunc/__init__.py,sha256=H6BWoCLRW2ZD47wQtL72SIZvTpD6REH7cUqIYWvCn0k,174
|
|
2
|
+
soifunc/deband.py,sha256=nbtRwktdN8Y-OuiSsj1mVg9vzJhJlu7r6dqs_TLa6rg,1174
|
|
3
|
+
soifunc/denoise.py,sha256=6MY4m3x64gEIgnbVT48htFthG51sLsERN1YGbNYTdGY,6798
|
|
4
|
+
soifunc/interpolate.py,sha256=PZIVcozHOMUOo7vZj1Q9vwByJ5d9lJvnCp_GRxgPZK0,4352
|
|
5
|
+
soifunc/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
soifunc/resize.py,sha256=PCq-nGt8ZHG4dlx3H1R_dRAebHWEc9Eu_coO3VRGlCY,3028
|
|
7
|
+
soifunc-0.11.0.dist-info/LICENSE,sha256=vgEDSMEV1J2nMiCgXE5_sjNtw2VT7_lP7rkAnrFKOWI,1068
|
|
8
|
+
soifunc-0.11.0.dist-info/METADATA,sha256=lnqZaM7DdbWgC4dbBfZGCcHt5f5UWYfLl0xv3LmSyak,3364
|
|
9
|
+
soifunc-0.11.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
10
|
+
soifunc-0.11.0.dist-info/RECORD,,
|
soifunc-0.10.0.dist-info/RECORD
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
soifunc/__init__.py,sha256=o8id_imdLYtSpVNfB-G4Pru9GtEPqdkcpyyW3yQt-6U,127
|
|
2
|
-
soifunc/deband.py,sha256=GB9ksv-G1EOkro7mEN44p1vxLCnY2x4d4SqKhHxQ6Z8,1176
|
|
3
|
-
soifunc/denoise.py,sha256=OaNZVEtuaVTy_onD0zMareexUvHuda0pIgcIJollFFc,6841
|
|
4
|
-
soifunc/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
-
soifunc/resize.py,sha256=E7tiiqvfvt_PMsJFSlZrr9heuYVuySQiZXEbQ7Kjacs,3045
|
|
6
|
-
soifunc-0.10.0.dist-info/LICENSE,sha256=vgEDSMEV1J2nMiCgXE5_sjNtw2VT7_lP7rkAnrFKOWI,1068
|
|
7
|
-
soifunc-0.10.0.dist-info/METADATA,sha256=_C-g7OvcdJNIBTbrc5NDFqznt2-Wnjp_7IKYUNZu8x0,3364
|
|
8
|
-
soifunc-0.10.0.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
|
9
|
-
soifunc-0.10.0.dist-info/RECORD,,
|
|
File without changes
|