code: def mmcv_runner_creator(cfg):
      from mmdet.datasets.builder import DATASETS
      from mmdet.datasets.custom import CustomDataset
      from mmdet.models import build_detector
      from mmdet.utils import (
          compat_cfg,
          find_latest_checkpoint,
          get_root_logger,
      )
      from mmdet.core import DistEvalHook, EvalHook, build_optimizer
      from mmcv.runner import (
          DistSamplerSeedHook,
          EpochBasedRunner,
          Fp16OptimizerHook,
          OptimizerHook,
          build_runner,
      )
  
      @DATASETS.register_module()
      class KittiTinyDataset(CustomDataset):
          CLASSES = ("Car", "Pedestrian", "Cyclist")
  
          def load_annotations(self, ann_file):
              cat2label = {k: i for i, k in enumerate(self.CLASSES)}
              # load image list from file
              image_list = mmcv.list_from_file(self.ann_file)
  
              data_infos = []
              # convert annotations to middle format
              for image_id in image_list:
                  filename = f"{self.img_prefix}/{image_id}.jpeg"
                  image = mmcv.imread(filename)
                  height, width = image.shape[:2]
  
                  data_info = dict(
                      filename=f"{image_id}.jpeg",
                      width=width,
                      height=height,
                  )
  
                  # load annotations
                  label_prefix = self.img_prefix.replace(
                      "image_2", "label_2"
                  )
                  lines = mmcv.list_from_file(
                      osp.join(label_prefix, f"{image_id}.txt")
                  )
  
                  content = [line.strip().split(" ") for line in lines]
                  bbox_names = [x[0] for x in content]
                  bboxes = [
                      [float(info) for info in x[4:8]] for x in content
                  ]
  
                  gt_bboxes = []
                  gt_labels = []
                  gt_bboxes_ignore = []
                  gt_labels_ignore = []
  
                  # filter 'DontCare'
                  for bbox_name, bbox in zip(bbox_names, bboxes):
                      if bbox_name in cat2label:
                          gt_labels.append(cat2label[bbox_name])
                          gt_bboxes.append(bbox)
                      else:
                          gt_labels_ignore.append(-1)
                          gt_bboxes_ignore.append(bbox)
  
                  data_anno = dict(
                      bboxes=np.array(
                          gt_bboxes, dtype=np.float32
                      ).reshape(-1, 4),
                      labels=np.array(gt_labels, dtype=int),
                      bboxes_ignore=np.array(
                          gt_bboxes_ignore, dtype=np.float32
                      ).reshape(-1, 4),
                      labels_ignore=np.array(
                          gt_labels_ignore, dtype=int
                      ),
                  )
  
                  data_info.update(ann=data_anno)
                  data_infos.append(data_info)
  
              return data_infos
  
      model = build_detector(cfg.model)
  
      cfg = compat_cfg(cfg)
      logger = get_root_logger(log_level=cfg.log_level)
  
      distributed = cfg.distributed
      validate = cfg.validate
  
      optimizer = build_optimizer(model, cfg.optimizer)
  
      runner = build_runner(
          cfg.runner,
          default_args=dict(
              model=model,
              optimizer=optimizer,
              work_dir=cfg.work_dir,
              logger=logger,
              meta=None,
          ),
      )
  
      # fp16 setting
      fp16_cfg = cfg.get("fp16", None)
      if fp16_cfg is None and cfg.get("device", None) == "npu":
          fp16_cfg = dict(loss_scale="dynamic")
      if fp16_cfg is not None:
          optimizer_config = Fp16OptimizerHook(
              **cfg.optimizer_config,
              **fp16_cfg,
              distributed=distributed,
          )
      elif distributed and "type" not in cfg.optimizer_config:
          optimizer_config = OptimizerHook(**cfg.optimizer_config)
      else:
          optimizer_config = cfg.optimizer_config
  
      # register hooks
      runner.register_training_hooks(
          cfg.lr_config,
          optimizer_config,
          cfg.checkpoint_config,
          cfg.log_config,
          cfg.get("momentum_config", None),
          custom_hooks_config=cfg.get("custom_hooks", None),
      )
  
      if distributed:
          if isinstance(runner, EpochBasedRunner):
              runner.register_hook(DistSamplerSeedHook())
      if validate:
          val_dataloader_default_args = dict(
              samples_per_gpu=1,
              workers_per_gpu=0,
              dist=distributed,
              shuffle=False,
              persistent_workers=False,
          )
  
          val_dataloader_args = {
              **val_dataloader_default_args,
              **cfg.data.get("val_dataloader", {}),
          }
          # Support batch_size > 1 in validation
  
          if val_dataloader_args["samples_per_gpu"] > 1:
              # Replace 'ImageToTensor' to 'DefaultFormatBundle'
              cfg.data.val.pipeline = replace_ImageToTensor(
                  cfg.data.val.pipeline
              )
          val_dataset = build_dataset(
              cfg.data.val, dict(test_mode=True)
          )
  
          val_dataloader = build_dataloader(
              val_dataset, **val_dataloader_args
          )
          eval_cfg = cfg.get("evaluation", {})
          eval_cfg["by_epoch"] = cfg.runner["type"] != "IterBasedRunner"
          eval_hook = DistEvalHook if distributed else EvalHook
          runner.register_hook(
              eval_hook(val_dataloader, **eval_cfg), priority="LOW"
          )
  
      resume_from = None
      if cfg.resume_from is None and cfg.get("auto_resume"):
          resume_from = find_latest_checkpoint(cfg.work_dir)
      if resume_from is not None:
          cfg.resume_from = resume_from
  
      if cfg.resume_from:
          runner.resume(cfg.resume_from)
      elif cfg.load_from:
          runner.load_checkpoint(cfg.load_from)
  
      return runner
  
file_path: BigDL/python/orca/example/learn/mmcv/faster_rcnn/train.py
imports: import argparse
  import os
  import numpy
  import os.path
  from os.path import exists, join
  from bigdl.orca import init_orca_context, stop_orca_context
  from bigdl.orca.data.file import get_remote_dir_to_local
  from bigdl.orca.learn.pytorch.experimential.mmcv.mmcv_ray_estimator import MMCVRayEstimator
  import mmcv
  from mmcv import Config
  from mmdet.apis import set_random_seed
  from mmdet.datasets import build_dataloader, build_dataset, replace_ImageToTensor
label_desc: Use image node_id 1 for calling a global function with example usage: mmcv_runner_creator(cfg) and returns: runner, data_infos