                         "and  landmarks. It is recommended to perfom Extract first for "
                         "superior results")
          extractor = Extractor(detector="cv2-dnn",
                                aligner="cv2-dnn",
                                multiprocess=False,
                                rotate_images=None,
                                min_size=20)
          extractor.launch()
          logger.debug("Loaded extractor")
          return extractor
 
</s> remove         extractor = Extractor("manual", "fan", multiprocess=True, normalize_method="hist")
 </s> add         extractor = Extractor("manual", "fan", "none", multiprocess=True, normalize_method="hist") </s> remove         extractor.set_batchsize("detector", 1)
        extractor.set_batchsize("aligner", 1)
 </s> add         for plugin_type in ("detect", "align", "mask"):
            extractor.set_batchsize(plugin_type, 1) </s> remove         """ Return a list of available aligners/detectors """
 </s> add         """ Return a list of available extractors of the given type

        Parameters
        ----------
        extractor_type: {'aligner', 'detector', 'masker'}
            The type of extractor to return the plugins for

        Returns
        -------
        list:
            A list of the available extractor plugin names for the given type
        """ </s> remove         """ Inititalize the extractor plugin
 </s> add         """ Initialize the extractor plugin </s> remove         argument_list.append({"opts": ("-D", "--detector"),
                              "action": Radio,
                              "type": str.lower,
                              "choices":  PluginLoader.get_available_extractors("detect"),
                              "default": default_detector,
                              "group": "Plugins",
                              "help": "R|Detector to use. Some of these have configurable "
                                      "settings in '/config/extract.ini' or 'Settings > Configure "
                                      "Extract 'Plugins':"
                                      "\nL|cv2-dnn: A CPU only extractor which is the least "
                                      "reliable and least resource intensive. Use this if not "
                                      "using a GPU and time is important."
                                      "\nL|mtcnn: Good detector. Fast on CPU, faster on GPU. Uses "
                                      "fewer resources than other GPU detectors but can often "
                                      "return more false positives."
                                      "\nL|s3fd: Best detector. Fast on GPU, slow on CPU. Can "
                                      "detect more faces and fewer false positives than other "
                                      "GPU detectors, but is a lot more resource intensive."})
        argument_list.append({"opts": ("-A", "--aligner"),
                              "action": Radio,
                              "type": str.lower,
                              "choices": PluginLoader.get_available_extractors("align"),
                              "default": default_aligner,
                              "group": "Plugins",
                              "help": "R|Aligner to use."
                                      "\nL|cv2-dnn: A CPU only landmark detector. Faster, less "
                                      "resource intensive, but less accurate. Only use this if "
                                      "not using a GPU and time is important."
                                      "\nL|fan: Best aligner. Fast on GPU, slow on CPU."})
        argument_list.append({"opts": ("-M", "--masker"),
                              "action": Radio,
                              "type": str.lower,
                              "choices": PluginLoader.get_available_extractors("mask"),
                              "default": "components",
                              "group": "Plugins",
                              "help": "R|Masker to use."
                                      "\nL|none: An array of all ones is created to provide a 4th "
                                      "channel that will not mask any portion of the image."
                                      "\nL|components: Mask designed to provide facial "
                                      "segmentation based on the positioning of landmark "
                                      "locations. A convex hull is constructed around the "
                                      "exterior of the landmarks to create a mask."
                                      "\nL|extended: Mask designed to provide facial segmentation "
                                      "based on the positioning of landmark locations. A convex "
                                      "hull is constructed around the exterior of the landmarks "
                                      "and the mask is extended upwards onto the forehead."
                                      "\nL|vgg-clear: Mask designed to provide smart segmentation "
                                      "of mostly frontal faces clear of obstructions.  Profile "
                                      "faces and obstructions may result in sub-par performance."
                                      "\nL|vgg-obstructed: Mask designed to provide smart "
                                      "segmentation of mostly frontal faces. The mask model has "
                                      "been specifically trained to recognize some facial "
                                      "obstructions (hands and eyeglasses). Profile faces may "
                                      "result in sub-par performance."
                                      "\nL|unet-dfl: Mask designed to provide smart segmentation "
                                      "of mostly frontal faces. The mask model has been trained "
                                      "by community members and will need testing for further "
                                      "description. Profile faces may result in sub-par "
                                      "performance."})
        argument_list.append({"opts": ("-nm", "--normalization"),
                              "action": Radio,
                              "type": str.lower,
                              "dest": "normalization",
                              "choices": ["none", "clahe", "hist", "mean"],
                              "default": "none",
                              "group": "plugins",
                              "help": "R|Performing normalization can help the aligner better "
                                      "align faces with difficult lighting conditions at an "
                                      "extraction speed cost. Different methods will yield "
                                      "different results on different sets. NB: This does not "
                                      "impact the output face, just the input to the aligner."
                                      "\nL|none: Don't perform normalization on the face."
                                      "\nL|clahe: Perform Contrast Limited Adaptive Histogram "
                                      "Equalization on the face."
                                      "\nL|hist: Equalize the histograms on the RGB channels."
                                      "\nL|mean: Normalize the face colors to the mean."})
        argument_list.append({"opts": ("-r", "--rotate-images"),
                              "type": str,
                              "dest": "rotate_images",
                              "default": None,
                              "group": "plugins",
                              "help": "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 increments of that size up "
                                      "to 360, or pass in a list of numbers to enumerate exactly "
                                      "what angles to check"})
        argument_list.append({"opts": ("-min", "--min-size"),
                              "type": int,
                              "action": Slider,
                              "dest": "min_size",
                              "min_max": (0, 1080),
                              "default": 0,
                              "rounding": 20,
                              "group": "Face Processing",
                              "help": "Filters out faces detected below this size. Length, in "
                                      "pixels across the diagonal of the bounding box. Set to 0 "
                                      "for off"})
        argument_list.append({"opts": ("-n", "--nfilter"),
                              "action": FilesFullPaths,
                              "filetypes": "image",
                              "dest": "nfilter",
                              "nargs": "+",
                              "default": None,
                              "group": "Face Processing",
                              "help": "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 image. Multiple "
                                      "images can be added space separated. NB: Using face filter "
                                      "will significantly decrease extraction speed and its "
                                      "accuracy cannot be guaranteed."})
        argument_list.append({"opts": ("-f", "--filter"),
                              "action": FilesFullPaths,
                              "filetypes": "image",
                              "dest": "filter",
                              "nargs": "+",
                              "default": None,
                              "group": "Face Processing",
                              "help": "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. Multiple images can be added "
                                      "space separated. NB: Using face filter will significantly "
                                      "decrease extraction speed and its accuracy cannot be "
                                      "guaranteed."})
        argument_list.append({"opts": ("-l", "--ref_threshold"),
                              "action": Slider,
                              "min_max": (0.01, 0.99),
                              "rounding": 2,
                              "type": float,
                              "dest": "ref_threshold",
                              "default": 0.4,
                              "group": "Face Processing",
                              "help": "For use with the optional nfilter/filter files. Threshold "
                                      "for positive face recognition. Lower values are stricter. "
                                      "NB: Using face filter will significantly decrease "
                                      "extraction speed and its accuracy cannot be "
                                      "guaranteed."})
        argument_list.append({"opts": ("-bt", "--blur-threshold"),
                              "type": float,
                              "action": Slider,
                              "min_max": (0.0, 100.0),
                              "rounding": 1,
                              "dest": "blur_thresh",
                              "default": 0.0,
                              "group": "Face Processing",
                              "help": "Automatically discard images blurrier than the specified "
                                      "threshold. Discarded images are moved into a \"blurry\" "
                                      "sub-folder. Lower values allow more blur. Set to 0.0 to "
                                      "turn off."})
        argument_list.append({"opts": ("-een", "--extract-every-n"),
                              "type": int,
                              "action": Slider,
                              "dest": "extract_every_n",
                              "min_max": (1, 100),
                              "default": 1,
                              "rounding": 1,
                              "group": "output",
                              "help": "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."})
        argument_list.append({"opts": ("-sz", "--size"),
                              "type": int,
                              "action": Slider,
                              "min_max": (128, 512),
                              "default": 256,
                              "rounding": 64,
                              "group": "output",
                              "help": "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."})
        argument_list.append({"opts": ("-si", "--save-interval"),
                              "dest": "save_interval",
                              "type": int,
                              "action": Slider,
                              "min_max": (0, 1000),
                              "rounding": 10,
                              "default": 0,
                              "group": "output",
                              "help": "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 process. NB: If extracting in 2 "
                                      "passes then the alignments file will only start to be "
                                      "saved out during the second pass. WARNING: Don't interrupt "
                                      "the script when writing the file because it might get "
                                      "corrupted. Set to 0 to turn off"})
        argument_list.append({"opts": ("-dl", "--debug-landmarks"),
                              "action": "store_true",
                              "dest": "debug_landmarks",
                              "group": "output",
                              "default": False,
                              "help": "Draw landmarks on the ouput faces for debugging purposes."})
        argument_list.append({"opts": ("-sp", "--singleprocess"),
                              "action": "store_true",
                              "default": False,
                              "backend": "nvidia",
                              "group": "settings",
                              "help": "Don't run extraction in parallel. Will run detection first "
                                      "then alignment (2 passes). Useful if VRAM is at a "
                                      "premium."})
        argument_list.append({"opts": ("-s", "--skip-existing"),
                              "action": "store_true",
                              "dest": "skip_existing",
                              "group": "settings",
                              "default": False,
                              "help": "Skips frames that have already been extracted and exist in "
                                      "the alignments file"})
        argument_list.append({"opts": ("-sf", "--skip-existing-faces"),
                              "action": "store_true",
                              "dest": "skip_faces",
                              "group": "settings",
                              "default": False,
                              "help": "Skip frames that already have detected faces in the "
                                      "alignments file"})
 </s> add         argument_list.append({
            "opts": ("-D", "--detector"),
            "action": Radio,
            "type": str.lower,
            "choices":  PluginLoader.get_available_extractors("detect"),
            "default": default_detector,
            "group": "Plugins",
            "help": "R|Detector to use. Some of these have configurable settings in "
                    "'/config/extract.ini' or 'Settings > Configure Extract 'Plugins':"
                    "\nL|cv2-dnn: A CPU only extractor which is the least reliable and least "
                    "resource intensive. Use this if not using a GPU and time is important."
                    "\nL|mtcnn: Good detector. Fast on CPU, faster on GPU. Uses fewer resources "
                    "than other GPU detectors but can often return more false positives."
                    "\nL|s3fd: Best detector. Fast on GPU, slow on CPU. Can detect more faces and "
                    "fewer false positives than other GPU detectors, but is a lot more resource "
                    "intensive."})
        argument_list.append({
            "opts": ("-A", "--aligner"),
            "action": Radio,
            "type": str.lower,
            "choices": PluginLoader.get_available_extractors("align"),
            "default": default_aligner,
            "group": "Plugins",
            "help": "R|Aligner to use."
                    "\nL|cv2-dnn: A CPU only landmark detector. Faster, less resource intensive, "
                    "but less accurate. Only use this if not using a GPU and time is important."
                    "\nL|fan: Best aligner. Fast on GPU, slow on CPU."})
        argument_list.append({
            "opts": ("-M", "--masker"),
            "action": Radio,
            "type": str.lower,
            "choices": PluginLoader.get_available_extractors("mask"),
            "default": "extended",
            "group": "Plugins",
            "help": "R|Masker to use. NB: Masker is not currently used by the rest of the process "
                    "but this will store a mask in the alignments file for use when it has been "
                    "implemented."
                    "\nL|none: An array of all ones is created to provide a 4th channel that will "
                    "not mask any portion of the image."
                    "\nL|components: Mask designed to provide facial segmentation based on the "
                    "positioning of landmark locations. A convex hull is constructed around the "
                    "exterior of the landmarks to create a mask."
                    "\nL|extended: Mask designed to provide facial segmentation based on the "
                    "positioning of landmark locations. A convex hull is constructed around the "
                    "exterior of the landmarks and the mask is extended upwards onto the forehead."
                    "\nL|vgg-clear: Mask designed to provide smart segmentation of mostly frontal "
                    "faces clear of obstructions. Profile faces and obstructions may result in "
                    "sub-par performance."
                    "\nL|vgg-obstructed: Mask designed to provide smart segmentation of mostly "
                    "frontal faces. The mask model has been specifically trained to recognize "
                    "some facial obstructions (hands and eyeglasses). Profile faces may result in "
                    "sub-par performance."
                    "\nL|unet-dfl: Mask designed to provide smart segmentation of mostly frontal "
                    "faces. The mask model has been trained by community members and will need "
                    "testing for further description. Profile faces may result in sub-par "
                    "performance."})
        argument_list.append({
            "opts": ("-nm", "--normalization"),
            "action": Radio,
            "type": str.lower,
            "dest": "normalization",
            "choices": ["none", "clahe", "hist", "mean"],
            "default": "none",
            "group": "plugins",
            "help": "R|Performing normalization can help the aligner better align faces with "
                    "difficult lighting conditions at an extraction speed cost. Different methods "
                    "will yield different results on different sets. NB: This does not impact the "
                    "output face, just the input to the aligner."
                    "\nL|none: Don't perform normalization on the face."
                    "\nL|clahe: Perform Contrast Limited Adaptive Histogram Equalization on the "
                    "face."
                    "\nL|hist: Equalize the histograms on the RGB channels."
                    "\nL|mean: Normalize the face colors to the mean."})
        argument_list.append({
            "opts": ("-r", "--rotate-images"),
            "type": str,
            "dest": "rotate_images",
            "default": None,
            "group": "plugins",
            "help": "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 "
                    "increments of that size up to 360, or pass in a list of numbers to enumerate "
                    "exactly what angles to check."})
        argument_list.append({
            "opts": ("-min", "--min-size"),
            "type": int,
            "action": Slider,
            "dest": "min_size",
            "min_max": (0, 1080),
            "default": 0,
            "rounding": 20,
            "group": "Face Processing",
            "help": "Filters out faces detected below this size. Length, in pixels across the "
                    "diagonal of the bounding box. Set to 0 for off"})
        argument_list.append({
            "opts": ("-n", "--nfilter"),
            "action": FilesFullPaths,
            "filetypes": "image",
            "dest": "nfilter",
            "nargs": "+",
            "default": None,
            "group": "Face Processing",
            "help": "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 "
                    "image. Multiple images can be added space separated. NB: Using face filter "
                    "will significantly decrease extraction speed and its accuracy cannot be "
                    "guaranteed."})
        argument_list.append({
            "opts": ("-f", "--filter"),
            "action": FilesFullPaths,
            "filetypes": "image",
            "dest": "filter",
            "nargs": "+",
            "default": None,
            "group": "Face Processing",
            "help": "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. "
                    "Multiple images can be added space separated. NB: Using face filter will "
                    "significantly decrease extraction speed and its accuracy cannot be "
                    "guaranteed."})
        argument_list.append({
            "opts": ("-l", "--ref_threshold"),
            "action": Slider,
            "min_max": (0.01, 0.99),
            "rounding": 2,
            "type": float,
            "dest": "ref_threshold",
            "default": 0.4,
            "group": "Face Processing",
            "help": "For use with the optional nfilter/filter files. Threshold for positive face "
                    "recognition. Lower values are stricter. NB: Using face filter will "
                    "significantly decrease extraction speed and its accuracy cannot be "
                    "guaranteed."})
        argument_list.append({
            "opts": ("-bt", "--blur-threshold"),
            "type": float,
            "action": Slider,
            "min_max": (0.0, 100.0),
            "rounding": 1,
            "dest": "blur_thresh",
            "default": 0.0,
            "group": "Face Processing",
            "help": "Automatically discard images blurrier than the specified threshold. "
                    "Discarded images are moved into a \"blurry\" sub-folder. Lower values allow "
                    "more blur. Set to 0.0 to turn off."})
        argument_list.append({
            "opts": ("-een", "--extract-every-n"),
            "type": int,
            "action": Slider,
            "dest": "extract_every_n",
            "min_max": (1, 100),
            "default": 1,
            "rounding": 1,
            "group": "output",
            "help": "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."})
        argument_list.append({
            "opts": ("-sz", "--size"),
            "type": int,
            "action": Slider,
            "min_max": (128, 512),
            "default": 256,
            "rounding": 64,
            "group": "output",
            "help": "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."})
        argument_list.append({
            "opts": ("-si", "--save-interval"),
            "dest": "save_interval",
            "type": int,
            "action": Slider,
            "min_max": (0, 1000),
            "rounding": 10,
            "default": 0,
            "group": "output",
            "help": "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 "
                    "process. NB: If extracting in 2 passes then the alignments file will only "
                    "start to be saved out during the second pass. WARNING: Don't interrupt the "
                    "script when writing the file because it might get corrupted. Set to 0 to "
                    "turn off"})
        argument_list.append({
            "opts": ("-dl", "--debug-landmarks"),
            "action": "store_true",
            "dest": "debug_landmarks",
            "group": "output",
            "default": False,
            "help": "Draw landmarks on the ouput faces for debugging purposes."})
        argument_list.append({
            "opts": ("-sp", "--singleprocess"),
            "action": "store_true",
            "default": False,
            "backend": "nvidia",
            "group": "settings",
            "help": "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."})
        argument_list.append({
            "opts": ("-s", "--skip-existing"),
            "action": "store_true",
            "dest": "skip_existing",
            "group": "settings",
            "default": False,
            "help": "Skips frames that have already been extracted and exist in the alignments "
                    "file"})
        argument_list.append({
            "opts": ("-sf", "--skip-existing-faces"),
            "action": "store_true",
            "dest": "skip_faces",
            "group": "settings",
            "default": False,
            "help": "Skip frames that already have detected faces in the alignments file"})
                              masker="none",
                              multiprocess=True,
                         "and  landmarks. It is recommended to perfom Extract first for "
                         "superior results")
          extractor = Extractor(detector="cv2-dnn",
                                aligner="cv2-dnn",
                              masker="none",
                              multiprocess=True,
                                rotate_images=None,
                                min_size=20)
          extractor.launch()
          logger.debug("Loaded extractor")
          return extractor
keep keep keep keep replace keep keep keep keep keep
 Smart Mask - Extract code review

- Lint simple_tests.py
- Only reformat alignments file if it exists otherwise change filename
- Update legacy alignments to new format at all stages
- faces_detect.Mask.from_dict - logging format fix
- convert.py fix otf for new pipeline
- cli.py - Add note that masks not used. Revert convert masks
- faces_detect.py - Revert non-extract code
- Add .p and .pickle extensions for serializer
- plugins/extract revert some changes
- scripts/fsmedia - Revert code changes
- Pipeline - cleanup
- Consistant alpha channel stripping (fixes single-process)
- Store landmarks as numpy array
- Code attribution
- Normalize feed face and reference face to 0.0 - 1.0 in convert
- Lock in mask VRAM sized
- Add documentation to plugin_loader
- Update alignments tool to work with new format 
scripts/convert.py