class_docstr: Implement the local spatial smoothing defence approach.
  
  | Paper link: https://arxiv.org/abs/1704.01155
  
  | Please keep in mind the limitations of defences. For more information on the limitations of this defence,
      see https://arxiv.org/abs/1803.09868 . For details on how to evaluate classifier security in general, see
      https://arxiv.org/abs/1902.06705
docstr: Apply local spatial smoothing to sample `x`.
  
  :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.
code: def __call__(
      self, x: np.ndarray, y: Optional[np.ndarray] = None
  ) -> Tuple[np.ndarray, Optional[np.ndarray]]:
      """
      Apply local spatial smoothing to sample `x`.
  
      :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.
      """
      x_ndim = x.ndim
      if x_ndim not in [4, 5]:
          raise ValueError(
              "Unrecognized input dimension. Spatial smoothing can only be applied to image and video data."
          )
  
      # get channel index
      channel_index = 1 if self.channels_first else x_ndim - 1
  
      filter_size = [self.window_size] * x_ndim
      # set filter_size at batch and channel indices to 1
      filter_size[0] = 1
      filter_size[channel_index] = 1
      # set filter_size at temporal index to 1
      if x_ndim == 5:
          # check if NCFHW or NFHWC
          temporal_index = 2 if self.channels_first else 1
          filter_size[temporal_index] = 1
      # Note median_filter:
      # * center pixel located lower right
      # * if window size even, use larger value (e.g. median(4,5)=5)
      result = median_filter(x, size=tuple(filter_size), mode="reflect")
  
      if self.clip_values is not None:
          np.clip(
              result,
              self.clip_values[0],
              self.clip_values[1],
              out=result,
          )
  
      return result, y
  
file_path: adversarial-robustness-toolbox/art/defences/preprocessor/spatial_smoothing.py
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  from typing import Optional, Tuple
  import numpy
  from scipy.ndimage import median_filter
  from art.utils import CLIP_VALUES_TYPE
  from art.defences.preprocessor.preprocessor import Preprocessor
label_desc: Use image node_id 2 for calling the SpatialSmoothing obj's underlying member method code with example usage: obj.__call__(x, y) and returns: result,  y