code: def _get_encoder_input(
      self, feats: Tensor
  ) -> tuple[Tensor, list[tuple[int, int]], list[int]]:
      # get projection features
      proj_feats: list[Tensor] = [
          self.input_proj[i](feat) for i, feat in enumerate(feats)
      ]
  
      if self.num_levels > len(proj_feats):
          len_srcs = len(proj_feats)
          for i in range(len_srcs, self.num_levels):
              if i == len_srcs:
                  proj_feats.append(self.input_proj[i](feats[-1]))
              else:
                  proj_feats.append(self.input_proj[i](proj_feats[-1]))
  
      # get encoder inputs
      feat_flatten_list: list[Tensor] = []
      spatial_shapes: list[tuple[int, int]] = []
      level_start_index: list[int] = [0]
  
      for i, feat in enumerate(proj_feats):
          _, _, h, w = feat.shape
          # [b, c, h, w] -> [b, h*w, c]
          feat_flatten_list.append(feat.flatten(2).permute(0, 2, 1))
          # [num_levels, 2]
          spatial_shapes.append((h, w))
          # [l], start index of each level
          level_start_index.append(h * w + level_start_index[-1])
  
      # [b, l, c]
      feat_flatten: Tensor = torch.concat(feat_flatten_list, 1)
  
      level_start_index.pop()
      return feat_flatten, spatial_shapes, level_start_index
  
imports: from __future__ import annotations
  from typing import Optional
  import torch
  from torch import nn
  from kornia.contrib.models.common import MLP, ConvNormAct
  from kornia.core import Module, Tensor, concatenate
label_desc: Use image node_id 3 for calling the RTDETRHead obj's underlying member method code with example usage: obj._get_encoder_input(feats) and returns: feat_flatten,  spatial_shapes,  level_start_index