              logger.debug("No output provided. Not creating saver")
              return None
          output_dir = str(get_folder(arguments.output, make_folder=True))
          logger.info("Saving preview masks to: '%s'", output_dir)
          saver = BackgroundIO(output_dir, "save", queue_size=16)
          logger.debug(saver)
          return saver
  
      def _get_extractor(self):
          """ Obtain a Mask extractor plugin and launch it
 
</s> remove     def skip_num(self):
        """ Number of frames to skip if extract_every_n is passed """
        return self.args.extract_every_n if hasattr(self.args, "extract_every_n") else 1
 </s> add     def _save_interval(self):
        """ int: The number of frames to be processed between each saving of the alignments file if
        it has been provided, otherwise ``None`` """
        if hasattr(self._args, "save_interval"):
            return self._args.save_interval
        return None

    @property
    def _skip_num(self):
        """ int: Number of frames to skip if extract_every_n has been provided """
        return self._args.extract_every_n if hasattr(self._args, "extract_every_n") else 1

    def _set_skip_list(self):
        """ Add the skip list to the image loader

        Checks against `extract_every_n` and the existence of alignments data (can exist if
        `skip_existing` or `skip_existing_faces` has been provided) and compiles a list of frame
        indices that should not be processed, providing these to :class:`lib.image.ImagesLoader`.
        """
        if self._skip_num == 1 and not self._alignments.data:
            logger.debug("No frames to be skipped")
            return
        skip_list = []
        for idx, filename in enumerate(self._images.file_list):
            if idx % self._skip_num != 0:
                logger.trace("Adding image '%s' to skip list due to extract_every_n = %s",
                             filename, self._skip_num)
                skip_list.append(idx)
            # Items may be in the alignments file if skip-existing[-faces] is selected
            elif os.path.basename(filename) in self._alignments.data:
                self._existing_count += 1
                logger.trace("Removing image: '%s' due to previously existing", filename)
                skip_list.append(idx)
        if self._existing_count != 0:
            logger.info("Skipping %s frames due to skip_existing/skip_existing_faces.",
                        self._existing_count)
        logger.debug("Adding skip list: %s", skip_list)
        self._images.add_skip_list(skip_list) </s> remove     def location(self):
        """ str: The folder or video that was passed in as the :attr:`path` parameter. """
        return self._location
 </s> add     def process_count(self):
        """ int: The number of images or video frames to be processed (IE the total count less
        items that are to be skipped from the :attr:`skip_list`)"""
        return self._count - len(self._skip_list)

    @property
    def is_video(self):
        """ bool: ``True`` if the input is a video, ``False`` if it is not """
        return self._is_video

    @property
    def file_list(self):
        """ list: A full list of files in the source location. This includes any files that will
        ultimately be skipped if a :attr:`skip_list` has been provided. If the input is a video
        then this is a list of dummy filenames as corresponding to an alignments file """
        return self._file_list </s> remove     def _check_input(self):
        """ Check whether the input path is valid and return if it is a video.
 </s> add     def add_skip_list(self, skip_list):
        """ Add a skip list to this :class:`ImagesLoader`

        Parameters
        ----------
        skip_list: list
            A list of indices corresponding to the frame indices that should be skipped
        """
        logger.debug(skip_list)
        self._skip_list = set(skip_list)

    def _check_for_video(self):
        """ Check whether the input is a video </s> remove     >>> saver = BackgroundIO('/path/to/save/folder', 'save')
    >>> for filename, image in <image_iterator>:
    >>>     saver.save(filename, image)
    >>> saver.close()
    """
 </s> add         args = (load_with_hash, )
        super().__init__(path, queue_size=queue_size, args=args)
        self._skip_list = set() if skip_list is None else set(skip_list) </s> remove         logger.trace("filename: '%s', image_shape: %s", image.shape)
 </s> add         logger.trace("filename: '%s', image_shape: %s", filename, image.shape)
        saver = ImagesSaver(output_dir)
              logger.debug("No output provided. Not creating saver")
              return None
          output_dir = str(get_folder(arguments.output, make_folder=True))
          logger.info("Saving preview masks to: '%s'", output_dir)
        saver = ImagesSaver(output_dir)
          logger.debug(saver)
          return saver
  
      def _get_extractor(self):
          """ Obtain a Mask extractor plugin and launch it
keep keep keep keep replace keep keep keep keep keep
 scripts.extract - code optimizations

Limit queue sizes to reduce RAM usage
Rename lib.image.BackgroundIO to ImageIO
Create separate ImagesLoader and ImagesSaver classes
Load/Save images from centralized lib.image.ImageIO
scripts.extract documentation 
tools/mask.py