alignments tool - Add batch mode

This commit is contained in:
torzdf 2023-02-24 00:38:28 +00:00
parent a076afa910
commit ec95c19534
7 changed files with 377 additions and 65 deletions

View File

@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: faceswap.spanish\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-14 18:36+0100\n"
"PO-Revision-Date: 2022-09-14 18:38+0100\n"
"POT-Creation-Date: 2023-02-24 00:27+0000\n"
"PO-Revision-Date: 2023-02-24 00:36+0000\n"
"Last-Translator: \n"
"Language-Team: tokafondo\n"
"Language: es_ES\n"
@ -47,8 +47,8 @@ msgstr " Debe indicar una carpeta de caras (-fc)."
#: tools/alignments/cli.py:46
msgid ""
" Must Pass in either a frames folder/source video file OR afaces folder (-fr "
"or -fc)."
" Must Pass in either a frames folder/source video file OR a faces folder (-"
"fr or -fc)."
msgstr ""
" Debe indicar una carpeta de fotogramas o archivo de vídeo de origen, o una "
"carpeta de caras (-fr o -fc)."
@ -82,11 +82,11 @@ msgid ""
"{1}\n"
"L|'from-faces': Generate alignment file(s) from a folder of extracted faces. "
"if the folder of faces comes from multiple sources, then multiple alignments "
"files will be created. NB: for faces which have been extracted folders of "
"source images, rather than a video, a single alignments file will be created "
"as there is no way for the process to know how many folders of images were "
"originally used. You do not need to provide an alignments file path to run "
"this job. {3}\n"
"files will be created. NB: for faces which have been extracted from folders "
"of source images, rather than a video, a single alignments file will be "
"created as there is no way for the process to know how many folders of "
"images were originally used. You do not need to provide an alignments file "
"path to run this job. {3}\n"
"L|'missing-alignments': Identify frames that do not exist in the alignments "
"file.{2}{0}\n"
"L|'missing-frames': Identify frames in the alignments file that do not "
@ -159,7 +159,7 @@ msgstr ""
"directorio de origen."
#: tools/alignments/cli.py:110 tools/alignments/cli.py:123
#: tools/alignments/cli.py:130 tools/alignments/cli.py:149
#: tools/alignments/cli.py:130 tools/alignments/cli.py:137
msgid "data"
msgstr "datos"
@ -187,12 +187,55 @@ msgstr ""
"Directorio que contiene los fotogramas de origen de los que se extrajeron "
"las caras."
#: tools/alignments/cli.py:140 tools/alignments/cli.py:164
#: tools/alignments/cli.py:174
#: tools/alignments/cli.py:138
msgid ""
"R|Run the aligmnents tool on multiple sources. The following jobs support "
"batch mode:\n"
"L|draw, extract, from-faces, missing-alignments, missing-frames, no-faces, "
"sort, spatial.\n"
"If batch mode is selected then the other options should be set as follows:\n"
"L|alignments_file: For 'sort' and 'spatial' this should point to the parent "
"folder containing the alignments files to be processed. For all other jobs "
"this option is ignored, and the alignments files must exist at their default "
"location relative to the original frames folder/video.\n"
"L|faces_dir: For 'from-faces' this should be a parent folder, containing sub-"
"folders of extracted faces from which to generate alignments files. For "
"'extract' this should be a parent folder where sub-folders will be created "
"for each extraction to be run. For all other jobs this option is ignored.\n"
"L|frames_dir: For 'draw', 'extract', 'missing-alignments', 'missing-frames' "
"and 'no-faces' this should be a parent folder containing video files or sub-"
"folders of images to perform the alignments job on. The alignments file "
"should exist at the default location. For all other jobs this option is "
"ignored."
msgstr ""
"R|Ejecute la herramienta de alineación en varias fuentes. Los siguientes "
"trabajos admiten el modo por lotes:\n"
"L|draw, extract, from-faces, missing-alignments, missing-frames, no-faces, "
"sort, spatial.\n"
"Si se selecciona el modo por lotes, las otras opciones deben configurarse de "
"la siguiente manera:\n"
"L|alignments_file: para 'sort' y 'spatial', debe apuntar a la carpeta "
"principal que contiene los archivos de alineación que se van a procesar. "
"Para todos los demás trabajos, esta opción se ignora y los archivos de "
"alineaciones deben existir en su ubicación predeterminada en relación con la "
"carpeta/video de fotogramas originales.\n"
"L|faces_dir: para 'from-faces', esta debe ser una carpeta principal que "
"contenga subcarpetas de caras extraídas desde las cuales generar archivos de "
"alineación. Para 'extraer', esta debe ser una carpeta principal donde se "
"crearán subcarpetas para cada extracción que se ejecute. Para todos los "
"demás trabajos, esta opción se ignora.\n"
"L|frames_dir: para 'draw', 'extract', 'missing-alignments', 'missing-frames' "
"y 'no-faces', esta debe ser una carpeta principal que contenga archivos de "
"video o subcarpetas de imágenes para realizar el trabajo de alineaciones en. "
"El archivo de alineaciones debe existir en la ubicación predeterminada. Para "
"todos los demás trabajos, esta opción se ignora."
#: tools/alignments/cli.py:164 tools/alignments/cli.py:175
#: tools/alignments/cli.py:185
msgid "extract"
msgstr "extracción"
#: tools/alignments/cli.py:141
#: tools/alignments/cli.py:165
msgid ""
"[Extract only] Extract every 'nth' frame. This option will skip frames when "
"extracting faces. For example a value of 1 will extract faces from every "
@ -203,22 +246,11 @@ msgstr ""
"caras de cada fotograma, un valor de 10 extraerá las caras de cada 10 "
"fotogramas."
#: tools/alignments/cli.py:150
msgid ""
"R|If selected then:\n"
"L|'frames_folder' should be a parent folder containing multiple videos/"
"folders of images you need to work on.\n"
"L|'faces_folder' should be a parent folder containing multiple folders of "
"faces you wish to manage.\n"
"L|'alignments_file'. should be a parent folder containing multiple alignment "
"files."
msgstr ""
#: tools/alignments/cli.py:165
#: tools/alignments/cli.py:176
msgid "[Extract only] The output size of extracted faces."
msgstr "[Sólo extracción] El tamaño de salida de las caras extraídas."
#: tools/alignments/cli.py:175
#: tools/alignments/cli.py:186
msgid ""
"[Extract only] Only extract faces that have been resized by this percent or "
"more to meet the specified extract size (`-sz`, `--size`). Useful for "

