class_docstr: Base class for Image-Text multi-modal learning
  
  Args:
      opts: command-line arguments
class_docstr_tok: ["Base","class","for","Image-Text","multi-modal","learning","Args",":","opts",":","command-line","arguments"]
docstr: Apply data augmentation to images and pre-processing to text captions
  
  Args:
      input_img: Input PIL Image
      captions_str: Text captions
      img_transform_fn: Image transform functions
      zero_shot: zero shot evaluation or not
  
  Returns:
      A tuple of image tensor, caption tensor, and max. sequence length of a sequence in caption tensor
docstr_tok: ["Apply","data","augmentation","to","images","and","pre-processing","to","text","captions","Args",":","input_img",":","Input","PIL","Image","captions_str",":","Text","captions","img_transform_fn",":","Image","transform","functions","zero_shot",":","zero","shot","evaluation","or","not","Returns",":","A","tuple","of","image","tensor",",","caption","tensor",",","and","max",".","sequence","length","of","a","sequence","in","caption","tensor"]
code: def _process_img_caption(
      self,
      input_img: Image.Image,
      captions_str: Union[str, List[str], List[List[str]]],
      img_transform_fn: T.BaseTransformation,
      zero_shot: bool,
  ) -> Tuple[Tensor, Tensor, int]:
      """Apply data augmentation to images and pre-processing to text captions
  
      Args:
          input_img: Input PIL Image
          captions_str: Text captions
          img_transform_fn: Image transform functions
          zero_shot: zero shot evaluation or not
  
      Returns:
          A tuple of image tensor, caption tensor, and max. sequence length of a sequence in caption tensor
      """
  
      data = {"image": input_img}
      img_tensor = img_transform_fn(data)["image"]
  
      if zero_shot and self.cached_zero_shot_captions is not None:
          return (
              img_tensor,
              self.cached_zero_shot_captions[0],
              self.cached_zero_shot_captions[1],
          )
  
      max_seq_len = 0
      # process caption
      if isinstance(captions_str, str):
          captions_tensor, max_seq_len = self._transform_text(
              self.text_tokenizer(caption_preprocessing(captions_str))
          )
      elif isinstance(captions_str, List):
          captions_tensor = []
          for captions_str_i in captions_str:
              if isinstance(captions_str_i, List):
                  # captions_str is [ [Num_templates_per_class] * Num_classes]
                  captions_tensor_i = []
                  for (
                      captions_str_i_j
                  ) in captions_str_i:  # number of templates per class
                      seq, seq_len = self._transform_text(
                          self.text_tokenizer(
                              caption_preprocessing(captions_str_i_j)
                          )
                      )
                      captions_tensor_i.append(seq)
                      max_seq_len = max(max_seq_len, seq_len)
                  captions_tensor_i = torch.stack(
                      captions_tensor_i, dim=0
                  )
                  captions_tensor.append(captions_tensor_i)
              elif isinstance(captions_str_i, str):
                  # captions_str is [Num_templates_per_image]
                  seq, seq_len = self._transform_text(
                      self.text_tokenizer(
                          caption_preprocessing(captions_str_i)
                      )
                  )
                  captions_tensor.append(seq)
                  max_seq_len = max(max_seq_len, seq_len)
              else:
                  logger.error(
                      "Got captions_str of type {}: {} from {}".format(
                          type(captions_str_i),
                          captions_str_i,
                          captions_str,
                      )
                  )
          # the shape of tensor is [Num_classes, captions_per_class, caption_length]
          # or [Captions_per_image, caption_length]
          captions_tensor = torch.stack(captions_tensor, dim=0)
      else:
          captions_tensor = None
          logger.error(
              "Captions should be either string, List[String] or List[List[str]]"
          )
  
      if zero_shot and self.cached_zero_shot_captions is None:
          self.cached_zero_shot_captions = (
              captions_tensor,
              max_seq_len,
          )
  
      return img_tensor, captions_tensor, max_seq_len
  
imports: import argparse
  import os
  from typing import Any, Dict, List, Mapping, Optional, Tuple, Union
  import torch
  from PIL import Image
  from torch import Tensor
  from data.collate_fns import COLLATE_FN_REGISTRY
  from data.datasets.dataset_base import BaseImageDataset
  from data.datasets.multi_modal_img_text.zero_shot import BaseZeroShotDataset, build_zero_shot_dataset
  from data.datasets.utils.text import caption_preprocessing
  from data.text_tokenizer import build_tokenizer
  from data.transforms import image_pil
  from data.transforms.common import Compose
  from utils import logger
  from utils.ddp_utils import is_master, is_start_rank_node
label_desc: Use image node_id 9 for calling the BaseMultiModalImgText obj's underlying member method code with example usage: obj._process_img_caption(input_img, captions_str, img_transform_fn, zero_shot) and returns: img_tensor,  captions_tensor,  max_seq_len, img_tensor,  self,  self