mirror of
https://github.com/k4yt3x/video2x.git
synced 2026-02-09 06:14:45 +08:00
Compare commits
50 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5eb6514e1 | ||
|
|
3f6a3addaa | ||
|
|
8f2113ab0a | ||
|
|
60cf792c23 | ||
|
|
7e87dac15e | ||
|
|
0b15fb7bd2 | ||
|
|
765db2512b | ||
|
|
e14fbea67b | ||
|
|
491f80d2d2 | ||
|
|
2f4953e6c7 | ||
|
|
3f36cb8b43 | ||
|
|
3e57e206c6 | ||
|
|
da0e47528c | ||
|
|
f6aac30f96 | ||
|
|
7d00189f2f | ||
|
|
751150fe64 | ||
|
|
eb2b62b056 | ||
|
|
cc1b0b5464 | ||
|
|
fe7ded7e53 | ||
|
|
5f2ad35d41 | ||
|
|
d688ca490e | ||
|
|
708c983c1e | ||
|
|
9b91016d98 | ||
|
|
b024581906 | ||
|
|
8fd3292cd6 | ||
|
|
e646825c57 | ||
|
|
fdf326108f | ||
|
|
e26561c56a | ||
|
|
9d7c3963c3 | ||
|
|
ce5d4051e5 | ||
|
|
9f6f1eee5b | ||
|
|
6ae7491652 | ||
|
|
d35472fbfb | ||
|
|
7166afdc0e | ||
|
|
d3db4e8cf1 | ||
|
|
f887dfe3a7 | ||
|
|
a41df138bf | ||
|
|
41833f4068 | ||
|
|
c0955ae7e4 | ||
|
|
682aeb82ff | ||
|
|
21407c831c | ||
|
|
7e34bf7516 | ||
|
|
4c5ca73e38 | ||
|
|
387a233daf | ||
|
|
781eb6686f | ||
|
|
c73edd9001 | ||
|
|
deb742ee8d | ||
|
|
5ef6eb7e8e | ||
|
|
6c5e079a1c | ||
|
|
1e384596ee |
2
.github/workflows/nightly.yml
vendored
2
.github/workflows/nightly.yml
vendored
@@ -1,7 +1,7 @@
|
||||
# Name: Video2X Nightly Build
|
||||
# Creator: K4YT3X
|
||||
# Date Created: May 12, 2020
|
||||
# Last Modified: May 13, 2020
|
||||
# Last Modified: May 28, 2020
|
||||
|
||||
name: Video2X Nightly Build
|
||||
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,3 +1,6 @@
|
||||
# QtCreator
|
||||
video2x_gui.pyproject.user
|
||||
|
||||
# PyCharm
|
||||
.idea/
|
||||
|
||||
|
||||
31
Dockerfile
Normal file
31
Dockerfile
Normal file
@@ -0,0 +1,31 @@
|
||||
# Name: Video2X Dockerfile
|
||||
# Creator: Danielle Douglas
|
||||
# Date Created: Unknown
|
||||
# Last Modified: January 14, 2020
|
||||
|
||||
# Editor: Lhanjian
|
||||
# Last Modified: May 24, 2020
|
||||
|
||||
# Editor: K4YT3X
|
||||
# Last Modified: June 5, 2020
|
||||
|
||||
# using Ubuntu LTS 19.10
|
||||
# Ubuntu 20.x is incompatible with Nvidia libraries
|
||||
FROM ubuntu:19.10
|
||||
|
||||
# file mainainter labels
|
||||
LABEL maintainer="Danielle Douglas <ddouglas87@gmail.com>"
|
||||
LABEL maintainer="Lhanjian <lhjay1@foxmail.com>"
|
||||
LABEL maintainer="K4YT3X <k4yt3x@k4yt3x.com>"
|
||||
|
||||
# run installation
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y git-core \
|
||||
&& git clone --recurse-submodules --progress https://github.com/k4yt3x/video2x.git /tmp/video2x/video2x \
|
||||
&& bash -e /tmp/video2x/video2x/src/video2x_setup_ubuntu.sh /
|
||||
|
||||
WORKDIR /video2x/src
|
||||
ENTRYPOINT ["python3.8", "/video2x/src/video2x.py"]
|
||||
|
||||
ENV NVIDIA_DRIVER_CAPABILITIES all
|
||||
ENV DEBIAN_FRONTEND teletype
|
||||
44
README.md
44
README.md
@@ -4,35 +4,47 @@
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
<img alt="Become a Patron!" src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" href="https://www.patreon.com/bePatron?u=34970782" height=20>
|
||||

