code: def forward(self, df: pd.DataFrame) -> pd.DataFrame:
      def _forward(row: pd.Series) -> np.ndarray:
          # Prepare gray image to batched gray image within size.
          rgb_img = row[0]
          try_to_import_cv2()
          import cv2
  
          gray_img = cv2.cvtColor(rgb_img, cv2.COLOR_RGB2GRAY)
          resized_gray_img = cv2.resize(
              gray_img, (100, 100), interpolation=cv2.INTER_AREA
          )
          resized_gray_img = np.moveaxis(resized_gray_img, -1, 0)
          batch_resized_gray_img = np.expand_dims(
              resized_gray_img, axis=0
          )
          batch_resized_gray_img = np.expand_dims(
              batch_resized_gray_img, axis=0
          )
          batch_resized_gray_img = batch_resized_gray_img.astype(
              np.float32
          )
  
          try_to_import_torch()
          import torch
  
          # Sift inference.
          with torch.no_grad():
              torch_feat = self.model(
                  torch.from_numpy(batch_resized_gray_img)
              )
              feat = torch_feat.numpy()
  
          # Feature reshape.
          feat = feat.reshape(1, -1)
          return feat
  
      ret = pd.DataFrame()
      ret["features"] = df.apply(_forward, axis=1)
      return ret
  
file_path: evadb/evadb/functions/sift_feature_extractor.py
imports: import numpy
  import pandas
  from evadb.catalog.catalog_type import NdArrayType
  from evadb.functions.abstract.abstract_function import AbstractFunction
  from evadb.functions.decorators.decorators import forward, setup
  from evadb.functions.decorators.io_descriptors.data_types import PandasDataframe
  from evadb.functions.gpu_compatible import GPUCompatible
  from evadb.utils.generic_utils import try_to_import_cv2, try_to_import_kornia, try_to_import_torch
label_desc: Use image node_id 4 for calling the SiftFeatureExtractor obj's underlying member method code with example usage: obj.forward(df) and returns: ret, feat