  
     lib
     plugins
     tools
 
</s> remove         io_args = (self._queue) if io_args is None else (self._queue, *io_args)
        retval = MultiThread(getattr(self, "_{}".format(self._task)), *io_args, thread_count=1)
        logger.trace(retval)
        return retval
 </s> add         if self._is_video:
            self._count = int(count_frames(self.location, fast=fast_count))
            self._file_list = [self._dummy_video_framename(i + 1) for i in range(self.count)]
        else:
            if isinstance(self.location, (list, tuple)):
                self._file_list = self.location
            else:
                self._file_list = get_image_paths(self.location)
            self._count = len(self.file_list) </s> remove         args: tuple
            The arguments to be passed to the load iterator
 </s> add         queue: queue.Queue()
            The ImageIO Queue </s> remove         queue = args[0]
        io_args = args[1:]
        iterator = self._load_video if self._is_video else self._load_images
 </s> add         iterator = self._from_video if self._is_video else self._from_folder </s> remove         for retval in iterator(*io_args):
 </s> add         for retval in iterator():
            filename, image = retval[:2]
            if image is None or (not image.any() and image.ndim not in (2, 3)):
                # All black frames will return not np.any() so check dims too
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue </s> remove     def _load_video(self, *args):  # pylint:disable=unused-argument
 </s> add     def _from_video(self):
   scripts
  
     lib
     plugins
   scripts
     tools
keep keep add 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 
docs/full/modules.rst