          extract_media.remove_image()
  
          faces_count = len(extract_media.detected_faces)
          if faces_count == 0:
              logger.verbose("No faces were detected in image: %s",
                             os.path.basename(extract_media.filename))
  
          if not self._verify_output and faces_count > 1:
              self._verify_output = True
  
 
</s> remove     def _output_faces(self, saver: ImagesSaver, extract_media: ExtractMedia) -> None:
 </s> add     def _output_faces(self, saver: Optional[ImagesSaver], extract_media: ExtractMedia) -> None: </s> remove         self._threads = []
 </s> add         self._threads: List[MultiThread] = [] </s> remove             logger.trace("Reloading image: '%s'", filename)
 </s> add             logger.trace("Reloading image: '%s'", filename)  # type: ignore </s> remove                 logger.trace("Adding image '%s' to skip list due to extract_every_n = %s",
                             filename, self._skip_num)
 </s> add                 logger.trace("Adding image '%s' to skip list due to "  # type: ignore
                             "extract_every_n = %s", filename, self._skip_num) </s> remove         Raises
        ------
        FaceswapError
            If a version 1.0 face appears in a 2.x set or vice versa
        """
        alignment_version = png_meta["source"]["alignments_version"]

        if not self._extract_version:
            logger.debug("Setting initial extract version: %s", alignment_version)
            self._extract_version = alignment_version
            if alignment_version == 1.0 and self._centering != "legacy":
                self._reset_cache(True)
            return
 </s> add             for future in futures.as_completed(proc):
                batch[proc[future], ..., :3] = future.result()
            logger.verbose("No faces were detected in image: %s",  # type: ignore
          extract_media.remove_image()
  
          faces_count = len(extract_media.detected_faces)
          if faces_count == 0:
            logger.verbose("No faces were detected in image: %s",  # type: ignore
                             os.path.basename(extract_media.filename))
  
          if not self._verify_output and faces_count > 1:
              self._verify_output = True
  
keep keep keep keep replace keep keep keep keep keep
 Data Augmentation update (#1263)

- lib.detected_face
    - Subclass Masks for Landmark based masks
    - Add training mask propery + methods to DetectedFace
  - lib.training_training
    - subclass TrainingDataGenerator for training and preview data
    - Split cache into own module
    - Reduce thread count to 1 to prevent image corruption + data re-use
    - Process on largest model input/output size rather than stored image size
    - Size and crop masks during caching stage
    - Implement ring buffer for data flow
    - Fix preview reload bug
  - augmentation
    - typing
    - switch color aug order
    - better initialization
    - Fix warp + landmark warp to correctly apply at different image scales
    - Slightly improved warp caching
    - Don't store whether image is_preview. Handle all data as training images implicitly
  - plugins.trainer: Typing and fixes to work with trainingdata refactor 
scripts/extract.py