              if self.load_queue.shutdown.is_set():
                  logger.debug("Load Queue: Stop signal received. Terminating")
                  break
              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
              if self.check_skipframe(filename):
                  if self.args.keep_unchanged:
                      logger.trace("Saving unchanged frame: %s", filename)
 
</s> remove             if self.stop:
 </s> add             if self._stop: </s> remove         cv2.imwrite(filename, image)  # pylint: disable=no-member
        logger.debug("Created timelapse: '%s'", filename)
 </s> add         cv2.imwrite(filename, image)
        logger.debug("Created time-lapse: '%s'", filename) </s> remove             save_iteration = iteration % self.args.save_interval == 0
            viewer = display_func if save_iteration or self.save_now else None
            timelapse = self.timelapse if save_iteration else None
 </s> add             save_iteration = iteration % self._args.save_interval == 0
            viewer = display_func if save_iteration or self._save_now else None
            timelapse = self._timelapse if save_iteration else None </s> remove                 if self.args.pingpong:
 </s> add                 if self._args.pingpong: </s> remove         filename = os.path.join(self.output_file, str(int(time.time())) + ".jpg")
 </s> add         filename = os.path.join(self._output_file, str(int(time.time())) + ".jpg")
                # All black frames will return not numpy.any() so check dims too
              if self.load_queue.shutdown.is_set():
                  logger.debug("Load Queue: Stop signal received. Terminating")
                  break
              if image is None or (not image.any() and image.ndim not in (2, 3)):
                # All black frames will return not numpy.any() so check dims too
                  logger.warning("Unable to open image. Skipping: '%s'", filename)
                  continue
              if self.check_skipframe(filename):
                  if self.args.keep_unchanged:
                      logger.trace("Saving unchanged frame: %s", filename)
keep keep keep keep replace keep keep keep keep keep
 Smart Masks - Training Implementation (#914)

* Smart Masks - Training

- Reinstate smart mask training code
- Reinstate mask_type back to model.config
- change 'replicate_input_mask to 'learn_mask'
- Add learn mask option
- Add mask loading from alignments to plugins.train.trainer
- Add mask_blur and mask threshold options
- _base.py - Pass mask options through training_opts dict
- plugins.train.model - check for mask_type not None for learn_mask and penalized_mask_loss
- Limit alignments loading to just those faces that appear in the training folder
- Raise error if not all training images have an alignment, and alignment file is required
- lib.training_data - Mask generation code
- lib.faces_detect - cv2 dimension stripping bugfix
- Remove cv2 linting code

* Update mask helptext in cli.py

* Fix Warp to Landmarks
Remove SHA1 hashing from training data

* Update mask training config

* Capture missing masks at training init

* lib.image.read_image_batch - Return filenames with batch for ordering

* scripts.train - Documentation

* plugins.train.trainer - documentation

* Ensure backward compatibility.
Fix convert for new predicted masks

* Update removed masks to components for legacy models. 
scripts/convert.py