          upper_left = self.transform(matrix_ones, batch["center_scale"], resolutions)
          bot_right = self.transform(matrix_size, batch["center_scale"], resolutions)
  
          # TODO second pass .. convert to matrix
          new_images = []
          for image, top_left, bottom_right in zip(batch["image"], upper_left, bot_right):
              height, width = image.shape[:2]
              channels = 3 if image.ndim > 2 else 1
              bottom_right_width, bottom_right_height = bottom_right[0].astype('int32')
              top_left_width, top_left_height = top_left[0].astype('int32')
              new_dim = (bottom_right_height - top_left_height,
                         bottom_right_width - top_left_width,
                         channels)
              new_img = np.empty(new_dim, dtype=np.uint8)
  
              new_x = slice(max(0, -top_left_width), min(bottom_right_width, width) - top_left_width)
              new_y = slice(max(0, -top_left_height),
                            min(bottom_right_height, height) - top_left_height)
              old_x = slice(max(0, top_left_width), min(bottom_right_width, width))
              old_y = slice(max(0, top_left_height), min(bottom_right_height, height))
              new_img[new_y, new_x] = image[old_y, old_x]
  
              interp = cv2.INTER_CUBIC if new_dim[0] < self.input_size else cv2.INTER_AREA
              new_images.append(cv2.resize(new_img, dsize=sizes, interpolation=interp))
          logger.trace("Cropped images")
          return new_images
  
      @staticmethod
      def transform(points, center_scales, resolutions):
          """ Transform Image """
 
</s> remove     def crop(self, batch):  # pylint:disable=too-many-locals
        """ Crop image around the center point """
 </s> add     def _crop_image(self,
                    image: np.ndarray,
                    top_left: np.ndarray,
                    bottom_right: np.ndarray) -> np.ndarray:
        """ Crop a single image

        Parameters
        ----------
        image: :class:`numpy.ndarray`
            The image to crop
        top_left: :class:`numpy.ndarray`
            The top left (x, y) point to crop from
        bottom_right: :class:`numpy.ndarray`
            The bottom right (x, y) point to crop to

        Returns
        -------
        :class:`numpy.ndarray`
            The cropped image
        """
        bottom_right_width, bottom_right_height = bottom_right[0].astype('int32')
        top_left_width, top_left_height = top_left[0].astype('int32')
        new_dim = (bottom_right_height - top_left_height,
                   bottom_right_width - top_left_width,
                   3 if image.ndim > 2 else 1)
        new_img = np.empty(new_dim, dtype=np.uint8)

        new_x = slice(max(0, -top_left_width),
                      min(bottom_right_width, image.shape[1]) - top_left_width)
        new_y = slice(max(0, -top_left_height),
                      min(bottom_right_height, image.shape[0]) - top_left_height)
        old_x = slice(max(0, top_left_width), min(bottom_right_width, image.shape[1]))
        old_y = slice(max(0, top_left_height), min(bottom_right_height, image.shape[0]))
        new_img[new_y, new_x] = image[old_y, old_x]

        interp = cv2.INTER_CUBIC if new_dim[0] < self.input_size else cv2.INTER_AREA
        return cv2.resize(new_img,
                          dsize=(self.input_size, self.input_size),
                          interpolation=interp)

    def crop(self, batch: AlignerBatch, center_scale: np.ndarray) -> List[np.ndarray]:
        """ Crop image around the center point

        Parameters
        ----------
        batch: :class:`AlignerBatch`
            The current batch to crop the image for
        center_scale: :class:`numpy.ndarray`
            The center and scale for the bounding box

        Returns
        -------
        list
            List of cropped images for the batch
        """ </s> remove         upper_left = self.transform(matrix_ones, batch["center_scale"], resolutions)
        bot_right = self.transform(matrix_size, batch["center_scale"], resolutions)
 </s> add         upper_left = self.transform(matrix_ones, center_scale, resolutions)
        bot_right = self.transform(matrix_size, center_scale, resolutions) </s> remove     @staticmethod
    def transform(points, center_scales, resolutions):
        """ Transform Image """
 </s> add     @classmethod
    def transform(cls,
                  points: np.ndarray,
                  center_scales: np.ndarray,
                  resolutions: np.ndarray) -> np.ndarray:
        """ Transform Image

        Parameters
        ----------
        points: :class:`numpy.ndarray`
            The points to transform
        center_scales: :class:`numpy.ndarray`
            The calculated centers and scales for the batch
        resolutions: :class:`numpy.ndarray`
            The resolutions
        """ </s> remove     @staticmethod
    def pad_image(box, image):
        """Pad image if face-box falls outside of boundaries """
 </s> add     @classmethod
    def pad_image(cls, box: List[int], image: np.ndarray) -> Tuple[np.ndarray, Tuple[int, int]]:
        """Pad image if face-box falls outside of boundaries

        Parameters
        ----------
        box: list
            The (`left`, `top`, `right`, `bottom`) roi box positions
        image: :class:`numpy.ndarray`
            The image to be padded

        Returns
        -------
        :class:`numpy.ndarray`
            The padded image
        """ </s> remove         logger.trace("Padding: (l: %s, t: %s, r: %s, b: %s)", pad_l, pad_t, pad_r, pad_b)
 </s> add         logger.trace("Padding: (l: %s, t: %s, r: %s, b: %s)",  # type:ignore
                     pad_l, pad_t, pad_r, pad_b)
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
          upper_left = self.transform(matrix_ones, batch["center_scale"], resolutions)
          bot_right = self.transform(matrix_size, batch["center_scale"], resolutions)
  
          # TODO second pass .. convert to matrix
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
        new_images = [self._crop_image(image, top_left, bottom_right)
                      for image, top_left, bottom_right in zip(batch.image, upper_left, bot_right)]
        logger.trace("Cropped images")  # type:ignore
          return new_images
  
      @staticmethod
      def transform(points, center_scales, resolutions):
          """ Transform Image """
keep keep keep keep replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace keep keep keep keep keep
 Extract updates:
  - Default CPU detector to MTCNN
  - add basic Aligner false positive filters
  - Typing: align + plugins
  - Use specific AlignerBatch class for alignment
  - 
plugins/extract/align/fan.py