vsdirty 0.1.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.
vsdirty/dirtyfixer.py ADDED
@@ -0,0 +1,113 @@
1
+ import vapoursynth as vs
2
+ from typing import List
3
+ from vstools import PlanesT
4
+ from vstools import depth
5
+ from .adutils import plane
6
+
7
+ core = vs.core
8
+
9
+ if not (hasattr(vs.core, 'fmtc') or hasattr(vs.core, 'bore')):
10
+ raise ImportError("'fmtc' and 'libbore' are mandatory. Make sure the DLLs are present in the plugins folder.")
11
+
12
+ def bore(
13
+ clip : vs.VideoNode,
14
+ ythickness: List[int] = None,
15
+ uthickness: List[int] = None,
16
+ vthickness: List[int] = None,
17
+ planes: PlanesT = 0,
18
+ singlePlane = True,
19
+ **kwargs
20
+ ) -> vs.VideoNode:
21
+ """
22
+ Apply bore filter to clip's edges to remove dirty lines.
23
+
24
+ Processes selected planes at their native resolution to avoid
25
+ unnecessary scaling artifacts. Uses full resolution for luma,
26
+ native chroma resolution for chroma planes.
27
+
28
+ Only bore.SinglePlane and bore.MultiPlane are implemented, the other functions will probably never be implemented.
29
+
30
+ :param clip: Input clip (YUV or GRAY, RGB not supported)
31
+ :param ythickness: List of luma border thicknesses to process. [top, bottom, left, right]. 0 means no processing.
32
+ :param uthickness: List of chroma U border thicknesses to process. [top, bottom, left, right]. 0 means no processing. if None, uses ythickness or vthickness if is not None.
33
+ :param vthickness: List of chroma V border thicknesses to process. [top, bottom, left, right]. 0 means no processing. if None, uses ythickness or uthickness if is not None.
34
+ :param planes: Plane(s) to process.
35
+ :param singlePlane: If True uses bore.SinglePlane, otherwise bore.MultiPlane. MultiPlane cannot be used with GRAY clips.
36
+ :return: Processed clip with corrected borders, same format as input
37
+ """
38
+
39
+ if ythickness is None:
40
+ ythickness = [1,1,1,1]
41
+
42
+ if clip.format.color_family == vs.RGB:
43
+ raise ValueError("bore: RGB clips are not supported.")
44
+
45
+ if planes is None:
46
+ raise ValueError("bore: planes cannot be None.")
47
+
48
+ if isinstance(planes, int):
49
+ planes = [planes]
50
+
51
+ def _get_tblr(thick):
52
+ if len(thick) == 2:
53
+ t, b = thick
54
+ l, r = 0, 0
55
+ elif len(thick) == 4:
56
+ t, b, l, r = thick
57
+ else:
58
+ t = thick[0] if len(thick) > 0 else 0
59
+ b = thick[1] if len(thick) > 1 else t
60
+ l = thick[2] if len(thick) > 2 else 0
61
+ r = thick[3] if len(thick) > 3 else l
62
+ return t, b, l, r
63
+
64
+ if uthickness is None:
65
+ if vthickness is not None:
66
+ uthickness = vthickness
67
+ else:
68
+ uthickness = ythickness
69
+ if vthickness is None:
70
+ if uthickness is not None:
71
+ vthickness = uthickness
72
+ else:
73
+ vthickness = ythickness
74
+
75
+ yt, yb, yl, yr = _get_tblr(ythickness)
76
+ ut, ub, ul, ur = _get_tblr(uthickness)
77
+ vt, vb, vl, vr = _get_tblr(vthickness)
78
+
79
+ if clip.format.color_family == vs.GRAY:
80
+ upclip = clip.resize.Bicubic(format=vs.YUV444PS)
81
+ fixY = plane(depth(core.bore.SinglePlane(upclip, top=yt, bottom=yb, left=yl, right=yr, plane=0), clip.format.bits_per_sample), 0)
82
+ return fixY
83
+
84
+ fixY = plane(clip, 0)
85
+ fixU = plane(clip, 1)
86
+ fixV = plane(clip, 2)
87
+
88
+ if 0 in planes:
89
+ upclip = clip.resize.Bicubic(format=vs.YUV444PS)
90
+ if singlePlane:
91
+ fixY = plane(depth(core.bore.SinglePlane(upclip, top=yt, bottom=yb, left=yl, right=yr, plane=0), clip.format.bits_per_sample), 0)
92
+ else:
93
+ fixY = plane(depth(core.bore.MultiPlane(upclip, top=yt, bottom=yb, left=yl, right=yr, plane=0), clip.format.bits_per_sample), 0)
94
+
95
+ if 1 in planes:
96
+ upclip = clip.resize.Bicubic(width=plane(clip, 1).width, height=plane(clip, 1).height, format=vs.YUV444PS)
97
+ upclip = core.std.ShufflePlanes([upclip, depth(clip,32), depth(clip,32)], planes=[0, 1, 2], colorfamily=vs.YUV)
98
+ if singlePlane:
99
+ fixU = plane(depth(core.bore.SinglePlane(upclip, top=ut, bottom=ub, left=ul, right=ur, plane=1), clip.format.bits_per_sample), 1)
100
+ else:
101
+ fixU = plane(depth(core.bore.MultiPlane(upclip, top=ut, bottom=ub, left=ul, right=ur, plane=1), clip.format.bits_per_sample), 1)
102
+
103
+ if 2 in planes:
104
+ upclip = clip.resize.Bicubic(width=plane(clip, 2).width, height=plane(clip, 2).height, format=vs.YUV444PS)
105
+ upclip = core.std.ShufflePlanes([upclip, depth(clip,32), depth(clip,32)], planes=[0, 1, 2], colorfamily=vs.YUV)
106
+ if singlePlane:
107
+ fixV = plane(depth(core.bore.SinglePlane(upclip, top=vt, bottom=vb, left=vl, right=vr, plane=2), clip.format.bits_per_sample), 2)
108
+ else:
109
+ fixV = plane(depth(core.bore.MultiPlane(upclip, top=vt, bottom=vb, left=vl, right=vr, plane=2), clip.format.bits_per_sample), 2)
110
+
111
+ merged = core.std.ShufflePlanes([fixY, fixU, fixV], planes=[0, 0, 0], colorfamily=vs.YUV)
112
+
113
+ return merged
@@ -0,0 +1,174 @@
1
+ Metadata-Version: 2.4
2
+ Name: vsdirty
3
+ Version: 0.1.0
4
+ Summary: VapourSynth wrappers for denoising, masking and edge fixing
5
+ Author: PingWer, Mhanz3500
6
+ Project-URL: Homepage, https://github.com/r74mi/vs-dirty
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.10
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: vapoursynth>=70
14
+ Requires-Dist: vstools
15
+ Requires-Dist: vsjetpack==1.1.0
16
+ Dynamic: license-file
17
+
18
+ # vs-dirty
19
+
20
+ A collection of VapourSynth wrappers and utility functions focused on advanced denoising, masking, and edge fixing.
21
+
22
+ ## Installation
23
+
24
+ You can install `vsdirty` via pip:
25
+
26
+ ```bash
27
+ pip install vsdirty
28
+ ```
29
+
30
+ Or build from source:
31
+
32
+ ```bash
33
+ git clone https://github.com/r74mi/vs-dirty.git
34
+ cd vs-dirty
35
+ pip install .
36
+ ```
37
+
38
+ ## Dependencies
39
+
40
+ This package relies on several external VapourSynth plugins. Ensure these are installed and available in your VapourSynth plugins folder.
41
+
42
+ | Plugin | URL |
43
+ | :--- | :--- |
44
+ | **fmtc** | [GitLab](https://gitlab.com/EleonoreMizo/fmtconv/) |
45
+ | **akarin** | [GitHub](https://github.com/AkarinVS/vapoursynth-plugin) |
46
+ | **cas** | [GitHub](https://github.com/HomeOfVapourSynthEvolution/VapourSynth-CAS) |
47
+ | **bore** | [GitHub](https://github.com/OpusGang/bore) |
48
+ | **mvtools** | [GitHub](https://github.com/dubhater/vapoursynth-mvtools) |
49
+ | **BM3DCuda** | [GitHub](https://github.com/WolframRhodium/VapourSynth-BM3DCUDA) |
50
+ | **nlm-cuda** | [GitHub](https://github.com/AmusementClub/vs-nlm-cuda) |
51
+ | **vsmlrt** | [GitHub](https://github.com/AmusementClub/vs-mlrt) |
52
+
53
+ ## `adenoise`
54
+
55
+ Designed specifically for film content, this intensive adaptive denoiser removes noise while carefully preserving fine textures and small elements. It combines `mc_degrain` (luma), `NLMeans`/`CBM3D` (chroma), and `BM3D` (luma), all modulated by adaptive masking.
56
+
57
+ **Presets:**
58
+ - `scan65mm` (Light)
59
+ - `scan35mm` (Medium)
60
+ - `scan16mm` (Heavy)
61
+ - `scan8mm` (Very Heavy)
62
+ - `digital` (Optimized for digital sources)
63
+ - `default` (Generic)
64
+
65
+ **Parameters:**
66
+
67
+ ```python
68
+ adenoise.default(clip: vs.VideoNode,
69
+ thsad: int = 500,
70
+ tr: int = 2,
71
+ sigma: float = 6,
72
+ luma_mask_weaken: float = 0.75,
73
+ luma_mask_thr: float = 0.196,
74
+ chroma_denoise: float | tuple[float, str] = [1.0, "nlm"],
75
+ precision: bool = True,
76
+ chroma_masking: bool = False,
77
+ show_mask: int = 0,
78
+ luma_over_texture: float = 0.4,
79
+ kwargs_flatmask: dict = {})
80
+ ```
81
+
82
+ - `clip`: Clip to process (YUV or GRAY 16bit, if not will be internally converted in 16bit).
83
+ - `thsad`: Thsad for mc_degrain (luma denoise strength and chroma ref).
84
+ Recommended values: 300-800
85
+ - `tr`: Temporal radius for temporal consistency across al the filter involved.
86
+ Recommended values: 2-3 (1 means no temporal denoise).
87
+ - `sigma`: Sigma for BM3D (luma denoise strength).
88
+ Recommended values: 1-5.
89
+ - `luma_mask_weaken`: Controls how much dark spots should be denoised. Lower values mean stronger overall denoise.
90
+ Recommended values: 0.6-0.9
91
+ - `luma_mask_thr`: Threshold that determines what is considered bright and what is dark in the luma mask.
92
+ Recommended values: 0.15-0.25
93
+ - `chroma_denoise`: Denoiser strength and type for chroma. NLMeans/CBM3D/ArtCNN.
94
+ Reccomended strength values: 0.5-2. If not given, 1.0 is used (or none for ArtCNN).
95
+ Accepted denoiser types: "nlm", "cbm3d", "artcnn". If not given, nlm is used.
96
+ - `precision`: If True, a flat mask is created to enhance the denoise strenght on flat areas avoiding textured area (95% accuracy).
97
+ - `chroma_masking`: If True, enables specific chroma masking for U/V planes.
98
+ - `show_mask`: 1 = Show the first luma mask, 2 = Show the textured luma mask, 3 = Show the complete luma mask, 4 = Show the Chroma U Plane mask (if chroma_masking = True), 5 = Show the Chroma V Plane mask (if chroma_masking = True). Any other value returns the denoised clip.
99
+ - `luma_over_texture`: Multiplier for the luma mask in precision mode. Lower value means more importance to textured areas, higher value means more importance to luma levels.
100
+ Accepted values: 0.0-1.0
101
+ - `kwargs_flatmask`: Additional arguments for flatmask creation.
102
+ dict values (check `hd_flatmask`'s docstring for more info):
103
+ - `sigma1`: This value should be decided based on the details level of the clip and how much grain and noise is present. Usually 1 for really textured clip, 2-3 for a normal clip, 4-5 for a clip with strong noise or grain.
104
+ - `texture_strength`: Texture strength for mask (0-inf). Values above 1 decrese the strength of the texture in the mask, lower values increase it. The max value is theoretical infinite, but there is no gain after some point.
105
+ - `edges_strength`: Edges strength for mask (0-1). Basic multiplier for edges strength.
106
+
107
+ - `return`: 16bit denoised clip. If show_mask is 1, 2, 3, 4 or 5, returns a tuple (denoised_clip, mask).
108
+
109
+ **Usage:**
110
+
111
+ ```python
112
+ from vsdirty import adenoise
113
+
114
+ # Apply default adaptive denoising
115
+ denoised = adenoise.scan16mm(clip)
116
+ ```
117
+
118
+
119
+ ## `bore`
120
+
121
+ A powerful edge cleaner (dirty line fixer) that processes borders at their native resolution to avoid scaling artifacts.
122
+
123
+ ```python
124
+ from vsdirty import bore
125
+
126
+ # Fix dirty lines: Top=1px, Bottom=1px, Left=2px, Right=2px
127
+ clean = bore(clip, ythickness=[1, 1, 2, 2])
128
+ ```
129
+
130
+ ## `msaa2x`
131
+
132
+ An antialiaser based on ArtCNN that targets specific edges to reduce aliasing without blurring textures.
133
+
134
+ ```python
135
+ from vsdirty import adfunc
136
+
137
+ # Apply antialiasing
138
+ aa_clip = adfunc.msaa2x(clip)
139
+ ```
140
+
141
+ ## `advanced_edgemask`
142
+
143
+ Generates a high-quality edge mask by combining Retinex preprocessing with multiple edge detectors (Kirsch, Sobel) to capture faint and complex edges.
144
+
145
+ ```python
146
+ from vsdirty import admask
147
+
148
+ emask = admask.advanced_edgemask(clip, luma_scaling=10)
149
+ ```
150
+
151
+ ## `hd_flatmask`
152
+
153
+ A specialized mask for flat areas, useful for protecting textures or targeting specific flat regions for filtering.
154
+
155
+ ```python
156
+ from vsdirty import admask
157
+
158
+ flat_mask = admask.hd_flatmask(clip)
159
+ ```
160
+
161
+ ## `diff_and_swap`
162
+
163
+ A utility to repair damaged frames in a "base" clip using a "correction" clip. It compares frames and swaps them if the difference exceeds a threshold.
164
+
165
+ ```python
166
+ from vsdirty import adutils
167
+
168
+ # automated patching
169
+ repaired, _ = adutils.diff_and_swap(correction_clip, base_clip, thr=30000)
170
+ ```
171
+
172
+ ## License
173
+
174
+ MIT License
@@ -0,0 +1,10 @@
1
+ vsdirty/__init__.py,sha256=zonL-cH2iKwEiu0TC3WKa-EQjyDmkKicN04NMIN5OnY,182
2
+ vsdirty/adfunc.py,sha256=-zXnWU76m-xZZWerAXLhWtWlBz90tUe3olhD18iqAew,28701
3
+ vsdirty/admask.py,sha256=cOqndbegtgnLBti6ABUrPXzby3xFqUNCq5GcAz-HJdI,17530
4
+ vsdirty/adutils.py,sha256=s9MHtFghwjZp9W160yWb5zVeBehC3KloK4kXDSBgFsc,7702
5
+ vsdirty/dirtyfixer.py,sha256=qAUvpliKHYp0Ivc6HIwkU9jFFnqv_VW7M12iuK4KLRQ,4934
6
+ vsdirty-0.1.0.dist-info/licenses/LICENSE,sha256=ytBUIbwDXahKm15kCB5kJy6kyFzwccf64igR1vKikNk,1075
7
+ vsdirty-0.1.0.dist-info/METADATA,sha256=9WusOZqR6z67-YXsf4H9x_KNcK8QlWlnkGjeQ2cxNj8,6612
8
+ vsdirty-0.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
9
+ vsdirty-0.1.0.dist-info/top_level.txt,sha256=2bWQbCuQp4y6_hKaWKvP8Ysc5-Z_0NRM01wKZYt8_7o,8
10
+ vsdirty-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 PingWer, Mhanz3500
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ vsdirty