              func = cv2.erode if ratio > 0 else cv2.dilate
              eroded.append(func(mask, kernel, iterations=1, anchor=anchor))
  
          mask = np.min(np.array(eroded), axis=0) if len(eroded) > 1 else eroded[0]
          return mask
  
      def _get_erosion_kernels(self, mask: np.ndarray) -> List[np.ndarray]:
          """ Get the erosion kernels for each of the center, left, top right and bottom erosions.
  
          An approximation is made based on the number of positive pixels within the mask to create
 
</s> remove                 val = max(kernel.shape) - 1 if idx < 3 else 0
 </s> add                 if ratio > 0:
                    val = max(kernel.shape) - 1 if idx < 3 else 0
                else:
                    val = 0 if idx < 3 else max(kernel.shape) - 1 </s> remove             mask = detected_face.mask[self.mask_type]
            mask.set_blur_and_threshold(blur_kernel=self.config["kernel_size"],
                                        blur_type=self.config["type"],
                                        blur_passes=self.config["passes"],
                                        threshold=self.config["threshold"])
            if sub_crop_offset is not None and np.any(sub_crop_offset):
                mask.set_sub_crop(sub_crop_offset, centering)
            mask = self._crop_to_coverage(mask.mask)
            mask_size = mask.shape[0]
            face_size = self.dummy.shape[0]
            if mask_size != face_size:
                interp = cv2.INTER_CUBIC if mask_size < face_size else cv2.INTER_AREA
                mask = cv2.resize(mask,
                                  self.dummy.shape[:2],
                                  interpolation=interp)[..., None]
            mask = mask.astype("float32") / 255.0
 </s> add             mask = self._get_stored_mask(detected_face, centering, sub_crop_offset)
 </s> remove         self._coverage_ratio = coverage_ratio
 </s> add     def _set_config(self,
                    configfile: Optional[str],
                    config: Optional[FaceswapConfig]) -> dict:
        """ Set the correct configuration for the plugin based on whether a config file
        or pre-loaded config has been passed in.

        Parameters
        ----------
        configfile: str
            Location of custom configuration ``ini`` file. If ``None`` then use the
            default config location
        config: :class:`lib.config.FaceswapConfig`
            Pre-loaded :class:`lib.config.FaceswapConfig`. If passed, then this will be
            used over any configuration on disk. If ``None`` then it is ignored.

        Returns
        -------
        dict
            The configuration in dictionary form for the given from
            :attr:`lib.config.FaceswapConfig.config_dict`
        """
        section = ".".join(self.__module__.split(".")[-2:])
        if config is None:
            retval = Config(section, configfile=configfile).config_dict
        else:
            config.section = section
            retval = config.config_dict
            config.section = None
        logger.debug("Config: %s", retval)
        return retval

    def _get_box(self, output_size: int) -> np.ndarray:
        """ Apply a gradient overlay to the edge of the swap box to smooth out any hard areas
        that where the face intersects with the edge of the swap area. </s> remove     def process(self,  # type:ignore # pylint:disable=arguments-differ
                detected_face: "DetectedFace",
                sub_crop_offset: Optional[np.ndarray],
                centering: Literal["legacy", "face", "head"],
                predicted_mask: Optional[np.ndarray] = None) -> Tuple[np.ndarray, np.ndarray]:
 </s> add         Gradient is created from 1/16th distance from the edge of the face box and uses the
        parameters as provided for mask blend settings

        Parameters
        ----------
        output_size: int
            The size of the box that contains the swapped face

        Returns
        -------
        :class:`numpy.ndarray`
            The box mask
        """
        box = np.zeros((output_size, output_size, 1), dtype="float32")
        edge = output_size // 32
        box[edge:-edge, edge:-edge] = 1.0

        box = BlurMask(self._config["type"],
                       box, self._config["kernel_size"],
                       self._config["passes"]).blurred
        return box

    def run(self,
            detected_face: DetectedFace,
            sub_crop_offset: Optional[np.ndarray],
            centering: Literal["legacy", "face", "head"],
            predicted_mask: Optional[np.ndarray] = None) -> Tuple[np.ndarray, np.ndarray]: </s> remove if TYPE_CHECKING:
    from lib.align import DetectedFace
 </s> add logger = logging.getLogger(__name__)
        return mask[..., None]
              func = cv2.erode if ratio > 0 else cv2.dilate
              eroded.append(func(mask, kernel, iterations=1, anchor=anchor))
  
          mask = np.min(np.array(eroded), axis=0) if len(eroded) > 1 else eroded[0]
        return mask[..., None]
  
      def _get_erosion_kernels(self, mask: np.ndarray) -> List[np.ndarray]:
          """ Get the erosion kernels for each of the center, left, top right and bottom erosions.
  
          An approximation is made based on the number of positive pixels within the mask to create
keep keep keep keep replace keep keep keep keep keep
 convert: remove box blend plugin 
plugins/convert/mask/mask_blend.py