class_docstr: Implements an abstract preprocessor object which performs casting, resizing, batching and normalization.
  
  Args:
  ----
      output_size: expected size of each page in format (H, W)
      batch_size: the size of page batches
      mean: mean value of the training distribution by channel
      std: standard deviation of the training distribution by channel
class_docstr_tok: ["Implements","an","abstract","preprocessor","object","which","performs","casting",",","resizing",",","batching","and","normalization",".","Args",":","--","--","output_size",":","expected","size","of","each","page","in","format","(","H",",","W",")","batch_size",":","the","size","of","page","batches","mean",":","mean","value","of","the","training","distribution","by","channel","std",":","standard","deviation","of","the","training","distribution","by","channel"]
docstr: Prepare document data for model forwarding
  
  Args:
  ----
      x: list of images (np.array) or tensors (already resized and batched)
  
  Returns:
  -------
      list of page batches
docstr_tok: ["Prepare","document","data","for","model","forwarding","Args",":","--","--","x",":","list","of","images","(","np.array",")","or","tensors","(","already","resized","and","batched",")","Returns",":","--","--","--","-","list","of","page","batches"]
code: def __call__(
      self,
      x: Union[
          torch.Tensor,
          np.ndarray,
          List[Union[torch.Tensor, np.ndarray]],
      ],
  ) -> List[torch.Tensor]:
      """Prepare document data for model forwarding
  
      Args:
      ----
          x: list of images (np.array) or tensors (already resized and batched)
  
      Returns:
      -------
          list of page batches
      """
      # Input type check
      if isinstance(x, (np.ndarray, torch.Tensor)):
          if x.ndim != 4:
              raise AssertionError("expected 4D Tensor")
          if isinstance(x, np.ndarray):
              if x.dtype not in (np.uint8, np.float32):
                  raise TypeError(
                      "unsupported data type for numpy.ndarray"
                  )
              x = torch.from_numpy(x.copy()).permute(0, 3, 1, 2)
          elif x.dtype not in (
              torch.uint8,
              torch.float16,
              torch.float32,
          ):
              raise TypeError("unsupported data type for torch.Tensor")
          # Resizing
          if x.shape[-2] != self.resize.size[0] or x.shape[-1] != self.resize.size[1]:  # type: ignore[union-attr]
              x = F.resize(
                  x,
                  self.resize.size,
                  interpolation=self.resize.interpolation,
                  antialias=self.resize.antialias,
              )
          # Data type
          if x.dtype == torch.uint8:  # type: ignore[union-attr]
              x = x.to(dtype=torch.float32).div(255).clip(0, 1)  # type: ignore[union-attr]
          else:
              x = x.to(dtype=torch.float32)  # type: ignore[union-attr]
          batches = [x]
  
      elif isinstance(x, list) and all(
          isinstance(sample, (np.ndarray, torch.Tensor)) for sample in x
      ):
          # Sample transform (to tensor, resize)
          samples = list(multithread_exec(self.sample_transforms, x))
          # Batching
          batches = self.batch_inputs(samples)  # type: ignore[assignment]
      else:
          raise TypeError(f"invalid input type: {type(x)}")
  
      # Batch transforms (normalize)
      batches = list(multithread_exec(self.normalize, batches))
  
      return batches
  
file_path: doctr/doctr/models/preprocessor/pytorch.py
imports: import math
  from typing import Any, List, Tuple, Union
  import numpy
  import torch
  from torch import nn
  from torchvision.transforms import functional
  from torchvision.transforms import transforms
  from doctr.transforms import Resize
  from doctr.utils.multithreading import multithread_exec
label_desc: Use image node_id 4 for calling the PreProcessor obj's underlying member method code with example usage: obj.__call__(x) and returns: batches