mirror of
https://github.com/zebrajr/faceswap.git
synced 2025-12-06 00:20:09 +01:00
alignments tool - Add batch mode
This commit is contained in:
parent
a076afa910
commit
ec95c19534
Binary file not shown.
|
|
@ -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 "
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -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 "
|
||||
|
|
|
|||
|
|
@ -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 "
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user