class_docstr: Standard anchor generator for 2D anchor-based detectors.
  
  Args:
      strides (list[int] | list[tuple[int, int]]): Strides of anchors
          in multiple feature levels in order (w, h).
      ratios (list[float]): The list of ratios between the height and width
          of anchors in a single level.
      scales (list[int] | None): Anchor scales for anchors in a single level.
          It cannot be set at the same time if `octave_base_scale` and
          `scales_per_octave` are set.
      base_sizes (list[int] | None): The basic sizes
          of anchors in multiple levels.
          If None is given, strides will be used as base_sizes.
          (If strides are non square, the shortest stride is taken.)
      scale_major (bool): Whether to multiply scales first when generating
          base anchors. If true, the anchors in the same row will have the
          same scales. By default it is True in V2.0
      octave_base_scale (int): The base scale of octave.
      scales_per_octave (int): Number of scales for each octave.
          `octave_base_scale` and `scales_per_octave` are usually used in
          retinanet and the `scales` should be None when they are set.
      centers (list[tuple[float, float]] | None): The centers of the anchor
          relative to the feature grid center in multiple feature levels.
          By default it is set to be None and not used. If a list of tuple of
          float is given, they will be used to shift the centers of anchors.
      center_offset (float): The offset of center in proportion to anchors'
          width and height. By default it is 0 in V2.0.
  
  Examples:
      >>> from mmdet.core import AnchorGenerator
      >>> self = AnchorGenerator([16], [1.], [1.], [9])
      >>> all_anchors = self.grid_anchors([(2, 2)], device='cpu')
      >>> print(all_anchors)
      [tensor([[-4.5000, -4.5000,  4.5000,  4.5000],
              [11.5000, -4.5000, 20.5000,  4.5000],
              [-4.5000, 11.5000,  4.5000, 20.5000],
              [11.5000, 11.5000, 20.5000, 20.5000]])]
      >>> self = AnchorGenerator([16, 32], [1.], [1.], [9, 18])
      >>> all_anchors = self.grid_anchors([(2, 2), (1, 1)], device='cpu')
      >>> print(all_anchors)
      [tensor([[-4.5000, -4.5000,  4.5000,  4.5000],
              [11.5000, -4.5000, 20.5000,  4.5000],
              [-4.5000, 11.5000,  4.5000, 20.5000],
              [11.5000, 11.5000, 20.5000, 20.5000]]),         tensor([[-9., -9., 9., 9.]])]
code: def __init__(
      self,
      strides,
      ratios,
      scales=None,
      base_sizes=None,
      scale_major=True,
      octave_base_scale=None,
      scales_per_octave=None,
      centers=None,
      center_offset=0.0,
  ):
      # check center and center_offset
      if center_offset != 0:
          assert centers is None, (
              "center cannot be set when center_offset"
              f"!=0, {centers} is given."
          )
      if not (0 <= center_offset <= 1):
          raise ValueError(
              "center_offset should be in range [0, 1], "
              f"{center_offset} is given."
          )
      if centers is not None:
          assert len(centers) == len(strides), (
              "The number of strides should be the same as centers, got "
              f"{strides} and {centers}"
          )
  
      # calculate base sizes of anchors
      self.strides = [_pair(stride) for stride in strides]
      self.base_sizes = (
          [min(stride) for stride in self.strides]
          if base_sizes is None
          else base_sizes
      )
      assert len(self.base_sizes) == len(self.strides), (
          "The number of strides should be the same as base sizes, got "
          f"{self.strides} and {self.base_sizes}"
      )
  
      # calculate scales of anchors
      assert (
          octave_base_scale is not None
          and scales_per_octave is not None
      ) ^ (scales is not None), (
          "scales and octave_base_scale with scales_per_octave cannot"
          " be set at the same time"
      )
      if scales is not None:
          self.scales = torch.Tensor(scales)
      elif (
          octave_base_scale is not None
          and scales_per_octave is not None
      ):
          octave_scales = np.array(
              [
                  2 ** (i / scales_per_octave)
                  for i in range(scales_per_octave)
              ]
          )
          scales = octave_scales * octave_base_scale
          self.scales = torch.Tensor(scales)
      else:
          raise ValueError(
              "Either scales or octave_base_scale with "
              "scales_per_octave should be set"
          )
  
      self.octave_base_scale = octave_base_scale
      self.scales_per_octave = scales_per_octave
      self.ratios = torch.Tensor(ratios)
      self.scale_major = scale_major
      self.centers = centers
      self.center_offset = center_offset
      self.base_anchors = self.gen_base_anchors()
  
imports: import mmcv
  import numpy
  import torch
  from torch.nn.modules.utils import _pair
  from .builder import ANCHOR_GENERATORS
label_desc: Use image node_id 1 to create a new AnchorGenerator object from inherited base classes: object with example: obj = AnchorGenerator(strides, ratios, scales, base_sizes, scale_major, octave_base_scale, scales_per_octave, centers, center_offset)