added frame preview, redesigned driver instance initiation and argument parsing

This commit is contained in:
k4yt3x 2020-05-11 04:17:21 -04:00
parent 99971bceb1
commit 91401977da
12 changed files with 413 additions and 222 deletions

View File

@ -4,7 +4,7 @@
Name: Video2X Upscale Progress Monitor
Author: BrianPetkovsek
Date Created: May 7, 2020
Last Modified: May 7, 2020
Last Modified: May 10, 2020
"""
# built-in imports
@ -47,7 +47,10 @@ class ProgressMonitor(threading.Thread):
while self.running:
with contextlib.suppress(FileNotFoundError):
self.upscaler.total_frames_upscaled = len([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.image_format.lower())]
if len(upscaled_frames) >= 1:
self.upscaler.last_frame_upscaled = sorted(upscaled_frames)[-1]
self.upscaler.total_frames_upscaled = len(upscaled_frames)
# update progress bar
delta = self.upscaler.total_frames_upscaled - previous_cycle_frames

View File

@ -4,7 +4,7 @@
Name: Video2X Upscaler
Author: K4YT3X
Date Created: December 10, 2018
Last Modified: May 9, 2020
Last Modified: May 10, 2020
Description: This file contains the Upscaler class. Each
instance of the Upscaler class is an upscaler on an image or
@ -76,8 +76,6 @@ class Upscaler:
# optional arguments
self.driver = 'waifu2x_caffe'
self.scale_width = None
self.scale_height = None
self.scale_ratio = None
self.processes = 1
self.video2x_cache_directory = pathlib.Path(tempfile.gettempdir()) / 'video2x'
@ -91,6 +89,7 @@ class Upscaler:
self.total_videos = 0
self.total_processed = 0
self.current_input_video = pathlib.Path()
self.last_frame_upscaled = pathlib.Path()
def create_temp_directories(self):
"""create temporary directories
@ -176,7 +175,7 @@ class Upscaler:
Avalon.error(_('Input path is neither a file nor a directory'))
raise FileNotFoundError(f'{self.input} is neither file nor directory')
# check Fmpeg settings
# check FFmpeg settings
ffmpeg_path = pathlib.Path(self.ffmpeg_settings['ffmpeg_path'])
if not ((pathlib.Path(ffmpeg_path / 'ffmpeg.exe').is_file() and
pathlib.Path(ffmpeg_path / 'ffprobe.exe').is_file()) or
@ -222,6 +221,23 @@ class Upscaler:
Avalon.error(_('Failed to parse driver argument: {}').format(e.args[0]))
raise e
# waifu2x-caffe scale_ratio, scale_width and scale_height check
if self.driver == 'waifu2x-caffe':
if (driver_settings['scale_width'] != 0 and driver_settings['scale_width'] == 0 or
driver_settings['scale_width'] == 0 and driver_settings['scale_width'] != 0):
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
elif self.driver_settings['scale_width'] != 0 and self.driver_settings['scale_height'] != 0:
self.driver_settings['scale_ratio'] = None
# if scale_width and scale_height not specified
# ensure they are None, not 0
else:
self.driver_settings['scale_width'] = None
self.driver_settings['scale_height'] = None
def _upscale_frames(self):
""" Upscale video frames with waifu2x-caffe
@ -269,43 +285,9 @@ class Upscaler:
# rotate list
process_directories = process_directories[-1:] + process_directories[:-1]
# create threads and start them
# create driver processes and start them
for process_directory in process_directories:
DriverWrapperMain = getattr(importlib.import_module(f'wrappers.{self.driver}'), 'WrapperMain')
driver = DriverWrapperMain(copy.deepcopy(self.driver_settings))
# if the driver being used is waifu2x-caffe
if self.driver == 'waifu2x_caffe':
self.process_pool.append(driver.upscale(process_directory,
self.upscaled_frames,
self.scale_ratio,
self.scale_width,
self.scale_height,
self.image_format,
self.bit_depth))
# if the driver being used is waifu2x-converter-cpp
elif self.driver == 'waifu2x_converter_cpp':
self.process_pool.append(driver.upscale(process_directory,
self.upscaled_frames,
self.scale_ratio,
self.processes,
self.image_format))
# if the driver being used is waifu2x-ncnn-vulkan
elif self.driver == 'waifu2x_ncnn_vulkan':
self.process_pool.append(driver.upscale(process_directory,
self.upscaled_frames,
self.scale_ratio,
self.processes))
# if the driver being used is srmd_ncnn_vulkan
elif self.driver == 'srmd_ncnn_vulkan':
self.process_pool.append(driver.upscale(process_directory,
self.upscaled_frames,
self.scale_ratio,
self.processes))
self.process_pool.append(self.driver_object.upscale(process_directory, self.upscaled_frames))
# start progress bar in a different thread
Avalon.debug_info(_('Starting progress monitor'))
@ -404,6 +386,13 @@ class Upscaler:
# define process pool to contain processes
self.process_pool = []
# load driver modules
DriverWrapperMain = getattr(importlib.import_module(f'wrappers.{self.driver}'), 'WrapperMain')
self.driver_object = DriverWrapperMain(self.driver_settings)
# load options from upscaler class into driver settings
self.driver_object.load_configurations(self)
# parse arguments for waifu2x
# check argument sanity
self._check_arguments()
@ -453,12 +442,8 @@ class Upscaler:
os.environ['PATH'] += f';{self.ffmpeg_settings["ffmpeg_path"]}'
Avalon.info(_('Starting to upscale extracted images'))
# import and initialize Anime4KCPP wrapper
DriverWrapperMain = getattr(importlib.import_module('wrappers.anime4kcpp'), 'WrapperMain')
driver = DriverWrapperMain(copy.deepcopy(self.driver_settings))
# run Anime4KCPP
self.process_pool.append(driver.upscale(self.current_input_video, output_video, self.scale_ratio, self.processes))
self.process_pool.append(self.driver_object.upscale(self.current_input_video, output_video))
self._wait()
Avalon.info(_('Upscaling completed'))
@ -494,24 +479,24 @@ class Upscaler:
framerate = float(Fraction(video_info['streams'][video_stream_index]['r_frame_rate']))
fm.pixel_format = video_info['streams'][video_stream_index]['pix_fmt']
# get a dict of all pixel formats and corresponding bit depth
pixel_formats = fm.get_pixel_formats()
if self.driver == 'waifu2x-caffe':
# get a dict of all pixel formats and corresponding bit depth
pixel_formats = fm.get_pixel_formats()
# try getting pixel format's corresponding bti depth
try:
self.bit_depth = pixel_formats[fm.pixel_format]
except KeyError:
Avalon.error(_('Unsupported pixel format: {}').format(fm.pixel_format))
raise UnsupportedPixelError(f'unsupported pixel format {fm.pixel_format}')
# try getting pixel format's corresponding bti depth
try:
self.driver_settings['output_depth'] = pixel_formats[fm.pixel_format]
except KeyError:
Avalon.error(_('Unsupported pixel format: {}').format(fm.pixel_format))
raise UnsupportedPixelError(f'unsupported pixel format {fm.pixel_format}')
Avalon.info(_('Framerate: {}').format(framerate))
# width/height will be coded width/height x upscale factor
if self.scale_ratio:
original_width = video_info['streams'][video_stream_index]['width']
original_height = video_info['streams'][video_stream_index]['height']
self.scale_width = int(self.scale_ratio * original_width)
self.scale_height = int(self.scale_ratio * original_height)
original_width = video_info['streams'][video_stream_index]['width']
original_height = video_info['streams'][video_stream_index]['height']
scale_width = int(self.scale_ratio * original_width)
scale_height = int(self.scale_ratio * original_height)
# upscale images one by one using waifu2x
Avalon.info(_('Starting to upscale extracted images'))
@ -523,7 +508,7 @@ class Upscaler:
# use user defined output size
self.process_pool.append(fm.assemble_video(framerate,
f'{self.scale_width}x{self.scale_height}',
f'{scale_width}x{scale_height}',
self.upscaled_frames))
self._wait()
Avalon.info(_('Conversion completed'))
@ -560,6 +545,7 @@ class Upscaler:
except (Exception, KeyboardInterrupt, SystemExit) as e:
with contextlib.suppress(ValueError):
self.cleanup_temp_directories()
self.running = False
raise e
# increment total number of videos processed

View File

@ -13,7 +13,7 @@ __ __ _ _ ___ __ __
Name: Video2X Controller
Creator: K4YT3X
Date Created: Feb 24, 2018
Last Modified: May 9, 2020
Last Modified: May 10, 2020
Editor: BrianPetkovsek
Last Modified: June 17, 2019
@ -103,21 +103,20 @@ def parse_arguments():
parser = argparse.ArgumentParser(prog='video2x', formatter_class=argparse.ArgumentDefaultsHelpFormatter, add_help=False)
# video options
general_options = parser.add_argument_group(_('General Options'))
general_options.add_argument('-h', '--help', action='help', help=_('show this help message and exit'))
general_options.add_argument('-i', '--input', type=pathlib.Path, help=_('source video file/directory'))
general_options.add_argument('-o', '--output', type=pathlib.Path, help=_('output video file/directory'))
general_options.add_argument('-c', '--config', type=pathlib.Path, help=_('video2x config file path'), action='store',
video2x_options = parser.add_argument_group(_('Video2X Options'))
video2x_options.add_argument('-h', '--help', action='help', help=_('show this help message and exit'))
video2x_options.add_argument('-i', '--input', type=pathlib.Path, help=_('source video file/directory'))
video2x_options.add_argument('-o', '--output', type=pathlib.Path, help=_('output video file/directory'))
video2x_options.add_argument('-c', '--config', type=pathlib.Path, help=_('video2x config file path'), action='store',
default=pathlib.Path(__file__).parent.absolute() / 'video2x.yaml')
general_options.add_argument('-d', '--driver', help=_('upscaling driver'), choices=AVAILABLE_DRIVERS, default='waifu2x_caffe')
general_options.add_argument('-p', '--processes', help=_('number of processes to use for upscaling'), action='store', type=int, default=1)
general_options.add_argument('-v', '--version', help=_('display version, lawful information and exit'), action='store_true')
video2x_options.add_argument('-v', '--version', help=_('display version, lawful information and exit'), action='store_true')
# scaling options
scaling_options = parser.add_argument_group(_('Scaling Options'))
scaling_options.add_argument('--width', help=_('output video width'), action='store', type=int)
scaling_options.add_argument('--height', help=_('output video height'), action='store', type=int)
scaling_options.add_argument('-r', '--ratio', help=_('scaling ratio'), action='store', type=float)
upscaling_options = parser.add_argument_group(_('Upscaling Options'))
upscaling_options.add_argument('-d', '--driver', help=_('upscaling driver'), choices=AVAILABLE_DRIVERS, default='waifu2x_caffe')
upscaling_options.add_argument('-r', '--ratio', help=_('scaling ratio'), action='store', type=float, default=2.0)
upscaling_options.add_argument('-p', '--processes', help=_('number of processes to use for upscaling'), action='store', type=int, default=1)
upscaling_options.add_argument('--preserve_frames', help=_('preserve extracted and upscaled frames'), action='store_true')
# if no driver arguments are specified
if '--' not in sys.argv:
@ -186,6 +185,13 @@ ffmpeg_settings['ffmpeg_path'] = os.path.expandvars(ffmpeg_settings['ffmpeg_path
image_format = config['video2x']['image_format'].lower()
preserve_frames = config['video2x']['preserve_frames']
# if preserve frames specified in command line
# overwrite config file options
if video2x_args.preserve_frames is True:
preserve_frames = True
# if cache directory not specified
# use default path: %TEMP%\video2x
if config['video2x']['video2x_cache_directory'] is None:
video2x_cache_directory = (pathlib.Path(tempfile.gettempdir()) / 'video2x')
else:
@ -211,8 +217,6 @@ try:
# set upscaler optional options
upscaler.driver = video2x_args.driver
upscaler.scale_width = video2x_args.width
upscaler.scale_height = video2x_args.height
upscaler.scale_ratio = video2x_args.ratio
upscaler.processes = video2x_args.processes
upscaler.video2x_cache_directory = video2x_cache_directory

View File

@ -18,8 +18,8 @@ waifu2x_caffe:
output_quality: -1 # output image quality
process: gpu # <cpu|gpu|cudnn> process mode
model_dir: null # path to custom model directory (don't append last / )
#scale_height: null # custom scale height
#scale_width: null # custom scale width
scale_height: 0 # custom scale height (specifying this will overwrite scale_ratio)
scale_width: 0 # custom scale width (specifying this will overwrite scale_ratio)
#scale_ratio: null # custom scale ratio
noise_level: 3 # <0|1|2|3> noise reduction level
mode: noise_scale # <noise|scale|noise_scale|auto_scale> image processing mode

View File

@ -4,7 +4,7 @@
Creator: Video2X GUI
Author: K4YT3X
Date Created: May 5, 2020
Last Modified: May 8, 2020
Last Modified: May 10, 2020
"""
# local imports
@ -219,6 +219,11 @@ class Video2XMainWindow(QMainWindow):
self.scale_ratio_double_spin_box = self.findChild(QDoubleSpinBox, 'scaleRatioDoubleSpinBox')
self.preserve_frames_check_box = self.findChild(QCheckBox, 'preserveFramesCheckBox')
# frame preview
self.frame_preview_show_preview_check_box = self.findChild(QCheckBox, 'framePreviewShowPreviewCheckBox')
self.frame_preview_keep_aspect_ratio_check_box = self.findChild(QCheckBox, 'framePreviewKeepAspectRatioCheckBox')
self.frame_preview_label = self.findChild(QLabel, 'framePreviewLabel')
# currently processing
self.currently_processing_label = self.findChild(QLabel, 'currentlyProcessingLabel')
self.current_progress_bar = self.findChild(QProgressBar, 'currentProgressBar')
@ -241,6 +246,8 @@ class Video2XMainWindow(QMainWindow):
self.enable_line_edit_file_drop(self.waifu2x_caffe_path_line_edit)
self.waifu2x_caffe_path_select_button = self.findChild(QPushButton, 'waifu2xCaffePathSelectButton')
self.waifu2x_caffe_path_select_button.clicked.connect(lambda: self.select_driver_binary_path(self.waifu2x_caffe_path_line_edit))
self.waifu2x_caffe_scale_width_spin_box = self.findChild(QSpinBox, 'waifu2xCaffeScaleWidthSpinBox')
self.waifu2x_caffe_scale_height_spin_box = self.findChild(QSpinBox, 'waifu2xCaffeScaleHeightSpinBox')
self.waifu2x_caffe_mode_combo_box = self.findChild(QComboBox, 'waifu2xCaffeModeComboBox')
self.waifu2x_caffe_noise_level_spin_box = self.findChild(QSpinBox, 'waifu2xCaffeNoiseLevelSpinBox')
self.waifu2x_caffe_process_combo_box = self.findChild(QComboBox, 'waifu2xCaffeProcessComboBox')
@ -377,6 +384,8 @@ class Video2XMainWindow(QMainWindow):
# waifu2x-caffe
settings = self.config['waifu2x_caffe']
self.waifu2x_caffe_scale_width_spin_box.setValue(settings['scale_width'])
self.waifu2x_caffe_scale_height_spin_box.setValue(settings['scale_height'])
self.waifu2x_caffe_path_line_edit.setText(str(pathlib.Path(os.path.expandvars(settings['path'])).absolute()))
self.waifu2x_caffe_mode_combo_box.setCurrentText(settings['mode'])
self.waifu2x_caffe_noise_level_spin_box.setValue(settings['noise_level'])
@ -441,6 +450,8 @@ class Video2XMainWindow(QMainWindow):
def resolve_driver_settings(self):
# waifu2x-caffe
self.config['waifu2x_caffe']['scale_width'] = self.waifu2x_caffe_scale_width_spin_box.value()
self.config['waifu2x_caffe']['scale_height'] = self.waifu2x_caffe_scale_height_spin_box.value()
self.config['waifu2x_caffe']['path'] = os.path.expandvars(self.waifu2x_caffe_path_line_edit.text())
self.config['waifu2x_caffe']['mode'] = self.waifu2x_caffe_mode_combo_box.currentText()
self.config['waifu2x_caffe']['noise_level'] = self.waifu2x_caffe_noise_level_spin_box.value()
@ -673,7 +684,7 @@ You can [submit an issue on GitHub](https://github.com/k4yt3x/video2x/issues/new
# initialize progress bar values
upscale_begin_time = time.time()
progress_callback.emit((upscale_begin_time, 0, 0, 0, 0, pathlib.Path()))
progress_callback.emit((upscale_begin_time, 0, 0, 0, 0, pathlib.Path(), pathlib.Path()))
# keep querying upscaling process and feed information to callback signal
while self.upscaler.running:
@ -683,12 +694,13 @@ You can [submit an issue on GitHub](https://github.com/k4yt3x/video2x/issues/new
self.upscaler.total_frames,
self.upscaler.total_processed,
self.upscaler.total_videos,
self.upscaler.current_input_video))
self.upscaler.current_input_video,
self.upscaler.last_frame_upscaled))
time.sleep(1)
# 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()))
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]
@ -697,6 +709,7 @@ You can [submit an issue on GitHub](https://github.com/k4yt3x/video2x/issues/new
total_processed = progress_information[3]
total_videos = progress_information[4]
current_input_video = progress_information[5]
last_frame_upscaled = progress_information[6]
# calculate fields based on frames and time elapsed
time_elapsed = time.time() - upscale_begin_time
@ -719,6 +732,27 @@ You can [submit an issue on GitHub](https://github.com/k4yt3x/video2x/issues/new
self.overall_progress_bar.setValue(total_processed)
self.currently_processing_label.setText('Currently Processing: {}'.format(str(current_input_video.name)))
# if show frame is checked, show preview image
if self.frame_preview_show_preview_check_box.isChecked() and last_frame_upscaled.is_file():
last_frame_pixmap = QtGui.QPixmap(str(last_frame_upscaled.absolute()))
# the -2 here behind geometry subtracts frame size from width and height
self.frame_preview_label.setPixmap(last_frame_pixmap.scaled(self.frame_preview_label.width() - 2,
self.frame_preview_label.height() - 2,
Qt.KeepAspectRatio))
# if keep aspect ratio is checked, don't stretch image
if self.frame_preview_keep_aspect_ratio_check_box.isChecked():
self.frame_preview_label.setScaledContents(False)
else:
self.frame_preview_label.setScaledContents(True)
# display image in label
self.frame_preview_label.show()
# if show frame is unchecked, clear image
elif self.frame_preview_show_preview_check_box.isChecked() is False:
self.frame_preview_label.clear()
def reset_progress_display(self):
# reset progress display UI elements
self.current_progress_bar.setMaximum(100)
@ -741,10 +775,10 @@ You can [submit an issue on GitHub](https://github.com/k4yt3x/video2x/issues/new
# resolve input and output directories from GUI
if len(self.input_table_data) == 0:
self.show_warning('Input path unspecified', standard_icon=QMessageBox.Warning)
self.show_warning('Input path unspecified')
return
if self.output_line_edit.text().strip() == '':
self.show_warning('Output path unspecified', standard_icon=QMessageBox.Warning)
self.show_warning('Output path unspecified')
return
if len(self.input_table_data) == 1:

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.12.0, 2020-05-10T00:59:03. -->
<!-- Written by QtCreator 4.12.0, 2020-05-11T04:13:22. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
@ -170,7 +170,7 @@
<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">C:/Users/k4yt3x/Documents/Projects/video2x/src</value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default"></value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>

View File

@ -235,99 +235,172 @@
</widget>
</item>
<item>
<widget class="QGroupBox" name="expressSettingsGroupBox">
<property name="title">
<string>Express Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QHBoxLayout" name="driverHorizontalLayout">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QGroupBox" name="expressSettingsGroupBox">
<property name="title">
<string>Express Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QLabel" name="driverLabel">
<layout class="QHBoxLayout" name="driverHorizontalLayout">
<item>
<widget class="QLabel" name="driverLabel">
<property name="text">
<string>Driver</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="driverComboBox">
<item>
<property name="text">
<string>Waifu2X Caffe</string>
</property>
</item>
<item>
<property name="text">
<string>Waifu2X Converter CPP</string>
</property>
</item>
<item>
<property name="text">
<string>Waifu2X NCNN Vulkan</string>
</property>
</item>
<item>
<property name="text">
<string>SRMD NCNN Vulkan</string>
</property>
</item>
<item>
<property name="text">
<string>Anime4KCPP</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="processesHorizontalLayout">
<item>
<widget class="QLabel" name="processesLabel">
<property name="text">
<string>Processes</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="processesSpinBox">
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="scaleRatioHorizontalLayout">
<item>
<widget class="QLabel" name="scaleRatioLabel">
<property name="text">
<string>Scale Ratio</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="scaleRatioDoubleSpinBox">
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>9999.989999999999782</double>
</property>
<property name="singleStep">
<double>0.500000000000000</double>
</property>
<property name="value">
<double>2.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="preserveFramesCheckBox">
<property name="text">
<string>Driver</string>
<string>Preserve Frames</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="driverComboBox">
<item>
<property name="text">
<string>Waifu2X Caffe</string>
</property>
</item>
<item>
<property name="text">
<string>Waifu2X Converter CPP</string>
</property>
</item>
<item>
<property name="text">
<string>Waifu2X NCNN Vulkan</string>
</property>
</item>
<item>
<property name="text">
<string>SRMD NCNN Vulkan</string>
</property>
</item>
<item>
<property name="text">
<string>Anime4KCPP</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="processesHorizontalLayout">
<item>
<widget class="QLabel" name="processesLabel">
<property name="text">
<string>Processes</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="processesSpinBox">
<property name="minimum">
<number>1</number>
<property name="tristate">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="scaleRatioHorizontalLayout">
</widget>
</item>
<item>
<widget class="QGroupBox" name="framePreviewGroupBox">
<property name="title">
<string>Frame Preview</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_14">
<item>
<widget class="QLabel" name="scaleRatioLabel">
<property name="text">
<string>Scale Ratio</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="scaleRatioDoubleSpinBox">
<property name="value">
<double>2.000000000000000</double>
</property>
</widget>
<layout class="QHBoxLayout" name="framPreviewHorizontalLayout">
<item>
<layout class="QVBoxLayout" name="framePreviewOptionsVerticalLayout">
<item>
<widget class="QCheckBox" name="framePreviewShowPreviewCheckBox">
<property name="text">
<string>Show Preview</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="framePreviewKeepAspectRatioCheckBox">
<property name="text">
<string>Keep Aspect Ratio</string>
</property>
</widget>
</item>
<item>
<spacer name="framePreviewOptionsVerticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="framePreviewLabel">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="text">
<string/>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="preserveFramesCheckBox">
<property name="text">
<string>Preserve Frames</string>
</property>
<property name="tristate">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
@ -360,6 +433,42 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="waifu2xCaffeScaleWidthHorizontalLayout">
<item>
<widget class="QLabel" name="waifu2xCaffeScaleWidthLabel">
<property name="text">
<string>Scale Width</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="waifu2xCaffeScaleWidthSpinBox">
<property name="maximum">
<number>999999</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="waifu2xCaffeScaleHeightHorizontalLayout">
<item>
<widget class="QLabel" name="waifu2xCaffeScaleHeightLabel">
<property name="text">
<string>Scale Height</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="waifu2xCaffeScaleHeightSpinBox">
<property name="maximum">
<number>999999</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="waifu2xCaffeModeHorizontalLayout">
<item>
@ -1123,7 +1232,17 @@
</widget>
</item>
<item>
<widget class="QSpinBox" name="anime4kCppPreFiltersSpinBox"/>
<widget class="QSpinBox" name="anime4kCppPreFiltersSpinBox">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>99999</number>
</property>
<property name="value">
<number>4</number>
</property>
</widget>
</item>
</layout>
</item>
@ -1137,7 +1256,11 @@
</widget>
</item>
<item>
<widget class="QSpinBox" name="anime4kCppPlatformIdSpinBox"/>
<widget class="QSpinBox" name="anime4kCppPlatformIdSpinBox">
<property name="maximum">
<number>99999</number>
</property>
</widget>
</item>
</layout>
</item>
@ -1153,7 +1276,7 @@
<item>
<widget class="QSpinBox" name="anime4kCppThreadsSpinBox">
<property name="maximum">
<number>999</number>
<number>99999</number>
</property>
<property name="value">
<number>16</number>
@ -1173,6 +1296,12 @@
</item>
<item>
<widget class="QDoubleSpinBox" name="anime4kCppStrengthColorSpinBox">
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>0.300000000000000</double>
</property>
@ -1227,7 +1356,11 @@
</widget>
</item>
<item>
<widget class="QSpinBox" name="anime4kCppDeviceIdSpinBox"/>
<widget class="QSpinBox" name="anime4kCppDeviceIdSpinBox">
<property name="maximum">
<number>99999</number>
</property>
</widget>
</item>
</layout>
</item>
@ -1241,7 +1374,17 @@
</widget>
</item>
<item>
<widget class="QSpinBox" name="anime4kCppPostFiltersSpinBox"/>
<widget class="QSpinBox" name="anime4kCppPostFiltersSpinBox">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>99999</number>
</property>
<property name="value">
<number>40</number>
</property>
</widget>
</item>
</layout>
</item>
@ -1301,6 +1444,9 @@
</item>
<item>
<widget class="QSpinBox" name="anime4kCppPassesSpinBox">
<property name="maximum">
<number>99999</number>
</property>
<property name="value">
<number>2</number>
</property>
@ -1333,6 +1479,9 @@
</item>
<item>
<widget class="QSpinBox" name="anime4kCppPushColorCountSpinBox">
<property name="maximum">
<number>99999</number>
</property>
<property name="value">
<number>2</number>
</property>
@ -1351,6 +1500,12 @@
</item>
<item>
<widget class="QDoubleSpinBox" name="anime4kCppStrengthGradientSpinBox">
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>

View File

@ -4,7 +4,7 @@
Name: Waifu2x Caffe Driver
Author: K4YT3X
Date Created: May 3, 2020
Last Modified: May 7, 2020
Last Modified: May 11, 2020
Description: This class is a high-level wrapper
for waifu2x-caffe.
@ -31,17 +31,24 @@ class WrapperMain:
self.driver_settings = driver_settings
self.print_lock = threading.Lock()
@staticmethod
def zero_to_one_float(value):
value = float(value)
if value < 0.0 or value > 1.0:
raise argparse.ArgumentTypeError(f'{value} is not between 0.0 and 1.0')
return value
@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('-i', '--input', type=pathlib.Path, help='File for loading')
# parser.add_argument('-o', '--output', type=pathlib.Path, help='File for outputting')
parser.add_argument('-i', '--input', type=str, help=argparse.SUPPRESS) # help='File for loading')
parser.add_argument('-o', '--output', type=str, help=argparse.SUPPRESS) # help='File for outputting')
parser.add_argument('-p', '--passes', type=int, help='Passes for processing')
parser.add_argument('-n', '--pushColorCount', type=int, help='Limit the number of color pushes')
parser.add_argument('-c', '--strengthColor', type=float, help='Strength for pushing color,range 0 to 1,higher for thinner')
parser.add_argument('-g', '--strengthGradient', type=float, help='Strength for pushing gradient,range 0 to 1,higher for sharper')
parser.add_argument('-c', '--strengthColor', type=WrapperMain.zero_to_one_float, help='Strength for pushing color,range 0 to 1,higher for thinner')
parser.add_argument('-g', '--strengthGradient', type=WrapperMain.zero_to_one_float, help='Strength for pushing gradient,range 0 to 1,higher for sharper')
parser.add_argument('-z', '--zoomFactor', type=float, help='zoom factor for resizing')
parser.add_argument('-t', '--threads', type=int, help='Threads count for video processing')
parser.add_argument('-f', '--fastMode', action='store_true', help='Faster but maybe low quality')
@ -58,7 +65,11 @@ class WrapperMain:
parser.add_argument('-C', '--codec', type=str, help='Specify the codec for encoding from mp4v(recommended in Windows), dxva(for Windows), avc1(H264, recommended in Linux), vp09(very slow), hevc(not support in Windowds), av01(not support in Windowds) (string [=mp4v])')
return parser.parse_args(arguments)
def upscale(self, input_file, output_file, zoom_factor, threads):
def load_configurations(self, upscaler):
self.driver_settings['zoomFactor'] = upscaler.scale_ratio
self.driver_settings['threads'] = upscaler.processes
def upscale(self, input_file, output_file):
"""This is the core function for WAIFU2X class
Arguments:
@ -71,8 +82,6 @@ class WrapperMain:
# overwrite config file settings
self.driver_settings['input'] = input_file
self.driver_settings['output'] = output_file
self.driver_settings['zoomFactor'] = zoom_factor
self.driver_settings['threads'] = threads
# Anime4KCPP will look for Anime4KCPPKernel.cl under the current working directory
# change the CWD to its containing directory so it will find it

View File

@ -4,7 +4,7 @@
Name: SRMD NCNN Vulkan Driver
Creator: K4YT3X
Date Created: April 26, 2020
Last Modified: May 9, 2020
Last Modified: May 11, 2020
Description: This class is a high-level wrapper
for srmd_ncnn_vulkan.
@ -42,8 +42,8 @@ class WrapperMain:
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=pathlib.Path, help='input image path (jpg/png) or directory')
# parser.add_argument('-o', type=pathlib.Path, help='output image path (png) or directory')
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('-n', type=int, choices=range(-1, 11), help='denoise level')
parser.add_argument('-s', type=int, choices=range(2, 5), help='upscale ratio')
parser.add_argument('-t', type=int, help='tile size (>=32)')
@ -53,7 +53,11 @@ class WrapperMain:
parser.add_argument('-x', action='store_true', help='enable tta mode')
return parser.parse_args(arguments)
def upscale(self, input_directory, output_directory, scale_ratio, threads):
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 SRMD ncnn Vulkan class
Arguments:
@ -65,8 +69,6 @@ class WrapperMain:
# overwrite config file settings
self.driver_settings['i'] = input_directory
self.driver_settings['o'] = output_directory
self.driver_settings['s'] = scale_ratio
self.driver_settings['j'] = '{}:{}:{}'.format(threads, threads, threads)
# by default, srmd-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

View File

@ -4,7 +4,7 @@
Name: Waifu2x Caffe Driver
Author: K4YT3X
Date Created: Feb 24, 2018
Last Modified: May 7, 2020
Last Modified: May 11, 2020
Description: This class is a high-level wrapper
for waifu2x-caffe.
@ -53,36 +53,30 @@ class WrapperMain:
parser.add_argument('-w', '--scale_width', type=int, help='custom scale width')
parser.add_argument('-s', '--scale_ratio', type=float, help='custom scale ratio')
parser.add_argument('-n', '--noise_level', type=int, choices=range(4), help='noise reduction level')
parser.add_argument('-m', '--mode', choices=['noise', 'scale', 'noise_scale'], help='image processing mode')
parser.add_argument('-e', '--output_extension', type=str, help='extention to output image file when output_path is (auto) or input_path is folder')
parser.add_argument('-m', '--mode', choices=['noise', 'scale', 'noise_scale', 'auto_scale'], help='image processing mode')
parser.add_argument('-e', '--output_extention', type=str, help='extention to output image file when output_path is (auto) or input_path is folder')
parser.add_argument('-l', '--input_extention_list', type=str, help='extention to input image file when input_path is folder')
# parser.add_argument('-o', '--output', type=pathlib.Path, help='path to output image file (when input_path is folder, output_path must be folder)')
# parser.add_argument('-i', '--input_file', type=pathlib.Path, help='(required) path to input image file')
parser.add_argument('-o', '--output', type=str, help=argparse.SUPPRESS) # help='path to output image file (when input_path is folder, output_path must be folder)')
parser.add_argument('-i', '--input_file', type=str, help=argparse.SUPPRESS) # help='(required) path to input image file')
return parser.parse_args(arguments)
def upscale(self, input_directory, output_directory, scale_ratio, scale_width, scale_height, image_format, bit_depth):
"""This is the core function for WAIFU2X class
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
Arguments:
input_directory {string} -- source directory path
output_directory {string} -- output directory path
width {int} -- output video width
height {int} -- output video height
# bit_depth will be 12 at this point
# it will up updated later
self.driver_settings['output_depth'] = 12
def upscale(self, input_directory, output_directory):
""" start upscaling process
"""
# overwrite config file settings
self.driver_settings['input_path'] = input_directory
self.driver_settings['output_path'] = output_directory
if scale_ratio:
self.driver_settings['scale_ratio'] = scale_ratio
elif scale_width and scale_height:
self.driver_settings['scale_width'] = scale_width
self.driver_settings['scale_height'] = scale_height
self.driver_settings['output_extention'] = image_format
self.driver_settings['output_depth'] = bit_depth
# list to be executed
# initialize the list with waifu2x binary path as the first element
execute = [self.driver_settings.pop('path')]

View File

@ -4,7 +4,7 @@
Name: Waifu2x Converter CPP Driver
Author: K4YT3X
Date Created: February 8, 2019
Last Modified: May 7, 2020
Last Modified: May 11, 2020
Description: This class is a high-level wrapper
for waifu2x-converter-cpp.
@ -61,12 +61,17 @@ class WrapperMain:
parser.add_argument('-g', '--generate-subdir', type=int, choices=range(2), help='Generate sub folder when recursive directory is enabled.')
parser.add_argument('-a', '--auto-naming', type=int, choices=range(2), help='Add postfix to output name when output path is not specified.\nSet 0 to disable this.')
parser.add_argument('-r', '--recursive-directory', type=int, choices=range(2), help='Search recursively through directories to find more images to process.')
# parser.add_argument('-o', '--output', type=pathlib.Pathh, help='path to output image file or directory (you should use the full path)')
# parser.add_argument('-i', '--input', type=pathlib.Path, help='(required) path to input image file or directory (you should use the full path)')
parser.add_argument('-o', '--output', type=str, help=argparse.SUPPRESS) # help='path to output image file or directory (you should use the full path)')
parser.add_argument('-i', '--input', type=str, help=argparse.SUPPRESS) # help='(required) path to input image file or directory (you should use the full path)')
parser.add_argument('--version', action='store_true', help='Displays version information and exits.')
return parser.parse_args(arguments)
def upscale(self, input_directory, output_directory, scale_ratio, jobs, image_format):
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()
def upscale(self, input_directory, output_directory):
""" Waifu2x Converter Driver Upscaler
This method executes the upscaling of extracted frames.
@ -80,9 +85,6 @@ class WrapperMain:
# overwrite config file settings
self.driver_settings['input'] = input_directory
self.driver_settings['output'] = output_directory
self.driver_settings['scale-ratio'] = scale_ratio
self.driver_settings['jobs'] = jobs
self.driver_settings['output-format'] = image_format
# models_rgb must be specified manually for waifu2x-converter-cpp
# if it's not specified in the arguments, create automatically

View File

@ -4,7 +4,7 @@
Name: Waifu2x NCNN Vulkan Driver
Creator: SAT3LL
Date Created: June 26, 2019
Last Modified: May 9, 2020
Last Modified: May 11, 2020
Editor: K4YT3X
Last Modified: February 22, 2020
@ -45,8 +45,8 @@ class WrapperMain:
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=pathlib.Path, help='input image path (jpg/png) or directory')
# parser.add_argument('-o', type=pathlib.Path, help='output image path (png) or directory')
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('-n', type=int, choices=range(-1, 4), help='denoise level')
parser.add_argument('-s', type=int, choices=range(1, 3), help='upscale ratio')
parser.add_argument('-t', type=int, help='tile size (>=32)')
@ -56,7 +56,11 @@ class WrapperMain:
parser.add_argument('-x', action='store_true', help='enable tta mode')
return parser.parse_args(arguments)
def upscale(self, input_directory, output_directory, scale_ratio, threads):
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 WAIFU2X class
Arguments:
@ -68,8 +72,6 @@ class WrapperMain:
# overwrite config file settings
self.driver_settings['i'] = input_directory
self.driver_settings['o'] = output_directory
self.driver_settings['s'] = int(scale_ratio)
self.driver_settings['j'] = '{}:{}:{}'.format(threads, threads, threads)
# by default, waifu2x-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