mirror of
https://github.com/deepfakes/faceswap
synced 2025-06-09 04:36:50 -04:00
* Core Updates - Remove lib.utils.keras_backend_quiet and replace with get_backend() where relevant - Document lib.gpu_stats and lib.sys_info - Remove call to GPUStats.is_plaidml from convert and replace with get_backend() - lib.gui.menu - typofix * Update Dependencies Bump Tensorflow Version Check * Port extraction to tf2 * Add custom import finder for loading Keras or tf.keras depending on backend * Add `tensorflow` to KerasFinder search path * Basic TF2 training running * model.initializers - docstring fix * Fix and pass tests for tf2 * Replace Keras backend tests with faceswap backend tests * Initial optimizers update * Monkey patch tf.keras optimizer * Remove custom Adam Optimizers and Memory Saving Gradients * Remove multi-gpu option. Add Distribution to cli * plugins.train.model._base: Add Mirror, Central and Default distribution strategies * Update tensorboard kwargs for tf2 * Penalized Loss - Fix for TF2 and AMD * Fix syntax for tf2.1 * requirements typo fix * Explicit None for clipnorm if using a distribution strategy * Fix penalized loss for distribution strategies * Update Dlight * typo fix * Pin to TF2.2 * setup.py - Install tensorflow from pip if not available in Conda * Add reduction options and set default for mirrored distribution strategy * Explicitly use default strategy rather than nullcontext * lib.model.backup_restore documentation * Remove mirrored strategy reduction method and default based on OS * Initial restructure - training * Remove PingPong Start model.base refactor * Model saving and resuming enabled * More tidying up of model.base * Enable backup and snapshotting * Re-enable state file Remove loss names from state file Fix print loss function Set snapshot iterations correctly * Revert original model to Keras Model structure rather than custom layer Output full model and sub model summary Change NNBlocks to callables rather than custom keras layers * Apply custom Conv2D layer * Finalize NNBlock restructure Update Dfaker blocks * Fix reloading model under a different distribution strategy * Pass command line arguments through to trainer * Remove training_opts from model and reference params directly * Tidy up model __init__ * Re-enable tensorboard logging Suppress "Model Not Compiled" warning * Fix timelapse * lib.model.nnblocks - Bugfix residual block Port dfaker bugfix original * dfl-h128 ported * DFL SAE ported * IAE Ported * dlight ported * port lightweight * realface ported * unbalanced ported * villain ported * lib.cli.args - Update Batchsize + move allow_growth to config * Remove output shape definition Get image sizes per side rather than globally * Strip mask input from encoder * Fix learn mask and output learned mask to preview * Trigger Allow Growth prior to setting strategy * Fix GUI Graphing * GUI - Display batchsize correctly + fix training graphs * Fix penalized loss * Enable mixed precision training * Update analysis displayed batch to match input * Penalized Loss - Multi-GPU Fix * Fix all losses for TF2 * Fix Reflect Padding * Allow different input size for each side of the model * Fix conv-aware initialization on reload * Switch allow_growth order * Move mixed_precision to cli * Remove distrubution strategies * Compile penalized loss sub-function into LossContainer * Bump default save interval to 250 Generate preview on first iteration but don't save Fix iterations to start at 1 instead of 0 Remove training deprecation warnings Bump some scripts.train loglevels * Add ability to refresh preview on demand on pop-up window * Enable refresh of training preview from GUI * Fix Convert Debug logging in Initializers * Fix Preview Tool * Update Legacy TF1 weights to TF2 Catch stats error on loading stats with missing logs * lib.gui.popup_configure - Make more responsive + document * Multiple Outputs supported in trainer Original Model - Mask output bugfix * Make universal inference model for convert Remove scaling from penalized mask loss (now handled at input to y_true) * Fix inference model to work properly with all models * Fix multi-scale output for convert * Fix clipnorm issue with distribution strategies Edit error message on OOM * Update plaidml losses * Add missing file * Disable gmsd loss for plaidnl * PlaidML - Basic training working * clipnorm rewriting for mixed-precision * Inference model creation bugfixes * Remove debug code * Bugfix: Default clipnorm to 1.0 * Remove all mask inputs from training code * Remove mask inputs from convert * GUI - Analysis Tab - Docstrings * Fix rate in totals row * lib.gui - Only update display pages if they have focus * Save the model on first iteration * plaidml - Fix SSIM loss with penalized loss * tools.alignments - Remove manual and fix jobs * GUI - Remove case formatting on help text * gui MultiSelect custom widget - Set default values on init * vgg_face2 - Move to plugins.extract.recognition and use plugins._base base class cli - Add global GPU Exclude Option tools.sort - Use global GPU Exlude option for backend lib.model.session - Exclude all GPUs when running in CPU mode lib.cli.launcher - Set backend to CPU mode when all GPUs excluded * Cascade excluded devices to GPU Stats * Explicit GPU selection for Train and Convert * Reduce Tensorflow Min GPU Multiprocessor Count to 4 * remove compat.v1 code from extract * Force TF to skip mixed precision compatibility check if GPUs have been filtered * Add notes to config for non-working AMD losses * Rasie error if forcing extract to CPU mode * Fix loading of legace dfl-sae weights + dfl-sae typo fix * Remove unused requirements Update sphinx requirements Fix broken rst file locations * docs: lib.gui.display * clipnorm amd condition check * documentation - gui.display_analysis * Documentation - gui.popup_configure * Documentation - lib.logger * Documentation - lib.model.initializers * Documentation - lib.model.layers * Documentation - lib.model.losses * Documentation - lib.model.nn_blocks * Documetation - lib.model.normalization * Documentation - lib.model.session * Documentation - lib.plaidml_stats * Documentation: lib.training_data * Documentation: lib.utils * Documentation: plugins.train.model._base * GUI Stats: prevent stats from using GPU * Documentation - Original Model * Documentation: plugins.model.trainer._base * linting * unit tests: initializers + losses * unit tests: nn_blocks * bugfix - Exclude gpu devices in train, not include * Enable Exclude-Gpus in Extract * Enable exclude gpus in tools * Disallow multiple plugin types in a single model folder * Automatically add exclude_gpus argument in for cpu backends * Cpu backend fixes * Relax optimizer test threshold * Default Train settings - Set mask to Extended * Update Extractor cli help text Update to Python 3.8 * Fix FAN to run on CPU * lib.plaidml_tools - typofix * Linux installer - check for curl * linux installer - typo fix
183 lines
6.8 KiB
Python
183 lines
6.8 KiB
Python
#!/usr/bin python3
|
|
""" Display Frame of the Faceswap GUI
|
|
|
|
This is the large right hand area of the GUI. At default, the Analysis tab is always displayed
|
|
here. Further optional tabs will also be displayed depending on the currently executing Faceswap
|
|
task. """
|
|
|
|
import logging
|
|
import tkinter as tk
|
|
from tkinter import ttk
|
|
|
|
from .display_analysis import Analysis
|
|
from .display_command import GraphDisplay, PreviewExtract, PreviewTrain
|
|
from .utils import get_config
|
|
|
|
logger = logging.getLogger(__name__) # pylint: disable=invalid-name
|
|
|
|
|
|
class DisplayNotebook(ttk.Notebook): # pylint: disable=too-many-ancestors
|
|
""" The tkinter Notebook that holds the display items.
|
|
|
|
Parameters
|
|
----------
|
|
parent: :class:`tk.PanedWindow`
|
|
The paned window that holds the Display Notebook
|
|
"""
|
|
|
|
def __init__(self, parent):
|
|
logger.debug("Initializing %s", self.__class__.__name__)
|
|
super().__init__(parent)
|
|
parent.add(self)
|
|
tk_vars = get_config().tk_vars
|
|
self._wrapper_var = tk_vars["display"]
|
|
self._runningtask = tk_vars["runningtask"]
|
|
|
|
self._set_wrapper_var_trace()
|
|
self._add_static_tabs()
|
|
# pylint:disable=unnecessary-comprehension
|
|
self._static_tabs = [child for child in self.tabs()]
|
|
self.bind("<<NotebookTabChanged>>", self._on_tab_change)
|
|
logger.debug("Initialized %s", self.__class__.__name__)
|
|
|
|
@property
|
|
def runningtask(self):
|
|
""" :class:`tkinter.BooleanVar`: The global tkinter variable that indicates whether a
|
|
Faceswap task is currently running or not. """
|
|
return self._runningtask
|
|
|
|
def _set_wrapper_var_trace(self):
|
|
""" Sets the trigger to update the displayed notebook's pages when the global tkinter
|
|
variable `display` is updated in the :class:`~lib.gui.wrapper.ProcessWrapper`. """
|
|
logger.debug("Setting wrapper var trace")
|
|
self._wrapper_var.trace("w", self._update_displaybook)
|
|
|
|
def _add_static_tabs(self):
|
|
""" Add the tabs to the Display Notebook that are permanently displayed.
|
|
|
|
Currently this is just the `Analysis` tab.
|
|
"""
|
|
logger.debug("Adding static tabs")
|
|
for tab in ("job queue", "analysis"):
|
|
if tab == "job queue":
|
|
continue # Not yet implemented
|
|
if tab == "analysis":
|
|
helptext = {"stats":
|
|
"Summary statistics for each training session"}
|
|
frame = Analysis(self, tab, helptext)
|
|
else:
|
|
frame = self._add_frame()
|
|
self.add(frame, text=tab.title())
|
|
|
|
def _add_frame(self):
|
|
""" Add a single frame for holding a static tab's contents.
|
|
|
|
Returns
|
|
-------
|
|
ttk.Frame
|
|
The frame, packed into position
|
|
"""
|
|
logger.debug("Adding frame")
|
|
frame = ttk.Frame(self)
|
|
frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5, pady=5)
|
|
return frame
|
|
|
|
def _command_display(self, command):
|
|
""" Build the relevant command specific tabs based on the incoming Faceswap command.
|
|
|
|
Parameters
|
|
----------
|
|
command: str
|
|
The Faceswap command that is being executed
|
|
"""
|
|
build_tabs = getattr(self, "_{}_tabs".format(command))
|
|
build_tabs()
|
|
|
|
def _extract_tabs(self, command="extract"):
|
|
""" Build the display tabs that are used for Faceswap extract and convert tasks.
|
|
|
|
Notes
|
|
-----
|
|
The same display tabs are used for both convert and extract tasks.
|
|
|
|
command: [`"extract"`, `"convert"`], optional
|
|
The command that the display tabs are being built for. Default: `"extract"`
|
|
|
|
"""
|
|
logger.debug("Build extract tabs")
|
|
helptext = ("Updates preview from output every 5 "
|
|
"seconds to limit disk contention")
|
|
PreviewExtract(self, "preview", helptext, 5000, command)
|
|
logger.debug("Built extract tabs")
|
|
|
|
def _train_tabs(self):
|
|
""" Build the display tabs that are used for the Faceswap train task."""
|
|
logger.debug("Build train tabs")
|
|
for tab in ("graph", "preview"):
|
|
if tab == "graph":
|
|
helptext = "Graph showing Loss vs Iterations"
|
|
GraphDisplay(self, "graph", helptext, 5000)
|
|
elif tab == "preview":
|
|
helptext = "Training preview. Updated on every save iteration"
|
|
PreviewTrain(self, "preview", helptext, 1000)
|
|
logger.debug("Built train tabs")
|
|
|
|
def _convert_tabs(self):
|
|
""" Build the display tabs that are used for the Faceswap convert task.
|
|
|
|
Notes
|
|
-----
|
|
The tabs displayed are the same as used for extract, so :func:`_extract_tabs` is called.
|
|
"""
|
|
logger.debug("Build convert tabs")
|
|
self._extract_tabs(command="convert")
|
|
logger.debug("Built convert tabs")
|
|
|
|
def _remove_tabs(self):
|
|
""" Remove all optional displayed command specific tabs from the notebook. """
|
|
for child in self.tabs():
|
|
if child in self._static_tabs:
|
|
continue
|
|
logger.debug("removing child: %s", child)
|
|
child_name = child.split(".")[-1]
|
|
child_object = self.children[child_name] # returns the OptionalDisplayPage object
|
|
child_object.close() # Call the OptionalDisplayPage close() method
|
|
self.forget(child)
|
|
|
|
def _update_displaybook(self, *args): # pylint: disable=unused-argument
|
|
""" Callback to be executed when the global tkinter variable `display`
|
|
(:attr:`wrapper_var`) is updated when a Faceswap task is executed.
|
|
|
|
Currently only updates when a core faceswap task (extract, train or convert) is executed.
|
|
|
|
Parameters
|
|
----------
|
|
args: tuple
|
|
Required for tkinter callback events, but unused.
|
|
|
|
"""
|
|
command = self._wrapper_var.get()
|
|
self._remove_tabs()
|
|
if not command or command not in ("extract", "train", "convert"):
|
|
return
|
|
self._command_display(command)
|
|
|
|
def _on_tab_change(self, event): # pylint:disable=unused-argument
|
|
""" Event trigger for tab change events.
|
|
|
|
Calls the selected tabs :func:`on_tab_select` method, if it exists, otherwise returns.
|
|
|
|
Parameters
|
|
----------
|
|
event: tkinter callback event
|
|
Required, but unused
|
|
"""
|
|
selected = self.select().split(".")[-1]
|
|
logger.debug("Selected tab: %s", selected)
|
|
selected_object = self.children[selected]
|
|
if hasattr(selected_object, "on_tab_select"):
|
|
logger.debug("Calling on_tab_select for '%s'", selected_object)
|
|
selected_object.on_tab_select()
|
|
else:
|
|
logger.debug("Object does not have on_tab_select method. Returning: '%s'",
|
|
selected_object)
|