{"id":20465624,"url":"https://github.com/kadirnar/sahi-learn","last_synced_at":"2025-07-07T02:35:00.454Z","repository":{"id":43255306,"uuid":"467429691","full_name":"kadirnar/sahi-learn","owner":"kadirnar","description":"Bu repo SAHI uygulamasını mantığını öğreniyoruz.","archived":false,"fork":false,"pushed_at":"2022-03-11T19:06:23.000Z","size":20154,"stargazers_count":12,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-27T00:22:43.588Z","etag":null,"topics":["deep-learning","machine-learning","pytorch","sahi"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kadirnar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-03-08T08:41:42.000Z","updated_at":"2024-09-27T22:52:37.000Z","dependencies_parsed_at":"2022-09-15T19:32:17.656Z","dependency_job_id":null,"html_url":"https://github.com/kadirnar/sahi-learn","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kadirnar%2Fsahi-learn","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kadirnar%2Fsahi-learn/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kadirnar%2Fsahi-learn/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kadirnar%2Fsahi-learn/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kadirnar","download_url":"https://codeload.github.com/kadirnar/sahi-learn/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248687740,"owners_count":21145760,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deep-learning","machine-learning","pytorch","sahi"],"created_at":"2024-11-15T13:19:15.427Z","updated_at":"2025-04-13T08:44:06.523Z","avatar_url":"https://github.com/kadirnar.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\u003ch1\u003e\n  SAHI-Learn: SAHI'den Beraber Kodlamak İster Misiniz\n\u003c/h1\u003e\n\u003ch4\u003e\n    \u003cimg width=\"700\" alt=\"teaser\" src=\"obss.png\"\u003e\n\u003c/h4\u003e\n\n\u003c/div\u003e\n\nHerkese merhabalar ben Kadir Nar. SAHI kütüphanesine gönüllü geliştiriciyim. \nBu repo SAHI kütüphanesine yeni bir model nasıl ekleneceğini anlattım.\n\n### Geliştiriciler için SAHI Yol Haritası\n\n- [DetectionModel(Detection)](#1-detectionmodeldetection)\u003cbr/\u003e\n- [load_model():](#2load_model)\u003cbr/\u003e\n- [perform_inference():](#3perform_inference)\u003cbr/\u003e\n- [num_categories():](#4num_categories)\u003cbr/\u003e\n- [has_mask():](#5has_mask)\u003cbr/\u003e\n- [category_names():](#6category_names)\u003cbr/\u003e\n- [_create_object_prediction_list_from_original_predictions():](#7_create_object_prediction_list_from_original_predictions)\u003cbr/\u003e\n\n\n### 1. DetectionModel(Detection) \nClass ismini oluştururkan model isminin yanına DetectionModel(Detection) yazıyoruz.\n\n### Örnekler:\n\n1.1 Mmdet:\n```\nclass MmdetDetectionModel(DetectionModel)\n```\n1.2 Yolov5:\n```\nclass Yolov5DetectionModel(DetectionModel):\n```\n1.3 Detectron2:\n```\nclass Detectron2DetectionModel(DetectionModel)\n```\n1.4 TorchVision:\n```\nclass TorchVisionDetectionModel(DetectionModel)\n```\n\n### 2.load_model(): \nBu fonksiyon 3 aşamadan oluşmaktadır.\n\na. Kütüphaneyi import ediyoruz. PYPI desteği olmayan kütüphanelerin kurulumunu desteklenmiyor.\n\nb. Modele girecek resimlerin image_size değerlerini güncellemeniz gerekiyor.\n\nc. category_mapping değişkenini {\"1\": \"pedestrian\"} bu formatta olması gerekiyor.\n\n### Örnekler:\n\n2.1 Mmdet:\n\n```\ndef load_model(self):\n    \"\"\"\n    Detection model is initialized and set to self.model.\n    \"\"\"\n    try:\n        import mmdet\n    except ImportError:\n        raise ImportError(\n            'Please run \"pip install -U mmcv mmdet\" ' \"to install MMDetection first for MMDetection inference.\"\n        )\n\n    from mmdet.apis import init_detector\n\n    # create model\n    model = init_detector(\n        config=self.config_path,\n        checkpoint=self.model_path,\n        device=self.device,\n    )\n\n    # update model image size\n    if self.image_size is not None:\n        model.cfg.data.test.pipeline[1][\"img_scale\"] = (self.image_size, self.image_size)\n\n    # set self.model\n    self.model = model\n\n    # set category_mapping\n    if not self.category_mapping:\n        category_mapping = {str(ind): category_name for ind, category_name in enumerate(self.category_names)}\n        self.category_mapping = category_mapping\n```\n2.2 Yolov5:\n```\n    def load_model(self):\n        \"\"\"\n        Detection model is initialized and set to self.model.\n        \"\"\"\n        try:\n            import yolov5\n        except ImportError:\n            raise ImportError('Please run \"pip install -U yolov5\" ' \"to install YOLOv5 first for YOLOv5 inference.\")\n\n        # set model\n        try:\n            model = yolov5.load(self.model_path, device=self.device)\n            model.conf = self.confidence_threshold\n            self.model = model\n        except Exception as e:\n            TypeError(\"model_path is not a valid yolov5 model path: \", e)\n\n        # set category_mapping\n        if not self.category_mapping:\n            category_mapping = {str(ind): category_name for ind, category_name in enumerate(self.category_names)}\n            self.category_mapping = category_mapping\n```\n2.3 Detectron2:\n```\ndef load_model(self):\n    try:\n        import detectron2\n    except ImportError:\n        raise ImportError(\n            \"Please install detectron2. Check \"\n            \"`https://detectron2.readthedocs.io/en/latest/tutorials/install.html` \"\n            \"for instalattion details.\"\n        )\n\n    from detectron2.config import get_cfg\n    from detectron2.data import MetadataCatalog\n    from detectron2.engine import DefaultPredictor\n    from detectron2.model_zoo import model_zoo\n\n    cfg = get_cfg()\n    cfg.MODEL.DEVICE = self.device\n\n    try:  # try to load from model zoo\n        config_file = model_zoo.get_config_file(self.config_path)\n        cfg.merge_from_file(config_file)\n        cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url(self.config_path)\n    except Exception as e:  # try to load from local\n        print(e)\n        if self.config_path is not None:\n            cfg.merge_from_file(self.config_path)\n        cfg.MODEL.WEIGHTS = self.model_path\n    # set input image size\n    if self.image_size is not None:\n        cfg.INPUT.MIN_SIZE_TEST = self.image_size\n        cfg.INPUT.MAX_SIZE_TEST = self.image_size\n    # init predictor\n    model = DefaultPredictor(cfg)\n\n    self.model = model\n\n    # detectron2 category mapping\n    if self.category_mapping is None:\n        try:  # try to parse category names from metadata\n            metadata = MetadataCatalog.get(cfg.DATASETS.TRAIN[0])\n            category_names = metadata.thing_classes\n            self.category_names = category_names\n            self.category_mapping = {\n                str(ind): category_name for ind, category_name in enumerate(self.category_names)\n            }\n        except Exception as e:\n            logger.warning(e)\n            # https://detectron2.readthedocs.io/en/latest/tutorials/datasets.html#update-the-config-for-new-datasets\n            if cfg.MODEL.META_ARCHITECTURE == \"RetinaNet\":\n                num_categories = cfg.MODEL.RETINANET.NUM_CLASSES\n            else:  # fasterrcnn/maskrcnn etc\n                num_categories = cfg.MODEL.ROI_HEADS.NUM_CLASSES\n            self.category_names = [str(category_id) for category_id in range(num_categories)]\n            self.category_mapping = {\n                str(ind): category_name for ind, category_name in enumerate(self.category_names)\n            }\n    else:\n        self.category_names = list(self.category_mapping.values())\n```\n2.4 TorchVision:\n```\ndef load_model(self):\n    try:\n        import torchvision\n    except ImportError:\n        raise ImportError(\n            \"torchvision is not installed. Please run 'pip install -U torchvision to use this \"\n            \"torchvision models'\"\n        )\n\n    # set model\n    try:\n        from sahi.utils.torch import torch\n\n        model = self.config_path\n        model.load_state_dict(torch.load(self.model_path))\n        model.eval()\n        model = model.to(self.device)\n        self.model = model\n    except Exception as e:\n        raise Exception(f\"Failed to load model from {self.model_path}. {e}\")\n\n    # set category_mapping\n    from sahi.utils.torchvision import COCO_CLASSES\n\n    if self.category_mapping is None:\n        category_names = {str(i): COCO_CLASSES[i] for i in range(len(COCO_CLASSES))}\n        self.category_mapping = category_names\n```\n\n\n### 3.perform_inference():\nBu fonksiyonda 3 aşamada oluşmaktadır.\n\na. Kütüphanenin import edilmesi gerekiyor.\n\nb. Resimlerin size değerinin güncellenmesi lazım.\n\nc. Modelin tahmin kodlarının yazılması gerekiyor.\n\n3.1 Mmdet:\n```\ndef perform_inference(self, image: np.ndarray, image_size: int = None):\n    \"\"\"\n    Prediction is performed using self.model and the prediction result is set to self._original_predictions.\n    Args:\n        image: np.ndarray\n            A numpy array that contains the image to be predicted. 3 channel image should be in RGB order.\n        image_size: int\n            Inference input size.\n    \"\"\"\n    try:\n        import mmdet\n    except ImportError:\n        raise ImportError(\n            'Please run \"pip install -U mmcv mmdet\" ' \"to install MMDetection first for MMDetection inference.\"\n        )\n\n    # Confirm model is loaded\n    assert self.model is not None, \"Model is not loaded, load it by calling .load_model()\"\n\n    # Supports only batch of 1\n    from mmdet.apis import inference_detector\n\n    # update model image size\n    if image_size is not None:\n        warnings.warn(\"Set 'image_size' at DetectionModel init.\", DeprecationWarning)\n        self.model.cfg.data.test.pipeline[1][\"img_scale\"] = (image_size, image_size)\n\n    # perform inference\n    if isinstance(image, np.ndarray):\n        # https://github.com/obss/sahi/issues/265\n        image = image[:, :, ::-1]\n    # compatibility with sahi v0.8.15\n    if not isinstance(image, list):\n        image = [image]\n    prediction_result = inference_detector(self.model, image)\n\n    self._original_predictions = prediction_result\n\n```\n3.2 Yolov5:\n```\ndef perform_inference(self, image: np.ndarray, image_size: int = None):\n    \"\"\"\n    Prediction is performed using self.model and the prediction result is set to self._original_predictions.\n    Args:\n        image: np.ndarray\n            A numpy array that contains the image to be predicted. 3 channel image should be in RGB order.\n        image_size: int\n            Inference input size.\n    \"\"\"\n    try:\n        import yolov5\n    except ImportError:\n        raise ImportError('Please run \"pip install -U yolov5\" ' \"to install YOLOv5 first for YOLOv5 inference.\")\n\n    # Confirm model is loaded\n    assert self.model is not None, \"Model is not loaded, load it by calling .load_model()\"\n\n    if image_size is not None:\n        warnings.warn(\"Set 'image_size' at DetectionModel init.\", DeprecationWarning)\n        prediction_result = self.model(image, size=image_size)\n    elif self.image_size is not None:\n        prediction_result = self.model(image, size=self.image_size)\n    else:\n        prediction_result = self.model(image)\n\n    self._original_predictions = prediction_result\n\n```\n3.3 Detectron2:\n```\ndef perform_inference(self, image: np.ndarray, image_size: int = None):\n    \"\"\"\n    Prediction is performed using self.model and the prediction result is set to self._original_predictions.\n    Args:\n        image: np.ndarray\n            A numpy array that contains the image to be predicted. 3 channel image should be in RGB order.\n    \"\"\"\n    try:\n        import detectron2\n    except ImportError:\n        raise ImportError(\"Please install detectron2 via `pip install detectron2`\")\n\n    # confirm image_size is not provided\n    if image_size is not None:\n        warnings.warn(\"Set 'image_size' at DetectionModel init.\")\n\n    # Confirm model is loaded\n    if self.model is None:\n        raise RuntimeError(\"Model is not loaded, load it by calling .load_model()\")\n\n    if isinstance(image, np.ndarray) and self.model.input_format == \"BGR\":\n        # convert RGB image to BGR format\n        image = image[:, :, ::-1]\n\n    prediction_result = self.model(image)\n\n    self._original_predictions = prediction_result\n```\n3.4 TorchVision:\n```\ndef perform_inference(self, image: np.ndarray, image_size: int = None):\n    \"\"\"\n    Prediction is performed using self.model and the prediction result is set to self._original_predictions.\n    Args:\n        image: np.ndarray\n            A numpy array that contains the image to be predicted. 3 channel image should be in RGB order.\n        image_size: int\n            Inference input size.\n    \"\"\"\n    if self.model is None:\n        raise ValueError(\"model not loaded.\")\n\n    from sahi.utils.torchvision import numpy_to_torch, resize_image\n\n    if self.image_size is not None:\n        image = resize_image(image, self.image_size)\n        image = numpy_to_torch(image)\n        prediction_result = self.model([image])\n\n    else:\n        prediction_result = self.model([image])\n\n    self._original_predictions = prediction_result\n```\n\n\n### 4.num_categories(): \nBu fonksiyonda tahmin edilen kategorilerin sayısını döndürmesi isteniyor.\n\n4.1 Mmdet:\n```\ndef num_categories(self):\n    \"\"\"\n    Returns number of categories\n    \"\"\"\n    if isinstance(self.model.CLASSES, str):\n        num_categories = 1\n    else:\n        num_categories = len(self.model.CLASSES)\n    return num_categories\n```\n4.2 Yolov5:\n```\ndef num_categories(self):\n    \"\"\"\n    Returns number of categories\n    \"\"\"\n    return len(self.model.names)\n```\n4.3 Detectron2:\n```\ndef num_categories(self):\n    \"\"\"\n    Returns number of categories\n    \"\"\"\n    num_categories = len(self.category_mapping)\n    return num_categories\n```\n4.4 TorchVision:\n```\ndef num_categories(self):\n    \"\"\"\n    Returns number of categories\n    \"\"\"\n    return len(self.category_mapping)\n```\n\n### 5.has_mask():\nBu fonksiyonda tahmin edilen kategorilerin maskleri olup olmadığını döndürmesi isteniyor.\n\n5.1 Mmdet:\n```\ndef has_mask(self):\n    \"\"\"\n    Returns if model output contains segmentation mask\n    \"\"\"\n    has_mask = self.model.with_mask\n    return has_mask```\n5.2 Yolov5:\n```\n5.2 Yolov5:\n```\ndef has_mask(self):\n    \"\"\"\n    Returns if model output contains segmentation mask\n    \"\"\"\n    has_mask = self.model.with_mask\n    return has_mask\n```\n5.3 Detectron2:\n```\nif get_bbox_from_bool_mask(mask) is not None:\n    bbox = None\nelse:\n    continue\n```\n5.4 TorchVision:\n```\ndef has_mask(self):\n    \"\"\"\n    Returns if model output contains segmentation mask\n    \"\"\"\n    return self.model.with_mask\n```\n\n### 6.category_names():\nBu fonksiyonda tahmin edilen kategorilerin isimlerini döndürmesi isteniyor.\n\n6.1 Mmdet:\n```\ndef category_names(self):\n    if type(self.model.CLASSES) == str:\n        # https://github.com/open-mmlab/mmdetection/pull/4973\n        return (self.model.CLASSES,)\n    else:\n        return self.model.CLASSES\n```\n6.2 Yolov5:\n```\ndef category_names(self):\n    return self.model.names\n```\n6.3 Detectron2:\n```\n# detectron2 category mapping\nif self.category_mapping is None:\n    try:  # try to parse category names from metadata\n        metadata = MetadataCatalog.get(cfg.DATASETS.TRAIN[0])\n        category_names = metadata.thing_classes\n        self.category_names = category_names\n```\n6.4 TorchVision:\n```\ndef category_names(self):\n    return self.category_mapping\n```\n\n### 7._create_object_prediction_list_from_original_predictions():\nBu fonksiyon da bir şablon üzerinden kodlama yapmanız sizin için daha rahat olacaktır. Fonksiyonunu altına direk bunu yazabilirsiniz.\n```\noriginal_predictions = self._original_predictions\n\n# compatilibty for sahi v0.8.15\nif isinstance(shift_amount_list[0], int):\n    shift_amount_list = [shift_amount_list]\nif full_shape_list is not None and isinstance(full_shape_list[0], int):\n    full_shape_list = [full_shape_list]\n```\nBundan sonra modeliniz tahminleme yaptıktan sonra bbox,mask,category_id, category_name ve score değerleri döndürmesi isteniyor. \nBu değerleri object_prediction değişkeninin içindeki none değerleri yerine yazmanız gerekiyor. Aşağıdaki şablon yapısını da bozmamanız istenmektedir.\n\n```\n    object_prediction = ObjectPrediction(\n        bbox=None,\n        bool_mask=None,\n        category_id=None,\n        category_name=sNone,\n        shift_amount=shift_amount,\n        score=None,\n        full_shape=full_shape,\n    )\n    object_prediction_list.append(object_prediction)\n\n# detectron2 DefaultPredictor supports single image\nobject_prediction_list_per_image = [object_prediction_list]\n\nself._object_prediction_list_per_image = object_prediction_list_per_image\n\n```\n\n7.1 Mmdet:\n```\ndef _create_object_prediction_list_from_original_predictions(\n    self,\n    shift_amount_list: Optional[List[List[int]]] = [[0, 0]],\n    full_shape_list: Optional[List[List[int]]] = None,\n):\n    \"\"\"\n    self._original_predictions is converted to a list of prediction.ObjectPrediction and set to\n    self._object_prediction_list_per_image.\n    Args:\n        shift_amount_list: list of list\n            To shift the box and mask predictions from sliced image to full sized image, should\n            be in the form of List[[shift_x, shift_y],[shift_x, shift_y],...]\n        full_shape_list: list of list\n            Size of the full image after shifting, should be in the form of\n            List[[height, width],[height, width],...]\n    \"\"\"\n    original_predictions = self._original_predictions\n    category_mapping = self.category_mapping\n\n    # compatilibty for sahi v0.8.15\n    shift_amount_list = fix_shift_amount_list(shift_amount_list)\n    full_shape_list = fix_full_shape_list(full_shape_list)\n\n    # parse boxes and masks from predictions\n    num_categories = self.num_categories\n    object_prediction_list_per_image = []\n    for image_ind, original_prediction in enumerate(original_predictions):\n        shift_amount = shift_amount_list[image_ind]\n        full_shape = None if full_shape_list is None else full_shape_list[image_ind]\n\n        if self.has_mask:\n            boxes = original_prediction[0]\n            masks = original_prediction[1]\n        else:\n            boxes = original_prediction\n\n        object_prediction_list = []\n\n        # process predictions\n        for category_id in range(num_categories):\n            category_boxes = boxes[category_id]\n            if self.has_mask:\n                category_masks = masks[category_id]\n            num_category_predictions = len(category_boxes)\n\n            for category_predictions_ind in range(num_category_predictions):\n                bbox = category_boxes[category_predictions_ind][:4]\n                score = category_boxes[category_predictions_ind][4]\n                category_name = category_mapping[str(category_id)]\n\n                # ignore low scored predictions\n                if score \u003c self.confidence_threshold:\n                    continue\n\n                # parse prediction mask\n                if self.has_mask:\n                    bool_mask = category_masks[category_predictions_ind]\n                else:\n                    bool_mask = None\n\n                # fix negative box coords\n                bbox[0] = max(0, bbox[0])\n                bbox[1] = max(0, bbox[1])\n                bbox[2] = max(0, bbox[2])\n                bbox[3] = max(0, bbox[3])\n\n                # fix out of image box coords\n                if full_shape is not None:\n                    bbox[0] = min(full_shape[1], bbox[0])\n                    bbox[1] = min(full_shape[0], bbox[1])\n                    bbox[2] = min(full_shape[1], bbox[2])\n                    bbox[3] = min(full_shape[0], bbox[3])\n\n                # ignore invalid predictions\n                if not (bbox[0] \u003c bbox[2]) or not (bbox[1] \u003c bbox[3]):\n                    logger.warning(f\"ignoring invalid prediction with bbox: {bbox}\")\n                    continue\n\n                object_prediction = ObjectPrediction(\n                    bbox=bbox,\n                    category_id=category_id,\n                    score=score,\n                    bool_mask=bool_mask,\n                    category_name=category_name,\n                    shift_amount=shift_amount,\n                    full_shape=full_shape,\n                )\n                object_prediction_list.append(object_prediction)\n        object_prediction_list_per_image.append(object_prediction_list)\n    self._object_prediction_list_per_image = object_prediction_list_per_image\n```\n7.2 Yolov5:\n```\ndef _create_object_prediction_list_from_original_predictions(\n    self,\n    shift_amount_list: Optional[List[List[int]]] = [[0, 0]],\n    full_shape_list: Optional[List[List[int]]] = None,\n):\n    \"\"\"\n    self._original_predictions is converted to a list of prediction.ObjectPrediction and set to\n    self._object_prediction_list_per_image.\n    Args:\n        shift_amount_list: list of list\n            To shift the box and mask predictions from sliced image to full sized image, should\n            be in the form of List[[shift_x, shift_y],[shift_x, shift_y],...]\n        full_shape_list: list of list\n            Size of the full image after shifting, should be in the form of\n            List[[height, width],[height, width],...]\n    \"\"\"\n    original_predictions = self._original_predictions\n\n    # compatilibty for sahi v0.8.15\n    shift_amount_list = fix_shift_amount_list(shift_amount_list)\n    full_shape_list = fix_full_shape_list(full_shape_list)\n\n    # handle all predictions\n    object_prediction_list_per_image = []\n    for image_ind, image_predictions_in_xyxy_format in enumerate(original_predictions.xyxy):\n        shift_amount = shift_amount_list[image_ind]\n        full_shape = None if full_shape_list is None else full_shape_list[image_ind]\n        object_prediction_list = []\n\n        # process predictions\n        for prediction in image_predictions_in_xyxy_format.cpu().detach().numpy():\n            x1 = int(prediction[0])\n            y1 = int(prediction[1])\n            x2 = int(prediction[2])\n            y2 = int(prediction[3])\n            bbox = [x1, y1, x2, y2]\n            score = prediction[4]\n            category_id = int(prediction[5])\n            category_name = self.category_mapping[str(category_id)]\n\n            # fix negative box coords\n            bbox[0] = max(0, bbox[0])\n            bbox[1] = max(0, bbox[1])\n            bbox[2] = max(0, bbox[2])\n            bbox[3] = max(0, bbox[3])\n\n            # fix out of image box coords\n            if full_shape is not None:\n                bbox[0] = min(full_shape[1], bbox[0])\n                bbox[1] = min(full_shape[0], bbox[1])\n                bbox[2] = min(full_shape[1], bbox[2])\n                bbox[3] = min(full_shape[0], bbox[3])\n\n            # ignore invalid predictions\n            if not (bbox[0] \u003c bbox[2]) or not (bbox[1] \u003c bbox[3]):\n                logger.warning(f\"ignoring invalid prediction with bbox: {bbox}\")\n                continue\n\n            object_prediction = ObjectPrediction(\n                bbox=bbox,\n                category_id=category_id,\n                score=score,\n                bool_mask=None,\n                category_name=category_name,\n                shift_amount=shift_amount,\n                full_shape=full_shape,\n            )\n            object_prediction_list.append(object_prediction)\n        object_prediction_list_per_image.append(object_prediction_list)\n\n    self._object_prediction_list_per_image = object_prediction_list_per_image\n```\n7.3 Detectron2:\n```\ndef _create_object_prediction_list_from_original_predictions(\n    self,\n    shift_amount_list: Optional[List[List[int]]] = [[0, 0]],\n    full_shape_list: Optional[List[List[int]]] = None,\n):\n    \"\"\"\n    self._original_predictions is converted to a list of prediction.ObjectPrediction and set to\n    self._object_prediction_list_per_image.\n    Args:\n        shift_amount_list: list of list\n            To shift the box and mask predictions from sliced image to full sized image, should\n            be in the form of List[[shift_x, shift_y],[shift_x, shift_y],...]\n        full_shape_list: list of list\n            Size of the full image after shifting, should be in the form of\n            List[[height, width],[height, width],...]\n    \"\"\"\n    original_predictions = self._original_predictions\n\n    # compatilibty for sahi v0.8.15\n    if isinstance(shift_amount_list[0], int):\n        shift_amount_list = [shift_amount_list]\n    if full_shape_list is not None and isinstance(full_shape_list[0], int):\n        full_shape_list = [full_shape_list]\n\n    # parse boxes, masks, scores, category_ids from predictions\n    boxes = original_predictions[\"instances\"].pred_boxes.tensor.tolist()\n    scores = original_predictions[\"instances\"].scores.tolist()\n    category_ids = original_predictions[\"instances\"].pred_classes.tolist()\n\n    # check if predictions contain mask\n    try:\n        masks = original_predictions[\"instances\"].pred_masks.tolist()\n    except AttributeError:\n        masks = None\n\n    # create object_prediction_list\n    object_prediction_list_per_image = []\n    object_prediction_list = []\n\n    # detectron2 DefaultPredictor supports single image\n    shift_amount = shift_amount_list[0]\n    full_shape = None if full_shape_list is None else full_shape_list[0]\n\n    for ind in range(len(boxes)):\n        score = scores[ind]\n        if score \u003c self.confidence_threshold:\n            continue\n\n        category_id = category_ids[ind]\n\n        if masks is None:\n            bbox = boxes[ind]\n            mask = None\n        else:\n            mask = np.array(masks[ind])\n\n            # check if mask is valid\n            if get_bbox_from_bool_mask(mask) is not None:\n                bbox = None\n            else:\n                continue\n\n        object_prediction = ObjectPrediction(\n            bbox=bbox,\n            bool_mask=mask,\n            category_id=category_id,\n            category_name=self.category_mapping[str(category_id)],\n            shift_amount=shift_amount,\n            score=score,\n            full_shape=full_shape,\n        )\n        object_prediction_list.append(object_prediction)\n\n    # detectron2 DefaultPredictor supports single image\n    object_prediction_list_per_image = [object_prediction_list]\n\n    self._object_prediction_list_per_image = object_prediction_list_per_image\n```\n7.4 TorchVision:\nNot: TorchVision kütüphanesinin geliştirilmeye devam etmektedir.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkadirnar%2Fsahi-learn","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkadirnar%2Fsahi-learn","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkadirnar%2Fsahi-learn/lists"}