class_docstr: Text recognition packer with image cropper. It is used to pack the
  parsed annotation info and crop out the word images from the full-size
  ones.
  
  Args:
      crop_with_warp (bool): Whether to crop the text from the original
          image using opencv warpPerspective.
      jitter (bool): (Applicable when crop_with_warp=True)
          Whether to jitter the box.
      jitter_ratio_x (float): (Applicable when crop_with_warp=True)
          Horizontal jitter ratio relative to the height.
      jitter_ratio_y (float): (Applicable when crop_with_warp=True)
          Vertical jitter ratio relative to the height.
      long_edge_pad_ratio (float): (Applicable when crop_with_warp=False)
          The ratio of padding the long edge of the cropped image.
          Defaults to 0.1.
      short_edge_pad_ratio (float): (Applicable when crop_with_warp=False)
          The ratio of padding the short edge of the cropped image.
          Defaults to 0.05.
docstr: Crop patches from image.
  
  Args:
      samples (Tuple): A tuple of (img_name, text).
  
  Return:
      List: The list of cropped patches.
docstr_tok: ["Crop","patches","from","image",".","Args",":","samples","(","Tuple",")",":","A","tuple","of","(","img_name",",","text",")",".","Return",":","List",":","The","list","of","cropped","patches","."]
code: def pack_instance(self, sample: Tuple) -> List:
      """Crop patches from image.
  
      Args:
          samples (Tuple): A tuple of (img_name, text).
  
      Return:
          List: The list of cropped patches.
      """
  
      def get_box(instance: Dict) -> List:
          if "box" in instance:
              return bbox2poly(instance["box"]).tolist()
          if "poly" in instance:
              return bbox2poly(poly2bbox(instance["poly"])).tolist()
  
      def get_poly(instance: Dict) -> List:
          if "poly" in instance:
              return instance["poly"]
          if "box" in instance:
              return bbox2poly(instance["box"]).tolist()
  
      data_list = []
      img_path, instances = sample
      img = mmcv.imread(img_path)
      for i, instance in enumerate(instances):
          if instance["ignore"]:
              continue
          if self.crop_with_warp:
              poly = get_poly(instance)
              patch = warp_img(
                  img, poly, self.jitter, self.jrx, self.jry
              )
          else:
              box = get_box(instance)
              patch = crop_img(img, box, self.lepr, self.sepr)
          if patch.shape[0] == 0 or patch.shape[1] == 0:
              continue
          text = instance["text"]
          patch_name = (
              osp.splitext(osp.basename(img_path))[0]
              + f"_{i}"
              + osp.splitext(osp.basename(img_path))[1]
          )
          dst_path = osp.join(
              self.crop_save_path, self.split, patch_name
          )
          mmcv.imwrite(patch, dst_path)
          rec_instance = dict(
              instances=[dict(text=text)],
              img_path=osp.join(
                  self.cropped_img_dir, self.split, patch_name
              ),
          )
          data_list.append(rec_instance)
  
      return data_list
  
file_path: mmocr/mmocr/datasets/preparers/packers/textrecog_packer.py
imports: import os.path
  from typing import Dict, List, Tuple
  import mmcv
  from mmengine import mkdir_or_exist
  from mmocr.registry import DATA_PACKERS
  from mmocr.utils import bbox2poly, crop_img, poly2bbox, warp_img
  from .base import BasePacker
label_desc: Use image node_id 2 for calling the TextRecogCropPacker obj's underlying member method code with example usage: obj.pack_instance(sample) and returns: data_list, bbox2poly, bbox2poly, instance, bbox2poly