      def _separate_target_mask(batch):
          """ Return the batch and the batch of final masks
  
          Returns the targets as a list of 4-dimensional ``numpy.ndarray`` s of shape (`batchsize`,
          `height`, `width`, 3). If the :attr:`batch` is 4 channels, then the masks will be split
          from the batch, with the largest output masks being returned in their own item.
          """
          batch = [tgt.astype("float32") / 255.0 for tgt in batch]
          if all(tgt.shape[-1] == 4 for tgt in batch):
              logger.trace("Batch contains mask")
              sizes = [item.shape[1] for item in batch]
 
</s> remove         batch = [tgt.astype("float32") / 255.0 for tgt in batch]
        if all(tgt.shape[-1] == 4 for tgt in batch):
            logger.trace("Batch contains mask")
            sizes = [item.shape[1] for item in batch]
            mask_batch = np.expand_dims(batch[sizes.index(max(sizes))][..., -1], axis=-1)
            batch = [item[..., :3] for item in batch]
            logger.trace("batch shapes: %s, mask_batch shape: %s",
                         [tgt.shape for tgt in batch], mask_batch.shape)
            retval = dict(targets=batch, masks=mask_batch)
        else:
            logger.trace("Batch has no mask")
            retval = dict(targets=batch)
 </s> add         logger.trace("target_batch shapes: %s", [tgt.shape for tgt in target_batch])
        retval = dict(targets=[batch[..., :3] for batch in target_batch],
                      masks=[target_batch[-1][..., 3:]])
        logger.trace("returning: %s", {k: [tgt.shape for tgt in v] for k, v in retval.items()}) </s> remove     def _separate_target_mask(batch):
 </s> add     def _separate_target_mask(target_batch): </s> remove             the format (`batchsize`, `height`, `width`, `1`). **NB:** This item will only exist \
            in the ``dict`` if a batch of 4 channel images has been passed in :attr:`batch`
 </s> add             the format (`batchsize`, `height`, `width`, `1`). </s> remove     def _get_landmarks(self, filenames, batch, side):
 </s> add     def _apply_mask(self, filenames, batch, side):
        """ Applies the mask to the 4th channel of the image. If masks are not being used
        applies a dummy all ones mask """
        logger.trace("Input batch shape: %s, side: %s", batch.shape, side)
        if self._masks is None:
            logger.trace("Creating dummy masks. side: %s", side)
            masks = np.ones_like(batch[..., :1], dtype=batch.dtype)
        else:
            logger.trace("Obtaining masks for batch. side: %s", side)
            masks = np.array([self._masks[side][filename].mask
                              for filename, face in zip(filenames, batch)], dtype=batch.dtype)
            masks = self._resize_masks(batch.shape[1], masks)

        logger.trace("masks shape: %s", masks.shape)
        batch = np.concatenate((batch, masks), axis=-1)
        logger.trace("Output batch shape: %s, side: %s", batch.shape, side)
        return batch

    @staticmethod
    def _resize_masks(target_size, masks):
        """ Resize the masks to the target size """
        logger.trace("target size: %s, masks shape: %s", target_size, masks.shape)
        mask_size = masks.shape[1]
        if target_size == mask_size:
            logger.trace("Mask and targets the same size. Not resizing")
            return masks
        interpolator = cv2.INTER_CUBIC if mask_size < target_size else cv2.INTER_AREA
        masks = np.array([cv2.resize(mask,
                                     (target_size, target_size),
                                     interpolation=interpolator)[..., None]
                          for mask in masks])
        logger.trace("Resized masks: %s", masks.shape)
        return masks

    def _get_landmarks(self, filenames, side): </s> remove         """ Timelapse samples """
        batch = next(self.timelapse_feed)
 </s> add         """ Compile the sample images for creating a time-lapse frame.

        Returns
        -------
        list
            The list of samples, targets and masks as :class:`numpy.ndarrays` for creating a
            time-lapse frame
        """
        batch = next(self._timelapse_feed)
        `height`, `width`, 3).

        The target masks are returned as its own item and is the 4th channel of the final target
        output.
      def _separate_target_mask(batch):
          """ Return the batch and the batch of final masks
  
          Returns the targets as a list of 4-dimensional ``numpy.ndarray`` s of shape (`batchsize`,
        `height`, `width`, 3).

        The target masks are returned as its own item and is the 4th channel of the final target
        output.
        `height`, `width`, 3).

        The target masks are returned as its own item and is the 4th channel of the final target
        output.
          """
          batch = [tgt.astype("float32") / 255.0 for tgt in batch]
          if all(tgt.shape[-1] == 4 for tgt in batch):
              logger.trace("Batch contains mask")
              sizes = [item.shape[1] for item in batch]
keep keep keep keep replace 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. 
lib/training_data.py