class_docstr: This class implements a `Single Shot Object Detector <https://arxiv.org/abs/1512.02325>`_
  
  Args:
      opts: command-line arguments
      encoder (BaseImageEncoder): Encoder network (e.g., ResNet or MobileViT)
class_docstr_tok: ["This","class","implements","a","`","Single","Shot","Object","Detector","<","https",":","\/\/arxiv.org\/abs\/1512.02325",">","`","_","Args",":","opts",":","command-line","arguments","encoder","(","BaseImageEncoder",")",":","Encoder","network","(","e.g.",",","ResNet","or","MobileViT",")"]
code: def __init__(self, opts, encoder: BaseImageEncoder) -> None:
      anchor_gen_name = getattr(opts, "anchor_generator.name", None)
      if anchor_gen_name is None or anchor_gen_name != "ssd":
          logger.error(
              "For SSD, we need --anchor-generator.name to be ssd"
          )
      anchor_box_generator = build_anchor_generator(opts=opts)
  
      output_strides_aspect_ratio = (
          anchor_box_generator.output_strides_aspect_ratio
      )
      output_strides = list(output_strides_aspect_ratio.keys())
      anchors_aspect_ratio = list(output_strides_aspect_ratio.values())
  
      n_os = len(output_strides)
  
      if getattr(opts, "matcher.name") != "ssd":
          logger.error("For SSD, we need --matcher.name as ssd")
  
      super().__init__(opts=opts, encoder=encoder)
  
      # delete layers that are not required in detection network
      self.encoder.classifier = None
      self.encoder.conv_1x1_exp = None
  
      proj_channels = getattr(
          opts,
          "model.detection.ssd.proj_channels",
          [512, 256, 256, 128, 128, 64],
      )
  
      proj_channels = proj_channels + [128] * (
          n_os - len(proj_channels)
      )
  
      if n_os != len(anchors_aspect_ratio) != len(proj_channels):
          logger.error(
              "SSD model requires anchors to be defined for feature maps from each output stride. Also"
              "len(anchors_aspect_ratio) == len(output_strides) == len(proj_channels). "
              "Got len(output_strides)={}, len(anchors_aspect_ratio)={}, len(proj_channels)={}."
              " Please specify correct arguments using following arguments: "
              "\n--model.detection.ssd.anchors-aspect-ratio "
              "\n--model.detection.ssd.output-strides"
              "\n--model.detection.ssd.proj-channels".format(
                  n_os, len(anchors_aspect_ratio), len(proj_channels)
              )
          )
      extra_layers = {}
      enc_channels_list = []
      in_channels = self.enc_l5_channels
  
      extra_proj_list = [256] * (
          len(output_strides) - len(proj_channels)
      )
      proj_channels = proj_channels + extra_proj_list
      for idx, os in enumerate(output_strides):
          out_channels = proj_channels[idx]
          if os == 8:
              enc_channels_list.append(self.enc_l3_channels)
          elif os == 16:
              enc_channels_list.append(self.enc_l4_channels)
          elif os == 32:
              enc_channels_list.append(self.enc_l5_channels)
          elif os > 32 and os != -1:
              extra_layers["os_{}".format(os)] = SeparableConv2d(
                  opts=opts,
                  in_channels=in_channels,
                  out_channels=out_channels,
                  kernel_size=3,
                  use_act=True,
                  use_norm=True,
                  stride=2,
              )
              enc_channels_list.append(out_channels)
              in_channels = out_channels
          elif os == -1:
              extra_layers["os_{}".format(os)] = nn.Sequential(
                  AdaptiveAvgPool2d(output_size=1),
                  ConvLayer2d(
                      opts=opts,
                      in_channels=in_channels,
                      out_channels=out_channels,
                      kernel_size=1,
                      use_act=True,
                      use_norm=False,
                  ),
              )
              enc_channels_list.append(out_channels)
              in_channels = out_channels
          else:
              raise NotImplementedError
      self.extra_layers = (
          None if not extra_layers else nn.ModuleDict(extra_layers)
      )
      if self.extra_layers is not None:
          self.reset_layers(module=self.extra_layers)
  
      self.fpn = None
      if getattr(opts, "model.detection.ssd.use_fpn", False):
          from cvnets.modules import FeaturePyramidNetwork
  
          fpn_channels = getattr(
              opts, "model.detection.ssd.fpn_out_channels", 256
          )
          self.fpn = FeaturePyramidNetwork(
              opts=opts,
              in_channels=enc_channels_list,
              output_strides=output_strides,
              out_channels=fpn_channels,
          )
          # update the enc_channels_list
          enc_channels_list = [fpn_channels] * len(output_strides)
          # for FPN, we do not need to do projections
          proj_channels = enc_channels_list
  
      # Anchor box related parameters
      self.conf_threshold = getattr(
          opts, "model.detection.ssd.conf_threshold", 0.01
      )
      self.nms_threshold = getattr(
          opts, "model.detection.ssd.nms_iou_threshold", 0.5
      )
      self.top_k = getattr(opts, "model.detection.ssd.top_k", 400)
      self.objects_per_image = getattr(
          opts, "model.detection.ssd.objects_per_image", 200
      )
  
      self.anchor_box_generator = anchor_box_generator
  
      anchors_aspect_ratio = (
          self.anchor_box_generator.num_anchors_per_os()
      )
  
      # Create SSD detection and classification heads
      anchor_steps = self.anchor_box_generator.step
  
      self.ssd_heads = nn.ModuleList()
  
      for os, in_dim, proj_dim, n_anchors, step in zip(
          output_strides,
          enc_channels_list,
          proj_channels,
          anchors_aspect_ratio,
          anchor_steps,
      ):
          self.ssd_heads += [
              SSDHead(
                  opts=opts,
                  in_channels=in_dim,
                  n_classes=self.n_detection_classes,
                  n_coordinates=self.coordinates,
                  n_anchors=n_anchors,
                  proj_channels=proj_dim,
                  kernel_size=3 if os != -1 else 1,
                  stride=step,
              )
          ]
  
      self.anchors_aspect_ratio = anchors_aspect_ratio
      self.output_strides = output_strides
  
      self.match_prior = build_matcher(opts=opts)
      self.step = self.anchor_box_generator.step
  
imports: import argparse
  import math
  from typing import Any, Dict, List, Optional, Tuple, Union
  import torch
  from torch import Tensor, nn
  from torchvision.ops import batched_nms
  from cvnets.anchor_generator import build_anchor_generator
  from cvnets.layers import AdaptiveAvgPool2d, ConvLayer2d, SeparableConv2d
  from cvnets.matcher_det import build_matcher
  from cvnets.misc.init_utils import initialize_conv_layer
  from cvnets.models import MODEL_REGISTRY
  from cvnets.models.classification.base_image_encoder import BaseImageEncoder
  from cvnets.models.detection import DetectionPredTuple
  from cvnets.models.detection.base_detection import BaseDetection
  from cvnets.modules import SSDHead
  from utils import logger
  from utils.common_utils import is_coreml_conversion
label_desc: Use image node_id 1 to create a new SingleShotMaskDetector object from inherited base classes: BaseDetection with example: obj = SingleShotMaskDetector(opts, encoder)