added time elapsed, time remaining and speed rate

This commit is contained in:
k4yt3x 2020-05-06 20:20:38 -04:00
parent 5fbc195740
commit 3168737fd4
2 changed files with 205 additions and 116 deletions

View File

@ -10,16 +10,13 @@ Last Modified: May 6, 2020
# local imports
from upscaler import Upscaler
# built-in imports
import pathlib
import sys
# built-in imports
import contextlib
import pathlib
import re
import shutil
import sys
import tempfile
import threading
import time
import traceback
import yaml
@ -45,21 +42,45 @@ AVAILABLE_DRIVERS = {
'Anime4KCPP': 'anime4kcpp'
}
def resource_path(relative_path: str) -> pathlib.Path:
try:
base_path = pathlib.Path(sys._MEIPASS)
except Exception:
base_path = pathlib.Path(__file__).parent
return base_path / relative_path
class UpscalerSignals(QObject):
finished = pyqtSignal()
class WorkerSignals(QObject):
progress = pyqtSignal(tuple)
error = pyqtSignal(str)
finished = pyqtSignal()
class Worker(QRunnable):
class ProgressBarWorker(QRunnable):
def __init__(self, fn, *args, **kwargs):
super(ProgressBarWorker, self).__init__()
self.fn = fn
self.args = args
self.kwargs = kwargs
self.signals = WorkerSignals()
self.kwargs['progress_callback'] = self.signals.progress
@pyqtSlot()
def run(self):
try:
self.fn(*self.args, **self.kwargs)
except Exception:
pass
class UpscalerWorker(QRunnable):
def __init__(self, fn, *args, **kwargs):
super(Worker, self).__init__()
super(UpscalerWorker, self).__init__()
# Store constructor arguments (re-used for processing)
self.fn = fn
self.args = args
self.kwargs = kwargs
self.signals = UpscalerSignals()
self.signals = WorkerSignals()
@pyqtSlot()
def run(self):
@ -78,9 +99,9 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
uic.loadUi('video2x_gui.ui', self)
uic.loadUi(str(resource_path('video2x_gui.ui')), self)
self.video2x_icon_path = str((pathlib.Path(__file__).parent / 'images' / 'video2x.png').absolute())
self.video2x_icon_path = str(resource_path('images/video2x.png'))
self.setWindowTitle(f'Video2X GUI {VERSION}')
self.setWindowIcon(QtGui.QIcon(self.video2x_icon_path))
@ -126,8 +147,11 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
# progress bar and start/stop controls
self.progress_bar = self.findChild(QtWidgets.QProgressBar, 'progressBar')
self.time_elapsed_label = self.findChild(QtWidgets.QLabel, 'timeElapsedLabel')
self.time_remaining_label = self.findChild(QtWidgets.QLabel, 'timeRemainingLabel')
self.rate_label = self.findChild(QtWidgets.QLabel, 'rateLabel')
self.start_button = self.findChild(QtWidgets.QPushButton, 'startButton')
self.start_button.clicked.connect(self.upscale)
self.start_button.clicked.connect(self.start)
self.stop_button = self.findChild(QtWidgets.QPushButton, 'stopButton')
self.stop_button.clicked.connect(self.stop)
@ -482,7 +506,7 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
message_box.setText(message)
message_box.exec_()
def start_progress_bar(self):
def start_progress_bar(self, progress_callback):
# initialize variables early
self.upscaler.progress_bar_exit_signal = False
@ -490,14 +514,43 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
self.upscaler.total_frames = 1
# initialize progress bar values
self.progress_bar.setValue(0)
upscale_begin_time = time.time()
progress_callback.emit((0, 0, 0, upscale_begin_time))
# keep querying upscaling process and feed information to callback signal
while not self.upscaler.progress_bar_exit_signal:
self.progress_bar.setValue(int(100 * self.upscaler.total_frames_upscaled / self.upscaler.total_frames))
progress_callback.emit((int(100 * self.upscaler.total_frames_upscaled / self.upscaler.total_frames),
self.upscaler.total_frames_upscaled,
self.upscaler.total_frames,
upscale_begin_time))
time.sleep(1)
self.progress_bar.setValue(100)
def upscale(self):
# upscale process will stop at 99%
# so it's set to 100 manually when all is done
progress_callback.emit((100, 0, 0, upscale_begin_time))
def set_progress(self, progress_information: tuple):
progress_percentage = progress_information[0]
total_frames_upscaled = progress_information[1]
total_frames = progress_information[2]
upscale_begin_time = progress_information[3]
# calculate fields based on frames and time elapsed
time_elapsed = time.time() - upscale_begin_time
try:
rate = total_frames_upscaled / (time.time() - upscale_begin_time)
time_remaining = (total_frames - total_frames_upscaled) / rate
except Exception:
rate = 0.0
time_remaining = 0.0
# set calculated values in GUI
self.progress_bar.setValue(progress_percentage)
self.time_elapsed_label.setText('Time Elapsed: {}'.format(time.strftime("%H:%M:%S", time.gmtime(time_elapsed))))
self.time_remaining_label.setText('Time Remaining: {}'.format(time.strftime("%H:%M:%S", time.gmtime(time_remaining))))
self.rate_label.setText('Rate (FPS): {}'.format(round(rate, 2)))
def start(self):
# start execution
try:
@ -505,6 +558,13 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
self.begin_time = time.time()
# resolve input and output directories from GUI
if self.input_line_edit.text().strip() == '':
self.show_error('Input path not specified')
return
if self.output_line_edit.text().strip() == '':
self.show_error('Output path not specified')
return
input_directory = pathlib.Path(self.input_line_edit.text())
output_directory = pathlib.Path(self.output_line_edit.text())
@ -520,8 +580,6 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
# if input specified is a single file
if input_directory.is_file():
# upscale single video file
# check for input output format mismatch
if output_directory.is_dir():
self.show_error('Input and output path type mismatch\n\
@ -547,11 +605,12 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
# start progress bar
if AVAILABLE_DRIVERS[self.driver_combo_box.currentText()] != 'anime4kcpp':
progress_bar_worker = Worker(self.start_progress_bar)
progress_bar_worker = ProgressBarWorker(self.start_progress_bar)
progress_bar_worker.signals.progress.connect(self.set_progress)
self.threadpool.start(progress_bar_worker)
# run upscaler
worker = Worker(self.upscaler.run)
worker = UpscalerWorker(self.upscaler.run)
worker.signals.error.connect(self.upscale_errored)
worker.signals.finished.connect(self.upscale_completed)
self.threadpool.start(worker)
@ -582,11 +641,11 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
# start progress bar
if AVAILABLE_DRIVERS[self.driver_combo_box.currentText()] != 'anime4kcpp':
progress_bar_worker = Worker(self.start_progress_bar)
progress_bar_worker = ProgressBarWorker(self.start_progress_bar)
self.threadpool.start(progress_bar_worker)
# run upscaler
worker = Worker(self.upscaler.run)
worker = UpscalerWorker(self.upscaler.run)
worker.signals.error.connect(self.upscale_errored)
worker.signals.finished.connect(self.upscale_completed)
self.threadpool.start(worker)
@ -598,8 +657,6 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
except Exception:
self.upscale_errored(traceback.format_exc())
finally:
self.upscale_completed()
def upscale_errored(self, error_message):
@ -624,7 +681,6 @@ class Video2XMainWindow(QtWidgets.QMainWindow):
# TODO unimplemented yet
pass
app = QtWidgets.QApplication(sys.argv)
window = Video2XMainWindow()
window.show()

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>617</width>
<height>474</height>
<width>691</width>
<height>503</height>
</rect>
</property>
<property name="windowTitle">
@ -194,82 +194,78 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QVBoxLayout" name="expressSettingsVerticalLayout">
<layout class="QHBoxLayout" name="driverHorizontalLayout">
<item>
<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>
<widget class="QLabel" name="driverLabel">
<property name="text">
<string>Driver</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="processesHorizontalLayout">
<widget class="QComboBox" name="driverComboBox">
<item>
<widget class="QLabel" name="processesLabel">
<property name="text">
<string>Processes</string>
</property>
</widget>
<property name="text">
<string>Waifu2X Caffe</string>
</property>
</item>
<item>
<widget class="QSpinBox" name="processesSpinBox">
<property name="minimum">
<number>1</number>
</property>
</widget>
<property name="text">
<string>Waifu2X Converter CPP</string>
</property>
</item>
</layout>
<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>
<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="value">
<double>2.000000000000000</double>
</property>
</widget>
</item>
</layout>
<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="value">
<double>2.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
@ -1188,7 +1184,7 @@
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="controlsHorizontalLayout">
<layout class="QVBoxLayout" name="controlsVerticalLayout">
<item>
<widget class="QProgressBar" name="progressBar">
<property name="value">
@ -1197,24 +1193,61 @@
</widget>
</item>
<item>
<widget class="QPushButton" name="startButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="stopButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Stop</string>
</property>
</widget>
<layout class="QHBoxLayout" name="timeControlsHorizontalLayout">
<item>
<widget class="QLabel" name="timeElapsedLabel">
<property name="acceptDrops">
<bool>false</bool>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="text">
<string>Time Elapsed: 00:00:00</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="timeRemainingLabel">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="text">
<string>Time Remaining: 00:00:00</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="rateLabel">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="text">
<string>Rate (FPS): 0.0</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="startButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="stopButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Stop</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
@ -1225,7 +1258,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>617</width>
<width>691</width>
<height>21</height>
</rect>
</property>