class_docstr: The class for implementing DRRG loss. This is partially adapted from
  https://github.com/GXYM/DRRG licensed under the MIT license.
  
  DRRG: `Deep Relational Reasoning Graph Network for Arbitrary Shape Text
  Detection <https://arxiv.org/abs/1908.05900>`_.
  
  Args:
      ohem_ratio (float): The negative/positive ratio in ohem. Defaults to
          3.0.
      downsample_ratio (float): Downsample ratio. Defaults to 1.0. TODO:
          remove it.
      orientation_thr (float): The threshold for distinguishing between
          head edge and tail edge among the horizontal and vertical edges
          of a quadrangle. Defaults to 2.0.
      resample_step (float): The step size for resampling the text center
          line. Defaults to 8.0.
      num_min_comps (int): The minimum number of text components, which
          should be larger than k_hop1 mentioned in paper. Defaults to 9.
      num_max_comps (int): The maximum number of text components. Defaults
          to 600.
      min_width (float): The minimum width of text components. Defaults to
          8.0.
      max_width (float): The maximum width of text components. Defaults to
          24.0.
      center_region_shrink_ratio (float): The shrink ratio of text center
          regions. Defaults to 0.3.
      comp_shrink_ratio (float): The shrink ratio of text components.
          Defaults to 1.0.
      comp_w_h_ratio (float): The width to height ratio of text components.
          Defaults to 0.3.
      min_rand_half_height(float): The minimum half-height of random text
          components. Defaults to 8.0.
      max_rand_half_height (float): The maximum half-height of random
          text components. Defaults to 24.0.
      jitter_level (float): The jitter level of text component geometric
          features. Defaults to 0.2.
      loss_text (dict): The loss config used to calculate the text loss.
          Defaults to ``dict(type='MaskedBalancedBCEWithLogitsLoss',
          fallback_negative_num=100, eps=1e-5)``.
      loss_center (dict): The loss config used to calculate the center loss.
          Defaults to ``dict(type='MaskedBCEWithLogitsLoss')``.
      loss_top (dict): The loss config used to calculate the top loss, which
          is a part of the height loss. Defaults to
          ``dict(type='SmoothL1Loss', reduction='none')``.
      loss_btm (dict): The loss config used to calculate the bottom loss,
          which is a part of the height loss. Defaults to
          ``dict(type='SmoothL1Loss', reduction='none')``.
      loss_sin (dict): The loss config used to calculate the sin loss.
          Defaults to ``dict(type='MaskedSmoothL1Loss')``.
      loss_cos (dict): The loss config used to calculate the cos loss.
          Defaults to ``dict(type='MaskedSmoothL1Loss')``.
      loss_gcn (dict): The loss config used to calculate the GCN loss.
          Defaults to ``dict(type='CrossEntropyLoss')``.
docstr: Generate random text components and their attributes to ensure the
  the number of text components in an image is larger than k_hop1, which
  is the number of one hop neighbors in KNN graph.
  
  Args:
      num_rand_comps (int): The number of random text components.
      center_sample_mask (ndarray): The region mask for sampling text
          component centers .
  
  Returns:
      ndarray: The random text component attributes
      (x, y, h, w, cos, sin, comp_label=0).