View File

@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-14 18:45+0100\n"
"PO-Revision-Date: 2022-11-26 16:43+0900\n"
"POT-Creation-Date: 2023-02-24 00:27+0000\n"
"PO-Revision-Date: 2023-02-24 00:34+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: ko_KR\n"
@ -16,7 +16,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.2\n"
"X-Generator: Poedit 3.0.1\n"
#: tools/alignments/cli.py:17
msgid ""
@ -45,8 +45,8 @@ msgstr " 얼굴 폴더를 무조건 전달해야 합니다 (-fc)."
#: tools/alignments/cli.py:46
msgid ""
" Must Pass in either a frames folder/source video file OR afaces folder (-fr "
"or -fc)."
" Must Pass in either a frames folder/source video file OR a faces folder (-"
"fr or -fc)."
msgstr ""
" 프레임 폴더나 원본 비디오 파일 또는 얼굴 폴더중 하나를 무조건 전달해야 합니"
"다 (-fr and -fc)."
@ -80,11 +80,11 @@ msgid ""
"{1}\n"
"L|'from-faces': Generate alignment file(s) from a folder of extracted faces. "
"if the folder of faces comes from multiple sources, then multiple alignments "
"files will be created. NB: for faces which have been extracted folders of "
"source images, rather than a video, a single alignments file will be created "
"as there is no way for the process to know how many folders of images were "
"originally used. You do not need to provide an alignments file path to run "
"this job. {3}\n"
"files will be created. NB: for faces which have been extracted from folders "
"of source images, rather than a video, a single alignments file will be "
"created as there is no way for the process to know how many folders of "
"images were originally used. You do not need to provide an alignments file "
"path to run this job. {3}\n"
"L|'missing-alignments': Identify frames that do not exist in the alignments "
"file.{2}{0}\n"
"L|'missing-frames': Identify frames in the alignments file that do not "
@ -146,7 +146,7 @@ msgstr ""
"L|'이동': 검색된 항목을 원본 디렉토리 내의 하위 폴더로 이동합니다."
#: tools/alignments/cli.py:110 tools/alignments/cli.py:123
#: tools/alignments/cli.py:130
#: tools/alignments/cli.py:130 tools/alignments/cli.py:137
msgid "data"
msgstr "데이터"
@ -171,12 +171,48 @@ msgstr "추출된 얼굴들이 저장된 디렉토리."
msgid "Directory containing source frames that faces were extracted from."
msgstr "얼굴 추출의 소스로 쓰인 원본 프레임이 저장된 디렉토리."
#: tools/alignments/cli.py:140 tools/alignments/cli.py:151
#: tools/alignments/cli.py:161
#: tools/alignments/cli.py:138
msgid ""
"R|Run the aligmnents tool on multiple sources. The following jobs support "
"batch mode:\n"
"L|draw, extract, from-faces, missing-alignments, missing-frames, no-faces, "
"sort, spatial.\n"
"If batch mode is selected then the other options should be set as follows:\n"
"L|alignments_file: For 'sort' and 'spatial' this should point to the parent "
"folder containing the alignments files to be processed. For all other jobs "
"this option is ignored, and the alignments files must exist at their default "
"location relative to the original frames folder/video.\n"
"L|faces_dir: For 'from-faces' this should be a parent folder, containing sub-"
"folders of extracted faces from which to generate alignments files. For "
"'extract' this should be a parent folder where sub-folders will be created "
"for each extraction to be run. For all other jobs this option is ignored.\n"
"L|frames_dir: For 'draw', 'extract', 'missing-alignments', 'missing-frames' "
"and 'no-faces' this should be a parent folder containing video files or sub-"
"folders of images to perform the alignments job on. The alignments file "
"should exist at the default location. For all other jobs this option is "
"ignored."
msgstr ""
"R|여러 소스에서 정렬 도구를 실행합니다. 다음 작업은 배치 모드를 지원합니다.\n"
"L|그리기, 추출, 얼굴부터, 정렬 누락, 프레임 누락, 얼굴 없음, 정렬, 공간.\n"
"배치 모드를 선택한 경우 다른 옵션을 다음과 같이 설정해야 합니다.\n"
"L|alignments_file: 'sort'및 'spatial'의 경우 처리할 정렬 파일이 포함된 상위 "
"폴더를 가리켜야 합니다. 다른 모든 작업의 경우 이 옵션은 무시되며 정렬 파일은 "
"원본 프레임 폴더/비디오에 상대적인 기본 위치에 있어야 합니다.\n"
"L|faces_dir: 'from-faces'의 경우 정렬 파일을 생성할 추출된 면의 하위 폴더를 "
"포함하는 상위 폴더여야 합니다. '추출'의 경우 실행할 각 추출에 대해 하위 폴더"
"가 생성되는 상위 폴더여야 합니다. 다른 모든 작업의 경우 이 옵션은 무시됩니"
"다.\n"
"L|frames_dir: 'draw', 'extract', 'missing-alignments', 'missing-frames' 및 "
"'no-faces'의 경우 비디오 파일이 포함된 상위 폴더 또는 정렬 작업을 수행할 이미"
"지의 하위 폴더여야 합니다. 에. 정렬 파일은 기본 위치에 있어야 합니다. 다른 모"
"든 작업의 경우 이 옵션은 무시됩니다."
#: tools/alignments/cli.py:164 tools/alignments/cli.py:175
#: tools/alignments/cli.py:185
msgid "extract"
msgstr "추출"
#: tools/alignments/cli.py:141
#: tools/alignments/cli.py:165
msgid ""
"[Extract only] Extract every 'nth' frame. This option will skip frames when "
"extracting faces. For example a value of 1 will extract faces from every "
@ -186,11 +222,11 @@ msgstr ""
"프레임을 건너뜁니다. 예를 들어, 값이 1이면 모든 프레임에서 얼굴이 추출되고, "
"값이 10이면 모든 10번째 프레임에서 얼굴이 추출됩니다."
#: tools/alignments/cli.py:152
#: tools/alignments/cli.py:176
msgid "[Extract only] The output size of extracted faces."
msgstr "[Extract only] 추출된 얼굴들의 결과 크기입니다."
#: tools/alignments/cli.py:162
#: tools/alignments/cli.py:186
msgid ""
"[Extract only] Only extract faces that have been resized by this percent or "
"more to meet the specified extract size (`-sz`, `--size`). Useful for "

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-14 18:45+0100\n"
"POT-Creation-Date: 2023-02-24 00:27+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -39,8 +39,8 @@ msgstr ""
#: tools/alignments/cli.py:46
msgid ""
" Must Pass in either a frames folder/source video file OR afaces folder (-fr "
"or -fc)."
" Must Pass in either a frames folder/source video file OR a faces folder (-"
"fr or -fc)."
msgstr ""
#: tools/alignments/cli.py:48
@ -70,11 +70,11 @@ msgid ""
"{1}\n"
"L|'from-faces': Generate alignment file(s) from a folder of extracted faces. "
"if the folder of faces comes from multiple sources, then multiple alignments "
"files will be created. NB: for faces which have been extracted folders of "
"source images, rather than a video, a single alignments file will be created "
"as there is no way for the process to know how many folders of images were "
"originally used. You do not need to provide an alignments file path to run "
"this job. {3}\n"
"files will be created. NB: for faces which have been extracted from folders "
"of source images, rather than a video, a single alignments file will be "
"created as there is no way for the process to know how many folders of "
"images were originally used. You do not need to provide an alignments file "
"path to run this job. {3}\n"
"L|'missing-alignments': Identify frames that do not exist in the alignments "
"file.{2}{0}\n"
"L|'missing-frames': Identify frames in the alignments file that do not "
@ -105,7 +105,7 @@ msgid ""
msgstr ""
#: tools/alignments/cli.py:110 tools/alignments/cli.py:123
#: tools/alignments/cli.py:130
#: tools/alignments/cli.py:130 tools/alignments/cli.py:137
msgid "data"
msgstr ""
@ -126,23 +126,45 @@ msgstr ""
msgid "Directory containing source frames that faces were extracted from."
msgstr ""
#: tools/alignments/cli.py:140 tools/alignments/cli.py:151
#: tools/alignments/cli.py:161
#: tools/alignments/cli.py:138
msgid ""
"R|Run the aligmnents tool on multiple sources. The following jobs support "
"batch mode:\n"
"L|draw, extract, from-faces, missing-alignments, missing-frames, no-faces, "
"sort, spatial.\n"
"If batch mode is selected then the other options should be set as follows:\n"
"L|alignments_file: For 'sort' and 'spatial' this should point to the parent "
"folder containing the alignments files to be processed. For all other jobs "
"this option is ignored, and the alignments files must exist at their default "
"location relative to the original frames folder/video.\n"
"L|faces_dir: For 'from-faces' this should be a parent folder, containing sub-"
"folders of extracted faces from which to generate alignments files. For "
"'extract' this should be a parent folder where sub-folders will be created "
"for each extraction to be run. For all other jobs this option is ignored.\n"
"L|frames_dir: For 'draw', 'extract', 'missing-alignments', 'missing-frames' "
"and 'no-faces' this should be a parent folder containing video files or sub-"
"folders of images to perform the alignments job on. The alignments file "
"should exist at the default location. For all other jobs this option is "
"ignored."
msgstr ""
#: tools/alignments/cli.py:164 tools/alignments/cli.py:175
#: tools/alignments/cli.py:185
msgid "extract"
msgstr ""
#: tools/alignments/cli.py:141
#: tools/alignments/cli.py:165
msgid ""
"[Extract only] Extract every 'nth' frame. This option will skip frames when "
"extracting faces. For example a value of 1 will extract faces from every "
"frame, a value of 10 will extract faces from every 10th frame."
msgstr ""
#: tools/alignments/cli.py:152
#: tools/alignments/cli.py:176
msgid "[Extract only] The output size of extracted faces."
msgstr ""
#: tools/alignments/cli.py:162
#: tools/alignments/cli.py:186
msgid ""
"[Extract only] Only extract faces that have been resized by this percent or "
"more to meet the specified extract size (`-sz`, `--size`). Useful for "

