class_docstr: Velocity feature extractor.
  
  Extracts histograms of optical flow magnitude and direction.
  
  Args:
      n_bins (int): Number of direction bins used for the feature histograms.
docstr: Extract velocioty features by filling a histogram.
  
  Args:
      flows (Tensor): Batch of optical flow images of shape (N, 2, H, W)
      boxes (Tensor): Bounding box coordinates of shaspe (M, 5). First column indicates batch index of the bbox.
  
  Returns:
      Tensor: Velocity feature tensor of shape (M, n_bins)
docstr_tok: ["Extract","velocioty","features","by","filling","a","histogram",".","Args",":","flows","(","Tensor",")",":","Batch","of","optical","flow","images","of","shape","(","N",",","2",",","H",",","W",")","boxes","(","Tensor",")",":","Bounding","box","coordinates","of","shaspe","(","M",",","5",")",".","First","column","indicates","batch","index","of","the","bbox",".","Returns",":","Tensor",":","Velocity","feature","tensor","of","shape","(","M",",","n_bins",")"]
code: def forward(self, flows: Tensor, boxes: Tensor) -> Tensor:
      """Extract velocioty features by filling a histogram.
  
      Args:
          flows (Tensor): Batch of optical flow images of shape (N, 2, H, W)
          boxes (Tensor): Bounding box coordinates of shaspe (M, 5). First column indicates batch index of the bbox.
  
      Returns:
          Tensor: Velocity feature tensor of shape (M, n_bins)
      """
      flow_regions = roi_align(flows, boxes, output_size=[224, 224])
  
      # cartesian to polar
      mag_batch = torch.linalg.norm(flow_regions, axis=1, ord=2)
      theta_batch = torch.atan2(
          flow_regions[:, 0, ...], flow_regions[:, 1, ...]
      )
  
      # compute velocity histogram
      velocity_histograms = []
      for mag, theta in zip(mag_batch, theta_batch):
          histogram_mag = torch.histogram(
              input=theta.cpu(),
              bins=self.n_bins,
              range=(-torch.pi, torch.pi),
              weight=mag.cpu(),
          ).hist
          histogram_counts = torch.histogram(
              input=theta.cpu(),
              bins=self.n_bins,
              range=(-torch.pi, torch.pi),
          ).hist
          final_histogram = torch.zeros_like(histogram_mag)
          mask = histogram_counts != 0
          final_histogram[mask] = (
              histogram_mag[mask] / histogram_counts[mask]
          )
          velocity_histograms.append(final_histogram)
  
      return torch.stack(velocity_histograms).to(flows.device)
  
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 VelocityExtractor obj's underlying member method code with example usage: obj.forward(flows, boxes) and returns: torch