docstr_tok: ["Generate","random","text","components","and","their","attributes","to","ensure","the","the","number","of","text","components","in","an","image","is","larger","than","k_hop1",",","which","is","the","number","of","one","hop","neighbors","in","KNN","graph",".","Args",":","num_rand_comps","(","int",")",":","The","number","of","random","text","components",".","center_sample_mask","(","ndarray",")",":","The","region","mask","for","sampling","text","component","centers",".","Returns",":","ndarray",":","The","random","text","component","attributes","(","x",",","y",",","h",",","w",",","cos",",","sin",",","comp_label=0",")","."]
code: def _generate_rand_comp_attribs(
      self, num_rand_comps: int, center_sample_mask: ndarray
  ) -> ndarray:
      """Generate random text components and their attributes to ensure the
      the number of text components in an image is larger than k_hop1, which
      is the number of one hop neighbors in KNN graph.
  
      Args:
          num_rand_comps (int): The number of random text components.
          center_sample_mask (ndarray): The region mask for sampling text
              component centers .
  
      Returns:
          ndarray: The random text component attributes
          (x, y, h, w, cos, sin, comp_label=0).
      """
  
      assert isinstance(num_rand_comps, int)
      assert num_rand_comps > 0
      assert center_sample_mask.ndim == 2
  
      h, w = center_sample_mask.shape
  
      max_rand_half_height = self.max_rand_half_height
      min_rand_half_height = self.min_rand_half_height
      max_rand_height = max_rand_half_height * 2
      max_rand_width = np.clip(
          max_rand_height * self.comp_w_h_ratio,
          self.min_width,
          self.max_width,
      )
      margin = (
          int(
              np.sqrt(
                  (max_rand_height / 2) ** 2 + (max_rand_width / 2) ** 2
              )
          )
          + 1
      )
  
      if 2 * margin + 1 > min(h, w):
          assert min(h, w) > (np.sqrt(2) * (self.min_width + 1))
          max_rand_half_height = max(
              min(h, w) / 4, self.min_width / 2 + 1
          )
          min_rand_half_height = max(
              max_rand_half_height / 4, self.min_width / 2
          )
  
          max_rand_height = max_rand_half_height * 2
          max_rand_width = np.clip(
              max_rand_height * self.comp_w_h_ratio,
              self.min_width,
              self.max_width,
          )
          margin = (
              int(
                  np.sqrt(
                      (max_rand_height / 2) ** 2
                      + (max_rand_width / 2) ** 2
                  )
              )
              + 1
          )
  
      inner_center_sample_mask = np.zeros_like(center_sample_mask)
      inner_center_sample_mask[
          margin : h - margin, margin : w - margin
      ] = center_sample_mask[margin : h - margin, margin : w - margin]
      kernel_size = int(np.clip(max_rand_half_height, 7, 21))
      inner_center_sample_mask = cv2.erode(
          inner_center_sample_mask,
          np.ones((kernel_size, kernel_size), np.uint8),
      )
  
      center_candidates = np.argwhere(inner_center_sample_mask > 0)
      num_center_candidates = len(center_candidates)
      sample_inds = np.random.choice(
          num_center_candidates, num_rand_comps
      )
      rand_centers = center_candidates[sample_inds]
  
      rand_top_height = np.random.randint(
          min_rand_half_height,
          max_rand_half_height,
          size=(len(rand_centers), 1),
      )
      rand_bot_height = np.random.randint(
          min_rand_half_height,
          max_rand_half_height,
          size=(len(rand_centers), 1),
      )
  
      rand_cos = 2 * np.random.random(size=(len(rand_centers), 1)) - 1
      rand_sin = 2 * np.random.random(size=(len(rand_centers), 1)) - 1
      scale = np.sqrt(1.0 / (rand_cos**2 + rand_sin**2 + 1e-8))
      rand_cos = rand_cos * scale
      rand_sin = rand_sin * scale
  
      height = rand_top_height + rand_bot_height
      width = np.clip(
          height * self.comp_w_h_ratio, self.min_width, self.max_width
      )
  
      rand_comp_attribs = np.hstack(
          [
              rand_centers[:, ::-1],
              height,
              width,
              rand_cos,
              rand_sin,
              np.zeros_like(rand_sin),
          ]
      ).astype(np.float32)
  
      return rand_comp_attribs
  
imports: from typing import Dict, List, Sequence, Tuple
  import cv2
  import numpy
  import torch
  from mmcv.image import imrescale
  from mmdet.models.utils import multi_apply
  from numpy import ndarray
  from numpy.linalg import norm
  from torch import Tensor
  from mmocr.registry import MODELS
  from mmocr.structures import TextDetDataSample
  from mmocr.utils import check_argument
  from .textsnake_module_loss import TextSnakeModuleLoss
label_desc: Use image node_id 7 for calling the DRRGModuleLoss obj's underlying member method code with example usage: obj._generate_rand_comp_attribs(num_rand_comps, center_sample_mask) and returns: rand_comp_attribs