          if image is not None and image.any():
              self.image = image
              self._image_to_face(image)
          logger.trace("Created from alignment: (x: %s, w: %s, y: %s. h: %s, "
                       "landmarks: %s)",
                       self.x, self.w, self.y, self.h, self.landmarks_xy)
  
      def _image_to_face(self, image):
          """ set self.image to be the cropped face from detected bounding box """
          logger.trace("Cropping face from image")
          self.face = image[self.top: self.bottom,
 
</s> remove         self.mask = alignment.get("mask", None)
 </s> add         if alignment.get("mask", None) is not None:
            self.mask = dict()
            for name, mask_dict in alignment["mask"].items():
                self.mask[name] = Mask()
                self.mask[name].from_dict(mask_dict) </s> remove 

class Mask():
    """ Face Mask information and convenience methods

    Holds a Faceswap mask as generated from :mod:`plugins.extract.mask` and the information
    required to transform it to its original frame.

    Holds convenience methods to handle the warping, storing and retrieval of the mask.

    Parameters
    ----------
    storage_size: int, optional
        The size (in pixels) that the mask should be stored at. Default: 128.

    Attributes
    ----------
    storage_dims: tuple
        The `(height, width)` of the stored mask.
    """

    def __init__(self, storage_size=128):
        self.storage_dims = (storage_size, storage_size)

        self._mask = None
        self._original_dims = None
        self._affine_matrix = None
        self._frame_dims = None
        self._intepolator = None

    @property
    def mask(self):
        """ numpy.ndarray: The mask at the size of :attr:`storage_dims` """
        return decompress(self._mask)

    @property
    def full_frame_mask(self):
        """ numpy.ndarray: The mask affined to the original full frame """
        mask = np.zeros(self._frame_dims + (1, ), dtype="uint8")
        mask = cv2.warpAffine(cv2.resize(self.mask, self._original_dims, cv2.INTER_CUBIC),
                              self._affine_matrix,
                              self._frame_dims,
                              mask,
                              flags=cv2.WARP_INVERSE_MAP | self._intepolator,
                              borderMode=cv2.BORDER_TRANSPARENT)
        logger.trace("mask shape: %s, mask dtype: %s, mask min: %s, mask max: %s",
                     mask.shape, mask.dtype, mask.min(), mask.max())
        return mask

    def add(self, mask, affine_matrix, frame_dims, interpolator):
        """ Add a Faceswap mask to this :class:`Mask`.

        The mask should be the original output from  :mod:`plugins.extract.mask`

        Parameters
        ----------
        mask: numpy.ndarray
            The mask that is to be added as output from :mod:`plugins.extract.mask`
            It should be in the range 0.0 - 1.0 ideally with a ``dtype`` of ``float32``
        affine_matrix: numpy.ndarray
            The transformation matrix required to transform the mask to the original frame.
        frame_dims: tuple
            The `(height, width)` dimensions of the original frame that this mask was created from.
        interpolator:
            The CV2 interpolator required to transform this mask to it's original frame
        """
        logger.trace("mask shape: %s, mask dtype: %s, mask min: %s, mask max: %s, "
                     "affine_matrix: %s, frame_dims: %s, interpolator: %s", mask.shape, mask.dtype,
                     mask.min(), mask.max(), affine_matrix, frame_dims, interpolator)
        self._original_dims = mask.shape[:2]
        self._affine_matrix = affine_matrix
        self._frame_dims = frame_dims
        self._intepolator = interpolator
        mask = (cv2.resize(mask,
                           self.storage_dims,
                           interpolation=cv2.INTER_AREA) * 255.0).astype("uint8")
        self._mask = compress(mask)
 </s> add  </s> remove         fsmask = Mask()
 </s> add         fsmask = Mask(storage_size=storage_size) </s> remove     def add_mask(self, name, mask, affine_matrix, frame_dims, interpolator):
 </s> add     def add_mask(self, name, mask, affine_matrix, frame_dims, interpolator, storage_size=128):
                     "landmarks: %s, mask: %s)",
                     self.x, self.w, self.y, self.h, self.landmarks_xy, self.mask)
          if image is not None and image.any():
              self.image = image
              self._image_to_face(image)
          logger.trace("Created from alignment: (x: %s, w: %s, y: %s. h: %s, "
                     "landmarks: %s, mask: %s)",
                     self.x, self.w, self.y, self.h, self.landmarks_xy, self.mask)
                     "landmarks: %s, mask: %s)",
                     self.x, self.w, self.y, self.h, self.landmarks_xy, self.mask)
  
      def _image_to_face(self, image):
          """ set self.image to be the cropped face from detected bounding box """
          logger.trace("Cropping face from image")
          self.face = image[self.top: self.bottom,
keep keep keep keep replace replace keep keep keep keep keep
 Mask extraction fixes

- Save mask to alignments file as dict
- Remove blur_kernel param from plugins
- Correctly read out the mask buffer on decompress
- Fix full frame mask output
- Remove BORDER_TRANSPARENT in warp_affine (it is bugged. Don't use it)
- Store the affine matrix for the saved mask size 
lib/faces_detect.py