def __call__(self, x: np.ndarray, y: np.ndarray | None = None) -> tuple[np.ndarray, np.ndarray | None]:
        """
        Apply preprocessing to input `x` and labels `y`.

        :param x: Sample to smooth with shape `(batch_size, width, height, depth)`.
        :param y: Labels of the sample `x`. This function does not affect them in any way.
        :return: Smoothed sample.
        """
        import torch

        x_tensor = torch.tensor(x, device=self.device)
        if y is not None:
            y_tensor: torch.Tensor | None = torch.tensor(y, device=self.device)
        else:
            y_tensor = None

        with torch.no_grad():
            x_tensor, y_tensor = self.forward(x_tensor, y_tensor)

        x_result = x_tensor.cpu().numpy()
        if y_tensor is not None:
            y_result: np.ndarray | None = y_tensor.cpu().numpy()
        else:
            y_result = None
        return x_result, y_result

        Apply preprocessing to input `x` and labels `y`.

        :param x: Sample to smooth with shape `(batch_size, width, height, depth)`.
        :param y: Labels of the sample `x`. This function does not affect them in any way.
        :return: Smoothed sample.
        
art/defences/preprocessor/preprocessor.py