|
||||
|
||||
<!--# Video2X Lossless Video Enlarger-->
|
||||
|
||||
### Official Discussion Group (Telegram): https://t.me/video2x
|
||||
|
||||
## [Download Stable/Beta Builds](https://github.com/k4yt3x/video2x/releases) (Windows)
|
||||
## [Download Stable/Beta Builds](https://github.com/k4yt3x/video2x/releases/latest) (Windows)
|
||||
|
||||
- **`Full`**: full package comes pre-configured with **all** dependencies like `FFmpeg` and `waifu2x-caffe`.
|
||||
- **`Light`**: ligt package comes with only Video2X binaries and a template configuration file. The user will either have to run the setup script or install and configure dependencies themselves.
|
||||
|
||||
Go to the **[Quick Start](#quick-start)** section for usages.
|
||||
|
||||
### [Download From Mirror](https://files.k4yt3x.com/Projects/Video2X/)
|
||||
### [Download From Mirror](https://files.k4yt3x.com/Projects/Video2X/latest)
|
||||
|
||||
In case you're unable to download the releases directly from GitHub, you can try downloading from the mirror site hosted by the author. Only releases will be updated in this directory, not nightly builds.
|
||||
|
||||
## [Download Nightly Builds](https://github.com/k4yt3x/video2x/actions) (Windows)
|
||||
|
||||
**You need to be logged into GitHub to be able to download GitHub Actions artifacts.**
|
||||
|
||||
Nightly builds are built automatically every time a new commit is pushed to the master branch. The lates nightly build is always up-to-date with the latest version of the code, but is less stable and may contain bugs. Nightly builds are handled by GitHub's integrated CI/CD tool, GitHub Actions.
|
||||
|
||||
To download the latest nightly build, go to the [GitHub Actions](https://github.com/k4yt3x/video2x/actions) tab, enter the last run of workflow "Video2X Nightly Build, and download the artifacts generated from the run.
|
||||
|
||||
## Introduction
|
||||
|
||||
Video2X is a video/GIF/image upscaling software based on Waifu2X, Anime4K and SRMD written in Python 3. It upscales videos, GIFs and images, restoring details from low-resolution inputs. Video2X also accepts GIF input to video output and video input to GIF output.
|
||||
Video2X is a video/GIF/image upscaling software based on Waifu2X, Anime4K, SRMD and RealSR written in Python 3. It upscales videos, GIFs and images, restoring details from low-resolution inputs. Video2X also accepts GIF input to video output and video input to GIF output.
|
||||
|
||||
Currently, Video2X supports the following drivers (implementations of algorithms).
|
||||
|
||||
- **Waifu2X Caffe**: Caffe implementation of waifu2x
|
||||
- **Waifu2X Converter CPP**: CPP implementation of waifu2x based on OpenCL and OpenCV
|
||||
- **Waifu2X NCNN Vulkan**: NCNN implementation of waifu2x based on Vulkan API
|
||||
- **SRMD NCNN Vulkan**: NCNN implementation of SRMD based on Vulkan API
|
||||
- **RealSR NCNN Vulkan**: NCNN implementation of RealSR based on Vulkan API
|
||||
- **Anime4KCPP**: CPP implementation of Anime4K
|
||||
|
||||
### Video Upscaling
|
||||
|
||||
@@ -170,6 +182,14 @@ To see a help page for driver-specific settings, use `-d` to select the driver a
|
||||
python video2x.py -d waifu2x_caffe -- --help
|
||||
```
|
||||
|
||||
### Running Video2X (Docker)
|
||||
|
||||
Video2X can be deployed via Docker.
|
||||
|
||||
```shell
|
||||
docker pull k4yt3x/video2x
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Documentations
|
||||
@@ -216,6 +236,12 @@ Are you interested in how the idea of Video2X was born? Do you want to know the
|
||||
### -c CONFIG, --config CONFIG
|
||||
video2x config file path
|
||||
|
||||
### --log LOG
|
||||
log file path (default: program_directory\video2x_%Y-%m-%d_%H-%M-%S.log)
|
||||
|
||||
### --nolog
|
||||
disable logging (default: False)
|
||||
|
||||
### -v, --version
|
||||
display version, lawful information and exit
|
||||
|
||||
@@ -230,6 +256,7 @@ Available options are:
|
||||
- waifu2x_converter_cpp
|
||||
- waifu2x_ncnn_vulkan
|
||||
- srmd_ncnn_vulkan
|
||||
- realsr_ncnn_vulkan
|
||||
- anime4kcpp
|
||||
|
||||
### -r RATIO, --ratio RATIO
|
||||
@@ -261,16 +288,19 @@ This project relies on the following software and projects.
|
||||
- [waifu2x-converter-cpp](https://github.com/DeadSix27/waifu2x-converter-cpp)
|
||||
- [waifu2x-ncnn-vulkan](https://github.com/nihui/waifu2x-ncnn-vulkan)
|
||||
- [srmd-ncnn-vulkan](https://github.com/nihui/srmd-ncnn-vulkan)
|
||||
- [realsr-ncnn-vulkan](https://github.com/nihui/realsr-ncnn-vulkan)
|
||||
- [Anime4K](https://github.com/bloc97/Anime4K)
|
||||
- [Anime4KCPP](https://github.com/TianZerL/Anime4KCPP)
|
||||
- [Gifski](https://github.com/ImageOptim/gifski)
|
||||
|
||||
## Special Thanks
|
||||
|
||||
Appreciations given to the following code contributors:
|
||||
Appreciations given to the following personnel who have contributed significantly to the project (specifically the technical perspective).
|
||||
|
||||
- @BrianPetkovsek
|
||||
- @SAT3LL
|
||||
- [@BrianPetkovsek](https://github.com/BrianPetkovsek)
|
||||
- [@sat3ll](https://github.com/sat3ll)
|
||||
- [@ddouglas87](https://github.com/ddouglas87)
|
||||
- [@lhanjian](https://github.com/lhanjian)
|
||||
|
||||
## Related Projects
|
||||
|
||||
|
||||
46
src/bilogger.py
Executable file
46
src/bilogger.py
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Creator: Video2X Bidirectional Logger
|
||||
Author: K4YT3X
|
||||
Date Created: June 4, 2020
|
||||
Last Modified: June 4, 2020
|
||||
"""
|
||||
|
||||
# built-in imports
|
||||
import _io
|
||||
import pathlib
|
||||
|
||||
|
||||
class BiLogger(object):
|
||||
""" A bidirectional logger that both prints the output
|
||||
and log all output to file.
|
||||
|
||||
Original code from: https://stackoverflow.com/a/14906787
|
||||
"""
|
||||
|
||||
def __init__(self, terminal: _io.TextIOWrapper, logfile: pathlib.Path):
|
||||
""" initialize BiLogger
|
||||
|
||||
Args:
|
||||
terminal (_io.TextIOWrapper): original terminal IO wrapper
|
||||
logfile (pathlib.Path): target log file path object
|
||||
"""
|
||||
self.terminal = terminal
|
||||
self.log = logfile.open(mode='a+')
|
||||
|
||||
def write(self, message: str):
|
||||
""" write message to original terminal output and log file
|
||||
|
||||
Args:
|
||||
message (str): message to write
|
||||
"""
|
||||
self.terminal.write(message)
|
||||
self.terminal.flush()
|
||||
self.log.write(message)
|
||||
self.log.flush()
|
||||
|
||||
def flush(self):
|
||||
""" flush logger (for compability only)
|
||||
"""
|
||||
pass
|
||||
2
src/build.ps1
Normal file → Executable file
2
src/build.ps1
Normal file → Executable file
@@ -9,7 +9,7 @@ executable (PE) releases automatically using PyInstaller.
|
||||
This script is currently only tuned for K4YT3X's environment.
|
||||
|
||||
To start a PowerShell session with execution policy bypass
|
||||
powershell –ExecutionPolicy Bypass
|
||||
powershell -ExecutionPolicy Bypass
|
||||
#>
|
||||
|
||||
if ($args.count -ne 1){
|
||||
|
||||
8
src/progress_monitor.py
Normal file → Executable file
8
src/progress_monitor.py
Normal file → Executable file
@@ -2,9 +2,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Name: Video2X Upscale Progress Monitor
|
||||
Author: BrianPetkovsek
|
||||
Author: K4YT3X
|
||||
Date Created: May 7, 2020
|
||||
Last Modified: May 10, 2020
|
||||
Last Modified: June 7, 2020
|
||||
"""
|
||||
|
||||
# built-in imports
|
||||
@@ -37,7 +37,7 @@ class ProgressMonitor(threading.Thread):
|
||||
# get number of extracted frames
|
||||
self.upscaler.total_frames = 0
|
||||
for directory in self.extracted_frames_directories:
|
||||
self.upscaler.total_frames += len([f for f in directory.iterdir() if str(f).lower().endswith(self.upscaler.image_format.lower())])
|
||||
self.upscaler.total_frames += len([f for f in directory.iterdir() if str(f).lower().endswith(self.upscaler.extracted_frame_format.lower())])
|
||||
|
||||
with tqdm(total=self.upscaler.total_frames, ascii=True, desc=_('Upscaling Progress')) as progress_bar:
|
||||
# tqdm update method adds the value to the progress
|
||||
@@ -47,7 +47,7 @@ class ProgressMonitor(threading.Thread):
|
||||
while self.running:
|
||||
|
||||
with contextlib.suppress(FileNotFoundError):
|
||||
upscaled_frames = [f for f in self.upscaler.upscaled_frames.iterdir() if str(f).lower().endswith(self.upscaler.image_format.lower())]
|
||||
upscaled_frames = [f for f in self.upscaler.upscaled_frames.iterdir() if str(f).lower().endswith(self.upscaler.extracted_frame_format.lower())]
|
||||
if len(upscaled_frames) >= 1:
|
||||
self.upscaler.last_frame_upscaled = sorted(upscaled_frames)[-1]
|
||||
self.upscaler.total_frames_upscaled = len(upscaled_frames)
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
avalon_framework
|
||||
colorama
|
||||
patool
|
||||
psutil
|
||||
pyqt5
|
||||
python-magic
|
||||
python-magic-bin
|
||||
pyunpack
|
||||
python-magic; platform_system != "Windows"
|
||||
python-magic-bin; platform_system == "Windows"
|
||||
pyyaml
|
||||
requests
|
||||
tqdm
|
||||
182
src/upscaler.py
182
src/upscaler.py
@@ -4,7 +4,7 @@
|
||||
Name: Video2X Upscaler
|
||||
Author: K4YT3X
|
||||
Date Created: December 10, 2018
|
||||
Last Modified: May 22, 2020
|
||||
Last Modified: June 8, 2020
|
||||
|
||||
Description: This file contains the Upscaler class. Each
|
||||
instance of the Upscaler class is an upscaler on an image or
|
||||
@@ -50,7 +50,7 @@ language.install()
|
||||
_ = language.gettext
|
||||
|
||||
# version information
|
||||
UPSCALER_VERSION = '4.1.1'
|
||||
UPSCALER_VERSION = '4.2.2'
|
||||
|
||||
# these names are consistent for
|
||||
# - driver selection in command line
|
||||
@@ -60,6 +60,7 @@ AVAILABLE_DRIVERS = ['waifu2x_caffe',
|
||||
'waifu2x_converter_cpp',
|
||||
'waifu2x_ncnn_vulkan',
|
||||
'srmd_ncnn_vulkan',
|
||||
'realsr_ncnn_vulkan',
|
||||
'anime4kcpp']
|
||||
|
||||
|
||||
@@ -72,21 +73,39 @@ class Upscaler:
|
||||
ArgumentError -- if argument is not valid
|
||||
"""
|
||||
|
||||
def __init__(self, input_path, output_path, driver_settings, ffmpeg_settings, gifski_settings):
|
||||
# mandatory arguments
|
||||
def __init__(
|
||||
self,
|
||||
input_path: pathlib.Path or list,
|
||||
output_path: pathlib.Path,
|
||||
driver_settings: dict,
|
||||
ffmpeg_settings: dict,
|
||||
gifski_settings: dict,
|
||||
driver: str = 'waifu2x_caffe',
|
||||
scale_ratio: float = None,
|
||||
processes: int = 1,
|
||||
video2x_cache_directory: pathlib.Path = pathlib.Path(tempfile.gettempdir()) / 'video2x',
|
||||
extracted_frame_format: str = 'png',
|
||||
image_output_extension: str = '.png',
|
||||
video_output_extension: str = '.mp4',
|
||||
preserve_frames: bool = False
|
||||
):
|
||||
|
||||
# required parameters
|
||||
self.input = input_path
|
||||
self.output = output_path
|
||||
self.driver_settings = driver_settings
|
||||
self.ffmpeg_settings = ffmpeg_settings
|
||||
self.gifski_settings = gifski_settings
|
||||
|
||||
# optional arguments
|
||||
self.driver = 'waifu2x_caffe'
|
||||
self.scale_ratio = None
|
||||
self.processes = 1
|
||||
self.video2x_cache_directory = pathlib.Path(tempfile.gettempdir()) / 'video2x'
|
||||
self.image_format = 'png'
|
||||
self.preserve_frames = False
|
||||
# optional parameters
|
||||
self.driver = driver
|
||||
self.scale_ratio = scale_ratio
|
||||
self.processes = processes
|
||||
self.video2x_cache_directory = video2x_cache_directory
|
||||
self.extracted_frame_format = extracted_frame_format
|
||||
self.image_output_extension = image_output_extension
|
||||
self.video_output_extension = video_output_extension
|
||||
self.preserve_frames = preserve_frames
|
||||
|
||||
# other internal members and signals
|
||||
self.running = False
|
||||
@@ -233,7 +252,7 @@ class Upscaler:
|
||||
if self.driver == 'waifu2x_caffe':
|
||||
if (driver_settings['scale_width'] != 0 and driver_settings['scale_height'] == 0 or
|
||||
driver_settings['scale_width'] == 0 and driver_settings['scale_height'] != 0):
|
||||
Avalon.error('Only one of scale_width and scale_height is specified for waifu2x-caffe')
|
||||
Avalon.error(_('Only one of scale_width and scale_height is specified for waifu2x-caffe'))
|
||||
raise AttributeError('only one of scale_width and scale_height is specified for waifu2x-caffe')
|
||||
|
||||
# if scale_width and scale_height are specified, ensure scale_ratio is None
|
||||
@@ -281,7 +300,7 @@ class Upscaler:
|
||||
process_directory.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# waifu2x-converter-cpp will perform multi-threading within its own process
|
||||
if self.driver in ['waifu2x_converter_cpp', 'waifu2x_ncnn_vulkan', 'srmd_ncnn_vulkan']:
|
||||
if self.driver in ['waifu2x_converter_cpp', 'waifu2x_ncnn_vulkan', 'srmd_ncnn_vulkan', 'realsr_ncnn_vulkan', 'anime4kcpp']:
|
||||
process_directories = [self.extracted_frames]
|
||||
|
||||
else:
|
||||
@@ -323,8 +342,8 @@ class Upscaler:
|
||||
# images need to be renamed to be recognizable for FFmpeg
|
||||
if self.driver == 'waifu2x_converter_cpp':
|
||||
for image in [f for f in self.upscaled_frames.iterdir() if f.is_file()]:
|
||||
renamed = re.sub(f'_\\[.*\\]\\[x(\\d+(\\.\\d+)?)\\]\\.{self.image_format}',
|
||||
f'.{self.image_format}',
|
||||
renamed = re.sub(f'_\\[.*\\]\\[x(\\d+(\\.\\d+)?)\\]\\.{self.extracted_frame_format}',
|
||||
f'.{self.extracted_frame_format}',
|
||||
str(image.name))
|
||||
(self.upscaled_frames / image).rename(self.upscaled_frames / renamed)
|
||||
|
||||
@@ -402,49 +421,93 @@ class Upscaler:
|
||||
self.driver_object.load_configurations(self)
|
||||
|
||||
# initialize FFmpeg object
|
||||
self.ffmpeg_object = Ffmpeg(self.ffmpeg_settings, image_format=self.image_format)
|
||||
self.ffmpeg_object = Ffmpeg(self.ffmpeg_settings, extracted_frame_format=self.extracted_frame_format)
|
||||
|
||||
# define processing queue
|
||||
self.processing_queue = queue.Queue()
|
||||
|
||||
Avalon.info(_('Loading files into processing queue'))
|
||||
Avalon.debug_info(_('Input path(s): {}').format(self.input))
|
||||
|
||||
# if input is a list of files
|
||||
if isinstance(self.input, list):
|
||||
|
||||
Avalon.info(_('Loading files from multiple paths'))
|
||||
Avalon.debug_info(_('Input path(s): {}').format(self.input))
|
||||
|
||||
# make output directory if it doesn't exist
|
||||
# make output directory if the input is a list or a directory
|
||||
if isinstance(self.input, list) or self.input.is_dir():
|
||||
self.output.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
for input_path in self.input:
|
||||
input_files = []
|
||||
|
||||
if input_path.is_file():
|
||||
output_path = self.output / input_path.name
|
||||
self.processing_queue.put((input_path.absolute(), output_path.absolute()))
|
||||
# if input is single directory
|
||||
# put it in a list for compability with the following code
|
||||
if not isinstance(self.input, list):
|
||||
input_paths = [self.input]
|
||||
else:
|
||||
input_paths = self.input
|
||||
|
||||
elif input_path.is_dir():
|
||||
for input_path in [f for f in input_path.iterdir() if f.is_file()]:
|
||||
output_path = self.output / input_path.name
|
||||
self.processing_queue.put((input_path.absolute(), output_path.absolute()))
|
||||
# flatten directories into file paths
|
||||
for input_path in input_paths:
|
||||
|
||||
# if input specified is single file
|
||||
elif self.input.is_file():
|
||||
Avalon.info(_('Loading single file'))
|
||||
Avalon.debug_info(_('Input path(s): {}').format(self.input))
|
||||
self.processing_queue.put((self.input.absolute(), self.output.absolute()))
|
||||
# if the input path is a single file
|
||||
# add the file's path object to input_files
|
||||
if input_path.is_file():
|
||||
input_files.append(input_path)
|
||||
|
||||
# if input specified is a directory
|
||||
elif self.input.is_dir():
|
||||
# if the input path is a directory
|
||||
# add all files under the directory into the input_files (non-recursive)
|
||||
elif input_path.is_dir():
|
||||
input_files.extend([f for f in input_path.iterdir() if f.is_file()])
|
||||
|
||||
Avalon.info(_('Loading files from directory'))
|
||||
Avalon.debug_info(_('Input path(s): {}').format(self.input))
|
||||
# make output directory if it doesn't exist
|
||||
self.output.mkdir(parents=True, exist_ok=True)
|
||||
for input_path in [f for f in self.input.iterdir() if f.is_file()]:
|
||||
output_path = self.output / input_path.name
|
||||
self.processing_queue.put((input_path.absolute(), output_path.absolute()))
|
||||
output_paths = []
|
||||
|
||||
for input_path in input_files:
|
||||
|
||||
# get file type
|
||||
# try python-magic if it's available
|
||||
try:
|
||||
input_file_mime_type = magic.from_file(str(input_path.absolute()), mime=True)
|
||||
input_file_type = input_file_mime_type.split('/')[0]
|
||||
input_file_subtype = input_file_mime_type.split('/')[1]
|
||||
except Exception:
|
||||
input_file_type = input_file_subtype = None
|
||||
|
||||
# in case python-magic fails to detect file type
|
||||
# try guessing file mime type with mimetypes
|
||||
if input_file_type not in ['image', 'video']:
|
||||
input_file_mime_type = mimetypes.guess_type(input_path.name)[0]
|
||||
input_file_type = input_file_mime_type.split('/')[0]
|
||||
input_file_subtype = input_file_mime_type.split('/')[1]
|
||||
|
||||
# set default output file suffixes
|
||||
# if image type is GIF, default output suffix is also .gif
|
||||
if input_file_mime_type == 'image/gif':
|
||||
output_path = self.output / (input_path.stem + '.gif')
|
||||
|
||||
elif input_file_type == 'image':
|
||||
output_path = self.output / (input_path.stem + self.image_output_extension)
|
||||
|
||||
elif input_file_type == 'video':
|
||||
output_path = self.output / (input_path.stem + self.video_output_extension)
|
||||
|
||||
# if file is none of: image, image/gif, video
|
||||
# skip to the next task
|
||||
else:
|
||||
Avalon.error(_('File {} ({}) neither an image nor a video').format(input_path, input_file_mime_type))
|
||||
Avalon.warning(_('Skipping this file'))
|
||||
continue
|
||||
|
||||
# if there is only one input file
|
||||
# do not modify output file suffix
|
||||
if isinstance(self.input, pathlib.Path) and self.input.is_file():
|
||||
output_path = self.output
|
||||
|
||||
output_path_id = 0
|
||||
while str(output_path) in output_paths:
|
||||
output_path = output_path.parent / pathlib.Path(f'{output_path.stem}_{output_path_id}{output_path.suffix}')
|
||||
output_path_id += 1
|
||||
|
||||
# record output path
|
||||
output_paths.append(str(output_path))
|
||||
|
||||
# push file information into processing queue
|
||||
self.processing_queue.put((input_path.absolute(), output_path.absolute(), input_file_mime_type, input_file_type, input_file_subtype))
|
||||
|
||||
# check argument sanity before running
|
||||
self._check_arguments()
|
||||
@@ -460,24 +523,8 @@ class Upscaler:
|
||||
try:
|
||||
while not self.processing_queue.empty():
|
||||
|
||||
# reset current processing progress for new job
|
||||
self.total_frames_upscaled = 0
|
||||
self.total_frames = 0
|
||||
|
||||
# get new job from queue
|
||||
self.current_input_file, output_path = self.processing_queue.get()
|
||||
|
||||
# get file type
|
||||
input_file_mime_type = magic.from_file(str(self.current_input_file.absolute()), mime=True)
|
||||
input_file_type = input_file_mime_type.split('/')[0]
|
||||
input_file_subtype = input_file_mime_type.split('/')[1]
|
||||
|
||||
# in case python-magic fails to detect file type
|
||||
# try guessing file mime type with mimetypes
|
||||
if input_file_type not in ['image', 'video']:
|
||||
input_file_mime_type = mimetypes.guess_type(self.current_input_file.name)[0]
|
||||
input_file_type = input_file_mime_type.split('/')[0]
|
||||
input_file_subtype = input_file_mime_type.split('/')[1]
|
||||
self.current_input_file, output_path, input_file_mime_type, input_file_type, input_file_subtype = self.processing_queue.get()
|
||||
|
||||
# start handling input
|
||||
# if input file is a static image
|
||||
@@ -549,15 +596,6 @@ class Upscaler:
|
||||
self._upscale_frames()
|
||||
Avalon.info(_('Upscaling completed'))
|
||||
|
||||
# if file is none of: image, image/gif, video
|
||||
# skip to the next task
|
||||
else:
|
||||
Avalon.error(_('File {} ({}) neither an image nor a video').format(self.current_input_file, input_file_mime_type))
|
||||
Avalon.warning(_('Skipping this file'))
|
||||
self.processing_queue.task_done()
|
||||
self.total_processed += 1
|
||||
continue
|
||||
|
||||
# start handling output
|
||||
# output can be either GIF or video
|
||||
|
||||
@@ -565,7 +603,7 @@ class Upscaler:
|
||||
if output_path.suffix.lower() == '.gif':
|
||||
Avalon.info(_('Converting extracted frames into GIF image'))
|
||||
gifski_object = Gifski(self.gifski_settings)
|
||||
self.process_pool.append(gifski_object.make_gif(self.upscaled_frames, output_path, framerate, self.image_format))
|
||||
self.process_pool.append(gifski_object.make_gif(self.upscaled_frames, output_path, framerate, self.extracted_frame_format))
|
||||
self._wait()
|
||||
Avalon.info(_('Conversion completed'))
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ __ __ _ _ ___ __ __
|
||||
Name: Video2X Controller
|
||||
Creator: K4YT3X
|
||||
Date Created: Feb 24, 2018
|
||||
Last Modified: May 23, 2020
|
||||
Last Modified: June 8, 2020
|
||||
|
||||
Editor: BrianPetkovsek
|
||||
Last Modified: June 17, 2019
|
||||
@@ -49,12 +49,14 @@ smooth and edges sharp.
|
||||
"""
|
||||
|
||||
# local imports
|
||||
from bilogger import BiLogger
|
||||
from upscaler import AVAILABLE_DRIVERS
|
||||
from upscaler import UPSCALER_VERSION
|
||||
from upscaler import Upscaler
|
||||
|
||||
# built-in imports
|
||||
import argparse
|
||||
import datetime
|
||||
import gettext
|
||||
import importlib
|
||||
import locale
|
||||
@@ -79,8 +81,7 @@ language = gettext.translation(DOMAIN, LOCALE_DIRECTORY, [default_locale], fallb
|
||||
language.install()
|
||||
_ = language.gettext
|
||||
|
||||
|
||||
CLI_VERSION = '4.0.1'
|
||||
CLI_VERSION = '4.1.1'
|
||||
|
||||
LEGAL_INFO = _('''Video2X CLI Version: {}
|
||||
Upscaler Version: {}
|
||||
@@ -118,6 +119,9 @@ def parse_arguments():
|
||||
|
||||
video2x_options.add_argument('-c', '--config', type=pathlib.Path, help=_('video2x config file path'), action='store',
|
||||
default=pathlib.Path(__file__).parent.absolute() / 'video2x.yaml')
|
||||
video2x_options.add_argument('--log', type=pathlib.Path, help=_('log file path'),
|
||||
default=pathlib.Path(__file__).parent.absolute() / f'video2x_{datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}.log')
|
||||
video2x_options.add_argument('--disable_logging', help=_('disable logging'), action='store_true')
|
||||
video2x_options.add_argument('-v', '--version', help=_('display version, lawful information and exit'), action='store_true')
|
||||
|
||||
# scaling options
|
||||
@@ -179,6 +183,13 @@ if video2x_args.version:
|
||||
print(LEGAL_INFO)
|
||||
sys.exit(0)
|
||||
|
||||
# redirect output to both terminal and log file
|
||||
if video2x_args.disable_logging is False:
|
||||
LOGFILE = video2x_args.log
|
||||
Avalon.debug_info(_('Redirecting console logs to {}').format(LOGFILE))
|
||||
sys.stdout = BiLogger(sys.stdout, LOGFILE)
|
||||
sys.stderr = BiLogger(sys.stderr, LOGFILE)
|
||||
|
||||
# read configurations from configuration file
|
||||
config = read_config(video2x_args.config)
|
||||
|
||||
@@ -195,7 +206,9 @@ gifski_settings = config['gifski']
|
||||
gifski_settings['gifski_path'] = os.path.expandvars(gifski_settings['gifski_path'])
|
||||
|
||||
# load video2x settings
|
||||
image_format = config['video2x']['image_format'].lower()
|
||||
extracted_frame_format = config['video2x']['extracted_frame_format'].lower()
|
||||
image_output_extension = config['video2x']['image_output_extension']
|
||||
video_output_extension = config['video2x']['video_output_extension']
|
||||
preserve_frames = config['video2x']['preserve_frames']
|
||||
|
||||
# if preserve frames specified in command line
|
||||
@@ -223,19 +236,24 @@ try:
|
||||
begin_time = time.time()
|
||||
|
||||
# initialize upscaler object
|
||||
upscaler = Upscaler(input_path=video2x_args.input,
|
||||
output_path=video2x_args.output,
|
||||
driver_settings=driver_settings,
|
||||
ffmpeg_settings=ffmpeg_settings,
|
||||
gifski_settings=gifski_settings)
|
||||
upscaler = Upscaler(
|
||||
# required parameters
|
||||
input_path=video2x_args.input,
|
||||
output_path=video2x_args.output,
|
||||
driver_settings=driver_settings,
|
||||
ffmpeg_settings=ffmpeg_settings,
|
||||
gifski_settings=gifski_settings,
|
||||
|
||||
# set upscaler optional options
|
||||
upscaler.driver = video2x_args.driver
|
||||
upscaler.scale_ratio = video2x_args.ratio
|
||||
upscaler.processes = video2x_args.processes
|
||||
upscaler.video2x_cache_directory = video2x_cache_directory
|
||||
upscaler.image_format = image_format
|
||||
upscaler.preserve_frames = preserve_frames
|
||||
# optional parameters
|
||||
driver=video2x_args.driver,
|
||||
scale_ratio=video2x_args.ratio,
|
||||
processes=video2x_args.processes,
|
||||
video2x_cache_directory=video2x_cache_directory,
|
||||
extracted_frame_format=extracted_frame_format,
|
||||
image_output_extension=image_output_extension,
|
||||
video_output_extension=video_output_extension,
|
||||
preserve_frames=preserve_frames
|
||||
)
|
||||
|
||||
# run upscaler
|
||||
upscaler.run()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Name: Video2X Configuration File
|
||||
# Creator: K4YT3X
|
||||
# Date Created: October 23, 2018
|
||||
# Last Modified: May 23, 2020
|
||||
# Last Modified: June 7, 2020
|
||||
# Values here are the default values. Change the value here to
|
||||
# save the default value permanently.
|
||||
# Items commented out are parameters irrelevant to this context
|
||||
@@ -76,6 +76,17 @@ srmd_ncnn_vulkan:
|
||||
g: 0 # gpu device to use (default=0)
|
||||
j: '1:2:2' # thread count for load/proc/save (default=1:2:2)
|
||||
x: false # enable tta mode
|
||||
realsr_ncnn_vulkan:
|
||||
path: '%LOCALAPPDATA%\video2x\realsr-ncnn-vulkan\realsr-ncnn-vulkan'
|
||||
v: null # verbose output
|
||||
#i: null # input-path: input image path (jpg/png) or directory
|
||||
#o: null # output-path: output image path (png) or directory
|
||||
s: 4 # upscale ratio (4, default=4)
|
||||
t: 0 # tile size (>=32/0=auto, default=0)
|
||||
m: null # realsr model path (default=models-DF2K)
|
||||
g: 0 # gpu device to use (default=0)
|
||||
j: '1:2:2' # thread count for load/proc/save (default=1:2:2)
|
||||
x: false # enable tta mode
|
||||
anime4kcpp:
|
||||
path: '%LOCALAPPDATA%\video2x\anime4kcpp\CLI\Anime4KCPP_CLI\Anime4KCPP_CLI'
|
||||
#input: null # File for loading (string [=./pic/p1.png])
|
||||
@@ -89,11 +100,12 @@ anime4kcpp:
|
||||
fastMode: false # Faster but maybe low quality
|
||||
videoMode: false # Video process
|
||||
preview: null # Preview image
|
||||
preprocessing: False # Enable pre processing
|
||||
postprocessing: False # Enable post processing
|
||||
preprocessing: false # Enable pre processing
|
||||
postprocessing: false # Enable post processing
|
||||
preFilters: 4 # Enhancement filter, only working when preProcessing is true,there are 5 options by binary:Median blur=0000001, Mean blur=0000010, CAS Sharpening=0000100, Gaussian blur weak=0001000, Gaussian blur=0010000, Bilateral filter=0100000, Bilateral filter faster=1000000, you can freely combine them, eg: Gaussian blur weak + Bilateral filter = 0001000 | 0100000 = 0101000 = 40(D) (unsigned int [=4])
|
||||
postFilters: 40 # Enhancement filter, only working when postProcessing is true,there are 5 options by binary:Median blur=0000001, Mean blur=0000010, CAS Sharpening=0000100, Gaussian blur weak=0001000, Gaussian blur=0010000, Bilateral filter=0100000, Bilateral filter faster=1000000, you can freely combine them, eg: Gaussian blur weak + Bilateral filter = 0001000 | 0100000 = 0101000 = 40(D), so you can put 40 to enable Gaussian blur weak and Bilateral filter, which also is what I recommend for image that < 1080P, 48 for image that >= 1080P, and for performance I recommend to use 72 for video that < 1080P, 80 for video that >=1080P (unsigned int [=40])
|
||||
GPUMode: False # Enable GPU acceleration
|
||||
GPUMode: false # Enable GPU acceleration
|
||||
CNNMode: false # Enable ACNet
|
||||
listGPUs: null # list GPUs
|
||||
platformID: 0 # Specify the platform ID (unsigned int [=0])
|
||||
deviceID: 0 # Specify the device ID (unsigned int [=0])
|
||||
@@ -156,6 +168,8 @@ gifski:
|
||||
nosort: false # Use files exactly in the order given, rather than sorted
|
||||
quiet: false # Do not show a progress bar
|
||||
video2x:
|
||||
video2x_cache_directory: null # default: %TEMP%\video2x
|
||||
image_format: png
|
||||
preserve_frames: false
|
||||
video2x_cache_directory: null # default: %TEMP%\video2x, directory where cache files are stored, will be deleted if preserve_frames is not set to true
|
||||
extracted_frame_format: png # png/jpg intermediate file format used for extracted frames during video processing
|
||||
image_output_extension: .png # image output extension during batch processing
|
||||
video_output_extension: .mp4 # video output extension during batch processing
|
||||
preserve_frames: false # if set to true, the cache directory won't be cleaned upon task completion
|
||||
|
||||
@@ -4,16 +4,18 @@
|
||||
Creator: Video2X GUI
|
||||
Author: K4YT3X
|
||||
Date Created: May 5, 2020
|
||||
Last Modified: May 23, 2020
|
||||
Last Modified: June 8, 2020
|
||||
"""
|
||||
|
||||
# local imports
|
||||
from bilogger import BiLogger
|
||||
from upscaler import UPSCALER_VERSION
|
||||
from upscaler import Upscaler
|
||||
from wrappers.ffmpeg import Ffmpeg
|
||||
|
||||
# built-in imports
|
||||
import contextlib
|
||||
import datetime
|
||||
import json
|
||||
import mimetypes
|
||||
import os
|
||||
@@ -32,7 +34,7 @@ from PyQt5.QtGui import *
|
||||
from PyQt5.QtWidgets import *
|
||||
import magic
|
||||
|
||||
GUI_VERSION = '2.4.0'
|
||||
GUI_VERSION = '2.7.1'
|
||||
|
||||
LEGAL_INFO = f'''Video2X GUI Version: {GUI_VERSION}\\
|
||||
Upscaler Version: {UPSCALER_VERSION}\\
|
||||
@@ -46,6 +48,7 @@ AVAILABLE_DRIVERS = {
|
||||
'Waifu2X Converter CPP': 'waifu2x_converter_cpp',
|
||||
'Waifu2X NCNN Vulkan': 'waifu2x_ncnn_vulkan',
|
||||
'SRMD NCNN Vulkan': 'srmd_ncnn_vulkan',
|
||||
'RealSR NCNN Vulkan': 'realsr_ncnn_vulkan',
|
||||
'Anime4KCPP': 'anime4kcpp'
|
||||
}
|
||||
|
||||
@@ -130,9 +133,12 @@ class InputTableModel(QAbstractTableModel):
|
||||
# if path is single file
|
||||
# determine file type
|
||||
elif file_path.is_file():
|
||||
input_file_mime_type = magic.from_file(str(file_path.absolute()), mime=True)
|
||||
input_file_type = input_file_mime_type.split('/')[0]
|
||||
input_file_subtype = input_file_mime_type.split('/')[1]
|
||||
try:
|
||||
input_file_mime_type = magic.from_file(str(file_path.absolute()), mime=True)
|
||||
input_file_type = input_file_mime_type.split('/')[0]
|
||||
input_file_subtype = input_file_mime_type.split('/')[1]
|
||||
except Exception:
|
||||
input_file_type = input_file_subtype = None
|
||||
|
||||
# in case python-magic fails to detect file type
|
||||
# try guessing file mime type with mimetypes
|
||||
@@ -186,6 +192,9 @@ class Video2XMainWindow(QMainWindow):
|
||||
super().__init__(*args, **kwargs)
|
||||
uic.loadUi(str(resource_path('video2x_gui.ui')), self)
|
||||
|
||||
# generate log file name
|
||||
self.logfile = pathlib.Path(__file__).parent.absolute() / f'video2x_{datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}.log'
|
||||
|
||||
# create thread pool for upscaler workers
|
||||
self.threadpool = QThreadPool()
|
||||
|
||||
@@ -248,7 +257,12 @@ class Video2XMainWindow(QMainWindow):
|
||||
# config file
|
||||
self.config_line_edit = self.findChild(QLineEdit, 'configLineEdit')
|
||||
self.enable_line_edit_file_drop(self.config_line_edit)
|
||||
self.config_line_edit.setText(str((pathlib.Path(__file__).parent / 'video2x.yaml').absolute()))
|
||||
|
||||
if getattr(sys, 'frozen', False):
|
||||
self.config_line_edit.setText(str((pathlib.Path(sys.executable).parent / 'video2x.yaml').absolute()))
|
||||
elif __file__:
|
||||
self.config_line_edit.setText(str((pathlib.Path(__file__).parent / 'video2x.yaml').absolute()))
|
||||
|
||||
self.config_select_file_button = self.findChild(QPushButton, 'configSelectButton')
|
||||
self.config_select_file_button.clicked.connect(self.select_config_file)
|
||||
|
||||
@@ -263,7 +277,10 @@ class Video2XMainWindow(QMainWindow):
|
||||
self.driver_combo_box.currentTextChanged.connect(self.update_gui_for_driver)
|
||||
self.processes_spin_box = self.findChild(QSpinBox, 'processesSpinBox')
|
||||
self.scale_ratio_double_spin_box = self.findChild(QDoubleSpinBox, 'scaleRatioDoubleSpinBox')
|
||||
self.image_output_extension_line_edit = self.findChild(QLineEdit, 'imageOutputExtensionLineEdit')
|
||||
self.video_output_extension_line_edit = self.findChild(QLineEdit, 'videoOutputExtensionLineEdit')
|
||||
self.preserve_frames_check_box = self.findChild(QCheckBox, 'preserveFramesCheckBox')
|
||||
self.disable_logging_check_box = self.findChild(QCheckBox, 'disableLoggingCheckBox')
|
||||
|
||||
# frame preview
|
||||
self.frame_preview_show_preview_check_box = self.findChild(QCheckBox, 'framePreviewShowPreviewCheckBox')
|
||||
@@ -346,6 +363,17 @@ class Video2XMainWindow(QMainWindow):
|
||||
self.srmd_ncnn_vulkan_jobs_line_edit = self.findChild(QLineEdit, 'srmdNcnnVulkanJobsLineEdit')
|
||||
self.srmd_ncnn_vulkan_tta_check_box = self.findChild(QCheckBox, 'srmdNcnnVulkanTtaCheckBox')
|
||||
|
||||
# realsr-ncnn-vulkan
|
||||
self.realsr_ncnn_vulkan_path_line_edit = self.findChild(QLineEdit, 'realsrNcnnVulkanPathLineEdit')
|
||||
self.enable_line_edit_file_drop(self.realsr_ncnn_vulkan_path_line_edit)
|
||||
self.realsr_ncnn_vulkan_path_select_button = self.findChild(QPushButton, 'realsrNcnnVulkanPathSelectButton')
|
||||
self.realsr_ncnn_vulkan_path_select_button.clicked.connect(lambda: self.select_driver_binary_path(self.realsr_ncnn_vulkan_path_line_edit))
|
||||
self.realsr_ncnn_vulkan_tile_size_spin_box = self.findChild(QSpinBox, 'realsrNcnnVulkanTileSizeSpinBox')
|
||||
self.realsr_ncnn_vulkan_model_combo_box = self.findChild(QComboBox, 'realsrNcnnVulkanModelComboBox')
|
||||
self.realsr_ncnn_vulkan_gpu_id_spin_box = self.findChild(QSpinBox, 'realsrNcnnVulkanGpuIdSpinBox')
|
||||
self.realsr_ncnn_vulkan_jobs_line_edit = self.findChild(QLineEdit, 'realsrNcnnVulkanJobsLineEdit')
|
||||
self.realsr_ncnn_vulkan_tta_check_box = self.findChild(QCheckBox, 'realsrNcnnVulkanTtaCheckBox')
|
||||
|
||||
# anime4k
|
||||
self.anime4kcpp_path_line_edit = self.findChild(QLineEdit, 'anime4kCppPathLineEdit')
|
||||
self.enable_line_edit_file_drop(self.anime4kcpp_path_line_edit)
|
||||
@@ -365,6 +393,7 @@ class Video2XMainWindow(QMainWindow):
|
||||
self.anime4kcpp_pre_processing_check_box = self.findChild(QCheckBox, 'anime4kCppPreProcessingCheckBox')
|
||||
self.anime4kcpp_post_processing_check_box = self.findChild(QCheckBox, 'anime4kCppPostProcessingCheckBox')
|
||||
self.anime4kcpp_gpu_mode_check_box = self.findChild(QCheckBox, 'anime4kCppGpuModeCheckBox')
|
||||
self.anime4kcpp_cnn_mode_check_box = self.findChild(QCheckBox, 'anime4kCppCnnModeCheckBox')
|
||||
|
||||
# FFmpeg settings
|
||||
# global options
|
||||
@@ -446,6 +475,9 @@ class Video2XMainWindow(QMainWindow):
|
||||
self.config['video2x']['video2x_cache_directory'] = str((pathlib.Path(tempfile.gettempdir()) / 'video2x').absolute())
|
||||
self.cache_line_edit.setText(self.config['video2x']['video2x_cache_directory'])
|
||||
|
||||
self.image_output_extension_line_edit.setText(self.config['video2x']['image_output_extension'])
|
||||
self.video_output_extension_line_edit.setText(self.config['video2x']['video_output_extension'])
|
||||
|
||||
# load preserve frames settings
|
||||
self.preserve_frames_check_box.setChecked(self.config['video2x']['preserve_frames'])
|
||||
self.start_button.setEnabled(True)
|
||||
@@ -497,6 +529,14 @@ class Video2XMainWindow(QMainWindow):
|
||||
self.srmd_ncnn_vulkan_jobs_line_edit.setText(settings['j'])
|
||||
self.srmd_ncnn_vulkan_tta_check_box.setChecked(settings['x'])
|
||||
|
||||
# realsr-ncnn-vulkan
|
||||
settings = self.config['realsr_ncnn_vulkan']
|
||||
self.realsr_ncnn_vulkan_path_line_edit.setText(str(pathlib.Path(os.path.expandvars(settings['path'])).absolute()))
|
||||
self.realsr_ncnn_vulkan_tile_size_spin_box.setValue(settings['t'])
|
||||
self.realsr_ncnn_vulkan_gpu_id_spin_box.setValue(settings['g'])
|
||||
self.realsr_ncnn_vulkan_jobs_line_edit.setText(settings['j'])
|
||||
self.realsr_ncnn_vulkan_tta_check_box.setChecked(settings['x'])
|
||||
|
||||
# anime4k
|
||||
settings = self.config['anime4kcpp']
|
||||
self.anime4kcpp_path_line_edit.setText(str(pathlib.Path(os.path.expandvars(settings['path'])).absolute()))
|
||||
@@ -514,6 +554,7 @@ class Video2XMainWindow(QMainWindow):
|
||||
self.anime4kcpp_pre_processing_check_box.setChecked(settings['preprocessing'])
|
||||
self.anime4kcpp_post_processing_check_box.setChecked(settings['postprocessing'])
|
||||
self.anime4kcpp_gpu_mode_check_box.setChecked(settings['GPUMode'])
|
||||
self.anime4kcpp_cnn_mode_check_box.setChecked(settings['CNNMode'])
|
||||
|
||||
# ffmpeg
|
||||
# global options
|
||||
@@ -598,6 +639,14 @@ class Video2XMainWindow(QMainWindow):
|
||||
self.config['srmd_ncnn_vulkan']['j'] = self.srmd_ncnn_vulkan_jobs_line_edit.text()
|
||||
self.config['srmd_ncnn_vulkan']['x'] = self.srmd_ncnn_vulkan_tta_check_box.isChecked()
|
||||
|
||||
# realsr-ncnn-vulkan
|
||||
self.config['realsr_ncnn_vulkan']['path'] = os.path.expandvars(self.realsr_ncnn_vulkan_path_line_edit.text())
|
||||
self.config['realsr_ncnn_vulkan']['t'] = self.realsr_ncnn_vulkan_tile_size_spin_box.value()
|
||||
self.config['realsr_ncnn_vulkan']['m'] = str((pathlib.Path(self.config['realsr_ncnn_vulkan']['path']).parent / self.realsr_ncnn_vulkan_model_combo_box.currentText()).absolute())
|
||||
self.config['realsr_ncnn_vulkan']['g'] = self.realsr_ncnn_vulkan_gpu_id_spin_box.value()
|
||||
self.config['realsr_ncnn_vulkan']['j'] = self.realsr_ncnn_vulkan_jobs_line_edit.text()
|
||||
self.config['realsr_ncnn_vulkan']['x'] = self.realsr_ncnn_vulkan_tta_check_box.isChecked()
|
||||
|
||||
# anime4k
|
||||
self.config['anime4kcpp']['path'] = os.path.expandvars(self.anime4kcpp_path_line_edit.text())
|
||||
self.config['anime4kcpp']['passes'] = self.anime4kcpp_passes_spin_box.value()
|
||||
@@ -614,6 +663,7 @@ class Video2XMainWindow(QMainWindow):
|
||||
self.config['anime4kcpp']['preprocessing'] = bool(self.anime4kcpp_pre_processing_check_box.isChecked())
|
||||
self.config['anime4kcpp']['postprocessing'] = bool(self.anime4kcpp_post_processing_check_box.isChecked())
|
||||
self.config['anime4kcpp']['GPUMode'] = bool(self.anime4kcpp_gpu_mode_check_box.isChecked())
|
||||
self.config['anime4kcpp']['CNNMode'] = bool(self.anime4kcpp_cnn_mode_check_box.isChecked())
|
||||
|
||||
# ffmpeg
|
||||
self.config['ffmpeg']['ffmpeg_path'] = os.path.expandvars(self.ffmpeg_path_line_edit.text())
|
||||
@@ -788,6 +838,10 @@ class Video2XMainWindow(QMainWindow):
|
||||
self.scale_ratio_double_spin_box.setMinimum(2.0)
|
||||
self.scale_ratio_double_spin_box.setMaximum(4.0)
|
||||
self.scale_ratio_double_spin_box.setValue(2.0)
|
||||
elif current_driver == 'realsr_ncnn_vulkan':
|
||||
self.scale_ratio_double_spin_box.setMinimum(4.0)
|
||||
self.scale_ratio_double_spin_box.setMaximum(4.0)
|
||||
self.scale_ratio_double_spin_box.setValue(4.0)
|
||||
|
||||
# update preferred processes/threads count
|
||||
if current_driver == 'anime4kcpp':
|
||||
@@ -802,12 +856,9 @@ class Video2XMainWindow(QMainWindow):
|
||||
self.input_table_view.setModel(self.input_table_model)
|
||||
|
||||
def input_table_delete_selected(self):
|
||||
items_to_delete = []
|
||||
for index in [i.row() for i in self.input_table_view.selectedIndexes()]:
|
||||
items_to_delete.append(self.input_table_data[index])
|
||||
|
||||
for item in items_to_delete:
|
||||
self.input_table_data.remove(item)
|
||||
indexes_to_delete = [i.row() for i in self.input_table_view.selectedIndexes()]
|
||||
for index in sorted(indexes_to_delete, reverse=True):
|
||||
del self.input_table_data[index]
|
||||
|
||||
self.update_output_path()
|
||||
self.update_input_table()
|
||||
@@ -858,9 +909,12 @@ class Video2XMainWindow(QMainWindow):
|
||||
if input_path.is_file():
|
||||
|
||||
# generate suffix automatically
|
||||
input_file_mime_type = magic.from_file(str(input_path.absolute()), mime=True)
|
||||
input_file_type = input_file_mime_type.split('/')[0]
|
||||
input_file_subtype = input_file_mime_type.split('/')[1]
|
||||
try:
|
||||
input_file_mime_type = magic.from_file(str(input_path.absolute()), mime=True)
|
||||
input_file_type = input_file_mime_type.split('/')[0]
|
||||
input_file_subtype = input_file_mime_type.split('/')[1]
|
||||
except Exception:
|
||||
input_file_type = input_file_subtype = None
|
||||
|
||||
# in case python-magic fails to detect file type
|
||||
# try guessing file mime type with mimetypes
|
||||
@@ -878,11 +932,11 @@ class Video2XMainWindow(QMainWindow):
|
||||
|
||||
# otherwise, use .png by default for all images
|
||||
else:
|
||||
suffix = '.png'
|
||||
suffix = self.image_output_extension_line_edit.text()
|
||||
|
||||
# if input is video, use .mp4 as output by default
|
||||
elif input_file_type == 'video':
|
||||
suffix = '.mp4'
|
||||
suffix = self.video_output_extension_line_edit.text()
|
||||
|
||||
# if failed to detect file type
|
||||
# use input file's suffix
|
||||
@@ -894,9 +948,9 @@ class Video2XMainWindow(QMainWindow):
|
||||
elif input_path.is_dir():
|
||||
output_path = input_path.parent / f'{input_path.stem}_output'
|
||||
|
||||
# try up to 1000 times
|
||||
# try a new name with a different file ID
|
||||
output_path_id = 0
|
||||
while output_path.exists() and output_path_id <= 1000:
|
||||
while output_path.exists():
|
||||
if input_path.is_file():
|
||||
output_path = input_path.parent / pathlib.Path(f'{input_path.stem}_output_{output_path_id}{suffix}')
|
||||
elif input_path.is_dir():
|
||||
@@ -994,8 +1048,9 @@ class Video2XMainWindow(QMainWindow):
|
||||
{}\\
|
||||
Check the console output for details.\\
|
||||
When reporting an error, please include console output.\\
|
||||
You can [submit an issue on GitHub](https://github.com/k4yt3x/video2x/issues/new?assignees=K4YT3X&labels=bug&template=bug-report.md&title={}) to report this error.'''
|
||||
message_box.setText(error_message.format(exception, urllib.parse.quote(str(exception))))
|
||||
You can [submit an issue on GitHub](https://github.com/k4yt3x/video2x/issues/new?assignees=K4YT3X&labels=bug&template=bug-report.md&title={}) to report this error.\\
|
||||
It\'s also highly recommended for you to attach the [log file]({}) under the programs\'s parent folder named {}.'''
|
||||
message_box.setText(error_message.format(exception, urllib.parse.quote(str(exception)), self.logfile.as_uri(), self.logfile.name))
|
||||
message_box.exec_()
|
||||
|
||||
def progress_monitor(self, progress_callback: pyqtSignal):
|
||||
@@ -1018,7 +1073,7 @@ You can [submit an issue on GitHub](https://github.com/k4yt3x/video2x/issues/new
|
||||
|
||||
# upscale process will stop at 99%
|
||||
# so it's set to 100 manually when all is done
|
||||
progress_callback.emit((upscale_begin_time, 0, 0, 0, 0, pathlib.Path(), pathlib.Path()))
|
||||
# progress_callback.emit((upscale_begin_time, 0, 0, 0, 0, pathlib.Path(), pathlib.Path()))
|
||||
|
||||
def set_progress(self, progress_information: tuple):
|
||||
upscale_begin_time = progress_information[0]
|
||||
@@ -1099,6 +1154,11 @@ You can [submit an issue on GitHub](https://github.com/k4yt3x/video2x/issues/new
|
||||
self.show_warning('Output path unspecified')
|
||||
return
|
||||
|
||||
if self.disable_logging_check_box.isChecked() is False:
|
||||
print(f'Redirecting console logs to {self.logfile}', file=sys.stderr)
|
||||
sys.stdout = BiLogger(sys.stdout, self.logfile)
|
||||
sys.stderr = BiLogger(sys.stderr, self.logfile)
|
||||
|
||||
if len(self.input_table_data) == 1:
|
||||
input_directory = self.input_table_data[0]
|
||||
else:
|
||||
@@ -1113,19 +1173,24 @@ You can [submit an issue on GitHub](https://github.com/k4yt3x/video2x/issues/new
|
||||
# load driver settings for the current driver
|
||||
self.driver_settings = self.config[AVAILABLE_DRIVERS[self.driver_combo_box.currentText()]]
|
||||
|
||||
self.upscaler = Upscaler(input_path=input_directory,
|
||||
output_path=output_directory,
|
||||
driver_settings=self.driver_settings,
|
||||
ffmpeg_settings=self.ffmpeg_settings,
|
||||
gifski_settings=self.gifski_settings)
|
||||
self.upscaler = Upscaler(
|
||||
# required parameters
|
||||
input_path=input_directory,
|
||||
output_path=output_directory,
|
||||
driver_settings=self.driver_settings,
|
||||
ffmpeg_settings=self.ffmpeg_settings,
|
||||
gifski_settings=self.gifski_settings,
|
||||
|
||||
# set optional options
|
||||
self.upscaler.driver = AVAILABLE_DRIVERS[self.driver_combo_box.currentText()]
|
||||
self.upscaler.scale_ratio = self.scale_ratio_double_spin_box.value()
|
||||
self.upscaler.processes = self.processes_spin_box.value()
|
||||
self.upscaler.video2x_cache_directory = pathlib.Path(os.path.expandvars(self.cache_line_edit.text()))
|
||||
self.upscaler.image_format = self.config['video2x']['image_format'].lower()
|
||||
self.upscaler.preserve_frames = bool(self.preserve_frames_check_box.isChecked())
|
||||
# optional parameters
|
||||
driver=AVAILABLE_DRIVERS[self.driver_combo_box.currentText()],
|
||||
scale_ratio=self.scale_ratio_double_spin_box.value(),
|
||||
processes=self.processes_spin_box.value(),
|
||||
video2x_cache_directory=pathlib.Path(os.path.expandvars(self.cache_line_edit.text())),
|
||||
extracted_frame_format=self.config['video2x']['extracted_frame_format'].lower(),
|
||||
image_output_extension=self.image_output_extension_line_edit.text(),
|
||||
video_output_extension=self.video_output_extension_line_edit.text(),
|
||||
preserve_frames=bool(self.preserve_frames_check_box.isChecked())
|
||||
)
|
||||
|
||||
# run upscaler
|
||||
worker = UpscalerWorker(self.upscaler.run)
|
||||
@@ -1147,6 +1212,10 @@ You can [submit an issue on GitHub](https://github.com/k4yt3x/video2x/issues/new
|
||||
self.upscale_errored(e)
|
||||
|
||||
def upscale_errored(self, exception: Exception):
|
||||
# send stop signal in case it's not triggered
|
||||
with contextlib.suppress(AttributeError):
|
||||
self.upscaler.running = False
|
||||
|
||||
self.show_error(exception)
|
||||
self.threadpool.waitForDone(5)
|
||||
self.start_button.setEnabled(True)
|
||||
|
||||
@@ -1,190 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 4.12.0, 2020-05-23T08:51:47. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{25c1e4a4-6b4a-4828-883b-6f32c3f7eba0}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<valuelist type="QVariantList" key="ClangCodeModel.CustomCommandLineKey">
|
||||
<value type="QString">-fno-delayed-template-parsing</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="ClangCodeModel.UseGlobalConfig">true</value>
|
||||
<value type="QString" key="ClangCodeModel.WarningConfigId">Builtin.Questionable</value>
|
||||
<valuemap type="QVariantMap" key="ClangTools">
|
||||
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
||||
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
||||
<value type="int" key="ClangTools.ParallelJobs">8</value>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
||||
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop (x86-windows-msvc2019-pe-64bit)</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop (x86-windows-msvc2019-pe-64bit)</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{5450e32e-f498-4c15-a0a5-7456f3375388}</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">-1</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="QString" key="Analyzer.Perf.CallgraphMode">dwarf</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Perf.Events">
|
||||
<value type="QString">cpu-cycles</value>
|
||||
</valuelist>
|
||||
<valuelist type="QVariantList" key="Analyzer.Perf.ExtraArguments"/>
|
||||
<value type="int" key="Analyzer.Perf.Frequency">250</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Perf.RecordArguments">
|
||||
<value type="QString">-e</value>
|
||||
<value type="QString">cpu-cycles</value>
|
||||
<value type="QString">--call-graph</value>
|
||||
<value type="QString">dwarf,4096</value>
|
||||
<value type="QString">-F</value>
|
||||
<value type="QString">250</value>
|
||||
</valuelist>
|
||||
<value type="QString" key="Analyzer.Perf.SampleMode">-F</value>
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Perf.StackSize">4096</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
|
||||
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
|
||||
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.KCachegrindExecutable">kcachegrind</value>
|
||||
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
|
||||
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
|
||||
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
|
||||
<value type="int">0</value>
|
||||
<value type="int">1</value>
|
||||
<value type="int">2</value>
|
||||
<value type="int">3</value>
|
||||
<value type="int">4</value>
|
||||
<value type="int">5</value>
|
||||
<value type="int">6</value>
|
||||
<value type="int">7</value>
|
||||
<value type="int">8</value>
|
||||
<value type="int">9</value>
|
||||
<value type="int">10</value>
|
||||
<value type="int">11</value>
|
||||
<value type="int">12</value>
|
||||
<value type="int">13</value>
|
||||
<value type="int">14</value>
|
||||
</valuelist>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">video2x_gui</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">PythonEditor.RunConfiguration.C:/Users/k4yt3x/Documents/Projects/video2x/src/video2x_gui.py</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">C:/Users/k4yt3x/Documents/Projects/video2x/src/video2x_gui.py</value>
|
||||
<value type="bool" key="PythonEditor.RunConfiguation.Buffered">false</value>
|
||||
<value type="QString" key="PythonEditor.RunConfiguation.Interpreter">{ffc39ed5-fbe0-4af8-8b16-9a60c393bdb8}</value>
|
||||
<value type="QString" key="PythonEditor.RunConfiguation.Script">C:\Users\k4yt3x\Documents\Projects\video2x\src\video2x_gui.py</value>
|
||||
<value type="QString" key="RunConfiguration.Arguments"></value>
|
||||
<value type="bool" key="RunConfiguration.Arguments.multi">false</value>
|
||||
<value type="QString" key="RunConfiguration.OverrideDebuggerStartup"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory"></value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
</qtcreator>
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>673</width>
|
||||
<height>802</height>
|
||||
<width>727</width>
|
||||
<height>908</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
@@ -342,6 +342,11 @@
|
||||
<string>SRMD NCNN Vulkan</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>RealSR NCNN Vulkan</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Anime4KCPP</string>
|
||||
@@ -402,6 +407,54 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="imageOutputExtensionHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="imageOutputExtensionLabel">
|
||||
<property name="text">
|
||||
<string>Image Output Extension</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="imageOutputExtensionLineEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>.png</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="videoOutputExtensionHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="videoOutputExtensionLabel">
|
||||
<property name="text">
|
||||
<string>Video Output Extension</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="videoOutputExtensionLineEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>.mp4</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="preserveFramesCheckBox">
|
||||
<property name="toolTip">
|
||||
@@ -415,6 +468,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="disableLoggingCheckBox">
|
||||
<property name="text">
|
||||
<string>Disable Logging</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -443,6 +503,9 @@
|
||||
<property name="text">
|
||||
<string>Keep Aspect Ratio</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -1384,6 +1447,131 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="realsrNcnnVulkanTab">
|
||||
<attribute name="title">
|
||||
<string>RealSR NCNN Vulkan</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_34">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="realsrNcnnVulkanPathHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="realsrNcnnVulkanPathLineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="realsrNcnnVulkanPathSelectButton">
|
||||
<property name="text">
|
||||
<string>Select Binary Path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="realsrNcnnVulkanTileSizeHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="realsrNcnnVulkanTileSizeLabel">
|
||||
<property name="text">
|
||||
<string>Tile Size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="realsrNcnnVulkanTileSizeSpinBox">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="realsrNcnnVulkanModelHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="realsrNcnnVulkanModelLabel">
|
||||
<property name="text">
|
||||
<string>Model</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="realsrNcnnVulkanModelComboBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If the input file contains very little noise, DF2K will produce sharper outputs.</p><p>However, if the input is noisy, DF2K might produce artifacts. DF2K_JPEG will then be preferred.</p></body></html></string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>models-DF2K_JPEG</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>models-DF2K</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="realsrNcnnVulkanGpuIdHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="realsrNcnnVulkanGpuIdLabel">
|
||||
<property name="text">
|
||||
<string>GPU ID</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="realsrNcnnVulkanGpuIdSpinBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="realsrNcnnVulkanJobsHorizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="realsrNcnnVulkanJobsLabel">
|
||||
<property name="text">
|
||||
<string>Jobs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="realsrNcnnVulkanJobsLineEdit">
|
||||
<property name="text">
|
||||
<string>1:2:2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="realsrNcnnVulkanTtaCheckBox">
|
||||
<property name="text">
|
||||
<string>TTA</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="realsrNcnnVulkanVerticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>331</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="anime4kCppTab">
|
||||
<attribute name="title">
|
||||
<string>Anime4K CPP</string>
|
||||
@@ -1555,6 +1743,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="anime4kCppCnnModeCheckBox">
|
||||
<property name="text">
|
||||
<string>CNN Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -2640,7 +2835,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>673</width>
|
||||
<width>727</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
Name: Video2X Setup Script
|
||||
Creator: K4YT3X
|
||||
Date Created: November 28, 2018
|
||||
Last Modified: May 16, 2020
|
||||
Last Modified: May 30, 2020
|
||||
|
||||
Editor: BrianPetkovsek
|
||||
Editor: SAT3LL
|
||||
@@ -17,8 +17,9 @@ Installation Details:
|
||||
- waifu2x-caffe: %LOCALAPPDATA%\\video2x\\waifu2x-caffe
|
||||
- waifu2x-cpp-converter: %LOCALAPPDATA%\\video2x\\waifu2x-converter-cpp
|
||||
- waifu2x_ncnn_vulkan: %LOCALAPPDATA%\\video2x\\waifu2x-ncnn-vulkan
|
||||
- anime4kcpp: %LOCALAPPDATA%\\video2x\\anime4kcpp
|
||||
- srmd_ncnn_vulkan: %LOCALAPPDATA%\\video2x\\srmd-ncnn-vulkan
|
||||
- realsr_ncnn_vulkan: %LOCALAPPDATA%\\video2x\\realsr-ncnn-vulkan
|
||||
- anime4kcpp: %LOCALAPPDATA%\\video2x\\anime4kcpp
|
||||
"""
|
||||
|
||||
# built-in imports
|
||||
@@ -43,19 +44,19 @@ import zipfile
|
||||
# Therefore, they will be installed during the Python dependency
|
||||
# installation step and imported later in the script.
|
||||
|
||||
SETUP_VERSION = '2.1.0'
|
||||
SETUP_VERSION = '2.2.1'
|
||||
|
||||
# global static variables
|
||||
LOCALAPPDATA = pathlib.Path(os.getenv('localappdata'))
|
||||
VIDEO2X_CONFIG = pathlib.Path(__file__).parent.absolute() / 'video2x.yaml'
|
||||
DRIVER_OPTIONS = ['all',
|
||||
'ffmpeg',
|
||||
'gifski',
|
||||
'waifu2x_caffe',
|
||||
'waifu2x_converter_cpp',
|
||||
'waifu2x_ncnn_vulkan',
|
||||
'anime4kcpp',
|
||||
'srmd_ncnn_vulkan']
|
||||
'srmd_ncnn_vulkan',
|
||||
'realsr_ncnn_vulkan',
|
||||
'anime4kcpp']
|
||||
|
||||
|
||||
def parse_arguments():
|
||||
@@ -137,7 +138,7 @@ class Video2xSetup:
|
||||
print('\nInstalling Gifski')
|
||||
import requests
|
||||
|
||||
# Get latest release of waifu2x-ncnn-vulkan via Github API
|
||||
# Get latest release of Gifski via Github API
|
||||
latest_release = requests.get('https://api.github.com/repos/ImageOptim/gifski/releases/latest').json()
|
||||
|
||||
for a in latest_release['assets']:
|
||||
@@ -193,7 +194,7 @@ class Video2xSetup:
|
||||
latest_release = requests.get('https://api.github.com/repos/nihui/waifu2x-ncnn-vulkan/releases/latest').json()
|
||||
|
||||
for a in latest_release['assets']:
|
||||
if re.search(r'waifu2x-ncnn-vulkan-\d*\.zip', a['browser_download_url']):
|
||||
if re.search(r'waifu2x-ncnn-vulkan-\d*-windows\.zip', a['browser_download_url']):
|
||||
waifu2x_ncnn_vulkan_zip = download(a['browser_download_url'], tempfile.gettempdir())
|
||||
self.trash.append(waifu2x_ncnn_vulkan_zip)
|
||||
|
||||
@@ -209,6 +210,58 @@ class Video2xSetup:
|
||||
# rename the newly extracted directory
|
||||
(LOCALAPPDATA / 'video2x' / zipf.namelist()[0]).rename(waifu2x_ncnn_vulkan_directory)
|
||||
|
||||
def _install_srmd_ncnn_vulkan(self):
|
||||
""" Install srmd-ncnn-vulkan
|
||||
"""
|
||||
print('\nInstalling srmd-ncnn-vulkan')
|
||||
import requests
|
||||
|
||||
# Get latest release of srmd-ncnn-vulkan via Github API
|
||||
latest_release = requests.get('https://api.github.com/repos/nihui/srmd-ncnn-vulkan/releases/latest').json()
|
||||
|
||||
for a in latest_release['assets']:
|
||||
if re.search(r'srmd-ncnn-vulkan-\d*-windows\.zip', a['browser_download_url']):
|
||||
srmd_ncnn_vulkan_zip = download(a['browser_download_url'], tempfile.gettempdir())
|
||||
self.trash.append(srmd_ncnn_vulkan_zip)
|
||||
|
||||
# extract and rename
|
||||
srmd_ncnn_vulkan_directory = LOCALAPPDATA / 'video2x' / 'srmd-ncnn-vulkan'
|
||||
with zipfile.ZipFile(srmd_ncnn_vulkan_zip) as zipf:
|
||||
zipf.extractall(LOCALAPPDATA / 'video2x')
|
||||
|
||||
# if directory already exists, remove it
|
||||
if srmd_ncnn_vulkan_directory.exists():
|
||||
shutil.rmtree(srmd_ncnn_vulkan_directory)
|
||||
|
||||
# rename the newly extracted directory
|
||||
(LOCALAPPDATA / 'video2x' / zipf.namelist()[0]).rename(srmd_ncnn_vulkan_directory)
|
||||
|
||||
def _install_realsr_ncnn_vulkan(self):
|
||||
""" Install realsr-ncnn-vulkan
|
||||
"""
|
||||
print('\nInstalling realsr-ncnn-vulkan')
|
||||
import requests
|
||||
|
||||
# Get latest release of realsr-ncnn-vulkan via Github API
|
||||
latest_release = requests.get('https://api.github.com/repos/nihui/realsr-ncnn-vulkan/releases/latest').json()
|
||||
|
||||
for a in latest_release['assets']:
|
||||
if re.search(r'realsr-ncnn-vulkan-\d*-windows\.zip', a['browser_download_url']):
|
||||
realsr_ncnn_vulkan_zip = download(a['browser_download_url'], tempfile.gettempdir())
|
||||
self.trash.append(realsr_ncnn_vulkan_zip)
|
||||
|
||||
# extract and rename
|
||||
realsr_ncnn_vulkan_directory = LOCALAPPDATA / 'video2x' / 'realsr-ncnn-vulkan'
|
||||
with zipfile.ZipFile(realsr_ncnn_vulkan_zip) as zipf:
|
||||
zipf.extractall(LOCALAPPDATA / 'video2x')
|
||||
|
||||
# if directory already exists, remove it
|
||||
if realsr_ncnn_vulkan_directory.exists():
|
||||
shutil.rmtree(realsr_ncnn_vulkan_directory)
|
||||
|
||||
# rename the newly extracted directory
|
||||
(LOCALAPPDATA / 'video2x' / zipf.namelist()[0]).rename(realsr_ncnn_vulkan_directory)
|
||||
|
||||
def _install_anime4kcpp(self):
|
||||
""" Install Anime4KCPP
|
||||
"""
|
||||
@@ -238,32 +291,6 @@ class Video2xSetup:
|
||||
shutil.rmtree(LOCALAPPDATA / 'video2x' / 'anime4kcpp')
|
||||
patoolib.extract_archive(str(anime4kcpp_7z), outdir=str(LOCALAPPDATA / 'video2x' / 'anime4kcpp'))
|
||||
|
||||
def _install_srmd_ncnn_vulkan(self):
|
||||
""" Install srmd-ncnn-vulkan
|
||||
"""
|
||||
print('\nInstalling srmd-ncnn-vulkan')
|
||||
import requests
|
||||
|
||||
# Get latest release of srmd-ncnn-vulkan via Github API
|
||||
latest_release = requests.get('https://api.github.com/repos/nihui/srmd-ncnn-vulkan/releases/latest').json()
|
||||
|
||||
for a in latest_release['assets']:
|
||||
if re.search(r'srmd-ncnn-vulkan-\d*\.zip', a['browser_download_url']):
|
||||
srmd_ncnn_vulkan_zip = download(a['browser_download_url'], tempfile.gettempdir())
|
||||
self.trash.append(srmd_ncnn_vulkan_zip)
|
||||
|
||||
# extract and rename
|
||||
srmd_ncnn_vulkan_directory = LOCALAPPDATA / 'video2x' / 'srmd-ncnn-vulkan'
|
||||
with zipfile.ZipFile(srmd_ncnn_vulkan_zip) as zipf:
|
||||
zipf.extractall(LOCALAPPDATA / 'video2x')
|
||||
|
||||
# if directory already exists, remove it
|
||||
if srmd_ncnn_vulkan_directory.exists():
|
||||
shutil.rmtree(srmd_ncnn_vulkan_directory)
|
||||
|
||||
# rename the newly extracted directory
|
||||
(LOCALAPPDATA / 'video2x' / zipf.namelist()[0]).rename(srmd_ncnn_vulkan_directory)
|
||||
|
||||
|
||||
def download(url, save_path, chunk_size=4096):
|
||||
""" Download file to local with requests library
|
||||
|
||||
223
src/video2x_setup_ubuntu.sh
Executable file
223
src/video2x_setup_ubuntu.sh
Executable file
@@ -0,0 +1,223 @@
|
||||
#!/usr/bin/bash -e
|
||||
# Name: Video2X Setup Script (Ubuntu)
|
||||
# Creator: K4YT3X
|
||||
# Date Created: June 5, 2020
|
||||
# Last Modified: June 7, 2020
|
||||
|
||||
# help message if input is incorrect of if -h/--help is specified
|
||||
if [ "$1" == "-h" ] || [ "$1" == "--help" ] || [ "$#" -gt 2 ]; then
|
||||
echo "usage: $0 INSTALLATION_PATH TEMP"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# set intallation path if specified
|
||||
if [ ! -z "$1" ]; then
|
||||
INSTALLATION_PATH=$1
|
||||
else
|
||||
INSTALLATION_PATH="$HOME/.local/share"
|
||||
fi
|
||||
|
||||
# set temp directory location if specified
|
||||
if [ ! -z "$2" ]; then
|
||||
TEMP=$2
|
||||
else
|
||||
TEMP="/tmp/video2x"
|
||||
fi
|
||||
|
||||
# environment variables
|
||||
export DEBIAN_FRONTEND="noninteractive"
|
||||
|
||||
# install basic utilities and add PPAs
|
||||
apt-get update
|
||||
apt-get install -y --no-install-recommends apt-utils software-properties-common
|
||||
|
||||
# add PPAs and sources
|
||||
add-apt-repository -y ppa:apt-fast/stable
|
||||
add-apt-repository -y ppa:graphics-drivers/ppa
|
||||
apt-get install -y --no-install-recommends apt-fast
|
||||
apt-fast update
|
||||
|
||||
# install runtime packages
|
||||
apt-fast install -y --no-install-recommends ffmpeg libmagic1 nvidia-cuda-toolkit nvidia-driver-440 python3.8
|
||||
|
||||
# install compilation packages
|
||||
apt-fast install -y --no-install-recommends git-core curl wget ca-certificates gnupg2 python3-dev python3-pip python3-setuptools python3-wheel
|
||||
|
||||
# add Nvidia sources
|
||||
curl -fsSL https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub | apt-key add -
|
||||
echo "deb https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64 /" >/etc/apt/sources.list.d/nvidia-ml.list
|
||||
apt-fast update
|
||||
|
||||
# install python3 packages
|
||||
git clone --recurse-submodules --progress https://github.com/k4yt3x/video2x.git --depth=1 $INSTALLATION_PATH/video2x
|
||||
python3.8 -m pip install -U pip
|
||||
python3.8 -m pip install -U -r $INSTALLATION_PATH/video2x/src/requirements.txt
|
||||
mkdir -v -p $INSTALLATION_PATH/video2x/src/dependencies
|
||||
|
||||
# install gifski
|
||||
apt-fast install -y --no-install-recommends cargo
|
||||
cargo install gifski
|
||||
|
||||
# install waifu2x-caffe
|
||||
apt-fast install -y --no-install-recommends autoconf build-essential cmake gcc-8 libatlas-base-dev libboost-atomic-dev libboost-chrono-dev libboost-date-time-dev libboost-filesystem-dev libboost-iostreams-dev libboost-python-dev libboost-system-dev libboost-thread-dev libcudnn7 libcudnn7-dev libgflags-dev libgoogle-glog-dev libhdf5-dev libleveldb-dev liblmdb-dev libopencv-dev libprotobuf-dev libsnappy-dev protobuf-compiler python-numpy texinfo yasm zlib1g-dev
|
||||
|
||||
git clone --recurse-submodules --depth=1 --progress --recurse-submodules https://github.com/nagadomi/waifu2x-caffe-ubuntu.git $TEMP/waifu2x-caffe-ubuntu
|
||||
git clone --recurse-submodules --progress --depth=1 https://github.com/nagadomi/caffe.git $TEMP/waifu2x-caffe-ubuntu/caffe
|
||||
|
||||
apt-get purge -y gcc g++
|
||||
ln -s /usr/bin/gcc-8 /usr/bin/gcc
|
||||
ln -s /usr/bin/g++-8 /usr/bin/g++
|
||||
mkdir -v -p $TEMP/waifu2x-caffe-ubuntu/build
|
||||
cd $TEMP/waifu2x-caffe-ubuntu/build
|
||||
cmake .. -DCMAKE_INSTALL_PREFIX=/usr
|
||||
make -j$(nproc) install
|
||||
|
||||
mv -v /tmp/video2x/waifu2x-caffe-ubuntu/bin $INSTALLATION_PATH/video2x/src/dependencies/waifu2x-caffe
|
||||
mv -v /tmp/video2x/waifu2x-caffe-ubuntu/build/waifu2x-caffe $INSTALLATION_PATH/video2x/src/dependencies/waifu2x-caffe/waifu2x-caffe
|
||||
|
||||
# install waifu2x-converter-cpp
|
||||
apt-fast install -y --no-install-recommends build-essential cmake libopencv-dev ocl-icd-opencl-dev
|
||||
git clone --recurse-submodules --depth=1 --progress https://github.com/DeadSix27/waifu2x-converter-cpp $TEMP/waifu2x-converter-cpp
|
||||
mkdir -v $TEMP/waifu2x-converter-cpp/build
|
||||
cd $TEMP/waifu2x-converter-cpp/build
|
||||
cmake ..
|
||||
make -j$(nproc)
|
||||
mv -v $TEMP/waifu2x-converter-cpp/build $INSTALLATION_PATH/video2x/src/dependencies/waifu2x-converter-cpp
|
||||
mv -v $TEMP/waifu2x-converter-cpp/models_rgb $INSTALLATION_PATH/video2x/src/dependencies/waifu2x-converter-cpp/models_rgb
|
||||
|
||||
# install waifu2x-ncnn-vulkan
|
||||
# download libvulkan1
|
||||
apt-fast install -y --no-install-recommends libvulkan1 unzip jq
|
||||
|
||||
# get latest release JSON as a string
|
||||
echo "Fetching latest waifu2x-ncnn-vulkan release information using GitHub API"
|
||||
waifu2x_ncnn_vulkan_latest_release=$(curl -s https://api.github.com/repos/nihui/waifu2x-ncnn-vulkan/releases/latest)
|
||||
|
||||
# count the number of assets in this release
|
||||
assets=$(echo "$waifu2x_ncnn_vulkan_latest_release" | jq -r '.assets | length')
|
||||
|
||||
# iterate through each of the assets and see if the name of the asset matches what we're looking for
|
||||
for i in $(seq $assets $END); do
|
||||
if echo "$waifu2x_ncnn_vulkan_latest_release" | jq -r ".assets["$(($i - 1))"].name" | egrep "^waifu2x-ncnn-vulkan-[0-9]*-linux\.zip$"; then
|
||||
download_link=$(echo "$waifu2x_ncnn_vulkan_latest_release" | jq -r ".assets["$(($i - 1))"].browser_download_url")
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# check if download_link variable is set
|
||||
if [ -z "$download_link" ]; then
|
||||
echo "$waifu2x_ncnn_vulkan_latest_release"
|
||||
echo "Error: unable to find waifu2x-ncnn-vulkan download link or GitHub API rate limit exceeded"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
waifu2x_ncnn_vulkan_zip="$TEMP/waifu2x-ncnn-vulkan-linux.zip"
|
||||
echo "Downloading $download_link to $waifu2x_ncnn_vulkan_zip"
|
||||
wget "$download_link" -O "$waifu2x_ncnn_vulkan_zip"
|
||||
unzip "$waifu2x_ncnn_vulkan_zip" -d $TEMP/waifu2x-ncnn-vulkan
|
||||
mv -v $TEMP/waifu2x-ncnn-vulkan/waifu2x-ncnn-vulkan-*-linux $INSTALLATION_PATH/video2x/src/dependencies/waifu2x-ncnn-vulkan
|
||||
|
||||
# install srmd-ncnn-vulkan
|
||||
# download libvulkan1
|
||||
apt-fast install -y --no-install-recommends libvulkan1 unzip jq
|
||||
|
||||
# get latest release JSON as a string
|
||||
echo "Fetching latest srmd-ncnn-vulkan release information using GitHub API"
|
||||
srmd_ncnn_vulkan_latest_release=$(curl -s https://api.github.com/repos/nihui/srmd-ncnn-vulkan/releases/latest)
|
||||
|
||||
# count the number of assets in this release
|
||||
assets=$(echo "$srmd_ncnn_vulkan_latest_release" | jq -r '.assets | length')
|
||||
|
||||
# iterate through each of the assets and see if the name of the asset matches what we're looking for
|
||||
for i in $(seq $assets $END); do
|
||||
if echo "$srmd_ncnn_vulkan_latest_release" | jq -r ".assets["$(($i - 1))"].name" | egrep "^srmd-ncnn-vulkan-[0-9]*-linux\.zip$"; then
|
||||
download_link=$(echo "$srmd_ncnn_vulkan_latest_release" | jq -r ".assets["$(($i - 1))"].browser_download_url")
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# check if download_link variable is set
|
||||
if [ -z "$download_link" ]; then
|
||||
echo "$srmd_ncnn_vulkan_latest_release"
|
||||
echo "Error: unable to find srmd-ncnn-vulkan download link or GitHub API rate limit exceeded"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
srmd_ncnn_vulkan_zip="$TEMP/srmd-ncnn-vulkan-linux.zip"
|
||||
echo "Downloading $download_link to $srmd_ncnn_vulkan_zip"
|
||||
wget "$download_link" -O "$srmd_ncnn_vulkan_zip"
|
||||
unzip "$srmd_ncnn_vulkan_zip" -d $TEMP/srmd-ncnn-vulkan
|
||||
mv -v $TEMP/srmd-ncnn-vulkan/srmd-ncnn-vulkan-*-linux $INSTALLATION_PATH/video2x/src/dependencies/srmd-ncnn-vulkan
|
||||
|
||||
# install realsr-ncnn-vulkan
|
||||
# download libvulkan1
|
||||
apt-fast install -y --no-install-recommends libvulkan1 unzip jq
|
||||
|
||||
# get latest release JSON as a string
|
||||
echo "Fetching latest realsr-ncnn-vulkan release information using GitHub API"
|
||||
realsr_ncnn_vulkan_latest_release=$(curl -s https://api.github.com/repos/nihui/realsr-ncnn-vulkan/releases/latest)
|
||||
|
||||
# count the number of assets in this release
|
||||
assets=$(echo "$realsr_ncnn_vulkan_latest_release" | jq -r '.assets | length')
|
||||
|
||||
# iterate through each of the assets and see if the name of the asset matches what we're looking for
|
||||
for i in $(seq $assets $END); do
|
||||
if echo "$realsr_ncnn_vulkan_latest_release" | jq -r ".assets["$(($i - 1))"].name" | egrep "^realsr-ncnn-vulkan-[0-9]*-linux\.zip$"; then
|
||||
download_link=$(echo "$realsr_ncnn_vulkan_latest_release" | jq -r ".assets["$(($i - 1))"].browser_download_url")
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# check if download_link variable is set
|
||||
if [ -z "$download_link" ]; then
|
||||
echo "$realsr_ncnn_vulkan_latest_release"
|
||||
echo "Error: unable to find realsr-ncnn-vulkan download link or GitHub API rate limit exceeded"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
realsr_ncnn_vulkan_zip="$TEMP/realsr-ncnn-vulkan-linux.zip"
|
||||
echo "Downloading $download_link to $realsr_ncnn_vulkan_zip"
|
||||
wget "$download_link" -O "$realsr_ncnn_vulkan_zip"
|
||||
unzip "$realsr_ncnn_vulkan_zip" -d $TEMP/realsr-ncnn-vulkan
|
||||
mv -v $TEMP/realsr-ncnn-vulkan/realsr-ncnn-vulkan-*-linux $INSTALLATION_PATH/video2x/src/dependencies/realsr-ncnn-vulkan
|
||||
|
||||
# rewrite config file values
|
||||
python3.8 - << EOF
|
||||
import yaml
|
||||
|
||||
with open('/video2x/src/video2x.yaml', 'r') as template:
|
||||
template_dict = yaml.load(template, Loader=yaml.FullLoader)
|
||||
template.close()
|
||||
|
||||
template_dict['ffmpeg']['ffmpeg_path'] = '/usr/bin'
|
||||
template_dict['gifski']['gifski_path'] = '/root/.cargo/bin/gifski'
|
||||
template_dict['waifu2x_caffe']['path'] = '/video2x/src/dependencies/waifu2x-caffe/waifu2x-caffe'
|
||||
template_dict['waifu2x_converter_cpp']['path'] = '/video2x/src/dependencies/waifu2x-converter-cpp/waifu2x-converter-cpp'
|
||||
template_dict['waifu2x_ncnn_vulkan']['path'] = '/video2x/src/dependencies/waifu2x-ncnn-vulkan/waifu2x-ncnn-vulkan'
|
||||
template_dict['srmd_ncnn_vulkan']['path'] = '/video2x/src/dependencies/srmd-ncnn-vulkan/srmd-ncnn-vulkan'
|
||||
template_dict['realsr_ncnn_vulkan']['path'] = '/video2x/src/dependencies/realsr-ncnn-vulkan/realsr-ncnn-vulkan'
|
||||
template_dict['anime4kcpp']['path'] = '/video2x/src/dependencies/anime4kcpp/anime4kcpp'
|
||||
|
||||
# write configuration into file
|
||||
with open('/video2x/src/video2x.yaml', 'w') as config:
|
||||
yaml.dump(template_dict, config)
|
||||
EOF
|
||||
|
||||
# clean up temp directory
|
||||
# purge default utilities
|
||||
apt-get purge -y git-core curl wget ca-certificates gnupg2 python3-dev python3-pip python3-setuptools
|
||||
|
||||
# purge waifu2x-caffe build dependencies
|
||||
apt-get purge -y autoconf build-essential cmake gcc-8 libatlas-base-dev libboost-atomic-dev libboost-chrono-dev libboost-date-time-dev libboost-filesystem-dev libboost-iostreams-dev libboost-python-dev libboost-system-dev libboost-thread-dev libcudnn7 libcudnn7-dev libgflags-dev libgoogle-glog-dev libhdf5-dev libleveldb-dev liblmdb-dev libopencv-dev libprotobuf-dev libsnappy-dev protobuf-compiler python-numpy texinfo yasm zlib1g-dev
|
||||
|
||||
# purge waifu2x-converter-cpp build dependencies
|
||||
apt-get purge -y libopencv-dev ocl-icd-opencl-dev
|
||||
|
||||
# purge waifu2x/srmd/realsr-ncnn-vulkan build dependencies
|
||||
apt-get purge -y unzip jq
|
||||
|
||||
# run autoremove and purge all unused packages
|
||||
apt-get autoremove --purge -y
|
||||
|
||||
# remove temp directory
|
||||
rm -vrf $TEMP
|
||||
1
src/wrappers/anime4kcpp.py
Normal file → Executable file
1
src/wrappers/anime4kcpp.py
Normal file → Executable file
@@ -59,6 +59,7 @@ class WrapperMain:
|
||||
parser.add_argument('-r', '--preFilters', type=int, help='Enhancement filter, only working when preProcessing is true,there are 5 options by binary:Median blur=0000001, Mean blur=0000010, CAS Sharpening=0000100, Gaussian blur weak=0001000, Gaussian blur=0010000, Bilateral filter=0100000, Bilateral filter faster=1000000, you can freely combine them, eg: Gaussian blur weak + Bilateral filter = 0001000 | 0100000 = 0101000 = 40(D)')
|
||||
parser.add_argument('-e', '--postFilters', type=int, help='Enhancement filter, only working when postProcessing is true,there are 5 options by binary:Median blur=0000001, Mean blur=0000010, CAS Sharpening=0000100, Gaussian blur weak=0001000, Gaussian blur=0010000, Bilateral filter=0100000, Bilateral filter faster=1000000, you can freely combine them, eg: Gaussian blur weak + Bilateral filter = 0001000 | 0100000 = 0101000 = 40(D), so you can put 40 to enable Gaussian blur weak and Bilateral filter, which also is what I recommend for image that < 1080P, 48 for image that >= 1080P, and for performance I recommend to use 72 for video that < 1080P, 80 for video that >=1080P')
|
||||
parser.add_argument('-q', '--GPUMode', action='store_true', help='Enable GPU acceleration')
|
||||
parser.add_argument('-w', '--CNNMode', action='store_true', help='Enable ACNet')
|
||||
parser.add_argument('-l', '--listGPUs', action='store_true', help='list GPUs')
|
||||
parser.add_argument('-h', '--platformID', type=int, help='Specify the platform ID')
|
||||
parser.add_argument('-d', '--deviceID', type=int, help='Specify the device ID')
|
||||
|
||||
10
src/wrappers/ffmpeg.py
Normal file → Executable file
10
src/wrappers/ffmpeg.py
Normal file → Executable file
@@ -4,7 +4,7 @@
|
||||
Name: Video2X FFmpeg Controller
|
||||
Author: K4YT3X
|
||||
Date Created: Feb 24, 2018
|
||||
Last Modified: May 14, 2020
|
||||
Last Modified: June 7, 2020
|
||||
|
||||
Description: This class handles all FFmpeg related operations.
|
||||
"""
|
||||
@@ -27,7 +27,7 @@ class Ffmpeg:
|
||||
and inserting audio tracks to videos.
|
||||
"""
|
||||
|
||||
def __init__(self, ffmpeg_settings, image_format='png'):
|
||||
def __init__(self, ffmpeg_settings, extracted_frame_format='png'):
|
||||
self.ffmpeg_settings = ffmpeg_settings
|
||||
|
||||
self.ffmpeg_path = pathlib.Path(self.ffmpeg_settings['ffmpeg_path'])
|
||||
@@ -35,7 +35,7 @@ class Ffmpeg:
|
||||
self.ffmpeg_probe_binary = self.ffmpeg_path / 'ffprobe'
|
||||
|
||||
# video metadata
|
||||
self.image_format = image_format
|
||||
self.extracted_frame_format = extracted_frame_format
|
||||
self.intermediate_file_name = pathlib.Path(self.ffmpeg_settings['intermediate_file_name'])
|
||||
self.pixel_format = self.ffmpeg_settings['extract_frames']['output_options']['-pix_fmt']
|
||||
|
||||
@@ -133,7 +133,7 @@ class Ffmpeg:
|
||||
|
||||
# specify output file
|
||||
execute.extend([
|
||||
extracted_frames / f'extracted_%0d.{self.image_format}'
|
||||
extracted_frames / f'extracted_%0d.{self.extracted_frame_format}'
|
||||
])
|
||||
|
||||
return(self._execute(execute))
|
||||
@@ -174,7 +174,7 @@ class Ffmpeg:
|
||||
# append input frames path into command
|
||||
execute.extend([
|
||||
'-i',
|
||||
upscaled_frames / f'extracted_%d.{self.image_format}'
|
||||
upscaled_frames / f'extracted_%d.{self.extracted_frame_format}'
|
||||
])
|
||||
|
||||
# read FFmpeg output options
|
||||
|
||||
6
src/wrappers/gifski.py
Normal file → Executable file
6
src/wrappers/gifski.py
Normal file → Executable file
@@ -4,7 +4,7 @@
|
||||
Name: Gifski Wrapper
|
||||
Creator: K4YT3X
|
||||
Date Created: May 11, 2020
|
||||
Last Modified: May 11, 2020
|
||||
Last Modified: June 7, 2020
|
||||
|
||||
Description: High-level wrapper for Gifski.
|
||||
"""
|
||||
@@ -22,7 +22,7 @@ class Gifski:
|
||||
def __init__(self, gifski_settings):
|
||||
self.gifski_settings = gifski_settings
|
||||
|
||||
def make_gif(self, upscaled_frames: pathlib.Path, output_path: pathlib.Path, framerate: float, image_format: str) -> subprocess.Popen:
|
||||
def make_gif(self, upscaled_frames: pathlib.Path, output_path: pathlib.Path, framerate: float, extracted_frame_format: str) -> subprocess.Popen:
|
||||
execute = [
|
||||
self.gifski_settings['gifski_path'],
|
||||
'-o',
|
||||
@@ -35,7 +35,7 @@ class Gifski:
|
||||
execute.extend(self._load_configuration())
|
||||
|
||||
# append frames location
|
||||
execute.extend([upscaled_frames / f'extracted_*.{image_format}'])
|
||||
execute.extend([upscaled_frames / f'extracted_*.{extracted_frame_format}'])
|
||||
|
||||
return(self._execute(execute))
|
||||
|
||||
|
||||
102
src/wrappers/realsr_ncnn_vulkan.py
Executable file
102
src/wrappers/realsr_ncnn_vulkan.py
Executable file
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Name: RealSR NCNN Vulkan Driver
|
||||
Creator: K4YT3X
|
||||
Date Created: May 26, 2020
|
||||
Last Modified: May 26, 2020
|
||||
|
||||
Description: This class is a high-level wrapper
|
||||
for realsr_ncnn_vulkan.
|
||||
"""
|
||||
|
||||
# built-in imports
|
||||
import argparse
|
||||
import os
|
||||
import pathlib
|
||||
import platform
|
||||
import shlex
|
||||
import subprocess
|
||||
import threading
|
||||
|
||||
# third-party imports
|
||||
from avalon_framework import Avalon
|
||||
|
||||
|
||||
class WrapperMain:
|
||||
"""This class communicates with RealSR NCNN Vulkan engine
|
||||
|
||||
An object will be created for this class, containing information
|
||||
about the binary address and the processing method. When being called
|
||||
by the main program, other detailed information will be passed to
|
||||
the upscale function.
|
||||
"""
|
||||
|
||||
def __init__(self, driver_settings):
|
||||
self.driver_settings = driver_settings
|
||||
self.print_lock = threading.Lock()
|
||||
|
||||
@staticmethod
|
||||
def parse_arguments(arguments):
|
||||
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter, add_help=False)
|
||||
parser.error = lambda message: (_ for _ in ()).throw(AttributeError(message))
|
||||
parser.add_argument('--help', action='help', help='show this help message and exit')
|
||||
parser.add_argument('-v', action='store_true', help='verbose output')
|
||||
parser.add_argument('-i', type=str, help=argparse.SUPPRESS) # help='input image path (jpg/png) or directory')
|
||||
parser.add_argument('-o', type=str, help=argparse.SUPPRESS) # help='output image path (png) or directory')
|
||||
parser.add_argument('-s', type=int, choices=[4], help='upscale ratio')
|
||||
parser.add_argument('-t', type=int, help='tile size (>=32/0=auto)')
|
||||
parser.add_argument('-m', type=str, help='realsr model path')
|
||||
parser.add_argument('-g', type=int, help='gpu device to use')
|
||||
parser.add_argument('-j', type=str, help='thread count for load/proc/save')
|
||||
parser.add_argument('-x', action='store_true', help='enable tta mode')
|
||||
return parser.parse_args(arguments)
|
||||
|
||||
def load_configurations(self, upscaler):
|
||||
self.driver_settings['s'] = int(upscaler.scale_ratio)
|
||||
self.driver_settings['j'] = '{}:{}:{}'.format(upscaler.processes, upscaler.processes, upscaler.processes)
|
||||
|
||||
def upscale(self, input_directory, output_directory):
|
||||
"""This is the core function for RealSR NCNN Vulkan class
|
||||
|
||||
Arguments:
|
||||
input_directory {string} -- source directory path
|
||||
output_directory {string} -- output directory path
|
||||
ratio {int} -- output video ratio
|
||||
"""
|
||||
|
||||
# overwrite config file settings
|
||||
self.driver_settings['i'] = input_directory
|
||||
self.driver_settings['o'] = output_directory
|
||||
|
||||
# by default, realsr-ncnn-vulkan will look for the models under the current working directory
|
||||
# change the working directory to its containing folder if model directory not specified
|
||||
if self.driver_settings['m'] is None and platform.system() == 'Windows':
|
||||
os.chdir(pathlib.Path(self.driver_settings['path']).parent)
|
||||
|
||||
# list to be executed
|
||||
# initialize the list with the binary path as the first element
|
||||
execute = [self.driver_settings['path']]
|
||||
|
||||
for key in self.driver_settings.keys():
|
||||
|
||||
value = self.driver_settings[key]
|
||||
|
||||
# null or None means that leave this option out (keep default)
|
||||
if key == 'path' or value is None or value is False:
|
||||
continue
|
||||
else:
|
||||
if len(key) == 1:
|
||||
execute.append(f'-{key}')
|
||||
else:
|
||||
execute.append(f'--{key}')
|
||||
|
||||
# true means key is an option
|
||||
if value is not True:
|
||||
execute.append(str(value))
|
||||
|
||||
# return the Popen object of the new process created
|
||||
self.print_lock.acquire()
|
||||
Avalon.debug_info(f'[upscaler] Subprocess {os.getpid()} executing: {shlex.join(execute)}')
|
||||
self.print_lock.release()
|
||||
return subprocess.Popen(execute)
|
||||
0
src/wrappers/srmd_ncnn_vulkan.py
Normal file → Executable file
0
src/wrappers/srmd_ncnn_vulkan.py
Normal file → Executable file
4
src/wrappers/waifu2x_caffe.py
Normal file → Executable file
4
src/wrappers/waifu2x_caffe.py
Normal file → Executable file
@@ -4,7 +4,7 @@
|
||||
Name: Waifu2x Caffe Driver
|
||||
Author: K4YT3X
|
||||
Date Created: Feb 24, 2018
|
||||
Last Modified: May 11, 2020
|
||||
Last Modified: June 7, 2020
|
||||
|
||||
Description: This class is a high-level wrapper
|
||||
for waifu2x-caffe.
|
||||
@@ -63,7 +63,7 @@ class WrapperMain:
|
||||
def load_configurations(self, upscaler):
|
||||
# use scale width and scale height if specified
|
||||
self.driver_settings['scale_ratio'] = upscaler.scale_ratio
|
||||
self.driver_settings['output_extention'] = upscaler.image_format
|
||||
self.driver_settings['output_extention'] = upscaler.extracted_frame_format
|
||||
|
||||
# bit_depth will be 12 at this point
|
||||
# it will up updated later
|
||||
|
||||
4
src/wrappers/waifu2x_converter_cpp.py
Normal file → Executable file
4
src/wrappers/waifu2x_converter_cpp.py
Normal file → Executable file
@@ -4,7 +4,7 @@
|
||||
Name: Waifu2x Converter CPP Driver
|
||||
Author: K4YT3X
|
||||
Date Created: February 8, 2019
|
||||
Last Modified: May 11, 2020
|
||||
Last Modified: June 7, 2020
|
||||
|
||||
Description: This class is a high-level wrapper
|
||||
for waifu2x-converter-cpp.
|
||||
@@ -69,7 +69,7 @@ class WrapperMain:
|
||||
def load_configurations(self, upscaler):
|
||||
self.driver_settings['scale-ratio'] = upscaler.scale_ratio
|
||||
self.driver_settings['jobs'] = upscaler.processes
|
||||
self.driver_settings['output-format'] = upscaler.image_format.lower()
|
||||
self.driver_settings['output-format'] = upscaler.extracted_frame_format.lower()
|
||||
|
||||
def upscale(self, input_directory, output_directory):
|
||||
""" Waifu2x Converter Driver Upscaler
|
||||
|
||||
0
src/wrappers/waifu2x_ncnn_vulkan.py
Normal file → Executable file
0
src/wrappers/waifu2x_ncnn_vulkan.py
Normal file → Executable file
Reference in New Issue
Block a user