diff --git a/lib/cli/args.py b/lib/cli/args.py index 8c0a501..90a3ee3 100644 --- a/lib/cli/args.py +++ b/lib/cli/args.py @@ -377,6 +377,15 @@ class ExtractArgs(ExtractConvertArgs): default_aligner = "fan" argument_list: List[Dict[str, Any]] = [] + argument_list.append(dict( + opts=("-b", "--batch-mode"), + action="store_true", + dest="batch_mode", + default=False, + group=_("Data"), + help=_("R|If selected then the input_dir should be a parent folder containing " + "multiple videos and/or folders of images you wish to extract from. The faces " + "will be output to separate sub-folders in the output_dir."))) argument_list.append(dict( opts=("-D", "--detector"), action=Radio, diff --git a/locales/es/LC_MESSAGES/lib.cli.args.mo b/locales/es/LC_MESSAGES/lib.cli.args.mo index 7d2e75a..56e1b25 100644 Binary files a/locales/es/LC_MESSAGES/lib.cli.args.mo and b/locales/es/LC_MESSAGES/lib.cli.args.mo differ diff --git a/locales/es/LC_MESSAGES/lib.cli.args.po b/locales/es/LC_MESSAGES/lib.cli.args.po index 37697c6..e2c2e7f 100644 --- a/locales/es/LC_MESSAGES/lib.cli.args.po +++ b/locales/es/LC_MESSAGES/lib.cli.args.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: faceswap.spanish\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-08-05 13:58+0100\n" -"PO-Revision-Date: 2022-08-05 14:04+0100\n" +"POT-Creation-Date: 2022-08-31 19:19+0100\n" +"PO-Revision-Date: 2022-08-31 19:20+0100\n" "Last-Translator: \n" "Language-Team: tokafondo\n" "Language: es\n" @@ -55,7 +55,7 @@ msgstr "" "almacenarlo en la carpeta pde instalación de faceswap" #: lib/cli/args.py:320 lib/cli/args.py:329 lib/cli/args.py:337 -#: lib/cli/args.py:655 lib/cli/args.py:664 +#: lib/cli/args.py:385 lib/cli/args.py:664 lib/cli/args.py:673 msgid "Data" msgstr "Datos" @@ -90,13 +90,23 @@ msgstr "" "Extrae caras de fuentes de imagen o video.\n" "Los plugins de extracción pueden ser configuradas en el menú de 'Ajustes'" -#: lib/cli/args.py:386 lib/cli/args.py:402 lib/cli/args.py:414 -#: lib/cli/args.py:453 lib/cli/args.py:471 lib/cli/args.py:483 -#: lib/cli/args.py:674 lib/cli/args.py:701 lib/cli/args.py:739 +#: lib/cli/args.py:386 +msgid "" +"R|If selected then the input_dir should be a parent folder containing " +"multiple videos and/or folders of images you wish to extract from. The faces " +"will be output to separate sub-folders in the output_dir." +msgstr "" +"Si se selecciona, input_dir debe ser una carpeta principal que contenga " +"varios videos y/o carpetas de imágenes de las que desea extraer. Las caras " +"se enviarán a subcarpetas separadas en output_dir." + +#: lib/cli/args.py:395 lib/cli/args.py:411 lib/cli/args.py:423 +#: lib/cli/args.py:462 lib/cli/args.py:480 lib/cli/args.py:492 +#: lib/cli/args.py:683 lib/cli/args.py:710 lib/cli/args.py:748 msgid "Plugins" msgstr "Extensiones" -#: lib/cli/args.py:387 +#: lib/cli/args.py:396 msgid "" "R|Detector to use. Some of these have configurable settings in '/config/" "extract.ini' or 'Settings > Configure Extract 'Plugins':\n" @@ -119,7 +129,7 @@ msgstr "" "detectar más caras y tiene menos falsos positivos que otros detectores " "basados en GPU, pero uso muchos más recursos." -#: lib/cli/args.py:403 +#: lib/cli/args.py:412 msgid "" "R|Aligner to use.\n" "L|cv2-dnn: A CPU only landmark detector. Faster, less resource intensive, " @@ -131,7 +141,7 @@ msgstr "" "pero es menos preciso. Elegir este si necesita rapidez y no usar la GPU.\n" "L|fan: El mejor alineador. Rápido en la GPU, y lento en la CPU." -#: lib/cli/args.py:415 +#: lib/cli/args.py:424 msgid "" "R|Additional Masker(s) to use. The masks generated here will all take up GPU " "RAM. You can select none, one or multiple masks, but the extraction may take " @@ -201,7 +211,7 @@ msgstr "" "referencia y la máscara se extiende hacia arriba en la frente.\n" "(eg: `-M unet-dfl vgg-clear`, `--masker vgg-obstructed`)" -#: lib/cli/args.py:454 +#: lib/cli/args.py:463 msgid "" "R|Performing normalization can help the aligner better align faces with " "difficult lighting conditions at an extraction speed cost. Different methods " @@ -224,7 +234,7 @@ msgstr "" "L|hist: Iguala los histogramas de los canales RGB.\n" "L|mean: Normalizar los colores de la cara a la media." -#: lib/cli/args.py:472 +#: lib/cli/args.py:481 msgid "" "The number of times to re-feed the detected face into the aligner. Each time " "the face is re-fed into the aligner the bounding box is adjusted by a small " @@ -241,7 +251,7 @@ msgstr "" "más veces se vuelva a introducir la cara en el alineador, menos " "microfluctuaciones se producirán, pero la extracción será más larga." -#: lib/cli/args.py:484 +#: lib/cli/args.py:493 msgid "" "If a face isn't found, rotate the images to try to find a face. Can find " "more faces at the cost of extraction speed. Pass in a single number to use " @@ -253,13 +263,13 @@ msgstr "" "un solo número para usar incrementos de ese tamaño hasta 360, o pase una " "lista de números para enumerar exactamente qué ángulos comprobar." -#: lib/cli/args.py:496 lib/cli/args.py:506 lib/cli/args.py:519 -#: lib/cli/args.py:533 lib/cli/args.py:776 lib/cli/args.py:790 -#: lib/cli/args.py:803 lib/cli/args.py:817 +#: lib/cli/args.py:505 lib/cli/args.py:515 lib/cli/args.py:528 +#: lib/cli/args.py:542 lib/cli/args.py:785 lib/cli/args.py:799 +#: lib/cli/args.py:812 lib/cli/args.py:826 msgid "Face Processing" msgstr "Proceso de Caras" -#: lib/cli/args.py:497 +#: lib/cli/args.py:506 msgid "" "Filters out faces detected below this size. Length, in pixels across the " "diagonal of the bounding box. Set to 0 for off" @@ -268,7 +278,7 @@ msgstr "" "a lo largo de la diagonal del cuadro delimitador. Establecer a 0 para " "desactivar" -#: lib/cli/args.py:507 lib/cli/args.py:791 +#: lib/cli/args.py:516 lib/cli/args.py:800 msgid "" "Optionally filter out people who you do not wish to process by passing in an " "image of that person. Should be a front portrait with a single person in the " @@ -282,7 +292,7 @@ msgstr "" "uso del filtro de caras disminuirá significativamente la velocidad de " "extracción y no se puede garantizar su precisión." -#: lib/cli/args.py:520 lib/cli/args.py:804 +#: lib/cli/args.py:529 lib/cli/args.py:813 msgid "" "Optionally select people you wish to process by passing in an image of that " "person. Should be a front portrait with a single person in the image. " @@ -296,7 +306,7 @@ msgstr "" "del filtro facial disminuirá significativamente la velocidad de extracción y " "no se puede garantizar su precisión." -#: lib/cli/args.py:534 lib/cli/args.py:818 +#: lib/cli/args.py:543 lib/cli/args.py:827 msgid "" "For use with the optional nfilter/filter files. Threshold for positive face " "recognition. Lower values are stricter. NB: Using face filter will " @@ -308,12 +318,12 @@ msgstr "" "NB: El uso del filtro facial disminuirá significativamente la velocidad de " "extracción y no se puede garantizar su precisión." -#: lib/cli/args.py:545 lib/cli/args.py:557 lib/cli/args.py:569 -#: lib/cli/args.py:581 +#: lib/cli/args.py:554 lib/cli/args.py:566 lib/cli/args.py:578 +#: lib/cli/args.py:590 msgid "output" msgstr "salida" -#: lib/cli/args.py:546 +#: lib/cli/args.py:555 msgid "" "The output size of extracted faces. Make sure that the model you intend to " "train supports your required size. This will only need to be changed for hi-" @@ -323,7 +333,7 @@ msgstr "" "pretende entrenar admite el tamaño deseado. Esto sólo tendrá que ser " "cambiado para los modelos de alta resolución." -#: lib/cli/args.py:558 +#: lib/cli/args.py:567 msgid "" "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 " @@ -333,7 +343,7 @@ msgstr "" "extraer las caras. Por ejemplo, un valor de 1 extraerá las caras de cada " "fotograma, un valor de 10 extraerá las caras de cada 10 fotogramas." -#: lib/cli/args.py:570 +#: lib/cli/args.py:579 msgid "" "Automatically save the alignments file after a set amount of frames. By " "default the alignments file is only saved at the end of the extraction " @@ -349,18 +359,18 @@ msgstr "" "ADVERTENCIA: No interrumpa el script al escribir el archivo porque podría " "corromperse. Poner a 0 para desactivar" -#: lib/cli/args.py:582 +#: lib/cli/args.py:591 msgid "Draw landmarks on the ouput faces for debugging purposes." msgstr "" "Dibujar puntos de referencia en las caras de salida para fines de depuración." -#: lib/cli/args.py:588 lib/cli/args.py:597 lib/cli/args.py:605 -#: lib/cli/args.py:612 lib/cli/args.py:830 lib/cli/args.py:841 -#: lib/cli/args.py:849 lib/cli/args.py:868 lib/cli/args.py:874 +#: lib/cli/args.py:597 lib/cli/args.py:606 lib/cli/args.py:614 +#: lib/cli/args.py:621 lib/cli/args.py:839 lib/cli/args.py:850 +#: lib/cli/args.py:858 lib/cli/args.py:877 lib/cli/args.py:883 msgid "settings" msgstr "ajustes" -#: lib/cli/args.py:589 +#: lib/cli/args.py:598 msgid "" "Don't run extraction in parallel. Will run each part of the extraction " "process separately (one after the other) rather than all at the smae time. " @@ -370,7 +380,7 @@ msgstr "" "extracción por separado (una tras otra) en lugar de hacerlo todo al mismo " "tiempo. Útil si la VRAM es escasa." -#: lib/cli/args.py:598 +#: lib/cli/args.py:607 msgid "" "Skips frames that have already been extracted and exist in the alignments " "file" @@ -378,19 +388,19 @@ msgstr "" "Omite los fotogramas que ya han sido extraídos y que existen en el archivo " "de alineaciones" -#: lib/cli/args.py:606 +#: lib/cli/args.py:615 msgid "Skip frames that already have detected faces in the alignments file" msgstr "" "Omitir los fotogramas que ya tienen caras detectadas en el archivo de " "alineaciones" -#: lib/cli/args.py:613 +#: lib/cli/args.py:622 msgid "Skip saving the detected faces to disk. Just create an alignments file" msgstr "" "No guardar las caras detectadas en el disco. Crear sólo un archivo de " "alineaciones" -#: lib/cli/args.py:635 +#: lib/cli/args.py:644 msgid "" "Swap the original faces in a source video/images to your final faces.\n" "Conversion plugins can be configured in the 'Settings' Menu" @@ -400,7 +410,7 @@ msgstr "" "Los plugins de conversión pueden ser configurados en el menú " "\"Configuración\"" -#: lib/cli/args.py:656 +#: lib/cli/args.py:665 msgid "" "Only required if converting from images to video. Provide The original video " "that the source frames were extracted from (for extracting the fps and " @@ -410,7 +420,7 @@ msgstr "" "original del que se extrajeron los fotogramas de origen (para extraer los " "fps y el audio)." -#: lib/cli/args.py:665 +#: lib/cli/args.py:674 msgid "" "Model directory. The directory containing the trained model you wish to use " "for conversion." @@ -418,7 +428,7 @@ msgstr "" "Directorio del modelo. El directorio que contiene el modelo entrenado que " "desea utilizar para la conversión." -#: lib/cli/args.py:675 +#: lib/cli/args.py:684 msgid "" "R|Performs color adjustment to the swapped face. Some of these options have " "configurable settings in '/config/convert.ini' or 'Settings > Configure " @@ -458,7 +468,7 @@ msgstr "" "colores. Generalmente no da resultados muy satisfactorios.\n" "L|none: No realice el ajuste de color." -#: lib/cli/args.py:702 +#: lib/cli/args.py:711 msgid "" "R|Masker to use. NB: The mask you require must exist within the alignments " "file. You can add additional masks with the Mask Tool.\n" @@ -534,7 +544,7 @@ msgstr "" "L|predicted: Si la opción 'Learn Mask' se habilitó durante el entrenamiento, " "esto usará la máscara que fue creada por el modelo entrenado." -#: lib/cli/args.py:740 +#: lib/cli/args.py:749 msgid "" "R|The plugin to use to output the converted images. The writers are " "configurable in '/config/convert.ini' or 'Settings > Configure Convert " @@ -560,11 +570,11 @@ msgstr "" "L|pillow: [images] Más lento que opencv, pero tiene más opciones y soporta " "más formatos." -#: lib/cli/args.py:759 lib/cli/args.py:766 lib/cli/args.py:860 +#: lib/cli/args.py:768 lib/cli/args.py:775 lib/cli/args.py:869 msgid "Frame Processing" msgstr "Proceso de fotogramas" -#: lib/cli/args.py:760 +#: lib/cli/args.py:769 #, python-format msgid "" "Scale the final output frames by this amount. 100%% will output the frames " @@ -574,7 +584,7 @@ msgstr "" "a los fotogramas a las dimensiones de origen. 50%% a la mitad de tamaño. " "200%% al doble de tamaño" -#: lib/cli/args.py:767 +#: lib/cli/args.py:776 msgid "" "Frame ranges to apply transfer to e.g. For frames 10 to 50 and 90 to 100 use " "--frame-ranges 10-50 90-100. Frames falling outside of the selected range " @@ -588,7 +598,7 @@ msgstr "" "imágenes, ¡los nombres de los archivos deben terminar con el número de " "fotograma!" -#: lib/cli/args.py:777 +#: lib/cli/args.py:786 msgid "" "If you have not cleansed your alignments file, then you can filter out faces " "by defining a folder here that contains the faces extracted from your input " @@ -604,7 +614,7 @@ msgstr "" "especificada. Si se deja en blanco, se convertirán todas las caras que " "existan en el archivo de alineaciones." -#: lib/cli/args.py:831 +#: lib/cli/args.py:840 msgid "" "The maximum number of parallel processes for performing conversion. " "Converting images is system RAM heavy so it is possible to run out of memory " @@ -621,7 +631,7 @@ msgstr "" "procesos que los disponibles en su sistema. Si 'singleprocess' está " "habilitado, este ajuste será ignorado." -#: lib/cli/args.py:842 +#: lib/cli/args.py:851 msgid "" "[LEGACY] This only needs to be selected if a legacy model is being loaded or " "if there are multiple models in the model folder" @@ -629,7 +639,7 @@ msgstr "" "[LEGACY] Sólo es necesario seleccionar esta opción si se está cargando un " "modelo heredado si hay varios modelos en la carpeta de modelos" -#: lib/cli/args.py:850 +#: lib/cli/args.py:859 msgid "" "Enable On-The-Fly Conversion. NOT recommended. You should generate a clean " "alignments file for your destination video. However, if you wish you can " @@ -644,7 +654,7 @@ msgstr "" "de baja calidad. Si se encuentra un archivo de alineaciones, esta opción " "será ignorada." -#: lib/cli/args.py:861 +#: lib/cli/args.py:870 msgid "" "When used with --frame-ranges outputs the unchanged frames that are not " "processed instead of discarding them." @@ -652,16 +662,16 @@ msgstr "" "Cuando se usa con --frame-ranges, la salida incluye los fotogramas no " "procesados en vez de descartarlos." -#: lib/cli/args.py:869 +#: lib/cli/args.py:878 msgid "Swap the model. Instead converting from of A -> B, converts B -> A" msgstr "" "Intercambiar el modelo. En vez de convertir de A a B, convierte de B a A" -#: lib/cli/args.py:875 +#: lib/cli/args.py:884 msgid "Disable multiprocessing. Slower but less resource intensive." msgstr "Desactiva el multiproceso. Es más lento, pero usa menos recursos." -#: lib/cli/args.py:891 +#: lib/cli/args.py:900 msgid "" "Train a model on extracted original (A) and swap (B) faces.\n" "Training models can take a long time. Anything from 24hrs to over a week\n" @@ -673,11 +683,11 @@ msgstr "" "hasta más de una semana.\n" "Los plugins de los modelos pueden configurarse en el menú \"Ajustes\"" -#: lib/cli/args.py:910 lib/cli/args.py:919 +#: lib/cli/args.py:919 lib/cli/args.py:928 msgid "faces" msgstr "caras" -#: lib/cli/args.py:911 +#: lib/cli/args.py:920 msgid "" "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 " @@ -687,7 +697,7 @@ msgstr "" "para la cara A. Esta es la cara original, es decir, la cara que se quiere " "eliminar y sustituir por la cara B." -#: lib/cli/args.py:920 +#: lib/cli/args.py:929 msgid "" "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 " @@ -697,12 +707,12 @@ msgstr "" "para la cara B. Esta es la cara de intercambio, es decir, la cara que se " "quiere colocar en la cabeza de la persona A." -#: lib/cli/args.py:928 lib/cli/args.py:940 lib/cli/args.py:956 -#: lib/cli/args.py:981 lib/cli/args.py:991 +#: lib/cli/args.py:937 lib/cli/args.py:949 lib/cli/args.py:965 +#: lib/cli/args.py:990 lib/cli/args.py:1000 msgid "model" msgstr "modelo" -#: lib/cli/args.py:929 +#: lib/cli/args.py:938 msgid "" "Model directory. This is where the training data will be stored. You should " "always specify a new folder for new models. If starting a new model, select " @@ -716,7 +726,7 @@ msgstr "" "carpeta que no exista (que se creará). Si continúa entrenando un modelo " "existente, especifique la ubicación del modelo existente." -#: lib/cli/args.py:941 +#: lib/cli/args.py:950 msgid "" "R|Load the weights from a pre-existing model into a newly created model. For " "most models this will load weights from the Encoder of the given model into " @@ -740,7 +750,7 @@ msgstr "" "NB: Los pesos solo se pueden cargar desde modelos del mismo complemento que " "desea entrenar." -#: lib/cli/args.py:957 +#: lib/cli/args.py:966 msgid "" "R|Select which trainer to use. Trainers can be configured from the Settings " "menu or the config folder.\n" @@ -785,7 +795,7 @@ msgstr "" "recursos (se necesita una GPU con una buena cantidad de VRAM). Bueno para " "los detalles, pero más susceptible a las diferencias de color." -#: lib/cli/args.py:982 +#: lib/cli/args.py:991 msgid "" "Output a summary of the model and exit. If a model folder is provided then a " "summary of the saved model is displayed. Otherwise a summary of the model " @@ -797,7 +807,7 @@ msgstr "" "muestra un resumen del modelo que crearía el complemento elegido y los " "ajustes de configuración." -#: lib/cli/args.py:992 +#: lib/cli/args.py:1001 msgid "" "Freeze the weights of the model. Freezing weights means that some of the " "parameters in the model will no longer continue to learn, but those that are " @@ -811,12 +821,12 @@ msgstr "" "congelará el codificador, pero algunos modelos pueden tener opciones de " "configuración para congelar otras capas." -#: lib/cli/args.py:1005 lib/cli/args.py:1017 lib/cli/args.py:1028 -#: lib/cli/args.py:1039 lib/cli/args.py:1122 +#: lib/cli/args.py:1014 lib/cli/args.py:1026 lib/cli/args.py:1037 +#: lib/cli/args.py:1048 lib/cli/args.py:1131 msgid "training" msgstr "entrenamiento" -#: lib/cli/args.py:1006 +#: lib/cli/args.py:1015 msgid "" "Batch size. This is the number of images processed through the model for " "each side per iteration. NB: As the model is fed 2 sides at a time, the " @@ -829,7 +839,7 @@ msgstr "" "momento es el doble del número que se establece aquí. Los lotes más grandes " "requieren más RAM de la GPU." -#: lib/cli/args.py:1018 +#: lib/cli/args.py:1027 msgid "" "Length of training in iterations. This is only really used for automation. " "There is no 'correct' number of iterations a model should be trained for. " @@ -844,7 +854,7 @@ msgstr "" "automáticamente en un número determinado de iteraciones, puede establecer " "ese valor aquí." -#: lib/cli/args.py:1029 +#: lib/cli/args.py:1038 msgid "" "[Deprecated - Use '-D, --distribution-strategy' instead] Use the Tensorflow " "Mirrored Distrubution Strategy to train on multiple GPUs." @@ -852,7 +862,7 @@ msgstr "" "[Obsoleto: use '-D, --distribution-strategy' en su lugar] Use la estrategia " "de distribución duplicada de Tensorflow para entrenar en varias GPU." -#: lib/cli/args.py:1040 +#: lib/cli/args.py:1049 msgid "" "R|Select the distribution stategy to use.\n" "L|default: Use Tensorflow's default distribution strategy.\n" @@ -864,16 +874,29 @@ msgid "" "GPUs. A copy of the model and all variables are loaded onto each GPU with " "batches distributed to each GPU at each iteration." msgstr "" +"562 / 5,000\n" +"Translation results\n" +"R|Seleccione la estrategia de distribución a utilizar.\n" +"L|default: utiliza la estrategia de distribución predeterminada de " +"Tensorflow.\n" +"L|central-storage: centraliza las variables en la CPU mientras que las " +"operaciones se realizan en 1 o más GPU locales. Esto puede ayudar a ahorrar " +"algo de VRAM a costa de cierta velocidad al no almacenar variables en la " +"GPU. Nota: Mixed-Precision no es compatible con configuraciones de múltiples " +"GPU.\n" +"L|mirrored: Admite el entrenamiento distribuido síncrono en varias GPU " +"locales. Se carga una copia del modelo y todas las variables en cada GPU con " +"lotes distribuidos a cada GPU en cada iteración." -#: lib/cli/args.py:1057 lib/cli/args.py:1067 +#: lib/cli/args.py:1066 lib/cli/args.py:1076 msgid "Saving" msgstr "Guardar" -#: lib/cli/args.py:1058 +#: lib/cli/args.py:1067 msgid "Sets the number of iterations between each model save." msgstr "Establece el número de iteraciones entre cada guardado del modelo." -#: lib/cli/args.py:1068 +#: lib/cli/args.py:1077 msgid "" "Sets the number of iterations before saving a backup snapshot of the model " "in it's current state. Set to 0 for off." @@ -881,11 +904,11 @@ msgstr "" "Establece el número de iteraciones antes de guardar una copia de seguridad " "del modelo en su estado actual. Establece 0 para que esté desactivado." -#: lib/cli/args.py:1075 lib/cli/args.py:1086 lib/cli/args.py:1097 +#: lib/cli/args.py:1084 lib/cli/args.py:1095 lib/cli/args.py:1106 msgid "timelapse" msgstr "intervalo" -#: lib/cli/args.py:1076 +#: lib/cli/args.py:1085 msgid "" "Optional for creating a timelapse. Timelapse will save an image of your " "selected faces into the timelapse-output folder at every save iteration. " @@ -899,7 +922,7 @@ msgstr "" "para crear el timelapse. También debe suministrar un parámetro --timelapse-" "output y un parámetro --timelapse-input-B." -#: lib/cli/args.py:1087 +#: lib/cli/args.py:1096 msgid "" "Optional for creating a timelapse. Timelapse will save an image of your " "selected faces into the timelapse-output folder at every save iteration. " @@ -913,7 +936,7 @@ msgstr "" "para crear el timelapse. También debe suministrar un parámetro --timelapse-" "output y un parámetro --timelapse-input-A." -#: lib/cli/args.py:1098 +#: lib/cli/args.py:1107 msgid "" "Optional for creating a timelapse. Timelapse will save an image of your " "selected faces into the timelapse-output folder at every save iteration. If " @@ -925,17 +948,17 @@ msgstr "" "Si se suministran las carpetas de entrada pero no la carpeta de salida, se " "guardará por defecto en la carpeta del modelo /timelapse/" -#: lib/cli/args.py:1107 lib/cli/args.py:1114 +#: lib/cli/args.py:1116 lib/cli/args.py:1123 msgid "preview" msgstr "previsualización" -#: lib/cli/args.py:1108 +#: lib/cli/args.py:1117 msgid "Show training preview output. in a separate window." msgstr "" "Mostrar la salida de la vista previa del entrenamiento. en una ventana " "separada." -#: lib/cli/args.py:1115 +#: lib/cli/args.py:1124 msgid "" "Writes the training result to a file. The image will be stored in the root " "of your FaceSwap folder." @@ -943,7 +966,7 @@ msgstr "" "Escribe el resultado del entrenamiento en un archivo. La imagen se " "almacenará en la raíz de su carpeta FaceSwap." -#: lib/cli/args.py:1123 +#: lib/cli/args.py:1132 msgid "" "Disables TensorBoard logging. NB: Disabling logs means that you will not be " "able to use the graph or analysis for this session in the GUI." @@ -951,12 +974,12 @@ msgstr "" "Desactiva el registro de TensorBoard. NB: Desactivar los registros significa " "que no podrá utilizar el gráfico o el análisis de esta sesión en la GUI." -#: lib/cli/args.py:1130 lib/cli/args.py:1139 lib/cli/args.py:1148 -#: lib/cli/args.py:1157 +#: lib/cli/args.py:1139 lib/cli/args.py:1148 lib/cli/args.py:1157 +#: lib/cli/args.py:1166 msgid "augmentation" msgstr "aumento" -#: lib/cli/args.py:1131 +#: lib/cli/args.py:1140 msgid "" "Warps training faces to closely matched Landmarks from the opposite face-set " "rather than randomly warping the face. This is the 'dfaker' way of doing " @@ -966,7 +989,7 @@ msgstr "" "conjunto de caras opuestas en lugar de deformar la cara al azar. Esta es la " "forma 'dfaker' de hacer la deformación." -#: lib/cli/args.py:1140 +#: lib/cli/args.py:1149 msgid "" "To effectively learn, a random set of images are flipped horizontally. " "Sometimes it is desirable for this not to occur. Generally this should be " @@ -977,7 +1000,7 @@ msgstr "" "general, esto debería dejarse sin efecto, excepto durante el 'entrenamiento " "de ajuste'." -#: lib/cli/args.py:1149 +#: lib/cli/args.py:1158 msgid "" "Color augmentation helps make the model less susceptible to color " "differences between the A and B sets, at an increased training time cost. " @@ -987,7 +1010,7 @@ msgstr "" "diferencias de color entre los conjuntos A y B, con un mayor coste de tiempo " "de entrenamiento. Activa esta opción para desactivar el aumento de color." -#: lib/cli/args.py:1158 +#: lib/cli/args.py:1167 msgid "" "Warping is integral to training the Neural Network. This option should only " "be enabled towards the very end of training to try to bring out more detail. " @@ -1000,7 +1023,7 @@ msgstr "" "esta opción desde el principio, es probable que arruine el modelo y se " "obtengan resultados terribles." -#: lib/cli/args.py:1183 +#: lib/cli/args.py:1192 msgid "Output to Shell console instead of GUI console" msgstr "Salida a la consola Shell en lugar de la consola GUI" diff --git a/locales/lib.cli.args.pot b/locales/lib.cli.args.pot index e91594f..5cdbb67 100644 --- a/locales/lib.cli.args.pot +++ b/locales/lib.cli.args.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-08-05 13:58+0100\n" +"POT-Creation-Date: 2022-08-31 19:19+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -46,7 +46,7 @@ msgid "Path to store the logfile. Leave blank to store in the faceswap folder" msgstr "" #: lib/cli/args.py:320 lib/cli/args.py:329 lib/cli/args.py:337 -#: lib/cli/args.py:655 lib/cli/args.py:664 +#: lib/cli/args.py:385 lib/cli/args.py:664 lib/cli/args.py:673 msgid "Data" msgstr "" @@ -73,13 +73,20 @@ msgid "" "Extraction plugins can be configured in the 'Settings' Menu" msgstr "" -#: lib/cli/args.py:386 lib/cli/args.py:402 lib/cli/args.py:414 -#: lib/cli/args.py:453 lib/cli/args.py:471 lib/cli/args.py:483 -#: lib/cli/args.py:674 lib/cli/args.py:701 lib/cli/args.py:739 +#: lib/cli/args.py:386 +msgid "" +"R|If selected then the input_dir should be a parent folder containing " +"multiple videos and/or folders of images you wish to extract from. The faces " +"will be output to separate sub-folders in the output_dir." +msgstr "" + +#: lib/cli/args.py:395 lib/cli/args.py:411 lib/cli/args.py:423 +#: lib/cli/args.py:462 lib/cli/args.py:480 lib/cli/args.py:492 +#: lib/cli/args.py:683 lib/cli/args.py:710 lib/cli/args.py:748 msgid "Plugins" msgstr "" -#: lib/cli/args.py:387 +#: lib/cli/args.py:396 msgid "" "R|Detector to use. Some of these have configurable settings in '/config/" "extract.ini' or 'Settings > Configure Extract 'Plugins':\n" @@ -92,7 +99,7 @@ msgid "" "intensive." msgstr "" -#: lib/cli/args.py:403 +#: lib/cli/args.py:412 msgid "" "R|Aligner to use.\n" "L|cv2-dnn: A CPU only landmark detector. Faster, less resource intensive, " @@ -100,7 +107,7 @@ msgid "" "L|fan: Best aligner. Fast on GPU, slow on CPU." msgstr "" -#: lib/cli/args.py:415 +#: lib/cli/args.py:424 msgid "" "R|Additional Masker(s) to use. The masks generated here will all take up GPU " "RAM. You can select none, one or multiple masks, but the extraction may take " @@ -135,7 +142,7 @@ msgid "" "(eg: `-M unet-dfl vgg-clear`, `--masker vgg-obstructed`)" msgstr "" -#: lib/cli/args.py:454 +#: lib/cli/args.py:463 msgid "" "R|Performing normalization can help the aligner better align faces with " "difficult lighting conditions at an extraction speed cost. Different methods " @@ -148,7 +155,7 @@ msgid "" "L|mean: Normalize the face colors to the mean." msgstr "" -#: lib/cli/args.py:472 +#: lib/cli/args.py:481 msgid "" "The number of times to re-feed the detected face into the aligner. Each time " "the face is re-fed into the aligner the bounding box is adjusted by a small " @@ -158,7 +165,7 @@ msgid "" "occur but the longer extraction will take." msgstr "" -#: lib/cli/args.py:484 +#: lib/cli/args.py:493 msgid "" "If a face isn't found, rotate the images to try to find a face. Can find " "more faces at the cost of extraction speed. Pass in a single number to use " @@ -166,19 +173,19 @@ msgid "" "exactly what angles to check." msgstr "" -#: lib/cli/args.py:496 lib/cli/args.py:506 lib/cli/args.py:519 -#: lib/cli/args.py:533 lib/cli/args.py:776 lib/cli/args.py:790 -#: lib/cli/args.py:803 lib/cli/args.py:817 +#: lib/cli/args.py:505 lib/cli/args.py:515 lib/cli/args.py:528 +#: lib/cli/args.py:542 lib/cli/args.py:785 lib/cli/args.py:799 +#: lib/cli/args.py:812 lib/cli/args.py:826 msgid "Face Processing" msgstr "" -#: lib/cli/args.py:497 +#: lib/cli/args.py:506 msgid "" "Filters out faces detected below this size. Length, in pixels across the " "diagonal of the bounding box. Set to 0 for off" msgstr "" -#: lib/cli/args.py:507 lib/cli/args.py:791 +#: lib/cli/args.py:516 lib/cli/args.py:800 msgid "" "Optionally filter out people who you do not wish to process by passing in an " "image of that person. Should be a front portrait with a single person in the " @@ -187,7 +194,7 @@ msgid "" "guaranteed." msgstr "" -#: lib/cli/args.py:520 lib/cli/args.py:804 +#: lib/cli/args.py:529 lib/cli/args.py:813 msgid "" "Optionally select people you wish to process by passing in an image of that " "person. Should be a front portrait with a single person in the image. " @@ -196,7 +203,7 @@ msgid "" "guaranteed." msgstr "" -#: lib/cli/args.py:534 lib/cli/args.py:818 +#: lib/cli/args.py:543 lib/cli/args.py:827 msgid "" "For use with the optional nfilter/filter files. Threshold for positive face " "recognition. Lower values are stricter. NB: Using face filter will " @@ -204,26 +211,26 @@ msgid "" "guaranteed." msgstr "" -#: lib/cli/args.py:545 lib/cli/args.py:557 lib/cli/args.py:569 -#: lib/cli/args.py:581 +#: lib/cli/args.py:554 lib/cli/args.py:566 lib/cli/args.py:578 +#: lib/cli/args.py:590 msgid "output" msgstr "" -#: lib/cli/args.py:546 +#: lib/cli/args.py:555 msgid "" "The output size of extracted faces. Make sure that the model you intend to " "train supports your required size. This will only need to be changed for hi-" "res models." msgstr "" -#: lib/cli/args.py:558 +#: lib/cli/args.py:567 msgid "" "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 "" -#: lib/cli/args.py:570 +#: lib/cli/args.py:579 msgid "" "Automatically save the alignments file after a set amount of frames. By " "default the alignments file is only saved at the end of the extraction " @@ -233,57 +240,57 @@ msgid "" "turn off" msgstr "" -#: lib/cli/args.py:582 +#: lib/cli/args.py:591 msgid "Draw landmarks on the ouput faces for debugging purposes." msgstr "" -#: lib/cli/args.py:588 lib/cli/args.py:597 lib/cli/args.py:605 -#: lib/cli/args.py:612 lib/cli/args.py:830 lib/cli/args.py:841 -#: lib/cli/args.py:849 lib/cli/args.py:868 lib/cli/args.py:874 +#: lib/cli/args.py:597 lib/cli/args.py:606 lib/cli/args.py:614 +#: lib/cli/args.py:621 lib/cli/args.py:839 lib/cli/args.py:850 +#: lib/cli/args.py:858 lib/cli/args.py:877 lib/cli/args.py:883 msgid "settings" msgstr "" -#: lib/cli/args.py:589 +#: lib/cli/args.py:598 msgid "" "Don't run extraction in parallel. Will run each part of the extraction " "process separately (one after the other) rather than all at the smae time. " "Useful if VRAM is at a premium." msgstr "" -#: lib/cli/args.py:598 +#: lib/cli/args.py:607 msgid "" "Skips frames that have already been extracted and exist in the alignments " "file" msgstr "" -#: lib/cli/args.py:606 +#: lib/cli/args.py:615 msgid "Skip frames that already have detected faces in the alignments file" msgstr "" -#: lib/cli/args.py:613 +#: lib/cli/args.py:622 msgid "Skip saving the detected faces to disk. Just create an alignments file" msgstr "" -#: lib/cli/args.py:635 +#: lib/cli/args.py:644 msgid "" "Swap the original faces in a source video/images to your final faces.\n" "Conversion plugins can be configured in the 'Settings' Menu" msgstr "" -#: lib/cli/args.py:656 +#: lib/cli/args.py:665 msgid "" "Only required if converting from images to video. Provide The original video " "that the source frames were extracted from (for extracting the fps and " "audio)." msgstr "" -#: lib/cli/args.py:665 +#: lib/cli/args.py:674 msgid "" "Model directory. The directory containing the trained model you wish to use " "for conversion." msgstr "" -#: lib/cli/args.py:675 +#: lib/cli/args.py:684 msgid "" "R|Performs color adjustment to the swapped face. Some of these options have " "configurable settings in '/config/convert.ini' or 'Settings > Configure " @@ -304,7 +311,7 @@ msgid "" "L|none: Don't perform color adjustment." msgstr "" -#: lib/cli/args.py:702 +#: lib/cli/args.py:711 msgid "" "R|Masker to use. NB: The mask you require must exist within the alignments " "file. You can add additional masks with the Mask Tool.\n" @@ -341,7 +348,7 @@ msgid "" "will use the mask that was created by the trained model." msgstr "" -#: lib/cli/args.py:740 +#: lib/cli/args.py:749 msgid "" "R|The plugin to use to output the converted images. The writers are " "configurable in '/config/convert.ini' or 'Settings > Configure Convert " @@ -356,18 +363,18 @@ msgid "" "more formats." msgstr "" -#: lib/cli/args.py:759 lib/cli/args.py:766 lib/cli/args.py:860 +#: lib/cli/args.py:768 lib/cli/args.py:775 lib/cli/args.py:869 msgid "Frame Processing" msgstr "" -#: lib/cli/args.py:760 +#: lib/cli/args.py:769 #, python-format msgid "" "Scale the final output frames by this amount. 100%% will output the frames " "at source dimensions. 50%% at half size 200%% at double size" msgstr "" -#: lib/cli/args.py:767 +#: lib/cli/args.py:776 msgid "" "Frame ranges to apply transfer to e.g. For frames 10 to 50 and 90 to 100 use " "--frame-ranges 10-50 90-100. Frames falling outside of the selected range " @@ -375,7 +382,7 @@ msgid "" "converting from images, then the filenames must end with the frame-number!" msgstr "" -#: lib/cli/args.py:777 +#: lib/cli/args.py:786 msgid "" "If you have not cleansed your alignments file, then you can filter out faces " "by defining a folder here that contains the faces extracted from your input " @@ -385,7 +392,7 @@ msgid "" "alignments file." msgstr "" -#: lib/cli/args.py:831 +#: lib/cli/args.py:840 msgid "" "The maximum number of parallel processes for performing conversion. " "Converting images is system RAM heavy so it is possible to run out of memory " @@ -395,13 +402,13 @@ msgid "" "your system. If singleprocess is enabled this setting will be ignored." msgstr "" -#: lib/cli/args.py:842 +#: lib/cli/args.py:851 msgid "" "[LEGACY] This only needs to be selected if a legacy model is being loaded or " "if there are multiple models in the model folder" msgstr "" -#: lib/cli/args.py:850 +#: lib/cli/args.py:859 msgid "" "Enable On-The-Fly Conversion. NOT recommended. You should generate a clean " "alignments file for your destination video. However, if you wish you can " @@ -410,51 +417,51 @@ msgid "" "alignments file is found, this option will be ignored." msgstr "" -#: lib/cli/args.py:861 +#: lib/cli/args.py:870 msgid "" "When used with --frame-ranges outputs the unchanged frames that are not " "processed instead of discarding them." msgstr "" -#: lib/cli/args.py:869 +#: lib/cli/args.py:878 msgid "Swap the model. Instead converting from of A -> B, converts B -> A" msgstr "" -#: lib/cli/args.py:875 +#: lib/cli/args.py:884 msgid "Disable multiprocessing. Slower but less resource intensive." msgstr "" -#: lib/cli/args.py:891 +#: lib/cli/args.py:900 msgid "" "Train a model on extracted original (A) and swap (B) faces.\n" "Training models can take a long time. Anything from 24hrs to over a week\n" "Model plugins can be configured in the 'Settings' Menu" msgstr "" -#: lib/cli/args.py:910 lib/cli/args.py:919 +#: lib/cli/args.py:919 lib/cli/args.py:928 msgid "faces" msgstr "" -#: lib/cli/args.py:911 +#: lib/cli/args.py:920 msgid "" "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." msgstr "" -#: lib/cli/args.py:920 +#: lib/cli/args.py:929 msgid "" "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." msgstr "" -#: lib/cli/args.py:928 lib/cli/args.py:940 lib/cli/args.py:956 -#: lib/cli/args.py:981 lib/cli/args.py:991 +#: lib/cli/args.py:937 lib/cli/args.py:949 lib/cli/args.py:965 +#: lib/cli/args.py:990 lib/cli/args.py:1000 msgid "model" msgstr "" -#: lib/cli/args.py:929 +#: lib/cli/args.py:938 msgid "" "Model directory. This is where the training data will be stored. You should " "always specify a new folder for new models. If starting a new model, select " @@ -463,7 +470,7 @@ msgid "" "the existing model." msgstr "" -#: lib/cli/args.py:941 +#: lib/cli/args.py:950 msgid "" "R|Load the weights from a pre-existing model into a newly created model. For " "most models this will load weights from the Encoder of the given model into " @@ -477,7 +484,7 @@ msgid "" "to train." msgstr "" -#: lib/cli/args.py:957 +#: lib/cli/args.py:966 msgid "" "R|Select which trainer to use. Trainers can be configured from the Settings " "menu or the config folder.\n" @@ -500,7 +507,7 @@ msgid "" "susceptible to color differences." msgstr "" -#: lib/cli/args.py:982 +#: lib/cli/args.py:991 msgid "" "Output a summary of the model and exit. If a model folder is provided then a " "summary of the saved model is displayed. Otherwise a summary of the model " @@ -508,7 +515,7 @@ msgid "" "displayed." msgstr "" -#: lib/cli/args.py:992 +#: lib/cli/args.py:1001 msgid "" "Freeze the weights of the model. Freezing weights means that some of the " "parameters in the model will no longer continue to learn, but those that are " @@ -517,12 +524,12 @@ msgid "" "layers." msgstr "" -#: lib/cli/args.py:1005 lib/cli/args.py:1017 lib/cli/args.py:1028 -#: lib/cli/args.py:1039 lib/cli/args.py:1122 +#: lib/cli/args.py:1014 lib/cli/args.py:1026 lib/cli/args.py:1037 +#: lib/cli/args.py:1048 lib/cli/args.py:1131 msgid "training" msgstr "" -#: lib/cli/args.py:1006 +#: lib/cli/args.py:1015 msgid "" "Batch size. This is the number of images processed through the model for " "each side per iteration. NB: As the model is fed 2 sides at a time, the " @@ -530,7 +537,7 @@ msgid "" "number that you set here. Larger batches require more GPU RAM." msgstr "" -#: lib/cli/args.py:1018 +#: lib/cli/args.py:1027 msgid "" "Length of training in iterations. This is only really used for automation. " "There is no 'correct' number of iterations a model should be trained for. " @@ -539,13 +546,13 @@ msgid "" "can set that value here." msgstr "" -#: lib/cli/args.py:1029 +#: lib/cli/args.py:1038 msgid "" "[Deprecated - Use '-D, --distribution-strategy' instead] Use the Tensorflow " "Mirrored Distrubution Strategy to train on multiple GPUs." msgstr "" -#: lib/cli/args.py:1040 +#: lib/cli/args.py:1049 msgid "" "R|Select the distribution stategy to use.\n" "L|default: Use Tensorflow's default distribution strategy.\n" @@ -558,25 +565,25 @@ msgid "" "batches distributed to each GPU at each iteration." msgstr "" -#: lib/cli/args.py:1057 lib/cli/args.py:1067 +#: lib/cli/args.py:1066 lib/cli/args.py:1076 msgid "Saving" msgstr "" -#: lib/cli/args.py:1058 +#: lib/cli/args.py:1067 msgid "Sets the number of iterations between each model save." msgstr "" -#: lib/cli/args.py:1068 +#: lib/cli/args.py:1077 msgid "" "Sets the number of iterations before saving a backup snapshot of the model " "in it's current state. Set to 0 for off." msgstr "" -#: lib/cli/args.py:1075 lib/cli/args.py:1086 lib/cli/args.py:1097 +#: lib/cli/args.py:1084 lib/cli/args.py:1095 lib/cli/args.py:1106 msgid "timelapse" msgstr "" -#: lib/cli/args.py:1076 +#: lib/cli/args.py:1085 msgid "" "Optional for creating a timelapse. Timelapse will save an image of your " "selected faces into the timelapse-output folder at every save iteration. " @@ -585,7 +592,7 @@ msgid "" "timelapse-input-B parameter." msgstr "" -#: lib/cli/args.py:1087 +#: lib/cli/args.py:1096 msgid "" "Optional for creating a timelapse. Timelapse will save an image of your " "selected faces into the timelapse-output folder at every save iteration. " @@ -594,7 +601,7 @@ msgid "" "timelapse-input-A parameter." msgstr "" -#: lib/cli/args.py:1098 +#: lib/cli/args.py:1107 msgid "" "Optional for creating a timelapse. Timelapse will save an image of your " "selected faces into the timelapse-output folder at every save iteration. If " @@ -602,53 +609,53 @@ msgid "" "model folder /timelapse/" msgstr "" -#: lib/cli/args.py:1107 lib/cli/args.py:1114 +#: lib/cli/args.py:1116 lib/cli/args.py:1123 msgid "preview" msgstr "" -#: lib/cli/args.py:1108 +#: lib/cli/args.py:1117 msgid "Show training preview output. in a separate window." msgstr "" -#: lib/cli/args.py:1115 +#: lib/cli/args.py:1124 msgid "" "Writes the training result to a file. The image will be stored in the root " "of your FaceSwap folder." msgstr "" -#: lib/cli/args.py:1123 +#: lib/cli/args.py:1132 msgid "" "Disables TensorBoard logging. NB: Disabling logs means that you will not be " "able to use the graph or analysis for this session in the GUI." msgstr "" -#: lib/cli/args.py:1130 lib/cli/args.py:1139 lib/cli/args.py:1148 -#: lib/cli/args.py:1157 +#: lib/cli/args.py:1139 lib/cli/args.py:1148 lib/cli/args.py:1157 +#: lib/cli/args.py:1166 msgid "augmentation" msgstr "" -#: lib/cli/args.py:1131 +#: lib/cli/args.py:1140 msgid "" "Warps training faces to closely matched Landmarks from the opposite face-set " "rather than randomly warping the face. This is the 'dfaker' way of doing " "warping." msgstr "" -#: lib/cli/args.py:1140 +#: lib/cli/args.py:1149 msgid "" "To effectively learn, a random set of images are flipped horizontally. " "Sometimes it is desirable for this not to occur. Generally this should be " "left off except for during 'fit training'." msgstr "" -#: lib/cli/args.py:1149 +#: lib/cli/args.py:1158 msgid "" "Color augmentation helps make the model less susceptible to color " "differences between the A and B sets, at an increased training time cost. " "Enable this option to disable color augmentation." msgstr "" -#: lib/cli/args.py:1158 +#: lib/cli/args.py:1167 msgid "" "Warping is integral to training the Neural Network. This option should only " "be enabled towards the very end of training to try to bring out more detail. " @@ -656,6 +663,6 @@ msgid "" "likely to kill a model and lead to terrible results." msgstr "" -#: lib/cli/args.py:1183 +#: lib/cli/args.py:1192 msgid "Output to Shell console instead of GUI console" msgstr "" diff --git a/locales/ru/LC_MESSAGES/lib.cli.args.mo b/locales/ru/LC_MESSAGES/lib.cli.args.mo index 396f83c..1396e1c 100644 Binary files a/locales/ru/LC_MESSAGES/lib.cli.args.mo and b/locales/ru/LC_MESSAGES/lib.cli.args.mo differ diff --git a/locales/ru/LC_MESSAGES/lib.cli.args.po b/locales/ru/LC_MESSAGES/lib.cli.args.po index aac0550..bf14c21 100644 --- a/locales/ru/LC_MESSAGES/lib.cli.args.po +++ b/locales/ru/LC_MESSAGES/lib.cli.args.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-08-05 13:58+0100\n" -"PO-Revision-Date: 2022-08-05 14:07+0100\n" +"POT-Creation-Date: 2022-08-31 19:19+0100\n" +"PO-Revision-Date: 2022-08-31 19:22+0100\n" "Last-Translator: \n" "Language-Team: \n" "Language: ru\n" @@ -58,7 +58,7 @@ msgstr "" "с faceswap" #: lib/cli/args.py:320 lib/cli/args.py:329 lib/cli/args.py:337 -#: lib/cli/args.py:655 lib/cli/args.py:664 +#: lib/cli/args.py:385 lib/cli/args.py:664 lib/cli/args.py:673 msgid "Data" msgstr "Данные" @@ -90,13 +90,23 @@ msgstr "" "Извлечь лица из изображений или видео источников.\n" "Плагины извлечения можно настроить в меню 'Настройки'" -#: lib/cli/args.py:386 lib/cli/args.py:402 lib/cli/args.py:414 -#: lib/cli/args.py:453 lib/cli/args.py:471 lib/cli/args.py:483 -#: lib/cli/args.py:674 lib/cli/args.py:701 lib/cli/args.py:739 +#: lib/cli/args.py:386 +msgid "" +"R|If selected then the input_dir should be a parent folder containing " +"multiple videos and/or folders of images you wish to extract from. The faces " +"will be output to separate sub-folders in the output_dir." +msgstr "" +"R|Если выбрано, то input_dir должна быть родительской папкой, содержащей " +"несколько видео и/или папок изображений, из которых вы хотите извлечь. Лица " +"будут выводиться в отдельные подпапки в output_dir." + +#: lib/cli/args.py:395 lib/cli/args.py:411 lib/cli/args.py:423 +#: lib/cli/args.py:462 lib/cli/args.py:480 lib/cli/args.py:492 +#: lib/cli/args.py:683 lib/cli/args.py:710 lib/cli/args.py:748 msgid "Plugins" msgstr "Плагины" -#: lib/cli/args.py:387 +#: lib/cli/args.py:396 msgid "" "R|Detector to use. Some of these have configurable settings in '/config/" "extract.ini' or 'Settings > Configure Extract 'Plugins':\n" @@ -120,7 +130,7 @@ msgstr "" "детектировать лицо в большем кол-ве ситуация и меньшим кол-вом ошибок, чем " "другие GPU, но значительно более требователен к ресурсам." -#: lib/cli/args.py:403 +#: lib/cli/args.py:412 msgid "" "R|Aligner to use.\n" "L|cv2-dnn: A CPU only landmark detector. Faster, less resource intensive, " @@ -133,7 +143,7 @@ msgstr "" "использовать GPU.\n" "L|fan: Лучший выравниватель. Быстрый на GPU, медленный на CPU." -#: lib/cli/args.py:415 +#: lib/cli/args.py:424 msgid "" "R|Additional Masker(s) to use. The masks generated here will all take up GPU " "RAM. You can select none, one or multiple masks, but the extraction may take " @@ -199,7 +209,7 @@ msgstr "" "ориентиров лица и расширяется вверх на лоб.\n" "(пример: `-M unet-dfl vgg-clear`, `--masker vgg-obstructed`)" -#: lib/cli/args.py:454 +#: lib/cli/args.py:463 msgid "" "R|Performing normalization can help the aligner better align faces with " "difficult lighting conditions at an extraction speed cost. Different methods " @@ -220,7 +230,7 @@ msgstr "" "L|hist: Выравнивание гистограммы каналов RGB каналов.\n" "L|mean: Усреднение цветов лица." -#: lib/cli/args.py:472 +#: lib/cli/args.py:481 msgid "" "The number of times to re-feed the detected face into the aligner. Each time " "the face is re-fed into the aligner the bounding box is adjusted by a small " @@ -235,7 +245,7 @@ msgstr "" "замедления скорости извлечения. Чем больше проходов выравнивания, тем меньше " "микродрожание, но тем дольше идет извлечение." -#: lib/cli/args.py:484 +#: lib/cli/args.py:493 msgid "" "If a face isn't found, rotate the images to try to find a face. Can find " "more faces at the cost of extraction speed. Pass in a single number to use " @@ -247,13 +257,13 @@ msgstr "" "использовать приращения этого размера до 360, либо передайте список чисел, " "чтобы точно указать, какие углы проверять." -#: lib/cli/args.py:496 lib/cli/args.py:506 lib/cli/args.py:519 -#: lib/cli/args.py:533 lib/cli/args.py:776 lib/cli/args.py:790 -#: lib/cli/args.py:803 lib/cli/args.py:817 +#: lib/cli/args.py:505 lib/cli/args.py:515 lib/cli/args.py:528 +#: lib/cli/args.py:542 lib/cli/args.py:785 lib/cli/args.py:799 +#: lib/cli/args.py:812 lib/cli/args.py:826 msgid "Face Processing" msgstr "Обработка лиц" -#: lib/cli/args.py:497 +#: lib/cli/args.py:506 msgid "" "Filters out faces detected below this size. Length, in pixels across the " "diagonal of the bounding box. Set to 0 for off" @@ -261,7 +271,7 @@ msgstr "" "Отбрасывает лица ниже указанного размера. Длина указывается в пикселях по " "диагонали. Установите в 0 для отключения" -#: lib/cli/args.py:507 lib/cli/args.py:791 +#: lib/cli/args.py:516 lib/cli/args.py:800 msgid "" "Optionally filter out people who you do not wish to process by passing in an " "image of that person. Should be a front portrait with a single person in the " @@ -275,7 +285,7 @@ msgstr "" "пробел. Прим.: Фильтрация лиц существенно снижает скорость извлечения, при " "этом точность не гарантируется." -#: lib/cli/args.py:520 lib/cli/args.py:804 +#: lib/cli/args.py:529 lib/cli/args.py:813 msgid "" "Optionally select people you wish to process by passing in an image of that " "person. Should be a front portrait with a single person in the image. " @@ -289,7 +299,7 @@ msgstr "" "изображений через пробел. Прим.: Использование фильтра существенно замедлит " "скорость извлечения. Также точность не гарантируется." -#: lib/cli/args.py:534 lib/cli/args.py:818 +#: lib/cli/args.py:543 lib/cli/args.py:827 msgid "" "For use with the optional nfilter/filter files. Threshold for positive face " "recognition. Lower values are stricter. NB: Using face filter will " @@ -300,12 +310,12 @@ msgstr "" "лица. Чем ниже значения, тем строже. Прим.: Использование фильтра лиц " "существенно замедлит скорость извлечения. Также точность не гарантируется." -#: lib/cli/args.py:545 lib/cli/args.py:557 lib/cli/args.py:569 -#: lib/cli/args.py:581 +#: lib/cli/args.py:554 lib/cli/args.py:566 lib/cli/args.py:578 +#: lib/cli/args.py:590 msgid "output" msgstr "вывод" -#: lib/cli/args.py:546 +#: lib/cli/args.py:555 msgid "" "The output size of extracted faces. Make sure that the model you intend to " "train supports your required size. This will only need to be changed for hi-" @@ -315,7 +325,7 @@ msgstr "" "поддерживает такой входной размер. Стоит изменять только для моделей " "высокого разрешения." -#: lib/cli/args.py:558 +#: lib/cli/args.py:567 msgid "" "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 " @@ -325,7 +335,7 @@ msgstr "" "извлечении. Например, значение 1 будет искать лица в каждом кадре, а " "значение 10 в каждом 10том кадре." -#: lib/cli/args.py:570 +#: lib/cli/args.py:579 msgid "" "Automatically save the alignments file after a set amount of frames. By " "default the alignments file is only saved at the end of the extraction " @@ -340,17 +350,17 @@ msgstr "" "только во время второго прохода. ВНИМАНИЕ: Не прерывайте выполнение во время " "записи, так как это может повлечь порчу файла. Установите в 0 для выключения" -#: lib/cli/args.py:582 +#: lib/cli/args.py:591 msgid "Draw landmarks on the ouput faces for debugging purposes." msgstr "Рисовать ландмарки на выходных лицах для нужд отладки." -#: lib/cli/args.py:588 lib/cli/args.py:597 lib/cli/args.py:605 -#: lib/cli/args.py:612 lib/cli/args.py:830 lib/cli/args.py:841 -#: lib/cli/args.py:849 lib/cli/args.py:868 lib/cli/args.py:874 +#: lib/cli/args.py:597 lib/cli/args.py:606 lib/cli/args.py:614 +#: lib/cli/args.py:621 lib/cli/args.py:839 lib/cli/args.py:850 +#: lib/cli/args.py:858 lib/cli/args.py:877 lib/cli/args.py:883 msgid "settings" msgstr "настройки" -#: lib/cli/args.py:589 +#: lib/cli/args.py:598 msgid "" "Don't run extraction in parallel. Will run each part of the extraction " "process separately (one after the other) rather than all at the smae time. " @@ -360,7 +370,7 @@ msgstr "" "стадия извлечения будет запущена отдельно (одна, за другой). Полезно при " "нехватке VRAM." -#: lib/cli/args.py:598 +#: lib/cli/args.py:607 msgid "" "Skips frames that have already been extracted and exist in the alignments " "file" @@ -368,16 +378,16 @@ msgstr "" "Пропускать кадры, которые уже были извлечены и существуют в файле " "выравнивания" -#: lib/cli/args.py:606 +#: lib/cli/args.py:615 msgid "Skip frames that already have detected faces in the alignments file" msgstr "Пропускать кадры, для которых в файле выравнивания есть найденные лица" -#: lib/cli/args.py:613 +#: lib/cli/args.py:622 msgid "Skip saving the detected faces to disk. Just create an alignments file" msgstr "" "Не сохранять найденные лица на носитель. Просто создать файл выравнивания" -#: lib/cli/args.py:635 +#: lib/cli/args.py:644 msgid "" "Swap the original faces in a source video/images to your final faces.\n" "Conversion plugins can be configured in the 'Settings' Menu" @@ -385,7 +395,7 @@ msgstr "" "Заменить оригиналы лица в исходном видео/фотографиях новыми.\n" "Плагины конвертации могут быть настроены в меню 'Настройки'" -#: lib/cli/args.py:656 +#: lib/cli/args.py:665 msgid "" "Only required if converting from images to video. Provide The original video " "that the source frames were extracted from (for extracting the fps and " @@ -395,7 +405,7 @@ msgstr "" "Предоставьте исходное видео, из которого были извлечены кадры (для настройки " "частоты кадров, а также аудио)." -#: lib/cli/args.py:665 +#: lib/cli/args.py:674 msgid "" "Model directory. The directory containing the trained model you wish to use " "for conversion." @@ -403,7 +413,7 @@ msgstr "" "Папка с моделью. Папка, содержащая обученную модель, которую вы хотите " "использовать для преобразования." -#: lib/cli/args.py:675 +#: lib/cli/args.py:684 msgid "" "R|Performs color adjustment to the swapped face. Some of these options have " "configurable settings in '/config/convert.ini' or 'Settings > Configure " @@ -442,7 +452,7 @@ msgstr "" "дает удовлетворительных результатов.\n" "L|none: Не производить подгонку цвета." -#: lib/cli/args.py:702 +#: lib/cli/args.py:711 msgid "" "R|Masker to use. NB: The mask you require must exist within the alignments " "file. You can add additional masks with the Mask Tool.\n" @@ -511,7 +521,7 @@ msgstr "" "L| predicted: Если во время обучения была включена опция «Learn Mask», будет " "использоваться маска, созданная обученной моделью." -#: lib/cli/args.py:740 +#: lib/cli/args.py:749 msgid "" "R|The plugin to use to output the converted images. The writers are " "configurable in '/config/convert.ini' or 'Settings > Configure Convert " @@ -537,11 +547,11 @@ msgstr "" "L|pillow: [изображения] Более медленный, чем opencv, но имеет больше опций и " "поддерживает больше форматов." -#: lib/cli/args.py:759 lib/cli/args.py:766 lib/cli/args.py:860 +#: lib/cli/args.py:768 lib/cli/args.py:775 lib/cli/args.py:869 msgid "Frame Processing" msgstr "Обработка кадров" -#: lib/cli/args.py:760 +#: lib/cli/args.py:769 #, python-format msgid "" "Scale the final output frames by this amount. 100%% will output the frames " @@ -551,7 +561,7 @@ msgstr "" "кадры в исходном размере. 50%% половина от размера, а 200%% в удвоенном " "размере" -#: lib/cli/args.py:767 +#: lib/cli/args.py:776 msgid "" "Frame ranges to apply transfer to e.g. For frames 10 to 50 and 90 to 100 use " "--frame-ranges 10-50 90-100. Frames falling outside of the selected range " @@ -564,7 +574,7 @@ msgstr "" "unchanged). Прим.: Если при конверсии используются изображения, то имена " "файлов должны заканчиваться номером кадра!" -#: lib/cli/args.py:777 +#: lib/cli/args.py:786 msgid "" "If you have not cleansed your alignments file, then you can filter out faces " "by defining a folder here that contains the faces extracted from your input " @@ -580,7 +590,7 @@ msgstr "" "Если оставить это поле пустым, то все лица, которые существуют в файле " "выравниваний будут сконвертированы." -#: lib/cli/args.py:831 +#: lib/cli/args.py:840 msgid "" "The maximum number of parallel processes for performing conversion. " "Converting images is system RAM heavy so it is possible to run out of memory " @@ -597,7 +607,7 @@ msgstr "" "будет использоваться больше процессов, чем доступно в вашей системе. Если " "включен одиночный процесс, этот параметр будет проигнорирован." -#: lib/cli/args.py:842 +#: lib/cli/args.py:851 msgid "" "[LEGACY] This only needs to be selected if a legacy model is being loaded or " "if there are multiple models in the model folder" @@ -605,7 +615,7 @@ msgstr "" "[СОВМЕСТИМОСТЬ] Это нужно выбирать только в том случае, если загружается " "устаревшая модель или если в папке сохранения есть несколько моделей" -#: lib/cli/args.py:850 +#: lib/cli/args.py:859 msgid "" "Enable On-The-Fly Conversion. NOT recommended. You should generate a clean " "alignments file for your destination video. However, if you wish you can " @@ -619,7 +629,7 @@ msgstr "" "использованию улучшенного конвейера экстракции и некачественных результатов. " "Если файл выравниваний найден, этот параметр будет проигнорирован." -#: lib/cli/args.py:861 +#: lib/cli/args.py:870 msgid "" "When used with --frame-ranges outputs the unchanged frames that are not " "processed instead of discarding them." @@ -627,16 +637,16 @@ msgstr "" "При использовании с --frame-range кадры не попавшие в диапазон выводятся " "неизменными, вместо их пропуска." -#: lib/cli/args.py:869 +#: lib/cli/args.py:878 msgid "Swap the model. Instead converting from of A -> B, converts B -> A" msgstr "" "Поменять модели местами. Вместо преобразования из A -> B, преобразует B -> A" -#: lib/cli/args.py:875 +#: lib/cli/args.py:884 msgid "Disable multiprocessing. Slower but less resource intensive." msgstr "Отключить многопроцессорность. Медленнее, но менее ресурсоемко." -#: lib/cli/args.py:891 +#: lib/cli/args.py:900 msgid "" "Train a model on extracted original (A) and swap (B) faces.\n" "Training models can take a long time. Anything from 24hrs to over a week\n" @@ -647,11 +657,11 @@ msgstr "" "Обучение моделей может занять долгое время: от 24 часов до недели\n" "Каждую модель можно отдельно настроить в меню «Настройки»" -#: lib/cli/args.py:910 lib/cli/args.py:919 +#: lib/cli/args.py:919 lib/cli/args.py:928 msgid "faces" msgstr "лица" -#: lib/cli/args.py:911 +#: lib/cli/args.py:920 msgid "" "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 " @@ -660,7 +670,7 @@ msgstr "" "Входная папка. Папка содержащая изображения для тренировки лица A. Это " "исходное лицо т.е. лицо, которое вы хотите убрать, заменив лицом B." -#: lib/cli/args.py:920 +#: lib/cli/args.py:929 msgid "" "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 " @@ -669,12 +679,12 @@ msgstr "" "Входная папка. Папка содержащая изображения для тренировки лица B. Это новое " "лицо т.е. лицо, которое вы хотите поместить на голову человека A." -#: lib/cli/args.py:928 lib/cli/args.py:940 lib/cli/args.py:956 -#: lib/cli/args.py:981 lib/cli/args.py:991 +#: lib/cli/args.py:937 lib/cli/args.py:949 lib/cli/args.py:965 +#: lib/cli/args.py:990 lib/cli/args.py:1000 msgid "model" msgstr "модель" -#: lib/cli/args.py:929 +#: lib/cli/args.py:938 msgid "" "Model directory. This is where the training data will be stored. You should " "always specify a new folder for new models. If starting a new model, select " @@ -688,7 +698,7 @@ msgstr "" "будет создана). Если вы хотите продолжить тренировку, выберите папку с уже " "существующими сохранениями." -#: lib/cli/args.py:941 +#: lib/cli/args.py:950 msgid "" "R|Load the weights from a pre-existing model into a newly created model. For " "most models this will load weights from the Encoder of the given model into " @@ -712,7 +722,7 @@ msgstr "" "NB: Вес можно загружать только из моделей того же плагина, который вы " "собираетесь тренировать." -#: lib/cli/args.py:957 +#: lib/cli/args.py:966 msgid "" "R|Select which trainer to use. Trainers can be configured from the Settings " "menu or the config folder.\n" @@ -758,7 +768,7 @@ msgstr "" "ресурсам (Вам потребуется GPU с хорошим количеством видеопамяти). Хороша для " "деталей, но подвержена к неправильной передаче цвета." -#: lib/cli/args.py:982 +#: lib/cli/args.py:991 msgid "" "Output a summary of the model and exit. If a model folder is provided then a " "summary of the saved model is displayed. Otherwise a summary of the model " @@ -770,7 +780,7 @@ msgstr "" "сводная информация о модели, которая будет создана выбранным плагином, и " "параметрами конфигурации." -#: lib/cli/args.py:992 +#: lib/cli/args.py:1001 msgid "" "Freeze the weights of the model. Freezing weights means that some of the " "parameters in the model will no longer continue to learn, but those that are " @@ -784,12 +794,12 @@ msgstr "" "некоторые модели могут иметь параметры конфигурации для замораживания других " "слоев." -#: lib/cli/args.py:1005 lib/cli/args.py:1017 lib/cli/args.py:1028 -#: lib/cli/args.py:1039 lib/cli/args.py:1122 +#: lib/cli/args.py:1014 lib/cli/args.py:1026 lib/cli/args.py:1037 +#: lib/cli/args.py:1048 lib/cli/args.py:1131 msgid "training" msgstr "тренировка" -#: lib/cli/args.py:1006 +#: lib/cli/args.py:1015 msgid "" "Batch size. This is the number of images processed through the model for " "each side per iteration. NB: As the model is fed 2 sides at a time, the " @@ -802,7 +812,7 @@ msgstr "" "изображений в два раза больше этого числа. Увеличение размера партии требует " "больше памяти GPU." -#: lib/cli/args.py:1018 +#: lib/cli/args.py:1027 msgid "" "Length of training in iterations. This is only really used for automation. " "There is no 'correct' number of iterations a model should be trained for. " @@ -816,7 +826,7 @@ msgstr "" "Однако, если вы хотите, чтобы тренировка прервалась после указанного кол-ва " "итерация, вы можете ввести это здесь." -#: lib/cli/args.py:1029 +#: lib/cli/args.py:1038 msgid "" "[Deprecated - Use '-D, --distribution-strategy' instead] Use the Tensorflow " "Mirrored Distrubution Strategy to train on multiple GPUs." @@ -825,7 +835,7 @@ msgstr "" "Используйте стратегию зеркального распространения Tensorflow для обучения на " "нескольких графических процессорах." -#: lib/cli/args.py:1040 +#: lib/cli/args.py:1049 msgid "" "R|Select the distribution stategy to use.\n" "L|default: Use Tensorflow's default distribution strategy.\n" @@ -837,16 +847,28 @@ msgid "" "GPUs. A copy of the model and all variables are loaded onto each GPU with " "batches distributed to each GPU at each iteration." msgstr "" +"R|Выберите стратегию распределения для использования.\n" +"L|default: использовать стратегию распространения Tensorflow по умолчанию.\n" +"L|central-storage: централизует переменные в ЦП, в то время как операции " +"выполняются на 1 или нескольких локальных графических процессорах. Это может " +"помочь сэкономить часть видеопамяти за счет некоторой скорости за счет " +"отказа от хранения переменных в графическом процессоре. Примечание. " +"Смешанная точность не поддерживается в конфигурациях с несколькими " +"графическими процессорами.\n" +"L|mirrored: поддерживает синхронное распределенное обучение на нескольких " +"локальных графических процессорах. Копия модели и все переменные загружаются " +"в каждый GPU, причем пакеты распределяются между каждым GPU на каждой " +"итерации." -#: lib/cli/args.py:1057 lib/cli/args.py:1067 +#: lib/cli/args.py:1066 lib/cli/args.py:1076 msgid "Saving" msgstr "Сохранение" -#: lib/cli/args.py:1058 +#: lib/cli/args.py:1067 msgid "Sets the number of iterations between each model save." msgstr "Установка количества итераций между сохранениями модели." -#: lib/cli/args.py:1068 +#: lib/cli/args.py:1077 msgid "" "Sets the number of iterations before saving a backup snapshot of the model " "in it's current state. Set to 0 for off." @@ -854,11 +876,11 @@ msgstr "" "Устанавливает кол-во итераций перед созданием резервной копии модели. " "Установите в 0 для отключения." -#: lib/cli/args.py:1075 lib/cli/args.py:1086 lib/cli/args.py:1097 +#: lib/cli/args.py:1084 lib/cli/args.py:1095 lib/cli/args.py:1106 msgid "timelapse" msgstr "таймлапс" -#: lib/cli/args.py:1076 +#: lib/cli/args.py:1085 msgid "" "Optional for creating a timelapse. Timelapse will save an image of your " "selected faces into the timelapse-output folder at every save iteration. " @@ -871,7 +893,7 @@ msgstr "" "папку лиц набора 'A' для использования при создании таймлапса. Вам также " "нужно указать параметры--timelapse-output и --timelapse-input-B." -#: lib/cli/args.py:1087 +#: lib/cli/args.py:1096 msgid "" "Optional for creating a timelapse. Timelapse will save an image of your " "selected faces into the timelapse-output folder at every save iteration. " @@ -885,7 +907,7 @@ msgstr "" "таймлапса. Вы также должны указать параметр --timelapse-output и --timelapse-" "input-A." -#: lib/cli/args.py:1098 +#: lib/cli/args.py:1107 msgid "" "Optional for creating a timelapse. Timelapse will save an image of your " "selected faces into the timelapse-output folder at every save iteration. If " @@ -897,15 +919,15 @@ msgstr "" "указаны только входные папки, то по умолчанию вывод будет сохранен вместе с " "моделью в подкаталог /timelapse/" -#: lib/cli/args.py:1107 lib/cli/args.py:1114 +#: lib/cli/args.py:1116 lib/cli/args.py:1123 msgid "preview" msgstr "предварительный просмотр" -#: lib/cli/args.py:1108 +#: lib/cli/args.py:1117 msgid "Show training preview output. in a separate window." msgstr "Показывать предварительный просмотр в отдельном окне." -#: lib/cli/args.py:1115 +#: lib/cli/args.py:1124 msgid "" "Writes the training result to a file. The image will be stored in the root " "of your FaceSwap folder." @@ -913,7 +935,7 @@ msgstr "" "Записывает результат тренировки в файл. Файл будет сохранен в коренной папке " "FaceSwap." -#: lib/cli/args.py:1123 +#: lib/cli/args.py:1132 msgid "" "Disables TensorBoard logging. NB: Disabling logs means that you will not be " "able to use the graph or analysis for this session in the GUI." @@ -921,12 +943,12 @@ msgstr "" "Отключает журнал TensorBoard. Примечание: Отключение журналов означает, что " "вы не сможете использовать графики или анализ сессии внутри GUI." -#: lib/cli/args.py:1130 lib/cli/args.py:1139 lib/cli/args.py:1148 -#: lib/cli/args.py:1157 +#: lib/cli/args.py:1139 lib/cli/args.py:1148 lib/cli/args.py:1157 +#: lib/cli/args.py:1166 msgid "augmentation" msgstr "аугментация" -#: lib/cli/args.py:1131 +#: lib/cli/args.py:1140 msgid "" "Warps training faces to closely matched Landmarks from the opposite face-set " "rather than randomly warping the face. This is the 'dfaker' way of doing " @@ -936,7 +958,7 @@ msgstr "" "Ориентирами/Landmarks противоположного набора лиц. Этот способ используется " "пакетом \"dfaker\"." -#: lib/cli/args.py:1140 +#: lib/cli/args.py:1149 msgid "" "To effectively learn, a random set of images are flipped horizontally. " "Sometimes it is desirable for this not to occur. Generally this should be " @@ -947,7 +969,7 @@ msgstr "" "происходило. Как правило, эту настройку не стоит трогать, за исключением " "периода «финальной шлифовки»." -#: lib/cli/args.py:1149 +#: lib/cli/args.py:1158 msgid "" "Color augmentation helps make the model less susceptible to color " "differences between the A and B sets, at an increased training time cost. " @@ -957,7 +979,7 @@ msgstr "" "цвета между наборами A and B ценой некоторого замедления скорости " "тренировки. Включите эту опцию для отключения цветовой аугментации." -#: lib/cli/args.py:1158 +#: lib/cli/args.py:1167 msgid "" "Warping is integral to training the Neural Network. This option should only " "be enabled towards the very end of training to try to bring out more detail. " @@ -970,7 +992,7 @@ msgstr "" "Включение этой опции с самого начала может убить модель и привести к ужасным " "результатам." -#: lib/cli/args.py:1183 +#: lib/cli/args.py:1192 msgid "Output to Shell console instead of GUI console" msgstr "Вывод в системную консоль вместо GUI" diff --git a/plugins/extract/_base.py b/plugins/extract/_base.py index 0d27e37..647b79b 100644 --- a/plugins/extract/_base.py +++ b/plugins/extract/_base.py @@ -4,7 +4,7 @@ """ import logging -from tensorflow.python.framework import errors_impl as tf_errors +from tensorflow.python.framework import errors_impl as tf_errors # pylint:disable=no-name-in-module # noqa from lib.multithreading import MultiThread from lib.queue_manager import queue_manager @@ -106,6 +106,7 @@ class Extractor(): "configfile: %s, instance: %s, )", self.__class__.__name__, git_model_id, model_filename, exclude_gpus, configfile, instance) + self._is_initialized = False self._instance = instance self._exclude_gpus = exclude_gpus self.config = _get_config(".".join(self.__module__.split(".")[-2:]), configfile=configfile) @@ -370,6 +371,12 @@ class Extractor(): """ logger.debug("initialize %s: (args: %s, kwargs: %s)", self.__class__.__name__, args, kwargs) + if self._is_initialized: + # When batch processing, plugins will be initialized on first job in batch + logger.debug("Plugin already initialized: %s (%s)", + self.name, self._plugin_type.title()) + return + logger.info("Initializing %s (%s)...", self.name, self._plugin_type.title()) self.queue_size = 1 name = self.name.replace(" ", "_").lower() @@ -391,6 +398,7 @@ class Extractor(): "option to `True`.") raise FaceswapError(msg) from err raise err + self._is_initialized = True logger.info("Initialized %s (%s) with batchsize of %s", self.name, self._plugin_type.title(), self.batchsize) diff --git a/plugins/extract/pipeline.py b/plugins/extract/pipeline.py index 5bdb774..c7a6f42 100644 --- a/plugins/extract/pipeline.py +++ b/plugins/extract/pipeline.py @@ -12,12 +12,12 @@ plugins either in parallel or in series, giving easy access to input and output. import logging import sys -from typing import cast, List, Optional, Tuple, TYPE_CHECKING +from typing import cast, Dict, Generator, List, Optional, Tuple, TYPE_CHECKING, Union import cv2 from lib.gpu_stats import GPUStats -from lib.queue_manager import queue_manager, QueueEmpty +from lib.queue_manager import EventQueue, queue_manager, QueueEmpty from lib.utils import get_backend from plugins.plugin_loader import PluginLoader @@ -29,6 +29,10 @@ else: if TYPE_CHECKING: import numpy as np from lib.align.detected_face import DetectedFace + from plugins.extract._base import Extractor as PluginExtractor + from plugins.extract.detect._base import Detector + from plugins.extract.align._base import Aligner + from plugins.extract.mask._base import Masker logger = logging.getLogger(__name__) # pylint:disable=invalid-name _INSTANCES = -1 # Tracking for multiple instances of pipeline @@ -91,9 +95,18 @@ class Extractor(): The current phase that the pipeline is running. Used in conjunction with :attr:`passes` and :attr:`final_pass` to indicate to the caller which phase is being processed """ - def __init__(self, detector, aligner, masker, configfile=None, multiprocess=False, - exclude_gpus=None, rotate_images=None, min_size=20, normalize_method=None, - re_feed=0, image_is_aligned=False): + def __init__(self, + detector: str, + aligner: str, + masker: Union[str, List[str]], + configfile: Optional[str] = None, + multiprocess: bool = False, + exclude_gpus: Optional[List[int]] = None, + rotate_images: Optional[List[int]] = None, + min_size: int = 20, + normalize_method: Optional[str] = None, + re_feed: int = 0, + image_is_aligned: bool = False) -> None: logger.debug("Initializing %s: (detector: %s, aligner: %s, masker: %s, configfile: %s, " "multiprocess: %s, exclude_gpus: %s, rotate_images: %s, min_size: %s, " "normalize_method: %s, re_feed: %s, image_is_aligned: %s)", @@ -121,7 +134,7 @@ class Extractor(): logger.debug("Initialized %s", self.__class__.__name__) @property - def input_queue(self): + def input_queue(self) -> EventQueue: """ queue: Return the correct input queue depending on the current phase The input queue is the entry point into the extraction pipeline. An :class:`ExtractMedia` @@ -135,11 +148,11 @@ class Extractor(): """ qname = f"extract{self._instance}_{self._current_phase[0]}_in" retval = self._queues[qname] - logger.trace("%s: %s", qname, retval) + logger.trace("%s: %s", qname, retval) # type: ignore return retval @property - def passes(self): + def passes(self) -> int: """ int: Returns the total number of passes the extractor needs to make. This is calculated on several factors (vram available, plugin choice, @@ -157,21 +170,21 @@ class Extractor(): >>> extractor.input_queue.put(extract_media) """ retval = len(self._phases) - logger.trace(retval) + logger.trace(retval) # type: ignore return retval @property - def phase_text(self): + def phase_text(self) -> str: """ str: The plugins that are running in the current phase, formatted for info text output. """ plugin_types = set(self._get_plugin_type_and_index(phase)[0] for phase in self._current_phase) retval = ", ".join(plugin_type.title() for plugin_type in list(plugin_types)) - logger.trace(retval) + logger.trace(retval) # type: ignore return retval @property - def final_pass(self): + def final_pass(self) -> bool: """ bool, Return ``True`` if this is the final extractor pass otherwise ``False`` Useful for iterating over the pipeline :attr:`passes` or :func:`detected_faces` and @@ -188,17 +201,24 @@ class Extractor(): >>> extractor.input_queue.put(extract_media) """ retval = self._phase_index == len(self._phases) - 1 - logger.trace(retval) + logger.trace(retval) # type: ignore return retval - def set_batchsize(self, plugin_type, batchsize): + def reset_phase_index(self) -> None: + """ Reset the current phase index back to 0. Used for when batch processing is used in + extract. """ + self._phase_index = 0 + + def set_batchsize(self, + plugin_type: Literal["align", "detect"], + batchsize: int) -> None: """ Set the batch size of a given :attr:`plugin_type` to the given :attr:`batchsize`. This should be set prior to :func:`launch` if the batch size is to be manually overridden Parameters ---------- - plugin_type: {'aligner', 'detector'} + plugin_type: {'align', 'detect'} The plugin_type to be overridden batchsize: int The batch size to use for this plugin type @@ -207,7 +227,7 @@ class Extractor(): plugin = getattr(self, f"_{plugin_type}") plugin.batchsize = batchsize - def launch(self): + def launch(self) -> None: """ Launches the plugin(s) This launches the plugins held in the pipeline, and should be called at the beginning @@ -223,7 +243,7 @@ class Extractor(): for phase in self._current_phase: self._launch_plugin(phase) - def detected_faces(self): + def detected_faces(self) -> Generator["ExtractMedia", None, None]: """ Generator that returns results, frame by frame from the extraction pipeline This is the exit point for the extraction pipeline and is used to obtain the output @@ -258,9 +278,6 @@ class Extractor(): self._join_threads() if self.final_pass: - # Cleanup queues - for q_name in self._queues: - queue_manager.del_queue(q_name) logger.debug("Detection Complete") else: self._phase_index += 1 @@ -268,7 +285,7 @@ class Extractor(): # <<< INTERNAL METHODS >>> # @property - def _parallel_scaling(self): + def _parallel_scaling(self) -> Dict[int, float]: """ dict: key is number of parallel plugins being loaded, value is the scaling factor that the total base vram for those plugins should be scaled by @@ -288,11 +305,11 @@ class Extractor(): 3: 0.55, 4: 0.5, 5: 0.4} - logger.trace(retval) + logger.trace(retval) # type: ignore return retval @property - def _vram_per_phase(self): + def _vram_per_phase(self) -> Dict[str, float]: """ dict: The amount of vram required for each phase in :attr:`_flow`. """ retval = {} for phase in self._flow: @@ -300,11 +317,11 @@ class Extractor(): attr = getattr(self, f"_{plugin_type}") attr = attr[idx] if idx is not None else attr retval[phase] = attr.vram - logger.trace(retval) + logger.trace(retval) # type: ignore return retval @property - def _total_vram_required(self): + def _total_vram_required(self) -> float: """ Return vram required for all phases plus the buffer """ vrams = self._vram_per_phase vram_required_count = sum(1 for p in vrams.values() if p > 0) @@ -316,32 +333,32 @@ class Extractor(): return retval @property - def _current_phase(self): + def _current_phase(self) -> List[str]: """ list: The current phase from :attr:`_phases` that is running through the extractor. """ retval = self._phases[self._phase_index] - logger.trace(retval) + logger.trace(retval) # type: ignore return retval @property - def _final_phase(self): + def _final_phase(self) -> str: """ Return the final phase from the flow list """ retval = self._flow[-1] - logger.trace(retval) + logger.trace(retval) # type: ignore return retval @property - def _output_queue(self): + def _output_queue(self) -> EventQueue: """ Return the correct output queue depending on the current phase """ if self.final_pass: qname = f"extract{self._instance}_{self._final_phase}_out" else: qname = f"extract{self._instance}_{self._phases[self._phase_index + 1][0]}_in" retval = self._queues[qname] - logger.trace("%s: %s", qname, retval) + logger.trace("%s: %s", qname, retval) # type: ignore return retval @property - def _all_plugins(self): + def _all_plugins(self) -> List["PluginExtractor"]: """ Return list of all plugin objects in this pipeline """ retval = [] for phase in self._flow: @@ -349,22 +366,22 @@ class Extractor(): attr = getattr(self, f"_{plugin_type}") attr = attr[idx] if idx is not None else attr retval.append(attr) - logger.trace("All Plugins: %s", retval) + logger.trace("All Plugins: %s", retval) # type: ignore return retval @property - def _active_plugins(self): + def _active_plugins(self) -> List["PluginExtractor"]: """ Return the plugins that are currently active based on pass """ retval = [] for phase in self._current_phase: plugin_type, idx = self._get_plugin_type_and_index(phase) attr = getattr(self, f"_{plugin_type}") retval.append(attr[idx] if idx is not None else attr) - logger.trace("Active plugins: %s", retval) + logger.trace("Active plugins: %s", retval) # type: ignore return retval @staticmethod - def _set_flow(detector, aligner, masker): + def _set_flow(detector: str, aligner: str, masker: List[str]) -> List[str]: """ Set the flow list based on the input plugins """ logger.debug("detector: %s, aligner: %s, masker: %s", detector, aligner, masker) retval = [] @@ -379,7 +396,7 @@ class Extractor(): return retval @staticmethod - def _get_plugin_type_and_index(flow_phase): + def _get_plugin_type_and_index(flow_phase: str) -> Tuple[str, Optional[int]]: """ Obtain the plugin type and index for the plugin for the given flow phase. When multiple plugins for the same phase are allowed (e.g. Mask) this will return @@ -399,16 +416,16 @@ class Extractor(): The index of this plugin type within the flow, if there are multiple plugins in use otherwise ``None`` if there is only 1 plugin in use for the given phase """ - idx = flow_phase.split("_")[-1] - if idx.isdigit(): - idx = int(idx) + sidx = flow_phase.split("_")[-1] + if sidx.isdigit(): + idx: Optional[int] = int(sidx) plugin_type = "_".join(flow_phase.split("_")[:-1]) else: plugin_type = flow_phase idx = None return plugin_type, idx - def _add_queues(self): + def _add_queues(self) -> Dict[str, EventQueue]: """ Add the required processing queues to Queue Manager """ queues = {} tasks = [f"extract{self._instance}_{phase}_in" for phase in self._flow] @@ -421,7 +438,7 @@ class Extractor(): return queues @staticmethod - def _get_vram_stats(): + def _get_vram_stats() -> Dict[str, Union[int, str]]: """ Obtain statistics on available VRAM and subtract a constant buffer from available vram. Returns @@ -432,14 +449,14 @@ class Extractor(): vram_buffer = 256 # Leave a buffer for VRAM allocation gpu_stats = GPUStats() stats = gpu_stats.get_card_most_free() - retval = dict(count=gpu_stats.device_count, - device=stats["device"], - vram_free=int(stats["free"] - vram_buffer), - vram_total=int(stats["total"])) + retval: Dict[str, Union[int, str]] = dict(count=gpu_stats.device_count, + device=stats["device"], + vram_free=int(stats["free"] - vram_buffer), + vram_total=int(stats["total"])) logger.debug(retval) return retval - def _set_parallel_processing(self, multiprocess): + def _set_parallel_processing(self, multiprocess: bool) -> bool: """ Set whether to run detect, align, and mask together or separately. Parameters @@ -459,17 +476,17 @@ class Extractor(): logger.debug("Parallel processing disabled by amd") return False - logger.verbose("%s - %sMB free of %sMB", + logger.verbose("%s - %sMB free of %sMB", # type: ignore self._vram_stats["device"], self._vram_stats["vram_free"], self._vram_stats["vram_total"]) - if self._vram_stats["vram_free"] <= self._total_vram_required: + if cast(int, self._vram_stats["vram_free"]) <= self._total_vram_required: logger.warning("Not enough free VRAM for parallel processing. " "Switching to serial") return False return True - def _set_phases(self, multiprocess): + def _set_phases(self, multiprocess: bool) -> List[List[str]]: """ If not enough VRAM is available, then chunk :attr:`_flow` up into phases that will fit into VRAM, otherwise return the single flow. @@ -484,9 +501,9 @@ class Extractor(): The jobs to be undertaken split into phases that fit into GPU RAM """ force_single_process = not multiprocess or get_backend() == "amd" - phases = [] - current_phase = [] - available = self._vram_stats["vram_free"] + phases: List[List[str]] = [] + current_phase: List[str] = [] + available = cast(int, self._vram_stats["vram_free"]) for phase in self._flow: num_plugins = len([p for p in current_phase if self._vram_per_phase[p] > 0]) num_plugins += 1 if self._vram_per_phase[phase] > 0 else 0 @@ -518,48 +535,59 @@ class Extractor(): return phases # << INTERNAL PLUGIN HANDLING >> # - def _load_align(self, aligner, configfile, normalize_method, re_feed): + def _load_align(self, + aligner: str, + configfile: Optional[str], + normalize_method: Optional[str], + re_feed: int) -> Optional["Aligner"]: """ Set global arguments and load aligner plugin """ if aligner is None or aligner.lower() == "none": logger.debug("No aligner selected. Returning None") return None aligner_name = aligner.replace("-", "_").lower() logger.debug("Loading Aligner: '%s'", aligner_name) - aligner = PluginLoader.get_aligner(aligner_name)(exclude_gpus=self._exclude_gpus, - configfile=configfile, - normalize_method=normalize_method, - re_feed=re_feed, - instance=self._instance) - return aligner + plugin = PluginLoader.get_aligner(aligner_name)(exclude_gpus=self._exclude_gpus, + configfile=configfile, + normalize_method=normalize_method, + re_feed=re_feed, + instance=self._instance) + return plugin - def _load_detect(self, detector, rotation, min_size, configfile): + def _load_detect(self, + detector: str, + rotation: Optional[List[int]], + min_size: int, + configfile: Optional[str]) -> Optional["Detector"]: """ Set global arguments and load detector plugin """ if detector is None or detector.lower() == "none": logger.debug("No detector selected. Returning None") return None detector_name = detector.replace("-", "_").lower() logger.debug("Loading Detector: '%s'", detector_name) - detector = PluginLoader.get_detector(detector_name)(exclude_gpus=self._exclude_gpus, - rotation=rotation, - min_size=min_size, - configfile=configfile, - instance=self._instance) - return detector + plugin = PluginLoader.get_detector(detector_name)(exclude_gpus=self._exclude_gpus, + rotation=rotation, + min_size=min_size, + configfile=configfile, + instance=self._instance) + return plugin - def _load_mask(self, masker, image_is_aligned, configfile): + def _load_mask(self, + masker: str, + image_is_aligned: bool, + configfile: Optional[str]) -> Optional["Masker"]: """ Set global arguments and load masker plugin """ if masker is None or masker.lower() == "none": logger.debug("No masker selected. Returning None") return None masker_name = masker.replace("-", "_").lower() logger.debug("Loading Masker: '%s'", masker_name) - masker = PluginLoader.get_masker(masker_name)(exclude_gpus=self._exclude_gpus, + plugin = PluginLoader.get_masker(masker_name)(exclude_gpus=self._exclude_gpus, image_is_aligned=image_is_aligned, configfile=configfile, instance=self._instance) - return masker + return plugin - def _launch_plugin(self, phase): + def _launch_plugin(self, phase: str) -> None: """ Launch an extraction plugin """ logger.debug("Launching %s plugin", phase) in_qname = f"extract{self._instance}_{phase}_in" @@ -578,7 +606,7 @@ class Extractor(): plugin.start() logger.debug("Launched %s plugin", phase) - def _set_extractor_batchsize(self): + def _set_extractor_batchsize(self) -> None: """ Sets the batch size of the requested plugins based on their vram, their vram_per_batch_requirements and the number of plugins being loaded in the current phase. @@ -597,15 +625,16 @@ class Extractor(): gpu_plugins = [p for p in self._current_phase if self._vram_per_phase[p] > 0] scaling = self._parallel_scaling.get(len(gpu_plugins), self._scaling_fallback) plugins_required = sum(self._vram_per_phase[p] for p in gpu_plugins) * scaling - if plugins_required + batch_required <= self._vram_stats["vram_free"]: + if plugins_required + batch_required <= cast(int, self._vram_stats["vram_free"]): logger.debug("Plugin requirements within threshold: (plugins_required: %sMB, " "vram_free: %sMB)", plugins_required, self._vram_stats["vram_free"]) return # Hacky split across plugins that use vram - available_vram = (self._vram_stats["vram_free"] - plugins_required) // len(gpu_plugins) + available_vram = (cast(int, self._vram_stats["vram_free"]) + - plugins_required) // len(gpu_plugins) self._set_plugin_batchsize(gpu_plugins, available_vram) - def set_aligner_normalization_method(self, method): + def set_aligner_normalization_method(self, method: str) -> None: """ Change the normalization method for faces fed into the aligner. Parameters @@ -613,10 +642,11 @@ class Extractor(): method: {"none", "clahe", "hist", "mean"} The normalization method to apply to faces prior to feeding into the aligner's model """ + assert self._align is not None logger.debug("Setting to: '%s'", method) self._align.set_normalize_method(method) - def _set_plugin_batchsize(self, gpu_plugins, available_vram): + def _set_plugin_batchsize(self, gpu_plugins: List[str], available_vram: float) -> None: """ Set the batch size for the given plugin based on given available vram. Do not update plugins which have a vram_per_batch of 0 (CPU plugins) due to zero division error. @@ -666,7 +696,7 @@ class Extractor(): for plugin in self._active_plugins: plugin.join() - def _check_and_raise_error(self): + def _check_and_raise_error(self) -> bool: """ Check all threads for errors and raise if one occurs """ for plugin in self._active_plugins: if plugin.check_and_raise_error(): diff --git a/plugins/plugin_loader.py b/plugins/plugin_loader.py index c631a52..44e55b6 100644 --- a/plugins/plugin_loader.py +++ b/plugins/plugin_loader.py @@ -3,7 +3,21 @@ import logging import os +import sys from importlib import import_module +from typing import Callable, List, Type, TYPE_CHECKING + +if TYPE_CHECKING: + from plugins.extract.detect._base import Detector + from plugins.extract.align._base import Aligner + from plugins.extract.mask._base import Masker + from plugins.train.model._base import ModelBase + from plugins.train.trainer._base import TrainerBase + +if sys.version_info < (3, 8): + from typing_extensions import Literal +else: + from typing import Literal logger = logging.getLogger(__name__) # pylint: disable=invalid-name @@ -21,7 +35,7 @@ class PluginLoader(): >>> aligner = PluginLoader.get_aligner('cv2-dnn') """ @staticmethod - def get_detector(name, disable_logging=False): + def get_detector(name: str, disable_logging: bool = False) -> Type["Detector"]: """ Return requested detector plugin Parameters @@ -40,7 +54,7 @@ class PluginLoader(): return PluginLoader._import("extract.detect", name, disable_logging) @staticmethod - def get_aligner(name, disable_logging=False): + def get_aligner(name: str, disable_logging: bool = False) -> Type["Aligner"]: """ Return requested aligner plugin Parameters @@ -59,7 +73,7 @@ class PluginLoader(): return PluginLoader._import("extract.align", name, disable_logging) @staticmethod - def get_masker(name, disable_logging=False): + def get_masker(name: str, disable_logging: bool = False) -> Type["Masker"]: """ Return requested masker plugin Parameters @@ -78,7 +92,7 @@ class PluginLoader(): return PluginLoader._import("extract.mask", name, disable_logging) @staticmethod - def get_model(name, disable_logging=False): + def get_model(name: str, disable_logging: bool = False) -> "ModelBase": """ Return requested training model plugin Parameters @@ -97,7 +111,7 @@ class PluginLoader(): return PluginLoader._import("train.model", name, disable_logging) @staticmethod - def get_trainer(name, disable_logging=False): + def get_trainer(name: str, disable_logging: bool = False) -> "TrainerBase": """ Return requested training trainer plugin Parameters @@ -116,7 +130,7 @@ class PluginLoader(): return PluginLoader._import("train.trainer", name, disable_logging) @staticmethod - def get_converter(category, name, disable_logging=False): + def get_converter(category: str, name: str, disable_logging: bool = False) -> Callable: """ Return requested converter plugin Converters work slightly differently to other faceswap plugins. They are created to do a @@ -136,10 +150,10 @@ class PluginLoader(): :class:`plugins.convert` object: A converter sub plugin """ - return PluginLoader._import("convert.{}".format(category), name, disable_logging) + return PluginLoader._import(f"convert.{category}", name, disable_logging) @staticmethod - def _import(attr, name, disable_logging): + def _import(attr: str, name: str, disable_logging: bool): """ Import the plugin's module Parameters @@ -164,12 +178,14 @@ class PluginLoader(): return getattr(module, ttl) @staticmethod - def get_available_extractors(extractor_type, add_none=False, extend_plugin=False): + def get_available_extractors(extractor_type: Literal["align", "detect", "mask"], + add_none: bool = False, + extend_plugin: bool = False) -> List[str]: """ Return a list of available extractors of the given type Parameters ---------- - extractor_type: {'aligner', 'detector', 'masker'} + extractor_type: {'align', 'detect', 'mask'} The type of extractor to return the plugins for add_none: bool, optional Append "none" to the list of returned plugins. Default: False @@ -207,7 +223,7 @@ class PluginLoader(): return extractors @staticmethod - def get_available_models(): + def get_available_models() -> List[str]: """ Return a list of available training models Returns @@ -224,7 +240,7 @@ class PluginLoader(): return models @staticmethod - def get_default_model(): + def get_default_model() -> str: """ Return the default training model plugin name Returns @@ -237,7 +253,7 @@ class PluginLoader(): return 'original' if 'original' in models else models[0] @staticmethod - def get_available_convert_plugins(convert_category, add_none=True): + def get_available_convert_plugins(convert_category: str, add_none: bool = True) -> List[str]: """ Return a list of available converter plugins in the given category Parameters diff --git a/scripts/extract.py b/scripts/extract.py index 6176f24..81bce50 100644 --- a/scripts/extract.py +++ b/scripts/extract.py @@ -6,19 +6,17 @@ from __future__ import annotations import logging import os import sys -from typing import List, Dict, TYPE_CHECKING, Optional +from argparse import Namespace +from typing import List, Dict, Optional from tqdm import tqdm from lib.image import encode_image, generate_thumbnail, ImagesLoader, ImagesSaver from lib.multithreading import MultiThread -from lib.utils import get_folder +from lib.utils import get_folder, _video_extensions from plugins.extract.pipeline import Extractor, ExtractMedia from scripts.fsmedia import Alignments, PostProcess, finalize -if TYPE_CHECKING: - import argparse - tqdm.monitor_interval = 0 # workaround for TqdmSynchronisationWarning logger = logging.getLogger(__name__) # pylint: disable=invalid-name @@ -42,23 +40,14 @@ class Extract(): # pylint:disable=too-few-public-methods The arguments to be passed to the extraction process as generated from Faceswap's command line arguments """ - def __init__(self, arguments: argparse.Namespace) -> None: + def __init__(self, arguments: Namespace) -> None: logger.debug("Initializing %s: (args: %s", self.__class__.__name__, arguments) self._args = arguments - self._output_dir = None if self._args.skip_saving_faces else get_folder( - self._args.output_dir) + self._input_locations = self._get_input_locations() + self._validate_batchmode() - logger.info("Output Directory: %s", self._args.output_dir) - self._images = ImagesLoader(self._args.input_dir, fast_count=True) - self._alignments = Alignments(self._args, True, self._images.is_video) - - self._existing_count = 0 - self._set_skip_list() - - self._post_process = PostProcess(arguments) configfile = self._args.configfile if hasattr(self._args, "configfile") else None normalization = None if self._args.normalization == "none" else self._args.normalization - maskers = ["components", "extended"] maskers += self._args.masker if self._args.masker else [] self._extractor = Extractor(self._args.detector, @@ -71,6 +60,127 @@ class Extract(): # pylint:disable=too-few-public-methods min_size=self._args.min_size, normalize_method=normalization, re_feed=self._args.re_feed) + + def _get_input_locations(self) -> List[str]: + """ Obtain the full path to input locations. Will be a list of locations if batch mode is + selected, or a containing a single location if batch mode is not selected. + + Returns + ------- + list: + The list of input location paths + """ + if not self._args.batch_mode or os.path.isfile(self._args.input_dir): + return [self._args.input_dir] # Not batch mode or a single file + + retval = [os.path.join(self._args.input_dir, fname) + for fname in os.listdir(self._args.input_dir) + if os.path.isdir(os.path.join(self._args.input_dir, fname)) + or os.path.splitext(fname)[-1].lower() in _video_extensions] + logger.debug("Input locations: %s", retval) + return retval + + def _validate_batchmode(self): + """ Validate the command line arguments. + + If batch-mode selected and there is only one object to extract from, then batch mode is + disabled + + If processing in batch mode, some of the given arguments may not make sense, in which case + a warning is shown and those options are reset. + + """ + if not self._args.batch_mode: + return + + if os.path.isfile(self._args.input_dir): + logger.warning("Batch mode selected but input is not a folder. Switching to normal " + "mode") + self._args.batch_mode = False + + if not self._input_locations: + logger.error("Batch mode selected, but no valid files found in input location: '%s'. " + "Exiting.", self._args.input_dir) + sys.exit(1) + + if self._args.alignments_path: + logger.warning("Custom alignments path not supported for batch mode. " + "Reverting to default.") + self._args.alignments_path = None + + def _output_for_input(self, input_location: str) -> str: + """ Obtain the path to an output folder for faces for a given input location. + + If not running in batch mode, then the user supplied output location will be returned, + otherwise a sub-folder within the user supplied output location will be returned based on + the input filename + + Parameters + ---------- + input_location: str + The full path to an input video or folder of images + """ + if not self._args.batch_mode: + return self._args.output_dir + + retval = os.path.join(self._args.output_dir, + os.path.splitext(os.path.basename(input_location))[0]) + logger.debug("Returning output: '%s' for input: '%s'", retval, input_location) + return retval + + def process(self): + """ The entry point for triggering the Extraction Process. + + Should only be called from :class:`lib.cli.launcher.ScriptExecutor` + """ + logger.info('Starting, this may take a while...') + inputs = self._input_locations + if self._args.batch_mode: + logger.info("Batch mode selected processing: %s", self._input_locations) + for job_no, location in enumerate(self._input_locations): + if self._args.batch_mode: + logger.info("Processing job %s of %s: '%s'", job_no + 1, len(inputs), location) + arguments = Namespace(**self._args.__dict__) + arguments.input_dir = location + arguments.output_dir = self._output_for_input(location) + else: + arguments = self._args + extract = _Extract(self._extractor, arguments) + extract.process() + self._extractor.reset_phase_index() + + +class _Extract(): # pylint:disable=too-few-public-methods + """ The Actual extraction process. + + This class is called by the parent :class:`Extract` process + + Parameters + ---------- + extractor: :class:`~plugins.extract.pipeline.Extractor` + The extractor pipeline for running extractions + arguments: :class:`argparse.Namespace` + The arguments to be passed to the extraction process as generated from Faceswap's command + line arguments + """ + def __init__(self, + extractor: Extractor, + arguments: Namespace) -> None: + logger.debug("Initializing %s: (extractor: %s, args: %s)", self.__class__.__name__, + extractor, arguments) + self._args = arguments + self._output_dir = None if self._args.skip_saving_faces else get_folder( + self._args.output_dir) + + logger.info("Output Directory: %s", self._output_dir) + self._images = ImagesLoader(self._args.input_dir, fast_count=True) + self._alignments = Alignments(self._args, True, self._images.is_video) + self._extractor = extractor + + self._existing_count = 0 + self._set_skip_list() + + self._post_process = PostProcess(arguments) self._threads: List[MultiThread] = [] self._verify_output = False logger.debug("Initialized %s", self.__class__.__name__) @@ -121,7 +231,6 @@ class Extract(): # pylint:disable=too-few-public-methods Should only be called from :class:`lib.cli.launcher.ScriptExecutor` """ - logger.info('Starting, this may take a while...') # from lib.queue_manager import queue_manager ; queue_manager.debug_monitor(3) self._threaded_redirector("load") self._run_extraction()