class_docstr: Feature extractor for AI-VAD.
  
  Args:
      n_velocity_bins (int): Number of discrete bins used for velocity histogram features.
      use_velocity_features (bool): Flag indicating if velocity features should be used.
      use_pose_features (bool): Flag indicating if pose features should be used.
      use_deep_features (bool): Flag indicating if deep features should be used.
docstr: Forward pass through the feature extractor.
  
  Extract any combination of velocity, pose and deep features depending on configuration.
  
  Args:
      rgb_batch (Tensor): Batch of RGB images of shape (N, 3, H, W)
      flow_batch (Tensor): Batch of optical flow images of shape (N, 2, H, W)
      regions (list[dict]): Region information per image in batch.
  Returns:
      list[dict]: Feature dictionary per image in batch.
docstr_tok: ["Forward","pass","through","the","feature","extractor",".","Extract","any","combination","of","velocity",",","pose","and","deep","features","depending","on","configuration",".","Args",":","rgb_batch","(","Tensor",")",":","Batch","of","RGB","images","of","shape","(","N",",","3",",","H",",","W",")","flow_batch","(","Tensor",")",":","Batch","of","optical","flow","images","of","shape","(","N",",","2",",","H",",","W",")","regions","(","list","[","dict","]",")",":","Region","information","per","image","in","batch",".","Returns",":","list","[","dict","]",":","Feature","dictionary","per","image","in","batch","."]
code: def forward(
      self,
      rgb_batch: Tensor,
      flow_batch: Tensor,
      regions: list[dict],
  ) -> list[dict]:
      """Forward pass through the feature extractor.
  
      Extract any combination of velocity, pose and deep features depending on configuration.
  
      Args:
          rgb_batch (Tensor): Batch of RGB images of shape (N, 3, H, W)
          flow_batch (Tensor): Batch of optical flow images of shape (N, 2, H, W)
          regions (list[dict]): Region information per image in batch.
      Returns:
          list[dict]: Feature dictionary per image in batch.
      """
      batch_size = rgb_batch.shape[0]
  
      # convert from list of [N, 4] tensors to single [N, 5] tensor where each row is [index-in-batch, x1, y1, x2, y2]
      boxes_list = [batch_item["boxes"] for batch_item in regions]
      indices = torch.repeat_interleave(
          torch.arange(len(regions)),
          Tensor([boxes.shape[0] for boxes in boxes_list]).int(),
      )
      boxes = torch.cat(
          [
              indices.unsqueeze(1).to(rgb_batch.device),
              torch.cat(boxes_list),
          ],
          dim=1,
      )
  
      # Extract features
      feature_dict = {}
      if self.use_velocity_features:
          velocity_features = self.velocity_extractor(flow_batch, boxes)
          feature_dict[FeatureType.VELOCITY] = [
              velocity_features[indices == i] for i in range(batch_size)
          ]
      if self.use_pose_features:
          pose_features = self.pose_extractor(rgb_batch, boxes_list)
          feature_dict[FeatureType.POSE] = pose_features
      if self.use_deep_features:
          deep_features = self.deep_extractor(
              rgb_batch, boxes, batch_size
          )
          feature_dict[FeatureType.DEEP] = [
              deep_features[indices == i] for i in range(batch_size)
          ]
  
      # dict of lists to list of dicts
      feature_collection = [
          dict(zip(feature_dict, item))
          for item in zip(*feature_dict.values())
      ]
  
      return feature_collection
  
imports: from __future__ import annotations
  from enum import Enum
  import torch
  from torch import Tensor, nn
  from torchvision.models.detection import KeypointRCNN_ResNet50_FPN_Weights, keypointrcnn_resnet50_fpn
  from torchvision.models.detection.roi_heads import keypointrcnn_inference
  from torchvision.ops import roi_align
  from torchvision.transforms import Normalize
  from anomalib.models.ai_vad.clip import clip
label_desc: Use image node_id 2 for calling the FeatureExtractor obj's underlying member method code with example usage: obj.forward(rgb_batch, flow_batch, regions) and returns: feature_collection