class_docstr: Implement TPS transform.
  
  This was partially adapted from https://github.com/ayumiymk/aster.pytorch
  
  Args:
      output_image_size (tuple[int, int]): The size of the output image.
          Defaults to (32, 128).
      num_control_points (int): The number of control points. Defaults to 20.
      margins (tuple[float, float]): The margins for control points to the
          top and down side of the image. Defaults to [0.05, 0.05].
class_docstr_tok: ["Implement","TPS","transform",".","This","was","partially","adapted","from","https",":","\/\/github.com\/ayumiymk\/aster.pytorch","Args",":","output_image_size","(","tuple","[","int",",","int","]",")",":","The","size","of","the","output","image",".","Defaults","to","(","32",",","128",")",".","num_control_points","(","int",")",":","The","number","of","control","points",".","Defaults","to","20.","margins","(","tuple","[","float",",","float","]",")",":","The","margins","for","control","points","to","the","top","and","down","side","of","the","image",".","Defaults","to","[","0.05",",","0.05","]","."]
docstr: Sample the input image at the given grid.
  
  Args:
      input (Tensor): The input image.
      grid (Tensor): The grid to sample the input image.
      canvas (Optional[Tensor]): The canvas to store the output image.
  Returns:
      Tensor: The sampled image.
docstr_tok: ["Sample","the","input","image","at","the","given","grid",".","Args",":","input","(","Tensor",")",":","The","input","image",".","grid","(","Tensor",")",":","The","grid","to","sample","the","input","image",".","canvas","(","Optional","[","Tensor","]",")",":","The","canvas","to","store","the","output","image",".","Returns",":","Tensor",":","The","sampled","image","."]
code: def _grid_sample(
      self,
      input: torch.Tensor,
      grid: torch.Tensor,
      canvas: Optional[torch.Tensor] = None,
  ) -> torch.Tensor:
      """Sample the input image at the given grid.
  
      Args:
          input (Tensor): The input image.
          grid (Tensor): The grid to sample the input image.
          canvas (Optional[Tensor]): The canvas to store the output image.
      Returns:
          Tensor: The sampled image.
      """
      output = F.grid_sample(input, grid, align_corners=True)
      if canvas is None:
          return output
      else:
          input_mask = input.data.new(input.size()).fill_(1)
          output_mask = F.grid_sample(
              input_mask, grid, align_corners=True
          )
          padded_output = output * output_mask + canvas * (
              1 - output_mask
          )
          return padded_output
  
imports: import itertools
  from typing import Dict, List, Optional, Tuple, Union
  import numpy
  import torch
  import torch.nn
  import torch.nn.functional
  from mmcv.cnn import ConvModule
  from mmocr.registry import MODELS
  from .base import BasePreprocessor
label_desc: Use image node_id 3 for calling the TPStransform obj's underlying member method code with example usage: obj._grid_sample(input, grid, canvas) and returns: output, padded_output