stouputils 1.12.1__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.
- stouputils/__init__.py +40 -0
- stouputils/__init__.pyi +14 -0
- stouputils/__main__.py +81 -0
- stouputils/_deprecated.py +37 -0
- stouputils/_deprecated.pyi +12 -0
- stouputils/all_doctests.py +160 -0
- stouputils/all_doctests.pyi +46 -0
- stouputils/applications/__init__.py +22 -0
- stouputils/applications/__init__.pyi +2 -0
- stouputils/applications/automatic_docs.py +634 -0
- stouputils/applications/automatic_docs.pyi +106 -0
- stouputils/applications/upscaler/__init__.py +39 -0
- stouputils/applications/upscaler/__init__.pyi +3 -0
- stouputils/applications/upscaler/config.py +128 -0
- stouputils/applications/upscaler/config.pyi +18 -0
- stouputils/applications/upscaler/image.py +247 -0
- stouputils/applications/upscaler/image.pyi +109 -0
- stouputils/applications/upscaler/video.py +287 -0
- stouputils/applications/upscaler/video.pyi +60 -0
- stouputils/archive.py +344 -0
- stouputils/archive.pyi +67 -0
- stouputils/backup.py +488 -0
- stouputils/backup.pyi +109 -0
- stouputils/collections.py +244 -0
- stouputils/collections.pyi +86 -0
- stouputils/continuous_delivery/__init__.py +27 -0
- stouputils/continuous_delivery/__init__.pyi +5 -0
- stouputils/continuous_delivery/cd_utils.py +243 -0
- stouputils/continuous_delivery/cd_utils.pyi +129 -0
- stouputils/continuous_delivery/github.py +522 -0
- stouputils/continuous_delivery/github.pyi +162 -0
- stouputils/continuous_delivery/pypi.py +91 -0
- stouputils/continuous_delivery/pypi.pyi +43 -0
- stouputils/continuous_delivery/pyproject.py +147 -0
- stouputils/continuous_delivery/pyproject.pyi +67 -0
- stouputils/continuous_delivery/stubs.py +86 -0
- stouputils/continuous_delivery/stubs.pyi +39 -0
- stouputils/ctx.py +408 -0
- stouputils/ctx.pyi +211 -0
- stouputils/data_science/config/get.py +51 -0
- stouputils/data_science/config/set.py +125 -0
- stouputils/data_science/data_processing/image/__init__.py +66 -0
- stouputils/data_science/data_processing/image/auto_contrast.py +79 -0
- stouputils/data_science/data_processing/image/axis_flip.py +58 -0
- stouputils/data_science/data_processing/image/bias_field_correction.py +74 -0
- stouputils/data_science/data_processing/image/binary_threshold.py +73 -0
- stouputils/data_science/data_processing/image/blur.py +59 -0
- stouputils/data_science/data_processing/image/brightness.py +54 -0
- stouputils/data_science/data_processing/image/canny.py +110 -0
- stouputils/data_science/data_processing/image/clahe.py +92 -0
- stouputils/data_science/data_processing/image/common.py +30 -0
- stouputils/data_science/data_processing/image/contrast.py +53 -0
- stouputils/data_science/data_processing/image/curvature_flow_filter.py +74 -0
- stouputils/data_science/data_processing/image/denoise.py +378 -0
- stouputils/data_science/data_processing/image/histogram_equalization.py +123 -0
- stouputils/data_science/data_processing/image/invert.py +64 -0
- stouputils/data_science/data_processing/image/laplacian.py +60 -0
- stouputils/data_science/data_processing/image/median_blur.py +52 -0
- stouputils/data_science/data_processing/image/noise.py +59 -0
- stouputils/data_science/data_processing/image/normalize.py +65 -0
- stouputils/data_science/data_processing/image/random_erase.py +66 -0
- stouputils/data_science/data_processing/image/resize.py +69 -0
- stouputils/data_science/data_processing/image/rotation.py +80 -0
- stouputils/data_science/data_processing/image/salt_pepper.py +68 -0
- stouputils/data_science/data_processing/image/sharpening.py +55 -0
- stouputils/data_science/data_processing/image/shearing.py +64 -0
- stouputils/data_science/data_processing/image/threshold.py +64 -0
- stouputils/data_science/data_processing/image/translation.py +71 -0
- stouputils/data_science/data_processing/image/zoom.py +83 -0
- stouputils/data_science/data_processing/image_augmentation.py +118 -0
- stouputils/data_science/data_processing/image_preprocess.py +183 -0
- stouputils/data_science/data_processing/prosthesis_detection.py +359 -0
- stouputils/data_science/data_processing/technique.py +481 -0
- stouputils/data_science/dataset/__init__.py +45 -0
- stouputils/data_science/dataset/dataset.py +292 -0
- stouputils/data_science/dataset/dataset_loader.py +135 -0
- stouputils/data_science/dataset/grouping_strategy.py +296 -0
- stouputils/data_science/dataset/image_loader.py +100 -0
- stouputils/data_science/dataset/xy_tuple.py +696 -0
- stouputils/data_science/metric_dictionnary.py +106 -0
- stouputils/data_science/metric_utils.py +847 -0
- stouputils/data_science/mlflow_utils.py +206 -0
- stouputils/data_science/models/abstract_model.py +149 -0
- stouputils/data_science/models/all.py +85 -0
- stouputils/data_science/models/base_keras.py +765 -0
- stouputils/data_science/models/keras/all.py +38 -0
- stouputils/data_science/models/keras/convnext.py +62 -0
- stouputils/data_science/models/keras/densenet.py +50 -0
- stouputils/data_science/models/keras/efficientnet.py +60 -0
- stouputils/data_science/models/keras/mobilenet.py +56 -0
- stouputils/data_science/models/keras/resnet.py +52 -0
- stouputils/data_science/models/keras/squeezenet.py +233 -0
- stouputils/data_science/models/keras/vgg.py +42 -0
- stouputils/data_science/models/keras/xception.py +38 -0
- stouputils/data_science/models/keras_utils/callbacks/__init__.py +20 -0
- stouputils/data_science/models/keras_utils/callbacks/colored_progress_bar.py +219 -0
- stouputils/data_science/models/keras_utils/callbacks/learning_rate_finder.py +148 -0
- stouputils/data_science/models/keras_utils/callbacks/model_checkpoint_v2.py +31 -0
- stouputils/data_science/models/keras_utils/callbacks/progressive_unfreezing.py +249 -0
- stouputils/data_science/models/keras_utils/callbacks/warmup_scheduler.py +66 -0
- stouputils/data_science/models/keras_utils/losses/__init__.py +12 -0
- stouputils/data_science/models/keras_utils/losses/next_generation_loss.py +56 -0
- stouputils/data_science/models/keras_utils/visualizations.py +416 -0
- stouputils/data_science/models/model_interface.py +939 -0
- stouputils/data_science/models/sandbox.py +116 -0
- stouputils/data_science/range_tuple.py +234 -0
- stouputils/data_science/scripts/augment_dataset.py +77 -0
- stouputils/data_science/scripts/exhaustive_process.py +133 -0
- stouputils/data_science/scripts/preprocess_dataset.py +70 -0
- stouputils/data_science/scripts/routine.py +168 -0
- stouputils/data_science/utils.py +285 -0
- stouputils/decorators.py +595 -0
- stouputils/decorators.pyi +242 -0
- stouputils/image.py +441 -0
- stouputils/image.pyi +172 -0
- stouputils/installer/__init__.py +18 -0
- stouputils/installer/__init__.pyi +5 -0
- stouputils/installer/common.py +67 -0
- stouputils/installer/common.pyi +39 -0
- stouputils/installer/downloader.py +101 -0
- stouputils/installer/downloader.pyi +24 -0
- stouputils/installer/linux.py +144 -0
- stouputils/installer/linux.pyi +39 -0
- stouputils/installer/main.py +223 -0
- stouputils/installer/main.pyi +57 -0
- stouputils/installer/windows.py +136 -0
- stouputils/installer/windows.pyi +31 -0
- stouputils/io.py +486 -0
- stouputils/io.pyi +213 -0
- stouputils/parallel.py +453 -0
- stouputils/parallel.pyi +211 -0
- stouputils/print.py +527 -0
- stouputils/print.pyi +146 -0
- stouputils/py.typed +1 -0
- stouputils-1.12.1.dist-info/METADATA +179 -0
- stouputils-1.12.1.dist-info/RECORD +138 -0
- stouputils-1.12.1.dist-info/WHEEL +4 -0
- stouputils-1.12.1.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
from ..continuous_delivery import version_to_float as version_to_float
|
|
2
|
+
from ..decorators import LogLevels as LogLevels, handle_error as handle_error, simple_cache as simple_cache
|
|
3
|
+
from ..io import clean_path as clean_path, json_dump as json_dump, super_open as super_open
|
|
4
|
+
from ..print import info as info
|
|
5
|
+
from collections.abc import Callable as Callable
|
|
6
|
+
|
|
7
|
+
REQUIREMENTS: list[str]
|
|
8
|
+
|
|
9
|
+
def check_dependencies(html_theme: str) -> None:
|
|
10
|
+
''' Check for each requirement if it is installed.
|
|
11
|
+
|
|
12
|
+
\tArgs:
|
|
13
|
+
\t\thtml_theme (str): HTML theme to use for the documentation, to check if it is installed (e.g. "breeze", "pydata_sphinx_theme", "furo", etc.)
|
|
14
|
+
\t'''
|
|
15
|
+
def get_sphinx_conf_content(project: str, project_dir: str, author: str, current_version: str, copyright: str, html_logo: str, html_favicon: str, html_theme: str = 'breeze', github_user: str = '', github_repo: str = '', version_list: list[str] | None = None, skip_undocumented: bool = True) -> str:
|
|
16
|
+
""" Get the content of the Sphinx configuration file.
|
|
17
|
+
|
|
18
|
+
\tArgs:
|
|
19
|
+
\t\tproject (str): Name of the project
|
|
20
|
+
\t\tproject_dir (str): Path to the project directory
|
|
21
|
+
\t\tauthor (str): Author of the project
|
|
22
|
+
\t\tcurrent_version (str): Current version
|
|
23
|
+
\t\tcopyright (str): Copyright information
|
|
24
|
+
\t\thtml_logo (str): URL to the logo
|
|
25
|
+
\t\thtml_favicon (str): URL to the favicon
|
|
26
|
+
\t\tgithub_user (str): GitHub username
|
|
27
|
+
\t\tgithub_repo (str): GitHub repository name
|
|
28
|
+
\t\tversion_list (list[str] | None): List of versions. Defaults to None
|
|
29
|
+
\t\tskip_undocumented (bool): Whether to skip undocumented members. Defaults to True
|
|
30
|
+
|
|
31
|
+
\tReturns:
|
|
32
|
+
\t\tstr: Content of the Sphinx configuration file
|
|
33
|
+
\t"""
|
|
34
|
+
def get_versions_from_github(github_user: str, github_repo: str, recent_minor_versions: int = 2) -> list[str]:
|
|
35
|
+
""" Get list of versions from GitHub gh-pages branch.
|
|
36
|
+
\tOnly shows detailed versions for the last N minor versions, and keeps only
|
|
37
|
+
\tthe latest patch version for older minor versions.
|
|
38
|
+
|
|
39
|
+
\tArgs:
|
|
40
|
+
\t\tgithub_user (str): GitHub username
|
|
41
|
+
\t\tgithub_repo (str): GitHub repository name
|
|
42
|
+
\t\trecent_minor_versions (int): Number of recent minor versions to show all patches for (-1 for all).
|
|
43
|
+
|
|
44
|
+
\tReturns:
|
|
45
|
+
\t\tlist[str]: List of versions, with 'latest' as first element
|
|
46
|
+
\t"""
|
|
47
|
+
def markdown_to_rst(markdown_content: str) -> str:
|
|
48
|
+
""" Convert markdown content to RST format.
|
|
49
|
+
|
|
50
|
+
\tArgs:
|
|
51
|
+
\t\tmarkdown_content (str): Markdown content
|
|
52
|
+
|
|
53
|
+
\tReturns:
|
|
54
|
+
\t\tstr: RST content
|
|
55
|
+
\t"""
|
|
56
|
+
def generate_index_rst(readme_path: str, index_path: str, project: str, github_user: str, github_repo: str, get_versions_function: Callable[[str, str, int], list[str]] = ..., recent_minor_versions: int = 2) -> None:
|
|
57
|
+
""" Generate index.rst from README.md content.
|
|
58
|
+
|
|
59
|
+
\tArgs:
|
|
60
|
+
\t\treadme_path (str): Path to the README.md file
|
|
61
|
+
\t\tindex_path (str): Path where index.rst should be created
|
|
62
|
+
\t\tproject (str): Name of the project
|
|
63
|
+
\t\tgithub_user (str): GitHub username
|
|
64
|
+
\t\tgithub_repo (str): GitHub repository name
|
|
65
|
+
\t\tget_versions_function (Callable[[str, str, int], list[str]]): Function to get versions from GitHub
|
|
66
|
+
\t\trecent_minor_versions (int): Number of recent minor versions to show all patches for. Defaults to 2
|
|
67
|
+
\t"""
|
|
68
|
+
def generate_documentation(source_dir: str, modules_dir: str, project_dir: str, build_dir: str) -> None:
|
|
69
|
+
""" Generate documentation using Sphinx.
|
|
70
|
+
|
|
71
|
+
\tArgs:
|
|
72
|
+
\t\tsource_dir (str): Source directory
|
|
73
|
+
\t\tmodules_dir (str): Modules directory
|
|
74
|
+
\t\tproject_dir (str): Project directory
|
|
75
|
+
\t\tbuild_dir (str): Build directory
|
|
76
|
+
\t"""
|
|
77
|
+
def generate_redirect_html(filepath: str) -> None:
|
|
78
|
+
""" Generate HTML content for redirect page.
|
|
79
|
+
|
|
80
|
+
\tArgs:
|
|
81
|
+
\t\tfilepath (str): Path to the file where the HTML content should be written
|
|
82
|
+
\t"""
|
|
83
|
+
def update_documentation(root_path: str, project: str, project_dir: str = '', author: str = 'Author', copyright: str = '2025, Author', html_logo: str = '', html_favicon: str = '', html_theme: str = 'breeze', github_user: str = '', github_repo: str = '', version: str | None = None, skip_undocumented: bool = True, recent_minor_versions: int = 2, get_versions_function: Callable[[str, str, int], list[str]] = ..., generate_index_function: Callable[..., None] = ..., generate_docs_function: Callable[..., None] = ..., generate_redirect_function: Callable[[str], None] = ..., get_conf_content_function: Callable[..., str] = ...) -> None:
|
|
84
|
+
''' Update the Sphinx documentation.
|
|
85
|
+
|
|
86
|
+
\tArgs:
|
|
87
|
+
\t\troot_path (str): Root path of the project
|
|
88
|
+
\t\tproject (str): Name of the project
|
|
89
|
+
\t\tproject_dir (str): Path to the project directory (to be used with generate_docs_function)
|
|
90
|
+
\t\tauthor (str): Author of the project
|
|
91
|
+
\t\tcopyright (str): Copyright information
|
|
92
|
+
\t\thtml_logo (str): URL to the logo
|
|
93
|
+
\t\thtml_favicon (str): URL to the favicon
|
|
94
|
+
\t\thtml_theme (str): Theme to use for the documentation. Defaults to "breeze"
|
|
95
|
+
\t\tgithub_user (str): GitHub username
|
|
96
|
+
\t\tgithub_repo (str): GitHub repository name
|
|
97
|
+
\t\tversion (str | None): Version to build documentation for (e.g. "1.0.0", defaults to "latest")
|
|
98
|
+
\t\tskip_undocumented (bool): Whether to skip undocumented members. Defaults to True
|
|
99
|
+
\t\trecent_minor_versions (int): Number of recent minor versions to show all patches for. Defaults to 2
|
|
100
|
+
|
|
101
|
+
\t\tget_versions_function (Callable[[str, str, int], list[str]]): Function to get versions from GitHub
|
|
102
|
+
\t\tgenerate_index_function (Callable[..., None]): Function to generate index.rst
|
|
103
|
+
\t\tgenerate_docs_function (Callable[..., None]): Function to generate documentation
|
|
104
|
+
\t\tgenerate_redirect_function (Callable[[str], None]): Function to create redirect file
|
|
105
|
+
\t\tget_conf_content_function (Callable[..., str]): Function to get Sphinx conf.py content
|
|
106
|
+
\t'''
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides utilities for upscaling images and videos using waifu2x-ncnn-vulkan (by default).
|
|
3
|
+
|
|
4
|
+
It includes functions to upscale individual images, batches of images in a folder,
|
|
5
|
+
and videos by processing them frame by frame. It also handles configuration and
|
|
6
|
+
installation of required dependencies.
|
|
7
|
+
|
|
8
|
+
.. raw:: html
|
|
9
|
+
|
|
10
|
+
<video width="100%" height="auto" controls>
|
|
11
|
+
<source src="https://raw.githubusercontent.com/Stoupy51/stouputils/refs/heads/main/assets/applications/upscaler.mp4" type="video/mp4">
|
|
12
|
+
Your browser does not support the video tag.
|
|
13
|
+
</video>
|
|
14
|
+
|
|
15
|
+
Example of script:
|
|
16
|
+
|
|
17
|
+
.. code-block:: python
|
|
18
|
+
|
|
19
|
+
# Imports
|
|
20
|
+
import stouputils.applications.upscaler as app
|
|
21
|
+
from stouputils.io import get_root_path
|
|
22
|
+
|
|
23
|
+
# Constants
|
|
24
|
+
ROOT: str = get_root_path(__file__) + "/upscaler"
|
|
25
|
+
INPUT_FOLDER: str = f"{ROOT}/input"
|
|
26
|
+
PROGRESS_FOLDER: str = f"{ROOT}/progress"
|
|
27
|
+
OUTPUT_FOLDER: str = f"{ROOT}/output"
|
|
28
|
+
|
|
29
|
+
# Main
|
|
30
|
+
if __name__ == "__main__":
|
|
31
|
+
app.video_upscaler_cli(INPUT_FOLDER, PROGRESS_FOLDER, OUTPUT_FOLDER)
|
|
32
|
+
"""
|
|
33
|
+
# ruff: noqa: F403
|
|
34
|
+
|
|
35
|
+
# Imports
|
|
36
|
+
from .config import *
|
|
37
|
+
from .image import *
|
|
38
|
+
from .video import *
|
|
39
|
+
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides configuration settings and constants for the upscaler application.
|
|
3
|
+
|
|
4
|
+
It defines the URLs for downloading dependencies like waifu2x-ncnn-vulkan and FFmpeg,
|
|
5
|
+
and provides a Config class with settings for upscaling operations, including output quality,
|
|
6
|
+
bitrates, executable paths, and command-line arguments for the underlying tools.
|
|
7
|
+
|
|
8
|
+
Configuration options include:
|
|
9
|
+
- Image quality settings (JPG quality)
|
|
10
|
+
- Video encoding parameters (bitrate, codec, etc.)
|
|
11
|
+
- Paths to external binaries (FFmpeg, waifu2x-ncnn-vulkan)
|
|
12
|
+
- Command-line arguments for upscaling and video processing
|
|
13
|
+
"""
|
|
14
|
+
# Constants
|
|
15
|
+
WAIFU2X_NCNN_VULKAN_RELEASES: dict[str, str] = {
|
|
16
|
+
"Windows": "https://github.com/nihui/waifu2x-ncnn-vulkan/releases/download/20220728/waifu2x-ncnn-vulkan-20220728-windows.zip",
|
|
17
|
+
"Linux": "https://github.com/nihui/waifu2x-ncnn-vulkan/releases/download/20220728/waifu2x-ncnn-vulkan-20220728-ubuntu.zip",
|
|
18
|
+
"Darwin": "https://github.com/nihui/waifu2x-ncnn-vulkan/releases/download/20220728/waifu2x-ncnn-vulkan-20220728-macos.zip"
|
|
19
|
+
}
|
|
20
|
+
""" URLs to download waifu2x-ncnn-vulkan from for each common platform. """
|
|
21
|
+
FFMPEG_RELEASES: dict[str, str] = {
|
|
22
|
+
"Windows": "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-gpl.zip",
|
|
23
|
+
"Linux": "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linux64-gpl.tar.xz",
|
|
24
|
+
"Darwin": "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-macos64-gpl.tar.xz"
|
|
25
|
+
}
|
|
26
|
+
""" URLs to download FFmpeg from for each common platform. """
|
|
27
|
+
YOUTUBE_BITRATE_RECOMMENDATIONS: dict[str, dict[str, dict[int, int]]] = {
|
|
28
|
+
"SDR": {
|
|
29
|
+
"standard": { # Standard Frame Rate (24, 25, 30)
|
|
30
|
+
4320: 160000, # 8K - 160 Mbps
|
|
31
|
+
2160: 45000, # 4K - 45 Mbps
|
|
32
|
+
1440: 16000, # 2K - 16 Mbps
|
|
33
|
+
1080: 8000, # 1080p - 8 Mbps
|
|
34
|
+
720: 5000, # 720p - 5 Mbps
|
|
35
|
+
480: 2500, # 480p - 2.5 Mbps
|
|
36
|
+
0: 1000 # 360p or lower - 1 Mbps
|
|
37
|
+
},
|
|
38
|
+
"high": { # High Frame Rate (48, 50, 60)
|
|
39
|
+
4320: 240000, # 8K - 240 Mbps
|
|
40
|
+
2160: 68000, # 4K - 68 Mbps
|
|
41
|
+
1440: 24000, # 2K - 24 Mbps
|
|
42
|
+
1080: 12000, # 1080p - 12 Mbps
|
|
43
|
+
720: 7500, # 720p - 7.5 Mbps
|
|
44
|
+
480: 4000, # 480p - 4 Mbps
|
|
45
|
+
0: 1500 # 360p or lower - 1.5 Mbps
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"HDR": {
|
|
49
|
+
"standard": { # Standard Frame Rate (24, 25, 30)
|
|
50
|
+
4320: 200000, # 8K - 200 Mbps
|
|
51
|
+
2160: 56000, # 4K - 56 Mbps
|
|
52
|
+
1440: 20000, # 2K - 20 Mbps
|
|
53
|
+
1080: 10000, # 1080p - 10 Mbps
|
|
54
|
+
0: 6500 # 720p or lower - 6.5 Mbps
|
|
55
|
+
},
|
|
56
|
+
"high": { # High Frame Rate (48, 50, 60)
|
|
57
|
+
4320: 300000, # 8K - 300 Mbps
|
|
58
|
+
2160: 85000, # 4K - 85 Mbps
|
|
59
|
+
1440: 30000, # 2K - 30 Mbps
|
|
60
|
+
1080: 15000, # 1080p - 15 Mbps
|
|
61
|
+
0: 9500 # 720p or lower - 9.5 Mbps
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
""" YouTube bitrate recommendations for different resolutions and frame rates.
|
|
66
|
+
|
|
67
|
+
This dictionary contains recommended bitrates for YouTube uploads based on:
|
|
68
|
+
- SDR vs HDR content
|
|
69
|
+
- Standard frame rate (24, 25, 30 fps) vs high frame rate (48, 50, 60 fps)
|
|
70
|
+
- Video resolution (from 360p up to 8K)
|
|
71
|
+
|
|
72
|
+
The values are in kbps (kilobits per second).
|
|
73
|
+
|
|
74
|
+
Source: https://support.google.com/youtube/answer/1722171
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
# Configuration class
|
|
78
|
+
class Config:
|
|
79
|
+
""" Configuration class for the upscaler. """
|
|
80
|
+
JPG_QUALITY: int = 95
|
|
81
|
+
""" JPG quality for the output images. (Range: 0-100) """
|
|
82
|
+
|
|
83
|
+
VIDEO_FINAL_BITRATE: int = -1
|
|
84
|
+
""" Video final bitrate for the output video. -1 for YouTube recommended bitrate based on the video resolution. """
|
|
85
|
+
|
|
86
|
+
FFMPEG_EXECUTABLE: str = "ffmpeg"
|
|
87
|
+
""" Path to the ffmpeg executable, default is "ffmpeg" in the PATH. """
|
|
88
|
+
|
|
89
|
+
FFMPEG_ARGS: tuple[str, ...] = (
|
|
90
|
+
"-c:a", "copy", # Copy the audio without re-encoding
|
|
91
|
+
"-c:v", "hevc_nvenc", # Encode the video
|
|
92
|
+
"-map", "0:v:0", # Map the first input -i (frames) as video
|
|
93
|
+
"-map", "1:a:0?", # Map the second input -i (sound) as audio, with '?' to ignore if no audio stream
|
|
94
|
+
"-preset", "slow", # Set the encoding preset to slow (slower but better quality)
|
|
95
|
+
"-y", # Overwrite the output file if it exists
|
|
96
|
+
)
|
|
97
|
+
""" Additional arguments sent to the ffmpeg executable when calling subprocess.run(). """
|
|
98
|
+
|
|
99
|
+
FFPROBE_EXECUTABLE: str = "ffprobe"
|
|
100
|
+
""" Path to the ffprobe executable, default is "ffprobe" in the PATH. Used to get the framerate of the video. """
|
|
101
|
+
|
|
102
|
+
FFMPEG_CHECK_HELP_TEXT: str = "usage: ffmpeg [options]"
|
|
103
|
+
""" If this text is present in the output of the ffmpeg executable, it means it's installed correctly. """
|
|
104
|
+
|
|
105
|
+
UPSCALER_EXECUTABLE: str = "waifu2x-ncnn-vulkan"
|
|
106
|
+
""" Path to the upscaler executable, default is "waifu2x-ncnn-vulkan" in the PATH. """
|
|
107
|
+
|
|
108
|
+
UPSCALER_ARGS: tuple[str, ...] = (
|
|
109
|
+
"-i", "INPUT_PATH", # Input file path
|
|
110
|
+
"-o", "OUTPUT_PATH", # Output file path
|
|
111
|
+
"-s", "UPSCALE_RATIO", # Upscaling ratio
|
|
112
|
+
"-n", "3", # Noise level
|
|
113
|
+
)
|
|
114
|
+
""" Arguments sent to the upscaler executable when calling subprocess.run(). """
|
|
115
|
+
|
|
116
|
+
UPSCALER_EXECUTABLE_HELP_TEXT: str = "Usage: waifu2x-ncnn-vulkan -i"
|
|
117
|
+
""" If this text is present in the output of the upscaler executable, it means it's installed correctly. """
|
|
118
|
+
|
|
119
|
+
SLIGHTLY_FASTER_MODE: bool = False
|
|
120
|
+
""" If True, the upscaler executable will be called once, which is slightly faster but you can't see the progress. """
|
|
121
|
+
|
|
122
|
+
# Variables
|
|
123
|
+
upscaler_executable_checked: bool = False
|
|
124
|
+
""" Whether the upscaler executable has been checked for. """
|
|
125
|
+
|
|
126
|
+
ffmpeg_executable_checked: bool = False
|
|
127
|
+
""" Whether the ffmpeg executable has been checked for. """
|
|
128
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
WAIFU2X_NCNN_VULKAN_RELEASES: dict[str, str]
|
|
2
|
+
FFMPEG_RELEASES: dict[str, str]
|
|
3
|
+
YOUTUBE_BITRATE_RECOMMENDATIONS: dict[str, dict[str, dict[int, int]]]
|
|
4
|
+
|
|
5
|
+
class Config:
|
|
6
|
+
""" Configuration class for the upscaler. """
|
|
7
|
+
JPG_QUALITY: int
|
|
8
|
+
VIDEO_FINAL_BITRATE: int
|
|
9
|
+
FFMPEG_EXECUTABLE: str
|
|
10
|
+
FFMPEG_ARGS: tuple[str, ...]
|
|
11
|
+
FFPROBE_EXECUTABLE: str
|
|
12
|
+
FFMPEG_CHECK_HELP_TEXT: str
|
|
13
|
+
UPSCALER_EXECUTABLE: str
|
|
14
|
+
UPSCALER_ARGS: tuple[str, ...]
|
|
15
|
+
UPSCALER_EXECUTABLE_HELP_TEXT: str
|
|
16
|
+
SLIGHTLY_FASTER_MODE: bool
|
|
17
|
+
upscaler_executable_checked: bool
|
|
18
|
+
ffmpeg_executable_checked: bool
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides utility functions for upscaling images using waifu2x-ncnn-vulkan.
|
|
3
|
+
|
|
4
|
+
It includes functions to upscale individual images, batches of images in a folder,
|
|
5
|
+
and handle intermediate operations like converting between image formats.
|
|
6
|
+
The module also manages temporary directories for partial processing and tracks
|
|
7
|
+
progress of batch operations.
|
|
8
|
+
|
|
9
|
+
Main functionalities:
|
|
10
|
+
|
|
11
|
+
- Converting frames between image formats (PNG to JPG)
|
|
12
|
+
- Upscaling individual images with configurable upscale ratio
|
|
13
|
+
- Batch processing folders of images with progress tracking
|
|
14
|
+
- Handling already processed images to resume interrupted operations
|
|
15
|
+
|
|
16
|
+
Example usage:
|
|
17
|
+
|
|
18
|
+
.. code-block:: python
|
|
19
|
+
|
|
20
|
+
from stouputils.applications.upscaler import upscale, upscale_folder
|
|
21
|
+
|
|
22
|
+
# Upscale a single image
|
|
23
|
+
upscale("input.jpg", "output.jpg", 2)
|
|
24
|
+
|
|
25
|
+
# Upscale a folder of images
|
|
26
|
+
upscale_folder("input_folder", "output_folder", 2)
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
# Imports
|
|
30
|
+
import os
|
|
31
|
+
import shutil
|
|
32
|
+
import subprocess
|
|
33
|
+
from tempfile import TemporaryDirectory
|
|
34
|
+
|
|
35
|
+
from PIL import Image
|
|
36
|
+
|
|
37
|
+
from ...installer import check_executable
|
|
38
|
+
from ...io import clean_path
|
|
39
|
+
from ...parallel import multithreading
|
|
40
|
+
from ...print import colored_for_loop, debug, info
|
|
41
|
+
from .config import WAIFU2X_NCNN_VULKAN_RELEASES, Config
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# Function to convert a PNG frame to JPG format
|
|
45
|
+
def convert_frame(frame_path: str, delete_png: bool = True) -> None:
|
|
46
|
+
""" Convert a PNG frame to JPG format to take less space.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
frame_path (str): Path to the PNG frame to convert.
|
|
50
|
+
delete_png (bool): Whether to delete the original PNG file after conversion.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
None: This function doesn't return anything.
|
|
54
|
+
|
|
55
|
+
Example:
|
|
56
|
+
.. code-block:: python
|
|
57
|
+
|
|
58
|
+
> convert_frame("input.png", delete_png=True)
|
|
59
|
+
> # input.png will be converted to input.jpg and the original file will be deleted
|
|
60
|
+
|
|
61
|
+
> convert_frame("input.png", delete_png=False)
|
|
62
|
+
> # input.png will be converted to input.jpg and the original file will be kept
|
|
63
|
+
"""
|
|
64
|
+
if frame_path.endswith(".png"):
|
|
65
|
+
with Image.open(frame_path) as img:
|
|
66
|
+
img.save(frame_path.replace(".png", ".jpg"), quality=Config.JPG_QUALITY)
|
|
67
|
+
if delete_png:
|
|
68
|
+
os.remove(frame_path)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# Function to get all frames in a folder
|
|
72
|
+
def get_all_files(folder: str, suffix: str | tuple[str, ...] = "") -> list[str]:
|
|
73
|
+
""" Get all files paths in a folder, with a specific suffix if provided.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
folder (str): Path to the folder containing the files.
|
|
77
|
+
suffix (str | tuple[str, ...]): Suffix of the files to get (e.g. ".png", ".jpg", etc.).
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
list[str]: List of all files paths in the folder.
|
|
81
|
+
|
|
82
|
+
Example:
|
|
83
|
+
>>> files: list[str] = get_all_files("some_folder", ".png")
|
|
84
|
+
>>> len(files)
|
|
85
|
+
0
|
|
86
|
+
"""
|
|
87
|
+
if not os.path.exists(folder):
|
|
88
|
+
return []
|
|
89
|
+
return [f"{folder}/{f}" for f in os.listdir(folder) if f.endswith(suffix)]
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# Function to create a temporary directory with not upscaled images
|
|
93
|
+
def create_temp_dir_for_not_upscaled(input_path: str, output_path: str) -> TemporaryDirectory[str] | None:
|
|
94
|
+
""" Creates a temporary directory containing only images that haven't been upscaled yet.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
input_path (str): Path to the folder containing input images.
|
|
98
|
+
output_path (str): Path to the folder where upscaled images are saved.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
TemporaryDirectory[str] | None: A temporary directory object if there are images to process,
|
|
102
|
+
None if all images are already upscaled.
|
|
103
|
+
"""
|
|
104
|
+
# Get all input images and the not upscaled images
|
|
105
|
+
all_inputs: list[str] = get_all_files(input_path)
|
|
106
|
+
not_upscaled_images: list[str] = [x for x in all_inputs if not os.path.exists(f"{output_path}/{os.path.basename(x)}")]
|
|
107
|
+
|
|
108
|
+
# If all images or none are already upscaled, return None
|
|
109
|
+
if len(not_upscaled_images) == 0 or (len(not_upscaled_images) == len(all_inputs)):
|
|
110
|
+
return None
|
|
111
|
+
|
|
112
|
+
# Create a temporary directory and copy the not upscaled images to it
|
|
113
|
+
temp_dir: TemporaryDirectory[str] = TemporaryDirectory()
|
|
114
|
+
debug(f"Creating temporary directory to process {len(not_upscaled_images)} images: {temp_dir.name}")
|
|
115
|
+
for image in not_upscaled_images:
|
|
116
|
+
shutil.copyfile(image, f"{temp_dir.name}/{os.path.basename(image)}")
|
|
117
|
+
return temp_dir
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
# Helper function to check if the upscaler executable is installed
|
|
121
|
+
def check_upscaler_executable() -> None:
|
|
122
|
+
if not Config.upscaler_executable_checked:
|
|
123
|
+
check_executable(Config.UPSCALER_EXECUTABLE, Config.UPSCALER_EXECUTABLE_HELP_TEXT, WAIFU2X_NCNN_VULKAN_RELEASES)
|
|
124
|
+
Config.upscaler_executable_checked = True
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
# Function to upscale an image
|
|
128
|
+
def upscale(input_path: str, output_path: str, upscale_ratio: int) -> None:
|
|
129
|
+
""" Upscale an input image (or a directory of images) with the upscaler executable.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
input_path (str): Path to the image to upscale (or a directory).
|
|
133
|
+
output_path (str): Path to the output image (or a directory).
|
|
134
|
+
upscale_ratio (int): Upscaling ratio.
|
|
135
|
+
|
|
136
|
+
Example:
|
|
137
|
+
.. code-block:: python
|
|
138
|
+
|
|
139
|
+
> upscale("folder", "folder", 2)
|
|
140
|
+
Traceback (most recent call last):
|
|
141
|
+
...
|
|
142
|
+
AssertionError: Input and output paths cannot be the same, got 'folder'
|
|
143
|
+
|
|
144
|
+
> upscale("stouputils", "stouputils/output.jpg", 2)
|
|
145
|
+
Traceback (most recent call last):
|
|
146
|
+
...
|
|
147
|
+
AssertionError: If input is a directory, output must be a directory too, got 'stouputils/output.jpg'
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
> upscale("input.jpg", "output.jpg", 2)
|
|
151
|
+
> # The input.jpg will be upscaled to output.jpg with a ratio of 2
|
|
152
|
+
|
|
153
|
+
> upscale("input_folder", "output_folder", 2)
|
|
154
|
+
> # The input_folder will be upscaled to output_folder with a ratio of 2
|
|
155
|
+
"""
|
|
156
|
+
check_upscaler_executable()
|
|
157
|
+
is_input_dir: bool = os.path.isdir(input_path)
|
|
158
|
+
is_output_dir: bool = os.path.isdir(output_path)
|
|
159
|
+
|
|
160
|
+
# Assertions
|
|
161
|
+
assert input_path != output_path, f"Input and output paths cannot be the same, got '{input_path}'"
|
|
162
|
+
invalid_dir_combination: bool = is_input_dir == True and is_output_dir == False # noqa: E712
|
|
163
|
+
assert not invalid_dir_combination, f"If input is a directory, output must be a directory too, got '{output_path}'"
|
|
164
|
+
|
|
165
|
+
# Convert output_path to a file path if it's a directory
|
|
166
|
+
if is_output_dir and not is_input_dir:
|
|
167
|
+
|
|
168
|
+
# Needs to be a PNG file to be converted to JPG later
|
|
169
|
+
output_file_name: str = os.path.basename(input_path).replace(".jpg", ".png")
|
|
170
|
+
output_path = clean_path(f"{output_path}/{output_file_name}")
|
|
171
|
+
is_output_dir = False
|
|
172
|
+
|
|
173
|
+
# If both input and output are folders, and there are images already upscaled in the output folder,
|
|
174
|
+
# Then create a temporary folder with not upscaled images
|
|
175
|
+
temp_dir: TemporaryDirectory[str] | None = None
|
|
176
|
+
if is_input_dir and is_output_dir:
|
|
177
|
+
temp_dir = create_temp_dir_for_not_upscaled(input_path, output_path)
|
|
178
|
+
if temp_dir:
|
|
179
|
+
input_path = temp_dir.name
|
|
180
|
+
|
|
181
|
+
# Build the command and run it
|
|
182
|
+
cmd: list[str] = [Config.UPSCALER_EXECUTABLE, *Config.UPSCALER_ARGS]
|
|
183
|
+
cmd[cmd.index("INPUT_PATH")] = input_path # Replace the input path
|
|
184
|
+
cmd[cmd.index("OUTPUT_PATH")] = output_path # Replace the output path
|
|
185
|
+
cmd[cmd.index("UPSCALE_RATIO")] = str(upscale_ratio) # Replace the upscaled ratio (if using waifu2x-ncnn-vulkan)
|
|
186
|
+
subprocess.run(cmd, capture_output=True)
|
|
187
|
+
|
|
188
|
+
# If the input was a temporary folder, delete it
|
|
189
|
+
if temp_dir:
|
|
190
|
+
temp_dir.cleanup()
|
|
191
|
+
|
|
192
|
+
# Convert the output frames to JPG format
|
|
193
|
+
if not is_output_dir:
|
|
194
|
+
convert_frame(output_path)
|
|
195
|
+
else:
|
|
196
|
+
frames_to_convert: list[str] = get_all_files(output_path, ".png")
|
|
197
|
+
if frames_to_convert:
|
|
198
|
+
multithreading(convert_frame, frames_to_convert, desc="Converting frames to JPG format")
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
# Function to upscale multiple images
|
|
202
|
+
def upscale_images(images: list[str], output_folder: str, upscale_ratio: int, desc: str = "Upscaling images") -> None:
|
|
203
|
+
""" Upscale multiple images from a list.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
images (list[str]): List of paths to the images to upscale.
|
|
207
|
+
output_folder (str): Path to the output folder where the upscaled images will be saved.
|
|
208
|
+
upscale_ratio (int): Upscaling ratio.
|
|
209
|
+
desc (str): Description of the function execution displayed in the progress bar.
|
|
210
|
+
No progress bar will be displayed if desc is empty.
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
None: This function doesn't return anything.
|
|
214
|
+
"""
|
|
215
|
+
for image_path in (colored_for_loop(images, desc=desc) if desc != "" else images):
|
|
216
|
+
upscale(image_path, output_folder, upscale_ratio)
|
|
217
|
+
|
|
218
|
+
# Function to upscale a folder of images
|
|
219
|
+
def upscale_folder(
|
|
220
|
+
input_folder: str,
|
|
221
|
+
output_folder: str,
|
|
222
|
+
upscale_ratio: int,
|
|
223
|
+
slightly_faster_mode: bool = True,
|
|
224
|
+
desc: str = "Upscaling folder"
|
|
225
|
+
) -> None:
|
|
226
|
+
""" Upscale all images in a folder.
|
|
227
|
+
|
|
228
|
+
Args:
|
|
229
|
+
input_folder (str): Path to the input folder containing the images to upscale.
|
|
230
|
+
output_folder (str): Path to the output folder where the upscaled images will be saved.
|
|
231
|
+
upscale_ratio (int): Upscaling ratio.
|
|
232
|
+
slightly_faster_mode (bool): Whether to use the slightly faster mode (no progress bar),
|
|
233
|
+
one call to the upscaler executable.
|
|
234
|
+
desc (str): Description of the function execution displayed in the progress bar.
|
|
235
|
+
No progress bar will be displayed if desc is empty.
|
|
236
|
+
|
|
237
|
+
Returns:
|
|
238
|
+
None: This function doesn't return anything.
|
|
239
|
+
"""
|
|
240
|
+
info(f"Upscaling '{input_folder}' to '{output_folder}' with a ratio of {upscale_ratio}...")
|
|
241
|
+
if slightly_faster_mode:
|
|
242
|
+
upscale(input_folder, output_folder, upscale_ratio)
|
|
243
|
+
else:
|
|
244
|
+
inputs: list[str] = get_all_files(input_folder)
|
|
245
|
+
not_upscaled_images: list[str] = [x for x in inputs if not os.path.exists(f"{output_folder}/{os.path.basename(x)}")]
|
|
246
|
+
upscale_images(not_upscaled_images, output_folder, upscale_ratio, desc=desc)
|
|
247
|
+
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
from ...installer import check_executable as check_executable
|
|
2
|
+
from ...io import clean_path as clean_path
|
|
3
|
+
from ...parallel import multithreading as multithreading
|
|
4
|
+
from ...print import colored_for_loop as colored_for_loop, debug as debug, info as info
|
|
5
|
+
from .config import Config as Config, WAIFU2X_NCNN_VULKAN_RELEASES as WAIFU2X_NCNN_VULKAN_RELEASES
|
|
6
|
+
from tempfile import TemporaryDirectory
|
|
7
|
+
|
|
8
|
+
def convert_frame(frame_path: str, delete_png: bool = True) -> None:
|
|
9
|
+
''' Convert a PNG frame to JPG format to take less space.
|
|
10
|
+
|
|
11
|
+
\tArgs:
|
|
12
|
+
\t\tframe_path (str): Path to the PNG frame to convert.
|
|
13
|
+
\t\tdelete_png (bool): Whether to delete the original PNG file after conversion.
|
|
14
|
+
|
|
15
|
+
\tReturns:
|
|
16
|
+
\t\tNone: This function doesn\'t return anything.
|
|
17
|
+
|
|
18
|
+
\tExample:
|
|
19
|
+
\t\t.. code-block:: python
|
|
20
|
+
|
|
21
|
+
\t\t\t> convert_frame("input.png", delete_png=True)
|
|
22
|
+
\t\t\t> # input.png will be converted to input.jpg and the original file will be deleted
|
|
23
|
+
|
|
24
|
+
\t\t\t> convert_frame("input.png", delete_png=False)
|
|
25
|
+
\t\t\t> # input.png will be converted to input.jpg and the original file will be kept
|
|
26
|
+
\t'''
|
|
27
|
+
def get_all_files(folder: str, suffix: str | tuple[str, ...] = '') -> list[str]:
|
|
28
|
+
''' Get all files paths in a folder, with a specific suffix if provided.
|
|
29
|
+
|
|
30
|
+
\tArgs:
|
|
31
|
+
\t\tfolder (str): Path to the folder containing the files.
|
|
32
|
+
\t\tsuffix (str | tuple[str, ...]): Suffix of the files to get (e.g. ".png", ".jpg", etc.).
|
|
33
|
+
|
|
34
|
+
\tReturns:
|
|
35
|
+
\t\tlist[str]: List of all files paths in the folder.
|
|
36
|
+
|
|
37
|
+
\tExample:
|
|
38
|
+
\t\t>>> files: list[str] = get_all_files("some_folder", ".png")
|
|
39
|
+
\t\t>>> len(files)
|
|
40
|
+
\t\t0
|
|
41
|
+
\t'''
|
|
42
|
+
def create_temp_dir_for_not_upscaled(input_path: str, output_path: str) -> TemporaryDirectory[str] | None:
|
|
43
|
+
""" Creates a temporary directory containing only images that haven't been upscaled yet.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
input_path (str): Path to the folder containing input images.
|
|
47
|
+
output_path (str): Path to the folder where upscaled images are saved.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
TemporaryDirectory[str] | None: A temporary directory object if there are images to process,
|
|
51
|
+
None if all images are already upscaled.
|
|
52
|
+
"""
|
|
53
|
+
def check_upscaler_executable() -> None: ...
|
|
54
|
+
def upscale(input_path: str, output_path: str, upscale_ratio: int) -> None:
|
|
55
|
+
''' Upscale an input image (or a directory of images) with the upscaler executable.
|
|
56
|
+
|
|
57
|
+
\tArgs:
|
|
58
|
+
\t\tinput_path (str): Path to the image to upscale (or a directory).
|
|
59
|
+
\t\toutput_path (str): Path to the output image (or a directory).
|
|
60
|
+
\t\tupscale_ratio (int): Upscaling ratio.
|
|
61
|
+
|
|
62
|
+
\tExample:
|
|
63
|
+
\t\t.. code-block:: python
|
|
64
|
+
|
|
65
|
+
\t\t\t> upscale("folder", "folder", 2)
|
|
66
|
+
\t\t\tTraceback (most recent call last):
|
|
67
|
+
\t\t\t\t...
|
|
68
|
+
\t\t\tAssertionError: Input and output paths cannot be the same, got \'folder\'
|
|
69
|
+
|
|
70
|
+
\t\t\t> upscale("stouputils", "stouputils/output.jpg", 2)
|
|
71
|
+
\t\t\tTraceback (most recent call last):
|
|
72
|
+
\t\t\t\t...
|
|
73
|
+
\t\t\tAssertionError: If input is a directory, output must be a directory too, got \'stouputils/output.jpg\'
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
\t\t\t> upscale("input.jpg", "output.jpg", 2)
|
|
77
|
+
\t\t\t> # The input.jpg will be upscaled to output.jpg with a ratio of 2
|
|
78
|
+
|
|
79
|
+
\t\t\t> upscale("input_folder", "output_folder", 2)
|
|
80
|
+
\t\t\t> # The input_folder will be upscaled to output_folder with a ratio of 2
|
|
81
|
+
\t'''
|
|
82
|
+
def upscale_images(images: list[str], output_folder: str, upscale_ratio: int, desc: str = 'Upscaling images') -> None:
|
|
83
|
+
""" Upscale multiple images from a list.
|
|
84
|
+
|
|
85
|
+
\tArgs:
|
|
86
|
+
\t\timages (list[str]): List of paths to the images to upscale.
|
|
87
|
+
\t\toutput_folder (str): Path to the output folder where the upscaled images will be saved.
|
|
88
|
+
\t\tupscale_ratio (int): Upscaling ratio.
|
|
89
|
+
\t\tdesc (str): Description of the function execution displayed in the progress bar.
|
|
90
|
+
\t\t\tNo progress bar will be displayed if desc is empty.
|
|
91
|
+
|
|
92
|
+
\tReturns:
|
|
93
|
+
\t\tNone: This function doesn't return anything.
|
|
94
|
+
\t"""
|
|
95
|
+
def upscale_folder(input_folder: str, output_folder: str, upscale_ratio: int, slightly_faster_mode: bool = True, desc: str = 'Upscaling folder') -> None:
|
|
96
|
+
""" Upscale all images in a folder.
|
|
97
|
+
|
|
98
|
+
\tArgs:
|
|
99
|
+
\t\tinput_folder (str): Path to the input folder containing the images to upscale.
|
|
100
|
+
\t\toutput_folder (str): Path to the output folder where the upscaled images will be saved.
|
|
101
|
+
\t\tupscale_ratio (int): Upscaling ratio.
|
|
102
|
+
\t\tslightly_faster_mode (bool): Whether to use the slightly faster mode (no progress bar),
|
|
103
|
+
\t\t\tone call to the upscaler executable.
|
|
104
|
+
\t\tdesc (str): Description of the function execution displayed in the progress bar.
|
|
105
|
+
\t\t\tNo progress bar will be displayed if desc is empty.
|
|
106
|
+
|
|
107
|
+
\tReturns:
|
|
108
|
+
\t\tNone: This function doesn't return anything.
|
|
109
|
+
\t"""
|