From 7606618dfa61ac589e1aec0f4044d08722f7e141 Mon Sep 17 00:00:00 2001 From: enesozi Date: Mon, 27 May 2024 16:09:22 +0300 Subject: [PATCH 1/8] Mmdet TensorRtTsupport added --- sahi/models/base.py | 6 +++- sahi/models/mmdet.py | 80 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 79 insertions(+), 7 deletions(-) diff --git a/sahi/models/base.py b/sahi/models/base.py index d1cd227d0..aa5394ef4 100644 --- a/sahi/models/base.py +++ b/sahi/models/base.py @@ -15,6 +15,7 @@ def __init__( model_path: Optional[str] = None, model: Optional[Any] = None, config_path: Optional[str] = None, + deploy_config_path: Optional[str] = None, device: Optional[str] = None, mask_threshold: float = 0.5, confidence_threshold: float = 0.3, @@ -27,9 +28,11 @@ def __init__( Init object detection/instance segmentation model. Args: model_path: str - Path for the instance segmentation model weight + Path for the instance segmentation model weight, .engine file if it's tensorrt config_path: str Path for the mmdetection instance segmentation model config file + deploy_config_path: str + Path for the mmdetection detection/instance segmentation deployment config file device: str Torch device, "cpu" or "cuda" mask_threshold: float @@ -47,6 +50,7 @@ def __init__( """ self.model_path = model_path self.config_path = config_path + self.deploy_config_path = deploy_config_path self.model = None self.device = device self.mask_threshold = mask_threshold diff --git a/sahi/models/mmdet.py b/sahi/models/mmdet.py index fb7000ee4..83c4a7fa1 100644 --- a/sahi/models/mmdet.py +++ b/sahi/models/mmdet.py @@ -16,13 +16,67 @@ try: - check_requirements(["torch", "mmdet", "mmcv", "mmengine"]) + check_requirements(["torch", "mmdet", "mmcv", "mmengine", "mmdeploy"]) + import torch + from mmdeploy.apis.utils import build_task_processor + from mmdeploy.utils import get_input_shape, load_config from mmdet.apis.det_inferencer import DetInferencer from mmdet.utils import ConfigType from mmengine.dataset import Compose from mmengine.infer.infer import ModelType + class DetTrtInferencerWrapper: + def __init__(self, deploy_cfg: str, model_cfg: str, engine_file: str, device: Optional[str] = None) -> None: + """ + Emulate DetInferencer(images) for TensorRT model + Args: + deploy_cfg: str + Deployment cfg file, for example, detection_tensorrt-fp16_static-640x640.py. + model_cfg: str + Model cfg file, for example, rtmdet_l_8xb32-300e_coco.py + engine_file: str + Serialized TensorRT file, i.e end2end.engine + """ + deploy_cfg, model_cfg = load_config( + deploy_cfg, + model_cfg, + ) + self.task_processor = build_task_processor(model_cfg, deploy_cfg, device) + self.model = self.task_processor.build_backend_model( + [engine_file], self.task_processor.update_data_preprocessor + ) + self.input_shape = get_input_shape(deploy_cfg) + self.output_names = set(self.model.output_names) + + def __call__(self, images: List[np.ndarray], batch_size: int = 1) -> dict: + """ + Emulate DetInferencerWrapper(images) for TensorRT model + Args: + images: list of np.ndarray + A list of numpy array that contains the image to be predicted. 3 channel image should be in RGB order. + batch_size: int + Inference batch size. Defaults to 1. + """ + + def _tensor_to_list(tensor): + return tensor.tolist() if tensor.numel() > 0 else [] + + results_dict = {"predictions": [], "visualization": []} + for image in images: + model_inputs, _ = self.task_processor.create_input(image, self.input_shape) + with torch.no_grad(): + results = self.model.test_step(model_inputs)[0] + predictions = [ + { + "scores": _tensor_to_list(results.pred_instances.scores.cpu()), + "labels": _tensor_to_list(results.pred_instances.labels.cpu()), + "bboxes": _tensor_to_list(results.pred_instances.bboxes.cpu()), + } + ] + results_dict["predictions"].extend(predictions) + return results_dict + class DetInferencerWrapper(DetInferencer): def __init__( self, @@ -94,6 +148,7 @@ def __init__( model_path: Optional[str] = None, model: Optional[Any] = None, config_path: Optional[str] = None, + deploy_config_path: Optional[str] = None, device: Optional[str] = None, mask_threshold: float = 0.5, confidence_threshold: float = 0.3, @@ -108,11 +163,14 @@ def __init__( self.scope = scope self.image_size = image_size + # Check if tensorrt deploy cfg is defined + self.trt = deploy_config_path is not None super().__init__( model_path, model, config_path, + deploy_config_path, device, mask_threshold, confidence_threshold, @@ -129,11 +187,15 @@ def load_model(self): """ Detection model is initialized and set to self.model. """ - # create model - model = DetInferencerWrapper( - self.config_path, self.model_path, device=self.device, scope=self.scope, image_size=self.image_size - ) + if self.trt: + model = DetTrtInferencerWrapper( + self.deploy_config_path, self.config_path, self.model_path, device=self.device.type + ) + else: + model = DetInferencerWrapper( + self.config_path, self.model_path, device=self.device, scope=self.scope, image_size=self.image_size + ) self.set_model(model) @@ -148,6 +210,9 @@ def set_model(self, model: Any): # set self.model self.model = model + if self.trt and not self.category_mapping: + raise ValueError("TensorRT model needs category_mapping defined and passed to the constructor") + # set category_mapping if not self.category_mapping: category_mapping = {str(ind): category_name for ind, category_name in enumerate(self.category_names)} @@ -190,7 +255,10 @@ def has_mask(self): """ Returns if model output contains segmentation mask """ - has_mask = self.model.model.with_mask + if self.trt: + has_mask = "masks" in self.model.output_names + else: + has_mask = self.model.model.with_mask return has_mask @property From a229ac190a62aead808df9b663b8ccd544238e94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enes=20=C3=96zipek?= Date: Sun, 2 Jun 2024 23:35:00 +0300 Subject: [PATCH 2/8] mmdeploy requirement added --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c3214e572..9ba16575d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -89,6 +89,8 @@ jobs: pip install mmengine==0.7.3 pip install mmcv==2.0.0 -f https://download.openmmlab.com/mmcv/dist/cpu/torch1.13.0/index.html pip install mmdet==3.0.0 + pip install mmdeploy==1.3.1 + pip install mmdeploy-runtime==1.3.1 - name: Install YOLOv5(7.0.13) run: > From f7c4e8470883ff3e55686c77d2e838d641c4a3bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enes=20=C3=96zipek?= Date: Sun, 2 Jun 2024 23:38:05 +0300 Subject: [PATCH 3/8] mim required for mmdeploy --- .github/workflows/ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ba16575d..5bea1bb8a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -89,8 +89,9 @@ jobs: pip install mmengine==0.7.3 pip install mmcv==2.0.0 -f https://download.openmmlab.com/mmcv/dist/cpu/torch1.13.0/index.html pip install mmdet==3.0.0 - pip install mmdeploy==1.3.1 - pip install mmdeploy-runtime==1.3.1 + pip install -U openmim + mim install mmdeploy==1.3.1 + mim install mmdeploy-runtime==1.3.1 - name: Install YOLOv5(7.0.13) run: > From 3945ef52647648502082f577fbd58dba79d90265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enes=20=C3=96zipek?= Date: Mon, 3 Jun 2024 01:15:00 +0300 Subject: [PATCH 4/8] mmdeploy added as a new step --- .github/workflows/ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5bea1bb8a..f32d21f3d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -86,10 +86,13 @@ jobs: - name: Install MMDetection(3.0.0) with MMCV(2.0.0) run: > + pip install -U openmim==0.3.9 pip install mmengine==0.7.3 pip install mmcv==2.0.0 -f https://download.openmmlab.com/mmcv/dist/cpu/torch1.13.0/index.html pip install mmdet==3.0.0 - pip install -U openmim + + - name: Install MMDeploy(1.3.1) + run: > mim install mmdeploy==1.3.1 mim install mmdeploy-runtime==1.3.1 From 5ddaa5464e2f8c94c0843a3303f55bd26c706076 Mon Sep 17 00:00:00 2001 From: enesozi Date: Mon, 3 Jun 2024 11:20:37 +0300 Subject: [PATCH 5/8] mmdeploy added --- .github/workflows/package_testing.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/package_testing.yml b/.github/workflows/package_testing.yml index 58f6c9b5d..12a4e4695 100644 --- a/.github/workflows/package_testing.yml +++ b/.github/workflows/package_testing.yml @@ -64,10 +64,16 @@ jobs: - name: Install MMDetection(3.0.0) with MMCV(2.0.0) run: > + pip install -U openmim==0.3.9 pip install mmengine==0.7.3 pip install mmcv==2.0.0 -f https://download.openmmlab.com/mmcv/dist/cpu/torch1.13.0/index.html pip install mmdet==3.0.0 + - name: Install MMDeploy(1.3.1) + run: > + mim install mmdeploy==1.3.1 + mim install mmdeploy-runtime==1.3.1 + - name: Install YOLOv5(7.0.13) run: > pip install yolov5==7.0.13 From 8f80d36e3180f8b3ed5ca1b39b8f7d1b4f9dd72a Mon Sep 17 00:00:00 2001 From: "fatih c. akyon" <34196005+fcakyon@users.noreply.github.com> Date: Mon, 3 Jun 2024 15:28:00 +0300 Subject: [PATCH 6/8] run mmdeploy installation steps as two separate commands --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f32d21f3d..9f59be0dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,6 +94,7 @@ jobs: - name: Install MMDeploy(1.3.1) run: > mim install mmdeploy==1.3.1 + mim install mmdeploy-runtime==1.3.1 - name: Install YOLOv5(7.0.13) From b42fce65684ddfbdad34f91b4e80c9ca810abf0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enes=20=C3=96zipek?= Date: Tue, 18 Jun 2024 11:08:53 +0300 Subject: [PATCH 7/8] Config object kept in trt inferencer --- sahi/models/mmdet.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sahi/models/mmdet.py b/sahi/models/mmdet.py index 797e9ac79..3ea72402c 100644 --- a/sahi/models/mmdet.py +++ b/sahi/models/mmdet.py @@ -42,6 +42,7 @@ def __init__(self, deploy_cfg: str, model_cfg: str, engine_file: str, device: Op deploy_cfg, model_cfg, ) + self.cfg = model_cfg self.task_processor = build_task_processor(model_cfg, deploy_cfg, device) self.model = self.task_processor.build_backend_model( [engine_file], self.task_processor.update_data_preprocessor @@ -255,8 +256,6 @@ def has_mask(self): """ Returns if model output contains segmentation mask """ - - # has_mask = self.model.model.with_mask train_pipeline = self.model.cfg["train_dataloader"]["dataset"]["pipeline"] has_mask = any(isinstance(item, dict) and any("mask" in key for key in item.keys()) for item in train_pipeline) From 19323f25e6242fe2cdef7684f448d032b5a10400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enes=20=C3=96zipek?= Date: Thu, 27 Jun 2024 15:52:40 +0300 Subject: [PATCH 8/8] deploy_cfg arg moved to the end --- sahi/models/base.py | 2 +- sahi/models/mmdet.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sahi/models/base.py b/sahi/models/base.py index aa5394ef4..501364fde 100644 --- a/sahi/models/base.py +++ b/sahi/models/base.py @@ -15,7 +15,6 @@ def __init__( model_path: Optional[str] = None, model: Optional[Any] = None, config_path: Optional[str] = None, - deploy_config_path: Optional[str] = None, device: Optional[str] = None, mask_threshold: float = 0.5, confidence_threshold: float = 0.3, @@ -23,6 +22,7 @@ def __init__( category_remapping: Optional[Dict] = None, load_at_init: bool = True, image_size: int = None, + deploy_config_path: Optional[str] = None, ): """ Init object detection/instance segmentation model. diff --git a/sahi/models/mmdet.py b/sahi/models/mmdet.py index 3ea72402c..b582cc99b 100644 --- a/sahi/models/mmdet.py +++ b/sahi/models/mmdet.py @@ -171,7 +171,6 @@ def __init__( model_path, model, config_path, - deploy_config_path, device, mask_threshold, confidence_threshold, @@ -179,6 +178,7 @@ def __init__( category_remapping, load_at_init, image_size, + deploy_config_path, ) def check_dependencies(self):