Skip to content

Commit

Permalink
Training startup updates
Browse files Browse the repository at this point in the history
  - Remove alignments path option from cli
  - Restructure training_data.py
  - Load alignment data from PNG header during first epoch
  - lib.image.read_image_batch - Add option to return metadata
  - lib.utils.get_image_paths - Add option for explicit extension
  - plugins.train.trainer._base - remove pre-cache alignments code
  - scripts.train - Check first image in training folders for metadata
  - Documentation
  • Loading branch information
torzdf committed Mar 21, 2021
1 parent 51376be commit 29cfdaa
Show file tree
Hide file tree
Showing 11 changed files with 1,356 additions and 1,445 deletions.
24 changes: 24 additions & 0 deletions docs/full/lib/training.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
****************
training package
****************

The training Package handles the processing of faces for feeding into a Faceswap model.

.. contents:: Contents
:local:

augmentation module
===================

.. automodule:: lib.training.augmentation
:members:
:undoc-members:
:show-inheritance:

generator module
================

.. automodule:: lib.training.generator
:members:
:undoc-members:
:show-inheritance:
18 changes: 0 additions & 18 deletions docs/full/lib/training_data.rst

This file was deleted.

22 changes: 0 additions & 22 deletions lib/cli/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -872,17 +872,6 @@ def get_argument_list():
help=_("Input directory. A directory containing training images for face A. This is "
"the original face, i.e. the face that you want to remove and replace with "
"face B.")))
argument_list.append(dict(
opts=("-ala", "--alignments-A"),
action=FileFullPaths,
filetypes='alignments',
type=str,
dest="alignments_path_a",
default=None,
group=_("faces"),
help=_("DEPRECATED - This option will be removed in a future update. Path to "
"alignments file for training set A. Defaults to <input-A>/alignments.json if "
"not provided.")))
argument_list.append(dict(
opts=("-B", "--input-B"),
action=DirFullPaths,
Expand All @@ -892,17 +881,6 @@ def get_argument_list():
help=_("Input directory. A directory containing training images for face B. This is "
"the swap face, i.e. the face that you want to place onto the head of person "
"A.")))
argument_list.append(dict(
opts=("-alb", "--alignments-B"),
action=FileFullPaths,
filetypes='alignments',
type=str,
dest="alignments_path_b",
default=None,
group=_("faces"),
help=_("DEPRECATED - This option will be removed in a future update. Path to "
"alignments file for training set B. Defaults to <input-B>/alignments.json if "
"not provided.")))
argument_list.append(dict(
opts=("-m", "--model-dir"),
action=DirFullPaths,
Expand Down
24 changes: 19 additions & 5 deletions lib/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ def read_image(filename, raise_error=False, with_metadata=False):
return retval


def read_image_batch(filenames):
def read_image_batch(filenames, with_metadata=False):
""" Load a batch of images from the given file locations.
Leverages multi-threading to load multiple images from disk at the same time leading to vastly
Expand All @@ -315,6 +315,10 @@ def read_image_batch(filenames):
----------
filenames: list
A list of ``str`` full paths to the images to be loaded.
with_metadata: bool, optional
Only returns a value if the images loaded are extracted Faceswap faces. If ``True`` then
returns the Faceswap metadata stored with in a Face images .png exif header.
Default: ``False``
Returns
-------
Expand All @@ -333,20 +337,30 @@ def read_image_batch(filenames):
logger.trace("Requested batch: '%s'", filenames)
executor = futures.ThreadPoolExecutor()
with executor:
images = {executor.submit(read_image, filename, raise_error=True): filename
images = {executor.submit(read_image, filename,
raise_error=True, with_metadata=with_metadata): filename
for filename in filenames}
batch = [None for _ in range(len(filenames))]
if with_metadata:
meta = [None for _ in range(len(filenames))]
# There is no guarantee that the same filename will not be passed through multiple times
# (and when shuffle is true this can definitely happen), so we can't just call
# filenames.index().
return_indices = {filename: [idx for idx, fname in enumerate(filenames)
if fname == filename]
for filename in set(filenames)}
for future in futures.as_completed(images):
batch[return_indices[images[future]].pop()] = future.result()
return_idx = return_indices[images[future]].pop()
if with_metadata:
batch[return_idx], meta[return_idx] = future.result()
else:
batch[return_idx] = future.result()

batch = np.array(batch)
logger.trace("Returning images: (filenames: %s, batch shape: %s)", filenames, batch.shape)
return batch
retval = (batch, meta) if with_metadata else batch
logger.trace("Returning images: (filenames: %s, batch shape: %s, with_metadata: %s)",
filenames, batch.shape, with_metadata)
return retval


def read_image_meta(filename):
Expand Down
6 changes: 6 additions & 0 deletions lib/training/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env python3
""" Package for handling alignments files, detected faces and aligned faces along with their
associated objects. """

from .augmentation import ImageAugmentation
from .generator import TrainingDataGenerator
Loading

0 comments on commit 29cfdaa

Please sign in to comment.