              samples. The array will be in the format (`batchsize`, `height`, `width`, \
              `channels`). **NB:** This item will only exist in the `dict` if :attr:`is_preview` \
              or :attr:`is_timelapse` is ``True``
          """
          logger.debug("Queue batches: (image_count: %s, batchsize: %s, side: '%s', do_shuffle: %s, "
                       "is_preview, %s, is_timelapse: %s)", len(images), batchsize, side, do_shuffle,
                       is_preview, is_timelapse)
          self._batchsize = batchsize
          self._face_cache = _get_cache(side, images, self._config)
          self._processing = ImageAugmentation(batchsize,
                                               is_preview or is_timelapse,
                                               self._model_input_size,
                                               self._model_output_shapes,
                                               self._coverage_ratio,
                                               self._config)
  
          if self._warp_to_landmarks and not self._face_cache.partially_loaded:
              self._face_cache.pre_fill(images, side)
  
          args = (images, side, do_shuffle, batchsize)
          batcher = BackgroundGenerator(self._minibatch, thread_count=2, args=args)
          return batcher.iterator()
  
      # << INTERNAL METHODS >> #
      def _validate_samples(self, data):
          """ Ensures that the total number of images within :attr:`images` is greater or equal to
          the selected :attr:`batchsize`. Raises an exception if this is not the case. """
          length = len(data)
          msg = ("Number of images is lower than batch-size (Note that too few "
                 "images may lead to bad training). # images: {}, "
                 "batch-size: {}".format(length, self._batchsize))
          try:
              assert length >= self._batchsize, msg
          except AssertionError as err:
              msg += ("\nYou should increase the number of images in your training set or lower "
                      "your batch-size.")
              raise FaceswapError(msg) from err
  
      def _minibatch(self, images, side, do_shuffle, batchsize):
          """ A generator function that yields the augmented, target and sample images.
          see :func:`minibatch_ab` for more details on the output. """
          logger.debug("Loading minibatch generator: (image_count: %s, side: '%s', do_shuffle: %s)",
                       len(images), side, do_shuffle)
          self._validate_samples(images)
  
          def _img_iter(imgs):
              while True:
                  if do_shuffle:
                      shuffle(imgs)
                  for img in imgs:
                      yield img
  
          img_iter = _img_iter(images)
          while True:
              img_paths = [next(img_iter) for _ in range(batchsize)]
              yield self._process_batch(img_paths, side)
  
          logger.debug("Finished minibatch generator: (side: '%s')", side)
  
      def _process_batch(self, filenames, side):
          """ Performs the augmentation and compiles target images and samples.
  
          If this is the first time a face has been loaded, then it's meta data is extracted from the
 
</s> remove         Returns
        -------
        bool
            ``True`` if the cache has been reset because of a face centering change due to
            legacy alignments, otherwise ``False``. """
        retval = self._has_reset
        if retval:
            logger.debug("Resetting 'has_reset' flag")
            self._has_reset = False
        return retval
 </s> add         Raises
        ------
        :class:`FaceswapError`
            If the number of images loaded is smaller than the selected batch size
        """
        length = len(self._images)
        msg = ("Number of images is lower than batch-size (Note that too few images may lead to "
               f"bad training). # images: {length}, batch-size: {self._batch_size}")
        try:
            assert length >= self._batch_size, msg
        except AssertionError as err:
            msg += ("\nYou should increase the number of images in your training set or lower "
                    "your batch-size.")
            raise FaceswapError(msg) from err </s> remove         Yields
        ------
        dict
            The following items are contained in each `dict` yielded from this iterator:

            * **feed** (:class:`numpy.ndarray`) - The feed for the model. The array returned is \
            in the format (`batchsize`, `height`, `width`, `channels`). This is the :attr:`x` \
            parameter for :func:`keras.models.model.train_on_batch`.

            * **targets** (`list`) - A list of 4-dimensional :class:`numpy.ndarray` objects in \
            the order and size of each output of the model as defined in \
            :attr:`model_output_shapes`. the format of these arrays will be (`batchsize`, \
            `height`, `width`, `3`). This is the :attr:`y` parameter for \
            :func:`keras.models.model.train_on_batch` **NB:** masks are not included in the \
            `targets` list. If required for feeding into the Keras model, they will need to be \
            added to this list in :mod:`plugins.train.trainer._base` from the `masks` key.

            * **masks** (:class:`numpy.ndarray`) - A 4-dimensional array containing the target \
            masks in the format (`batchsize`, `height`, `width`, `1`).

            * **samples** (:class:`numpy.ndarray`) - A 4-dimensional array containing the samples \
            for feeding to the model's predict function for generating preview and time-lapse \
            samples. The array will be in the format (`batchsize`, `height`, `width`, \
            `channels`). **NB:** This item will only exist in the `dict` if :attr:`is_preview` \
            or :attr:`is_timelapse` is ``True``
 </s> add         Returns
        -------
        list
            List of 4-dimensional target images, at all model output sizes, with masks compiled
            into channels 4+ for each output size </s> remove     def _process_batch(self, filenames, side):
 </s> add     def process_batch(self,
                      filenames: List[str],
                      images: np.ndarray,
                      detected_faces: List[DetectedFace],
                      batch: np.ndarray) -> BatchType: </s> remove     def cache_metadata(self, filenames):
        """ Obtain the batch with metadata for items that need caching and cache them to
        :attr:`_cache`.
 </s> add         def _img_iter(imgs):
            """ Infinite iterator for recursing through image list and reshuffling at each epoch"""
            while True:
                if do_shuffle:
                    shuffle(imgs)
                for img in imgs:
                    yield img

        img_iter = _img_iter(self._images[:])
        while True:
            img_paths = [next(img_iter)  # pylint:disable=stop-iteration-return
                         for _ in range(self._batch_size)]
            retval = self._process_batch(img_paths)
            yield retval

    def _get_images_with_meta(self, filenames: List[str]) -> Tuple[np.ndarray, List[DetectedFace]]:
        """ Obtain the raw face images with associated :class:`DetectedFace` objects for this
        batch.

        If this is the first time a face has been loaded, then it's meta data is extracted
        from the png header and added to :attr:`_face_cache`. </s> remove         If this is the first time a face has been loaded, then it's meta data is extracted from the
        png header and added to :attr:`_face_cache`

        See
        :func:`minibatch_ab` for more details on the output.

 </s> add 
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
              samples. The array will be in the format (`batchsize`, `height`, `width`, \
              `channels`). **NB:** This item will only exist in the `dict` if :attr:`is_preview` \
              or :attr:`is_timelapse` is ``True``
          """
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
        logger.trace("Compiling targets: batch shape: %s", batch.shape)  # type: ignore
        if len(self._output_sizes) == 1 and self._output_sizes[0] == self._process_size:
            # Rolling buffer here makes next to no difference, so just create array on the fly
            retval = [self._to_float32(batch)]
        else:
            retval = [self._to_float32(np.array([cv2.resize(image, (size, size), cv2.INTER_AREA)
                                                 for image in batch]))
                      for size in self._output_sizes]
        logger.trace("Processed targets: %s", [t.shape for t in retval])  # type: ignore
        return retval
  
      def _process_batch(self, filenames, side):
          """ Performs the augmentation and compiles target images and samples.
  
          If this is the first time a face has been loaded, then it's meta data is extracted from the
keep keep keep keep replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace 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 
lib/training/generator.py