class_docstr: Implement query generator of the Contrastive denoising (CDN) proposed in
  `DINO: DETR with Improved DeNoising Anchor Boxes for End-to-End Object
  Detection <https://arxiv.org/abs/2203.03605>`_
  
  Code is modified from the `official github repo
  <https://github.com/IDEA-Research/DINO>`_.
  
  Args:
      num_classes (int): Number of object classes.
      embed_dims (int): The embedding dimensions of the generated queries.
      num_matching_queries (int): The queries number of the matching part.
          Used for generating dn_mask.
      label_noise_scale (float): The scale of label noise, defaults to 0.5.
      box_noise_scale (float): The scale of box noise, defaults to 1.0.
      group_cfg (:obj:`ConfigDict` or dict, optional): The config of the
          denoising queries grouping, includes `dynamic`, `num_dn_queries`,
          and `num_groups`. Two grouping strategies, 'static dn groups' and
          'dynamic dn groups', are supported. When `dynamic` is `False`,
          the `num_groups` should be set, and the number of denoising query
          groups will always be `num_groups`. When `dynamic` is `True`, the
          `num_dn_queries` should be set, and the group number will be
          dynamic to ensure that the denoising queries number will not exceed
          `num_dn_queries` to prevent large fluctuations of memory. Defaults
          to `None`.
docstr: Generate noisy bboxes and their query embeddings.
  
  The strategy for generating noisy bboxes is as follow:
  
  .. code:: text
  
      +--------------------+
      |      negative      |
      |    +----------+    |
      |    | positive |    |
      |    |    +-----|----+------------+
      |    |    |     |    |            |
      |    +----+-----+    |            |
      |         |          |            |
      +---------+----------+            |
                |                       |
                |        gt bbox        |
                |                       |
                |             +---------+----------+
                |             |         |          |
                |             |    +----+-----+    |
                |             |    |    |     |    |
                +-------------|--- +----+     |    |
                              |    | positive |    |
                              |    +----------+    |
                              |      negative      |
                              +--------------------+
  
   The random noise is added to the top-left and down-right point
   positions, hence, normalized (x, y, x, y) format of bboxes are
   required. The noisy bboxes of positive queries have the points
   both within the inner square, while those of negative queries
   have the points both between the inner and outer squares.
  
  Besides, the length of outer square is twice as long as that of
  the inner square, i.e., self.box_noise_scale * w_or_h / 2.
  NOTE The noise is added to all the bboxes. Moreover, there is still
  unconsidered case when one point is within the positive square and
  the others is between the inner and outer squares.
  
  Args:
      gt_bboxes (Tensor): The concatenated gt bboxes of all samples
          in the batch, has shape (num_target_total, 4) with the last
          dimension arranged as (cx, cy, w, h) where
          `num_target_total = sum(num_target_list)`.
      num_groups (int): The number of denoising query groups.
  
  Returns:
      Tensor: The output noisy bboxes, which are embedded by normalized
      (cx, cy, w, h) format bboxes going through inverse_sigmoid, has
      shape (num_noisy_targets, 4) with the last dimension arranged as
      (cx, cy, w, h), where
      `num_noisy_targets = num_target_total * num_groups * 2`.