View File

@ -4,16 +4,15 @@ import logging
import os
import sys
from typing import Any, TYPE_CHECKING
from argparse import Namespace
from typing import Any, cast, List, Dict, Optional
from lib.utils import _video_extensions
from lib.utils import _video_extensions, FaceswapError
from .media import AlignmentData
from .jobs import Check, Sort, Spatial # noqa pylint: disable=unused-import
from .jobs_faces import FromFaces, RemoveFaces, Rename # noqa pylint: disable=unused-import
from .jobs_frames import Draw, Extract # noqa pylint: disable=unused-import
if TYPE_CHECKING:
from argparse import Namespace
logger = logging.getLogger(__name__) # pylint: disable=invalid-name
@ -24,12 +23,211 @@ class Alignments(): # pylint:disable=too-few-public-methods
The tool allows for manipulation, and working with Faceswap alignments files.
This parent class handles creating the individual job arguments when running in batch-mode or
triggers the job when not running in batch mode
Parameters
----------
arguments: :class:`argparse.Namespace`
The :mod:`argparse` arguments as passed in from :mod:`tools.py`
"""
def __init__(self, arguments: "Namespace") -> None:
def __init__(self, arguments: Namespace) -> None:
logger.debug("Initializing %s: (arguments: %s)", self.__class__.__name__, arguments)
self._requires_alignments = ["sort", "spatial"]
self._requires_faces = ["extract", "from-faces"]
self._requires_frames = ["draw",
"extract",
"missing-alignments",
"missing-frames",
"no-faces"]
self._args = arguments
self._batch_mode = self._validate_batch_mode()
self._locations = self._get_locations()
def _validate_batch_mode(self) -> bool:
""" Validate that the selected job supports batch processing
Returns
-------
bool
``True`` if batch mode has been selected otherwise ``False``
"""
batch_mode: bool = self._args.batch_mode
if not batch_mode:
logger.debug("Running in standard mode")
return batch_mode
valid = self._requires_alignments + self._requires_faces + self._requires_frames
if self._args.job not in valid:
logger.error("Job '%s' does not support batch mode. Please select a job from %s or "
"disable batch mode", self._args.job, valid)
sys.exit(1)
logger.debug("Running in batch mode")
return batch_mode
def _get_alignments_locations(self) -> Dict[str, List[Optional[str]]]:
""" Obtain the full path to alignments files in a parent (batch) location
These are jobs that only require an alignments file as input, so frames and face locations
are returned as a list of ``None`` values corresponding to the number of alignments files
detected
Returns
-------
dict[str, list[Optional[str]]]:
The list of alignments location paths and None lists for frames and faces locations
"""
if not self._args.alignments_file:
logger.error("Please provide an 'alignments_file' location for '%s' job",
self._args.job)
sys.exit(1)
alignments = [os.path.join(self._args.alignments_file, fname)
for fname in os.listdir(self._args.alignments_file)
if os.path.splitext(fname)[-1].lower() == ".fsa"
and os.path.splitext(fname)[0].endswith("alignments")]
if not alignments:
logger.error("No alignment files found in '%s'", self._args.alignments_file)
sys.exit(1)
logger.info("Batch mode selected. Processing alignments: %s", alignments)
retval = dict(alignments_file=alignments,
faces_dir=[None for _ in range(len(alignments))],
frames_dir=[None for _ in range(len(alignments))])
return retval
def _get_frames_locations(self) -> Dict[str, List[Optional[str]]]:
""" Obtain the full path to frame locations along with corresponding alignments file
locations contained within the parent (batch) location
Returns
-------
dict[str, list[Optional[str]]]:
list of frames and alignments location paths. If the job requires an output faces
location then the faces folders are also returned, otherwise the faces will be a list
of ``Nones`` corresponding to the number of jobs to run
"""
if not self._args.frames_dir:
logger.error("Please provide a 'frames_dir' location for '%s' job", self._args.job)
sys.exit(1)
frames: list[str] = []
alignments: list[str] = []
candidates = [os.path.join(self._args.frames_dir, fname)
for fname in os.listdir(self._args.frames_dir)
if os.path.isdir(os.path.join(self._args.frames_dir, fname))
or os.path.splitext(fname)[-1].lower() in _video_extensions]
logger.debug("Frame candidates: %s", candidates)
for candidate in candidates:
fname = os.path.join(candidate, "alignments.fsa")
if os.path.isdir(candidate) and os.path.exists(fname):
frames.append(candidate)
alignments.append(fname)
continue
fname = f"{os.path.splitext(candidate)[0]}_alignments.fsa"
if os.path.isfile(candidate) and os.path.exists(fname):
frames.append(candidate)
alignments.append(fname)
continue
logger.warning("Can't locate alignments file for '%s'. Skipping.", candidate)
if not frames:
logger.error("No valid videos or frames folders found in '%s'", self._args.frames_dir)
sys.exit(1)
if self._args.job not in self._requires_faces: # faces not required for frames input
faces: list[Optional[str]] = [None for _ in range(len(frames))]
else:
if not self._args.faces_dir:
logger.error("Please provide a 'faces_dir' location for '%s' job", self._args.job)
sys.exit(1)
faces = [os.path.join(self._args.faces_dir, os.path.basename(os.path.splitext(frm)[0]))
for frm in frames]
logger.info("Batch mode selected. Processing frames: %s",
[os.path.basename(frame) for frame in frames])
return dict(alignments_file=cast(List[Optional[str]], alignments),
frames_dir=cast(List[Optional[str]], frames),
faces_dir=faces)
def _get_locations(self) -> Dict[str, List[Optional[str]]]:
""" Obtain the full path to any frame, face and alignments input locations for the
selected job when running in batch mode. If not running in batch mode, then the original
passed in values are returned in lists
Returns
-------
dict[str, list[Optional[str]]]
A dictionary corresponding to the alignments, frames_dir and faces_dir arguments
with a list of full paths for each job
"""
job: str = self._args.job
if not self._batch_mode: # handle with given arguments
retval = dict(alignments_file=[self._args.alignments_file],
faces_dir=[self._args.faces_dir],
frames_dir=[self._args.frames_dir])
elif job in self._requires_alignments: # Jobs only requiring an alignments file location
retval = self._get_alignments_locations()
elif job in self._requires_frames: # Jobs that require a frames folder
retval = self._get_frames_locations()
elif job in self._requires_faces and job not in self._requires_frames:
# Jobs that require faces as input
faces = [os.path.join(self._args.faces_dir, folder)
for folder in os.listdir(self._args.faces_dir)
if os.path.isdir(os.path.join(self._args.faces_dir, folder))]
if not faces:
logger.error("No folders found in '%s'", self._args.faces_dir)
sys.exit(1)
retval = dict(faces_dir=faces,
frames_dir=[None for _ in range(len(faces))],
alignments_file=[None for _ in range(len(faces))])
logger.info("Batch mode selected. Processing faces: %s",
[os.path.basename(folder) for folder in faces])
else:
raise FaceswapError(f"Unhandled job: {self._args.job}. This is a bug. Please report "
"to the developers")
logger.debug("File locations: %s", retval)
return retval
def process(self):
""" The entry point for the Alignments tool from :mod:`lib.tools.alignments.cli`.
Launches the selected alignments job.
"""
num_jobs = len(self._locations["frames_dir"])
for idx, (frames, faces, alignments) in enumerate(zip(self._locations["frames_dir"],
self._locations["faces_dir"],
self._locations["alignments_file"])):
if num_jobs > 1:
logger.info("Processing job %s of %s", idx + 1, num_jobs)
args = Namespace(**self._args.__dict__)
args.frames_dir = frames
args.faces_dir = faces
args.alignments_file = alignments
tool = _Alignments(args)
tool.process()
class _Alignments(): # pylint:disable=too-few-public-methods
""" The main entry point for Faceswap's Alignments Tool. This tool is part of the Faceswap
Tools suite and should be called from the ``python tools.py alignments`` command.
The tool allows for manipulation, and working with Faceswap alignments files.
Parameters
----------
arguments: :class:`argparse.Namespace`
The :mod:`argparse` arguments as passed in from :mod:`tools.py`
"""
def __init__(self, arguments: Namespace) -> None:
logger.debug("Initializing %s: (arguments: '%s'", self.__class__.__name__, arguments)
self._args = arguments
job = self._args.job

View File

@ -43,7 +43,7 @@ class AlignmentsArgs(FaceSwapArgs):
"""
frames_dir = _(" Must Pass in a frames folder/source video file (-fr).")
faces_dir = _(" Must Pass in a faces folder (-fc).")
frames_or_faces_dir = _(" Must Pass in either a frames folder/source video file OR a"
frames_or_faces_dir = _(" Must Pass in either a frames folder/source video file OR a "
"faces folder (-fr or -fc).")
frames_and_faces_dir = _(" Must Pass in a frames folder/source video file AND a faces "
"folder (-fr and -fc).")
@ -67,9 +67,9 @@ class AlignmentsArgs(FaceSwapArgs):
"\nL|'from-faces': Generate alignment file(s) from a folder of extracted "
"faces. if the folder of faces comes from multiple sources, then multiple "
"alignments files will be created. NB: for faces which have been extracted "
"folders of source images, rather than a video, a single alignments file will "
"be created as there is no way for the process to know how many folders of "
"images were originally used. You do not need to provide an alignments file "
"from folders of source images, rather than a video, a single alignments file "
"will be created as there is no way for the process to know how many folders "
"of images were originally used. You do not need to provide an alignments file "
"path to run this job. {3}"
"\nL|'missing-alignments': Identify frames that do not exist in the alignments "
"file.{2}{0}"
@ -129,6 +129,30 @@ class AlignmentsArgs(FaceSwapArgs):
filetypes="video",
group=_("data"),
help=_("Directory containing source frames that faces were extracted from.")))
argument_list.append(dict(
opts=("-B", "--batch-mode"),
action="store_true",
dest="batch_mode",
default=False,
group=_("data"),
help=_("R|Run the aligmnents tool on multiple sources. The following jobs support "
"batch mode:"
"\nL|draw, extract, from-faces, missing-alignments, missing-frames, no-faces, "
"sort, spatial."
"\nIf batch mode is selected then the other options should be set as follows:"
"\nL|alignments_file: For 'sort' and 'spatial' this should point to the parent "
"folder containing the alignments files to be processed. For all other jobs "
"this option is ignored, and the alignments files must exist at their default "
"location relative to the original frames folder/video."
"\nL|faces_dir: For 'from-faces' this should be a parent folder, containing "
"sub-folders of extracted faces from which to generate alignments files. For "
"'extract' this should be a parent folder where sub-folders will be created "
"for each extraction to be run. For all other jobs this option is ignored."
"\nL|frames_dir: For 'draw', 'extract', 'missing-alignments', 'missing-frames' "
"and 'no-faces' this should be a parent folder containing video files or sub-"
"folders of images to perform the alignments job on. The alignments file "
"should exist at the default location. For all other jobs this option is "
"ignored.")))
argument_list.append(dict(
opts=("-een", "--extract-every-n"),
type=int,