Skip to content

Commit

Permalink
Add Mask importing to the mask tool (#1376)
Browse files Browse the repository at this point in the history
* lib.align.alignments: expose count_faces_in_frame
* tools.mask: refactor and fix frame output to display all masks in a single frame
* tools.mask: add import mask process
* manual tool: Remove NN masks on landmark edit
  • Loading branch information
torzdf authored Mar 12, 2024
1 parent d1dfce8 commit 7a16f75
Show file tree
Hide file tree
Showing 17 changed files with 2,339 additions and 837 deletions.
18 changes: 15 additions & 3 deletions lib/align/alignments.py
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ def get_faces_in_frame(self, frame_name: str) -> list[AlignmentFileDict]:
frame_data = self._data.get(frame_name, T.cast(AlignmentDict, {}))
return frame_data.get("faces", T.cast(list[AlignmentFileDict], []))

def _count_faces_in_frame(self, frame_name: str) -> int:
def count_faces_in_frame(self, frame_name: str) -> int:
""" Return number of faces that appear within :attr:`data` for the given frame_name.
Parameters
Expand Down Expand Up @@ -464,7 +464,7 @@ def delete_face_at_index(self, frame_name: str, face_index: int) -> bool:
"""
logger.debug("Deleting face %s for frame_name '%s'", face_index, frame_name)
face_index = int(face_index)
if face_index + 1 > self._count_faces_in_frame(frame_name):
if face_index + 1 > self.count_faces_in_frame(frame_name):
logger.debug("No face to delete: (frame_name: '%s', face_index %s)",
frame_name, face_index)
return False
Expand Down Expand Up @@ -493,7 +493,7 @@ def add_face(self, frame_name: str, face: AlignmentFileDict) -> int:
if frame_name not in self._data:
self._data[frame_name] = {"faces": [], "video_meta": {}}
self._data[frame_name]["faces"].append(face)
retval = self._count_faces_in_frame(frame_name) - 1
retval = self.count_faces_in_frame(frame_name) - 1
logger.debug("Returning new face index: %s", retval)
return retval

Expand Down Expand Up @@ -542,6 +542,18 @@ def filter_faces(self, filter_dict: dict[str, list[int]], filter_out: bool = Fal
source_frame, face_idx)
del frame_data["faces"][face_idx]

def update_from_dict(self, data: dict[str, AlignmentDict]) -> None:
""" Replace all alignments with the contents of the given dictionary
Parameters
----------
data: dict[str, AlignmentDict]
The alignments, in correctly formatted dictionary form, to be populated into this
:class:`Alignments`
"""
logger.debug("Populating alignments with %s entries", len(data))
self._data = data

# << GENERATORS >> #
def yield_faces(self) -> Generator[tuple[str, list[AlignmentFileDict], int, str], None, None]:
""" Generator to obtain all faces with meta information from :attr:`data`. The results
Expand Down
Binary file modified locales/es/LC_MESSAGES/tools.mask.cli.mo
Binary file not shown.
196 changes: 150 additions & 46 deletions locales/es/LC_MESSAGES/tools.mask.cli.po
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: faceswap.spanish\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-02-20 23:42+0000\n"
"PO-Revision-Date: 2023-02-20 23:45+0000\n"
"POT-Creation-Date: 2024-03-11 23:45+0000\n"
"PO-Revision-Date: 2024-03-11 23:50+0000\n"
"Last-Translator: \n"
"Language-Team: tokafondo\n"
"Language: es_ES\n"
Expand All @@ -16,30 +16,36 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 3.0.1\n"
"X-Generator: Poedit 3.4.2\n"

#: tools/mask/cli.py:15
msgid "This command lets you generate masks for existing alignments."
msgid ""
"This tool allows you to generate, import, export or preview masks for "
"existing alignments."
msgstr ""
"Este comando permite generar máscaras para las alineaciones existentes."
"Esta herramienta le permite generar, importar, exportar o obtener una vista "
"previa de máscaras para alineaciones existentes.\n"
"Genere, importe, exporte o obtenga una vista previa de máscaras para "
"archivos de alineaciones existentes."

#: tools/mask/cli.py:24
#: tools/mask/cli.py:25
msgid ""
"Mask tool\n"
"Generate masks for existing alignments files."
"Generate, import, export or preview masks for existing alignments files."
msgstr ""
"Herramienta de máscara\n"
"Genera máscaras para los archivos de alineación existentes."
"Genere, importe, exporte o obtenga una vista previa de máscaras para "
"archivos de alineaciones existentes."

#: tools/mask/cli.py:33 tools/mask/cli.py:44 tools/mask/cli.py:54
#: tools/mask/cli.py:64
#: tools/mask/cli.py:35 tools/mask/cli.py:47 tools/mask/cli.py:58
#: tools/mask/cli.py:69
msgid "data"
msgstr "datos"

#: tools/mask/cli.py:36
#: tools/mask/cli.py:39
msgid ""
"Full path to the alignments file to add the mask to if not at the default "
"location. NB: If the input-type is faces and you wish to update the "
"Full path to the alignments file that contains the masks if not at the "
"default location. NB: If the input-type is faces and you wish to update the "
"corresponding alignments file, then you must provide a value here as the "
"location cannot be automatically detected."
msgstr ""
Expand All @@ -48,13 +54,13 @@ msgstr ""
"actualizar el archivo de alineaciones correspondiente, debe proporcionar un "
"valor aquí ya que la ubicación no se puede detectar automáticamente."

#: tools/mask/cli.py:47
#: tools/mask/cli.py:51
msgid "Directory containing extracted faces, source frames, or a video file."
msgstr ""
"Directorio que contiene las caras extraídas, los fotogramas de origen o un "
"archivo de vídeo."

#: tools/mask/cli.py:56
#: tools/mask/cli.py:61
msgid ""
"R|Whether the `input` is a folder of faces or a folder frames/video\n"
"L|faces: The input is a folder containing extracted faces.\n"
Expand All @@ -64,7 +70,7 @@ msgstr ""
"L|faces: La entrada es una carpeta que contiene caras extraídas.\n"
"L|frames: La entrada es una carpeta que contiene fotogramas o es un vídeo"

#: tools/mask/cli.py:65
#: tools/mask/cli.py:71
msgid ""
"R|Run the mask tool on multiple sources. If selected then the other options "
"should be set as follows:\n"
Expand All @@ -89,11 +95,11 @@ msgstr ""
"con 'caras' como tipo de entrada, solo se actualizará el encabezado PNG "
"dentro de las caras extraídas."

#: tools/mask/cli.py:81 tools/mask/cli.py:113
#: tools/mask/cli.py:87 tools/mask/cli.py:119
msgid "process"
msgstr "proceso"

#: tools/mask/cli.py:82
#: tools/mask/cli.py:89
msgid ""
"R|Masker to use.\n"
"L|bisenet-fp: Relatively lightweight NN based mask that provides more "
Expand All @@ -118,9 +124,8 @@ msgid ""
"some facial obstructions (hands and eyeglasses). Profile faces may result in "
"sub-par performance.\n"
"L|unet-dfl: Mask designed to provide smart segmentation of mostly frontal "
"faces. The mask model has been trained by community members and will need "
"testing for further description. Profile faces may result in sub-par "
"performance."
"faces. The mask model has been trained by community members. Profile faces "
"may result in sub-par performance."
msgstr ""
"R|Máscara a utilizar.\n"
"L|bisenet-fp: Máscara relativamente ligera basada en NN que proporciona un "
Expand Down Expand Up @@ -152,40 +157,119 @@ msgstr ""
"descripción. Los rostros de perfil pueden dar lugar a un rendimiento "
"inferior."

#: tools/mask/cli.py:114
#: tools/mask/cli.py:121
msgid ""
"R|Whether to update all masks in the alignments files, only those faces that "
"do not already have a mask of the given `mask type` or just to output the "
"masks to the `output` location.\n"
"L|all: Update the mask for all faces in the alignments file.\n"
"R|The Mask tool process to perform.\n"
"L|all: Update the mask for all faces in the alignments file for the selected "
"'masker'.\n"
"L|missing: Create a mask for all faces in the alignments file where a mask "
"does not previously exist.\n"
"L|output: Don't update the masks, just output them for review in the given "
"output folder."
msgstr ""
"R|Si se actualizan todas las máscaras en los archivos de alineación, sólo "
"aquellas caras que no tienen ya una máscara del \"tipo de máscara\" dado o "
"sólo se envían las máscaras a la ubicación \"de salida\".\n"
"L|all: Actualiza la máscara de todas las caras del archivo de alineación.\n"
"L|missing: Crea una máscara para todas las caras del fichero de alineaciones "
"en las que no existe una máscara previamente.\n"
"L|output: No actualiza las máscaras, sólo las emite para su revisión en la "
"carpeta de salida dada."

#: tools/mask/cli.py:127 tools/mask/cli.py:134 tools/mask/cli.py:147
#: tools/mask/cli.py:160 tools/mask/cli.py:169
"does not previously exist for the selected 'masker'.\n"
"L|output: Don't update the masks, just output the selected 'masker' for "
"review/editing in external tools to the given output folder.\n"
"L|import: Import masks that have been edited outside of faceswap into the "
"alignments file. Note: 'custom' must be the selected 'masker' and the masks "
"must be in the same format as the 'input-type' (frames or faces)"
msgstr ""
"R|Процесс инструмента «Маска», который необходимо выполнить.\n"
"L|all: обновить маску для всех лиц в файле выравниваний для выбранного "
"«masker».\n"
"L|missing: создать маску для всех граней в файле выравниваний, где маска "
"ранее не существовала для выбранного «masker».\n"
"L|output: не обновляйте маски, просто выведите выбранный «masker» для "
"просмотра/редактирования во внешних инструментах в данную выходную папку.\n"
"L|import: импортируйте маски, которые были отредактированы вне Facewap, в "
"файл выравниваний. Примечание. «custom» должен быть выбранным «masker», а "
"маски должны быть в том же формате, что и «input-type» (frames или faces)."

#: tools/mask/cli.py:135 tools/mask/cli.py:154 tools/mask/cli.py:174
msgid "import"
msgstr "importar"

#: tools/mask/cli.py:137
msgid ""
"R|Import only. The path to the folder that contains masks to be imported.\n"
"L|How the masks are provided is not important, but they will be stored, "
"internally, as 8-bit grayscale images.\n"
"L|If the input are images, then the masks must be named exactly the same as "
"input frames/faces (excluding the file extension).\n"
"L|If the input is a video file, then the filename of the masks is not "
"important but should contain the frame number at the end of the filename "
"(but before the file extension). The frame number can be separated from the "
"rest of the filename by any non-numeric character and can be padded by any "
"number of zeros. The frame number must correspond correctly to the frame "
"number in the original video (starting from frame 1)."
msgstr ""
"R|Sólo importar. La ruta a la carpeta que contiene las máscaras que se "
"importarán.\n"
"L|Cómo se proporcionan las máscaras no es importante, pero se almacenarán "
"internamente como imágenes en escala de grises de 8 bits.\n"
"L|Si la entrada son imágenes, entonces las máscaras deben tener el mismo "
"nombre que los cuadros/caras de entrada (excluyendo la extensión del "
"archivo).\n"
"L|Si la entrada es un archivo de vídeo, entonces el nombre del archivo de "
"las máscaras no es importante pero debe contener el número de fotograma al "
"final del nombre del archivo (pero antes de la extensión del archivo). El "
"número de fotograma se puede separar del resto del nombre del archivo "
"mediante cualquier carácter no numérico y se puede rellenar con cualquier "
"número de ceros. El número de fotograma debe corresponder correctamente al "
"número de fotograma del vídeo original (a partir del fotograma 1)."

#: tools/mask/cli.py:156
msgid ""
"R|Import only. The centering to use when importing masks. Note: For any job "
"other than 'import' this option is ignored as mask centering is handled "
"internally.\n"
"L|face: Centers the mask on the center of the face, adjusting for pitch and "
"yaw. Outside of requirements for full head masking/training, this is likely "
"to be the best choice.\n"
"L|head: Centers the mask on the center of the head, adjusting for pitch and "
"yaw. Note: You should only select head centering if you intend to include "
"the full head (including hair) within the mask and are looking to train a "
"full head model.\n"
"L|legacy: The 'original' extraction technique. Centers the mask near the of "
"the nose with and crops closely to the face. Can result in the edges of the "
"mask appearing outside of the training area."
msgstr ""
"R|Sólo importar. El centrado a utilizar al importar máscaras. Nota: Para "
"cualquier trabajo que no sea \"importar\", esta opción se ignora ya que el "
"centrado de la máscara se maneja internamente.\n"
"L|cara: centra la máscara en el centro de la cara, ajustando el tono y la "
"orientación. Aparte de los requisitos para el entrenamiento/enmascaramiento "
"de cabeza completa, esta probablemente sea la mejor opción.\n"
"L|head: centra la máscara en el centro de la cabeza, ajustando el cabeceo y "
"la guiñada. Nota: Sólo debe seleccionar el centrado de la cabeza si desea "
"incluir la cabeza completa (incluido el cabello) dentro de la máscara y "
"desea entrenar un modelo de cabeza completa.\n"
"L|legacy: La técnica de extracción 'original'. Centra la máscara cerca de la "
"nariz y la recorta cerca de la cara. Puede provocar que los bordes de la "
"máscara aparezcan fuera del área de entrenamiento."

#: tools/mask/cli.py:179
msgid ""
"Import only. The size, in pixels to internally store the mask at.\n"
"The default is 128 which is fine for nearly all usecases. Larger sizes will "
"result in larger alignments files and longer processing."
msgstr ""
"Sólo importar. El tamaño, en píxeles, para almacenar internamente la "
"máscara.\n"
"El valor predeterminado es 128, que está bien para casi todos los casos de "
"uso. Los tamaños más grandes darán como resultado archivos de alineaciones "
"más grandes y un procesamiento más largo."

#: tools/mask/cli.py:187 tools/mask/cli.py:195 tools/mask/cli.py:209
#: tools/mask/cli.py:223 tools/mask/cli.py:233
msgid "output"
msgstr "salida"

#: tools/mask/cli.py:128
#: tools/mask/cli.py:189
msgid ""
"Optional output location. If provided, a preview of the masks created will "
"be output in the given folder."
msgstr ""
"Ubicación de salida opcional. Si se proporciona, se obtendrá una vista "
"previa de las máscaras creadas en la carpeta indicada."

#: tools/mask/cli.py:138
#: tools/mask/cli.py:200
msgid ""
"Apply gaussian blur to the mask output. Has the effect of smoothing the "
"edges of the mask giving less of a hard edge. the size is in pixels. This "
Expand All @@ -198,7 +282,7 @@ msgstr ""
"redondeará al siguiente número impar. NB: Sólo afecta a la vista previa de "
"salida. Si se ajusta a 0, se desactiva"

#: tools/mask/cli.py:151
#: tools/mask/cli.py:214
msgid ""
"Helps reduce 'blotchiness' on some masks by making light shades white and "
"dark shades black. Higher values will impact more of the mask. NB: Only "
Expand All @@ -209,7 +293,7 @@ msgstr ""
"más a la máscara. NB: Sólo afecta a la vista previa de salida. Si se ajusta "
"a 0, se desactiva"

#: tools/mask/cli.py:161
#: tools/mask/cli.py:225
msgid ""
"R|How to format the output when processing is set to 'output'.\n"
"L|combined: The image contains the face/frame, face mask and masked face.\n"
Expand All @@ -224,7 +308,7 @@ msgstr ""
"enmascarada.\n"
"L|mask: Sólo emite la máscara como una imagen de un solo canal."

#: tools/mask/cli.py:170
#: tools/mask/cli.py:235
msgid ""
"R|Whether to output the whole frame or only the face box when using output "
"processing. Only has an effect when using frames as input."
Expand All @@ -233,6 +317,26 @@ msgstr ""
"el cuadro de la cara cuando se utiliza el procesamiento de salida. Sólo "
"tiene efecto cuando se utilizan cuadros como entrada."

#~ msgid ""
#~ "R|Whether to update all masks in the alignments files, only those faces "
#~ "that do not already have a mask of the given `mask type` or just to "
#~ "output the masks to the `output` location.\n"
#~ "L|all: Update the mask for all faces in the alignments file.\n"
#~ "L|missing: Create a mask for all faces in the alignments file where a "
#~ "mask does not previously exist.\n"
#~ "L|output: Don't update the masks, just output them for review in the "
#~ "given output folder."
#~ msgstr ""
#~ "R|Si se actualizan todas las máscaras en los archivos de alineación, sólo "
#~ "aquellas caras que no tienen ya una máscara del \"tipo de máscara\" dado "
#~ "o sólo se envían las máscaras a la ubicación \"de salida\".\n"
#~ "L|all: Actualiza la máscara de todas las caras del archivo de "
#~ "alineación.\n"
#~ "L|missing: Crea una máscara para todas las caras del fichero de "
#~ "alineaciones en las que no existe una máscara previamente.\n"
#~ "L|output: No actualiza las máscaras, sólo las emite para su revisión en "
#~ "la carpeta de salida dada."

#~ msgid ""
#~ "Full path to the alignments file to add the mask to. NB: if the mask "
#~ "already exists in the alignments file it will be overwritten."
Expand Down
Binary file modified locales/kr/LC_MESSAGES/tools.mask.cli.mo
Binary file not shown.
Loading

0 comments on commit 7a16f75

Please sign in to comment.