docstr_tok: ["Generate","noisy","bboxes","and","their","query","embeddings",".","The","strategy","for","generating","noisy","bboxes","is","as","follow",":","..","code",":",":","text","+","--","--","--","--","--","--","--","--","--","--","+","|","negative","|","|","+","--","--","--","--","--","+","|","|","|","positive","|","|","|","|","+","--","--","-|","--","--","+","--","--","--","--","--","--","+","|","|","|","|","|","|","|","+","--","--","+","--","--","-+","|","|","|","|","|","|","+","--","--","--","--","-+","--","--","--","--","--","+","|","|","|","|","gt","bbox","|","|","|","|","+","--","--","--","--","-+","--","--","--","--","--","+","|","|","|","|","|","|","+","--","--","+","--","--","-+","|","|","|","|","|","|","|","+","--","--","--","--","--","--","-|","--","-","+","--","--","+","|","|","|","|","positive","|","|","|","+","--","--","--","--","--","+","|","|","negative","|","+","--","--","--","--","--","--","--","--","--","--","+","The","random","noise","is","added","to","the","top-left","and","down-right","point","positions",",","hence",",","normalized","(","x",",","y",",","x",",","y",")","format","of","bboxes","are","required",".","The","noisy","bboxes","of","positive","queries","have","the","points","both","within","the","inner","square",",","while","those","of","negative","queries","have","the","points","both","between","the","inner","and","outer","squares",".","Besides",",","the","length","of","outer","square","is","twice","as","long","as","that","of","the","inner","square",",","i.e.",",","self.box_noise_scale","*","w_or_h","\/","2",".","NOTE","The","noise","is","added","to","all","the","bboxes",".","Moreover",",","there","is","still","unconsidered","case","when","one","point","is","within","the","positive","square","and","the","others","is","between","the","inner","and","outer","squares",".","Args",":","gt_bboxes","(","Tensor",")",":","The","concatenated","gt","bboxes","of","all","samples","in","the","batch",",","has","shape","(","num_target_total",",","4",")","with","the","last","dimension","arranged","as","(","cx",",","cy",",","w",",","h",")","where","`","num_target_total","=","sum","(","num_target_list",")","`",".","num_groups","(","int",")",":","The","number","of","denoising","query","groups",".","Returns",":","Tensor",":","The","output","noisy","bboxes",",","which","are","embedded","by","normalized","(","cx",",","cy",",","w",",","h",")","format","bboxes","going","through","inverse_sigmoid",",","has","shape","(","num_noisy_targets",",","4",")","with","the","last","dimension","arranged","as","(","cx",",","cy",",","w",",","h",")",",","where","`","num_noisy_targets","=","num_target_total","*","num_groups","*","2","`","."]
code: def generate_dn_bbox_query(
      self, gt_bboxes: Tensor, num_groups: int
  ) -> Tensor:
      """Generate noisy bboxes and their query embeddings.
  
      The strategy for generating noisy bboxes is as follow:
  
      .. code:: text
  
          +--------------------+
          |      negative      |
          |    +----------+    |
          |    | positive |    |
          |    |    +-----|----+------------+
          |    |    |     |    |            |
          |    +----+-----+    |            |
          |         |          |            |
          +---------+----------+            |
                    |                       |
                    |        gt bbox        |
                    |                       |
                    |             +---------+----------+
                    |             |         |          |
                    |             |    +----+-----+    |
                    |             |    |    |     |    |
                    +-------------|--- +----+     |    |
                                  |    | positive |    |
                                  |    +----------+    |
                                  |      negative      |
                                  +--------------------+
  
       The random noise is added to the top-left and down-right point
       positions, hence, normalized (x, y, x, y) format of bboxes are
       required. The noisy bboxes of positive queries have the points
       both within the inner square, while those of negative queries
       have the points both between the inner and outer squares.
  
      Besides, the length of outer square is twice as long as that of
      the inner square, i.e., self.box_noise_scale * w_or_h / 2.
      NOTE The noise is added to all the bboxes. Moreover, there is still
      unconsidered case when one point is within the positive square and
      the others is between the inner and outer squares.
  
      Args:
          gt_bboxes (Tensor): The concatenated gt bboxes of all samples
              in the batch, has shape (num_target_total, 4) with the last
              dimension arranged as (cx, cy, w, h) where
              `num_target_total = sum(num_target_list)`.
          num_groups (int): The number of denoising query groups.
  
      Returns:
          Tensor: The output noisy bboxes, which are embedded by normalized
          (cx, cy, w, h) format bboxes going through inverse_sigmoid, has
          shape (num_noisy_targets, 4) with the last dimension arranged as
          (cx, cy, w, h), where
          `num_noisy_targets = num_target_total * num_groups * 2`.
      """
      assert self.box_noise_scale > 0
      device = gt_bboxes.device
  
      # expand gt_bboxes as groups
      gt_bboxes_expand = gt_bboxes.repeat(2 * num_groups, 1)  # xyxy
  
      # obtain index of negative queries in gt_bboxes_expand
      positive_idx = torch.arange(
          len(gt_bboxes), dtype=torch.long, device=device
      )
      positive_idx = positive_idx.unsqueeze(0).repeat(num_groups, 1)
      positive_idx += (
          2
          * len(gt_bboxes)
          * torch.arange(num_groups, dtype=torch.long, device=device)[
              :, None
          ]
      )
      positive_idx = positive_idx.flatten()
      negative_idx = positive_idx + len(gt_bboxes)
  
      # determine the sign of each element in the random part of the added
      # noise to be positive or negative randomly.
      rand_sign = (
          torch.randint_like(
              gt_bboxes_expand, low=0, high=2, dtype=torch.float32
          )
          * 2.0
          - 1.0
      )  # [low, high), 1 or -1, randomly
  
      # calculate the random part of the added noise
      rand_part = torch.rand_like(gt_bboxes_expand)  # [0, 1)
      rand_part[negative_idx] += 1.0  # pos: [0, 1); neg: [1, 2)
      rand_part *= rand_sign  # pos: (-1, 1); neg: (-2, -1] U [1, 2)
  
      # add noise to the bboxes
      bboxes_whwh = bbox_xyxy_to_cxcywh(gt_bboxes_expand)[:, 2:].repeat(
          1, 2
      )
      noisy_bboxes_expand = (
          gt_bboxes_expand
          + torch.mul(rand_part, bboxes_whwh) * self.box_noise_scale / 2
      )  # xyxy
      noisy_bboxes_expand = noisy_bboxes_expand.clamp(min=0.0, max=1.0)
      noisy_bboxes_expand = bbox_xyxy_to_cxcywh(noisy_bboxes_expand)
  
      dn_bbox_query = inverse_sigmoid(noisy_bboxes_expand, eps=1e-3)
      return dn_bbox_query
  
imports: import warnings
  from typing import Tuple, Union
  import torch
  from mmengine.model import BaseModule
  from torch import Tensor, nn
  from mmdet.structures import SampleList
  from mmdet.structures.bbox import bbox_xyxy_to_cxcywh
  from mmdet.utils import OptConfigType
  from .deformable_detr_layers import DeformableDetrTransformerDecoder
  from .utils import MLP, coordinate_to_encoding, inverse_sigmoid
label_desc: Use image node_id 5 for calling the CdnQueryGenerator obj's underlying member method code with example usage: obj.generate_dn_bbox_query(gt_bboxes, num_groups) and returns: dn_bbox_query