def forward(
        self,
        rgb_batch: torch.Tensor,
        flow_batch: torch.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 (torch.Tensor): Batch of RGB images of shape ``(N, 3, H, W)``.
            flow_batch (torch.Tensor): Batch of optical flow images of shape
                ``(N, 2, H, W)``.
            regions (list[dict]): Region information per image in batch. Each dict
                contains bounding boxes of shape ``(M, 4)``.

        Returns:
            list[dict]: Feature dictionary per image in batch. Each dict contains
                the enabled feature types as keys with corresponding feature tensors
                as values.

        Example:
            >>> import torch
            >>> from anomalib.models.video.ai_vad.features import VideoRegionFeatureExtractor
            >>> extractor = VideoRegionFeatureExtractor()
            >>> rgb_batch = torch.randn(32, 3, 256, 256)  # (N, C, H, W)
            >>> flow_batch = torch.randn(32, 2, 256, 256)  # (N, 2, H, W)
            >>> regions = [{"boxes": torch.randn(5, 4)}] * 32  # List of region dicts
            >>> features = extractor(rgb_batch, flow_batch, regions)
            >>> features[0].keys()  # Features for first image
            dict_keys(['velocity', 'pose', 'deep'])
        """
        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)),
            torch.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
        return [dict(zip(feature_dict, item, strict=True)) for item in zip(*feature_dict.values(), strict=True)]
Forward pass through the feature extractor.

        Extract any combination of velocity, pose and deep features depending on
        configuration.

        Args:
            rgb_batch (torch.Tensor): Batch of RGB images of shape ``(N, 3, H, W)``.
            flow_batch (torch.Tensor): Batch of optical flow images of shape
                ``(N, 2, H, W)``.
            regions (list[dict]): Region information per image in batch. Each dict
                contains bounding boxes of shape ``(M, 4)``.

        Returns:
            list[dict]: Feature dictionary per image in batch. Each dict contains
                the enabled feature types as keys with corresponding feature tensors
                as values.

        Example:
            >>> import torch
            >>> from anomalib.models.video.ai_vad.features import VideoRegionFeatureExtractor
            >>> extractor = VideoRegionFeatureExtractor()
            >>> rgb_batch = torch.randn(32, 3, 256, 256)  # (N, C, H, W)
            >>> flow_batch = torch.randn(32, 2, 256, 256)  # (N, 2, H, W)
            >>> regions = [{"boxes": torch.randn(5, 4)}] * 32  # List of region dicts
            >>> features = extractor(rgb_batch, flow_batch, regions)
            >>> features[0].keys()  # Features for first image
            dict_keys(['velocity', 'pose', 'deep'])
        
src/anomalib/models/video/ai_vad/features.py