PytorchWildlife 1.2.3__tar.gz → 1.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pytorchwildlife-1.2.3/PytorchWildlife.egg-info → pytorchwildlife-1.2.4}/PKG-INFO +37 -7
- pytorchwildlife-1.2.4/PytorchWildlife/models/detection/__init__.py +4 -0
- pytorchwildlife-1.2.4/PytorchWildlife/models/detection/rtdetr_apache/__init__.py +2 -0
- pytorchwildlife-1.2.4/PytorchWildlife/models/detection/rtdetr_apache/megadetectorv6_apache.py +44 -0
- pytorchwildlife-1.2.4/PytorchWildlife/models/detection/rtdetr_apache/rtdetr_apache_base.py +225 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/ultralytics_based/yolov5_base.py +0 -1
- pytorchwildlife-1.2.4/PytorchWildlife/models/detection/yolo_mit/__init__.py +2 -0
- pytorchwildlife-1.2.4/PytorchWildlife/models/detection/yolo_mit/megadetectorv6_mit.py +44 -0
- pytorchwildlife-1.2.4/PytorchWildlife/models/detection/yolo_mit/yolo/__init__.py +15 -0
- pytorchwildlife-1.2.4/PytorchWildlife/models/detection/yolo_mit/yolo/config.py +168 -0
- pytorchwildlife-1.2.4/PytorchWildlife/models/detection/yolo_mit/yolo_mit_base.py +220 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4/PytorchWildlife.egg-info}/PKG-INFO +37 -7
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife.egg-info/SOURCES.txt +8 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/README.md +35 -5
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/setup.py +2 -2
- pytorchwildlife-1.2.3/PytorchWildlife/models/detection/__init__.py +0 -2
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/LICENSE.md +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PW_FT_classification/__init__.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PW_FT_classification/main.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/__init__.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/data/__init__.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/data/datasets.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/data/transforms.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/__init__.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/classification/__init__.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/classification/base_classifier.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/classification/resnet_base/__init__.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/classification/resnet_base/amazon.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/classification/resnet_base/base_classifier.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/classification/resnet_base/custom_weights.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/classification/resnet_base/opossum.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/classification/resnet_base/serengeti.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/classification/timm_base/DFNE.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/classification/timm_base/Deepfaune.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/classification/timm_base/__init__.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/classification/timm_base/base_classifier.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/base_detector.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/herdnet/__init__.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/herdnet/animaloc/__init__.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/herdnet/animaloc/data/__init__.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/herdnet/animaloc/data/patches.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/herdnet/animaloc/data/types.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/herdnet/animaloc/eval/__init__.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/herdnet/animaloc/eval/lmds.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/herdnet/animaloc/eval/stitchers.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/herdnet/dla.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/herdnet/herdnet.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/herdnet/model.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/ultralytics_based/Deepfaune.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/ultralytics_based/__init__.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/ultralytics_based/megadetectorv5.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/ultralytics_based/megadetectorv6.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/ultralytics_based/megadetectorv6_distributed.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/ultralytics_based/yolov8_base.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/ultralytics_based/yolov8_distributed.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/utils/__init__.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/utils/misc.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/utils/post_process.py +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife.egg-info/dependency_links.txt +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife.egg-info/requires.txt +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife.egg-info/top_level.txt +0 -0
- {pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/setup.cfg +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PytorchWildlife
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.4
|
|
4
4
|
Summary: a PyTorch Collaborative Deep Learning Framework for Conservation.
|
|
5
5
|
Home-page: https://github.com/microsoft/CameraTraps/
|
|
6
6
|
Author: Andres Hernandez, Zhongqi Miao, Daniela Ruiz Lopez, Isai Daniel Chacon Silva
|
|
7
|
-
Author-email: v-
|
|
7
|
+
Author-email: v-hernandres@microsoft.com, zhongqimiao@microsoft.com, v-druizlopez@microsoft.com, v-ichaconsil@microsoft.com
|
|
8
8
|
License: MIT
|
|
9
9
|
Keywords: pytorch_wildlife,pytorch,wildlife,megadetector,conservation,animal,detection,classification
|
|
10
10
|
Classifier: Development Status :: 3 - Alpha
|
|
@@ -63,16 +63,46 @@ Dynamic: summary
|
|
|
63
63
|
|
|
64
64
|
## 📣 Announcements
|
|
65
65
|
|
|
66
|
-
###
|
|
66
|
+
### 🚀 We’re Open for Contributions!
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
We’re excited to announce that **Pytorch-Wildlife** is now open to community contributions!
|
|
69
|
+
If you’d like to get involved and help improve the project, we’d love to have you on board.
|
|
69
70
|
|
|
70
|
-
|
|
71
|
+
👉 **Check out our Contribution Guidelines:**
|
|
71
72
|
|
|
72
|
-
|
|
73
|
+
[📚 How to Participate](https://microsoft.github.io/CameraTraps/contribute/#how-to-participate)
|
|
73
74
|
|
|
74
|
-
|
|
75
|
+
You’ll find everything you need there — from how to pick an issue, to submitting your first pull request.
|
|
76
|
+
Let’s build this together! 🐾🌱
|
|
75
77
|
|
|
78
|
+
### V 1.2.4
|
|
79
|
+
|
|
80
|
+
The inference code for the MIT YOLO and Apache RT‑DETR models is now available! To use either one, just load it like any other PyTorch‑Wildlife model:
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from pw_detection import MegaDetectorV6MIT, MegaDetectorV6Apache
|
|
84
|
+
|
|
85
|
+
# MIT YOLO
|
|
86
|
+
detector = MegaDetectorV6MIT(
|
|
87
|
+
device=DEVICE,
|
|
88
|
+
pretrained=True,
|
|
89
|
+
version="MDV6-mit-yolov9-e"
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
# Apache RT‑DETR
|
|
93
|
+
detector = MegaDetectorV6Apache(
|
|
94
|
+
device=DEVICE,
|
|
95
|
+
pretrained=True,
|
|
96
|
+
version="MDV6-apa-rtdetr-e"
|
|
97
|
+
)
|
|
98
|
+
```
|
|
99
|
+
Valid versions:
|
|
100
|
+
- MDV6-mit-yolov9-c
|
|
101
|
+
- MDV6-mit-yolov9-e
|
|
102
|
+
- MDV6-apa-rtdetr-c
|
|
103
|
+
- MDV6-apa-rtdetr-e
|
|
104
|
+
|
|
105
|
+
You can also try out the full pipeline using the `detection_classification_pipeline_demo.py` script in the demo folder.
|
|
76
106
|
|
|
77
107
|
#### Previous versions:
|
|
78
108
|
- [What's New](https://microsoft.github.io/CameraTraps/releases/release_notes/)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
|
|
2
|
+
from .rtdetr_apache_base import RTDETRApacheBase
|
|
3
|
+
|
|
4
|
+
__all__ = [
|
|
5
|
+
'MegaDetectorV6Apache'
|
|
6
|
+
]
|
|
7
|
+
|
|
8
|
+
class MegaDetectorV6Apache(RTDETRApacheBase):
|
|
9
|
+
"""
|
|
10
|
+
MegaDetectorV6 is a specialized class derived from the RTDETRApacheBase class
|
|
11
|
+
that is specifically designed for detecting animals, persons, and vehicles.
|
|
12
|
+
|
|
13
|
+
Attributes:
|
|
14
|
+
CLASS_NAMES (dict): Mapping of class IDs to their respective names.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
CLASS_NAMES = {
|
|
18
|
+
0: "animal",
|
|
19
|
+
1: "person",
|
|
20
|
+
2: "vehicle"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
def __init__(self, weights=None, device="cpu", pretrained=True, version='MDV6-rtdetr-x-apache'):
|
|
24
|
+
"""
|
|
25
|
+
Initializes the MegaDetectorV6 model with the option to load pretrained weights.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
weights (str, optional): Path to the weights file.
|
|
29
|
+
device (str, optional): Device to load the model on (e.g., "cpu" or "cuda"). Default is "cpu".
|
|
30
|
+
pretrained (bool, optional): Whether to load the pretrained model. Default is True.
|
|
31
|
+
version (str, optional): Version of the model to load. Default is 'MDV6-rtdetr-x-apache'.
|
|
32
|
+
"""
|
|
33
|
+
self.IMAGE_SIZE = 640
|
|
34
|
+
|
|
35
|
+
if version == "MDV6-apa-rtdetr-c":
|
|
36
|
+
url = "https://zenodo.org/records/15398270/files/MDV6-apa-rtdetr-c.pth?download=1"
|
|
37
|
+
self.MODEL_NAME = "MDV6-apa-rtdetr-c.pth"
|
|
38
|
+
elif version == "MDV6-apa-rtdetr-e":
|
|
39
|
+
url = "https://zenodo.org/records/15398270/files/MDV6-apa-rtdetr-e.pth?download=1"
|
|
40
|
+
self.MODEL_NAME = "MDV6-apa-rtdetr-e.pth"
|
|
41
|
+
else:
|
|
42
|
+
raise ValueError('Select a valid model version: MDV6-apa-rtdetr-c or MDV6-apa-rtdetr-e')
|
|
43
|
+
|
|
44
|
+
super(MegaDetectorV6Apache, self).__init__(weights=weights, device=device, url=url)
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
""" RT-DETR Apache base detector class. """
|
|
5
|
+
|
|
6
|
+
# Importing basic libraries
|
|
7
|
+
import os
|
|
8
|
+
import supervision as sv
|
|
9
|
+
import wget
|
|
10
|
+
import torch
|
|
11
|
+
import torch.nn as nn
|
|
12
|
+
import torchvision.transforms as T
|
|
13
|
+
|
|
14
|
+
from ..base_detector import BaseDetector
|
|
15
|
+
from ....data import datasets as pw_data
|
|
16
|
+
from PIL import Image
|
|
17
|
+
|
|
18
|
+
import sys
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
project_root = Path(__file__).resolve().parent
|
|
21
|
+
sys.path.append(str(project_root))
|
|
22
|
+
from rtdetrv2_pytorch.src.core import YAMLConfig
|
|
23
|
+
|
|
24
|
+
class RTDETRApacheBase(BaseDetector):
|
|
25
|
+
"""
|
|
26
|
+
Base detector class for RTDETRApacheBase framework. This class provides utility methods for
|
|
27
|
+
loading the model, generating results, and performing single and batch image detections.
|
|
28
|
+
"""
|
|
29
|
+
def __init__(self, weights=None, device="cpu", url=None):
|
|
30
|
+
"""
|
|
31
|
+
Initialize the RT-DETR apache detector.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
weights (str, optional):
|
|
35
|
+
Path to the model weights. Defaults to None.
|
|
36
|
+
device (str, optional):
|
|
37
|
+
Device for model inference. Defaults to "cpu".
|
|
38
|
+
url (str, optional):
|
|
39
|
+
URL to fetch the model weights. Defaults to None.
|
|
40
|
+
"""
|
|
41
|
+
self.transform = T.Compose([
|
|
42
|
+
T.Resize((640, 640)),
|
|
43
|
+
T.ToTensor(),
|
|
44
|
+
])
|
|
45
|
+
self.weights = weights
|
|
46
|
+
self.device = device
|
|
47
|
+
self.url = url
|
|
48
|
+
super(RTDETRApacheBase, self).__init__(weights=self.weights, device=self.device, url=self.url)
|
|
49
|
+
self._load_model(weights=self.weights, device=self.device, url=self.url)
|
|
50
|
+
|
|
51
|
+
def _load_model(self, weights=None, device="cpu", url=None):
|
|
52
|
+
"""
|
|
53
|
+
Load the RT-DETR apache model weights.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
weights (str, optional):
|
|
57
|
+
Path to the model weights. Defaults to None.
|
|
58
|
+
device (str, optional):
|
|
59
|
+
Device for model inference. Defaults to "cpu".
|
|
60
|
+
url (str, optional):
|
|
61
|
+
URL to fetch the model weights. Defaults to None.
|
|
62
|
+
Raises:
|
|
63
|
+
Exception: If weights are not provided.
|
|
64
|
+
"""
|
|
65
|
+
if weights:
|
|
66
|
+
resume = weights
|
|
67
|
+
elif url:
|
|
68
|
+
if not os.path.exists(os.path.join(torch.hub.get_dir(), "checkpoints", self.MODEL_NAME)):
|
|
69
|
+
os.makedirs(os.path.join(torch.hub.get_dir(), "checkpoints"), exist_ok=True)
|
|
70
|
+
resume = wget.download(url, out=os.path.join(torch.hub.get_dir(), "checkpoints"))
|
|
71
|
+
else:
|
|
72
|
+
resume = os.path.join(torch.hub.get_dir(), "checkpoints", self.MODEL_NAME)
|
|
73
|
+
else:
|
|
74
|
+
raise Exception("Need weights for inference.")
|
|
75
|
+
|
|
76
|
+
if self.MODEL_NAME == "MDV6-apa-rtdetr-c.pth":
|
|
77
|
+
config = os.path.join(project_root, "rtdetrv2_pytorch/configs/rtdetrv2/rtdetrv2_r18vd_120e_megadetector.yml")
|
|
78
|
+
elif self.MODEL_NAME == "MDV6-apa-rtdetr-e.pth":
|
|
79
|
+
config = os.path.join(project_root, "rtdetrv2_pytorch/configs/rtdetrv2/rtdetrv2_r101vd_6x_megadetector.yml")
|
|
80
|
+
else:
|
|
81
|
+
raise ValueError('Select a valid model version: MDV6-apa-rtdetr-c or MDV6-apa-rtdetr-e')
|
|
82
|
+
|
|
83
|
+
cfg = YAMLConfig(config, resume=resume)
|
|
84
|
+
|
|
85
|
+
checkpoint = torch.load(resume, map_location='cpu')
|
|
86
|
+
if 'ema' in checkpoint:
|
|
87
|
+
state = checkpoint['ema']['module']
|
|
88
|
+
else:
|
|
89
|
+
state = checkpoint['model']
|
|
90
|
+
|
|
91
|
+
cfg.model.load_state_dict(state)
|
|
92
|
+
|
|
93
|
+
class Model(nn.Module):
|
|
94
|
+
def __init__(self, ) -> None:
|
|
95
|
+
super().__init__()
|
|
96
|
+
self.model = cfg.model.deploy()
|
|
97
|
+
self.postprocessor = cfg.postprocessor.deploy()
|
|
98
|
+
|
|
99
|
+
def forward(self, images, orig_target_sizes):
|
|
100
|
+
outputs = self.model(images)
|
|
101
|
+
outputs = self.postprocessor(outputs, orig_target_sizes)
|
|
102
|
+
return outputs
|
|
103
|
+
|
|
104
|
+
self.model = Model().to(self.device)
|
|
105
|
+
|
|
106
|
+
def results_generation(self, preds, img_id, id_strip=None):
|
|
107
|
+
"""
|
|
108
|
+
Generate results for detection based on model predictions.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
preds (List[torch.Tensor]):
|
|
112
|
+
Model predictions.
|
|
113
|
+
img_id (str):
|
|
114
|
+
Image identifier.
|
|
115
|
+
id_strip (str, optional):
|
|
116
|
+
Strip specific characters from img_id. Defaults to None.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
dict: Dictionary containing image ID, detections, and labels.
|
|
120
|
+
"""
|
|
121
|
+
class_id = preds[0].cpu().numpy().astype(int)
|
|
122
|
+
xyxy = preds[1].detach().cpu().numpy()
|
|
123
|
+
confidence = preds[2].detach().cpu().numpy()
|
|
124
|
+
|
|
125
|
+
results = {"img_id": str(img_id).strip(id_strip)}
|
|
126
|
+
results["detections"] = sv.Detections(
|
|
127
|
+
xyxy=xyxy,
|
|
128
|
+
confidence=confidence,
|
|
129
|
+
class_id=class_id
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
results["labels"] = [
|
|
133
|
+
f"{self.CLASS_NAMES[class_id]} {confidence:0.2f}"
|
|
134
|
+
for _, _, confidence, class_id, _, _ in results["detections"]
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
return results
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def single_image_detection(self, img, img_path=None, det_conf_thres=0.2, id_strip=None):
|
|
141
|
+
"""
|
|
142
|
+
Perform detection on a single image.
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
img (str or ndarray):
|
|
146
|
+
Image path or ndarray of images.
|
|
147
|
+
img_path (str, optional):
|
|
148
|
+
Image path or identifier.
|
|
149
|
+
det_conf_thres (float, optional):
|
|
150
|
+
Confidence threshold for predictions. Defaults to 0.2.
|
|
151
|
+
id_strip (str, optional):
|
|
152
|
+
Characters to strip from img_id. Defaults to None.
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
dict: Detection results.
|
|
156
|
+
"""
|
|
157
|
+
if type(img) == str:
|
|
158
|
+
if img_path is None:
|
|
159
|
+
img_path = img
|
|
160
|
+
im_pil = Image.open(img_path).convert('RGB')
|
|
161
|
+
else:
|
|
162
|
+
im_pil = Image.fromarray(img)
|
|
163
|
+
|
|
164
|
+
w, h = im_pil.size
|
|
165
|
+
orig_size = torch.tensor([w, h])[None].to(self.device)
|
|
166
|
+
im_data = self.transform(im_pil)[None].to(self.device)
|
|
167
|
+
labels, boxes, scores = self.model(im_data, orig_size)
|
|
168
|
+
|
|
169
|
+
scr = scores[0]
|
|
170
|
+
lab = labels[0][scr > det_conf_thres]
|
|
171
|
+
box = boxes[0][scr > det_conf_thres]
|
|
172
|
+
scrs = scores[0][scr > det_conf_thres]
|
|
173
|
+
|
|
174
|
+
return self.results_generation([lab, box, scrs], img_path, id_strip)
|
|
175
|
+
|
|
176
|
+
def batch_image_detection(self, data_path, batch_size=16, det_conf_thres=0.2, id_strip=None):
|
|
177
|
+
"""
|
|
178
|
+
Perform detection on a batch of images.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
data_path (str):
|
|
182
|
+
Path containing all images for inference.
|
|
183
|
+
batch_size (int, optional):
|
|
184
|
+
Batch size for inference. Defaults to 16.
|
|
185
|
+
det_conf_thres (float, optional):
|
|
186
|
+
Confidence threshold for predictions. Defaults to 0.2.
|
|
187
|
+
id_strip (str, optional):
|
|
188
|
+
Characters to strip from img_id. Defaults to None.
|
|
189
|
+
extension (str, optional):
|
|
190
|
+
Image extension to search for. Defaults to "JPG"
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
list: List of detection results for all images.
|
|
194
|
+
"""
|
|
195
|
+
dataset = pw_data.DetectionImageFolder(
|
|
196
|
+
data_path,
|
|
197
|
+
transform=self.transform,
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
results = []
|
|
201
|
+
for i in range(len(dataset)):
|
|
202
|
+
im_pil = Image.open(dataset.images[i]).convert('RGB')
|
|
203
|
+
w, h = im_pil.size
|
|
204
|
+
orig_size = torch.tensor([w, h])[None].to(self.device)
|
|
205
|
+
im_data = self.transform(im_pil)[None].to(self.device)
|
|
206
|
+
|
|
207
|
+
labels, boxes, scores = self.model(im_data, orig_size)
|
|
208
|
+
|
|
209
|
+
scr = scores[0]
|
|
210
|
+
lab = labels[0][scr > det_conf_thres]
|
|
211
|
+
box = boxes[0][scr > det_conf_thres]
|
|
212
|
+
scrs = scores[0][scr > det_conf_thres]
|
|
213
|
+
|
|
214
|
+
res = self.results_generation([lab, box, scrs], dataset.images[i], id_strip)
|
|
215
|
+
|
|
216
|
+
# Normalize the coordinates for timelapse compatibility
|
|
217
|
+
size = orig_size[0].cpu().numpy()
|
|
218
|
+
normalized_coords = [[x1 / size[1], y1 / size[0], x2 / size[1], y2 / size[0]] for x1, y1, x2, y2 in res["detections"].xyxy]
|
|
219
|
+
res["normalized_coords"] = normalized_coords
|
|
220
|
+
results.append(res)
|
|
221
|
+
|
|
222
|
+
return results
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
|
|
@@ -15,7 +15,6 @@ from torch.utils.data import DataLoader
|
|
|
15
15
|
from torch.hub import load_state_dict_from_url
|
|
16
16
|
|
|
17
17
|
from yolov5.utils.general import non_max_suppression, scale_boxes
|
|
18
|
-
# from .yolov5_utils import non_max_suppression, scale_boxes
|
|
19
18
|
from ..base_detector import BaseDetector
|
|
20
19
|
from ....data import transforms as pw_trans
|
|
21
20
|
from ....data import datasets as pw_data
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
|
|
2
|
+
from .yolo_mit_base import YOLOMITBase
|
|
3
|
+
|
|
4
|
+
__all__ = [
|
|
5
|
+
'MegaDetectorV6MIT'
|
|
6
|
+
]
|
|
7
|
+
|
|
8
|
+
class MegaDetectorV6MIT(YOLOMITBase):
|
|
9
|
+
"""
|
|
10
|
+
MegaDetectorV6 is a specialized class derived from the YOLOMITBase class
|
|
11
|
+
that is specifically designed for detecting animals, persons, and vehicles.
|
|
12
|
+
|
|
13
|
+
Attributes:
|
|
14
|
+
CLASS_NAMES (dict): Mapping of class IDs to their respective names.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
CLASS_NAMES = {
|
|
18
|
+
0: "animal",
|
|
19
|
+
1: "person",
|
|
20
|
+
2: "vehicle"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
def __init__(self, weights=None, device="cpu", pretrained=True, version='MDV6-yolov9-c-mit'):
|
|
24
|
+
"""
|
|
25
|
+
Initializes the MegaDetectorV6 model with the option to load pretrained weights.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
weights (str, optional): Path to the weights file.
|
|
29
|
+
device (str, optional): Device to load the model on (e.g., "cpu" or "cuda"). Default is "cpu".
|
|
30
|
+
pretrained (bool, optional): Whether to load the pretrained model. Default is True.
|
|
31
|
+
version (str, optional): Version of the model to load. Default is 'MDV6-yolov9-c-mit'.
|
|
32
|
+
"""
|
|
33
|
+
self.IMAGE_SIZE = 640
|
|
34
|
+
|
|
35
|
+
if version == 'MDV6-mit-yolov9-c':
|
|
36
|
+
url = "https://zenodo.org/records/15398270/files/MDV6-mit-yolov9-c.ckpt?download=1"
|
|
37
|
+
self.MODEL_NAME = "MDV6-mit-yolov9-c.ckpt"
|
|
38
|
+
elif version == 'MDV6-mit-yolov9-e':
|
|
39
|
+
url = "https://zenodo.org/records/15398270/files/MDV6-mit-yolov9-e.ckpt?download=1"
|
|
40
|
+
self.MODEL_NAME = "MDV6-mit-yolov9-e.ckpt"
|
|
41
|
+
else:
|
|
42
|
+
raise ValueError('Select a valid model version: MDV6-mit-yolov9-c or MDV6-mit-yolov9-e')
|
|
43
|
+
|
|
44
|
+
super(MegaDetectorV6MIT, self).__init__(weights=weights, device=device, url=url)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from yolo.model.yolo import create_model
|
|
2
|
+
from yolo.config import Config, NMSConfig
|
|
3
|
+
from yolo.tools.data_loader import AugmentationComposer, create_dataloader
|
|
4
|
+
from yolo.utils.model_utils import PostProcess
|
|
5
|
+
from yolo.utils.bounding_box_utils import create_converter
|
|
6
|
+
|
|
7
|
+
all = [
|
|
8
|
+
"create_model",
|
|
9
|
+
"Config",
|
|
10
|
+
"NMSConfig",
|
|
11
|
+
"AugmentationComposer"
|
|
12
|
+
"create_dataloader",
|
|
13
|
+
"PostProcess",
|
|
14
|
+
"create_converter",
|
|
15
|
+
]
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Any, Dict, List, Optional, Union
|
|
3
|
+
from torch import nn
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@dataclass
|
|
7
|
+
class AnchorConfig:
|
|
8
|
+
strides: List[int]
|
|
9
|
+
reg_max: Optional[int]
|
|
10
|
+
anchor_num: Optional[int]
|
|
11
|
+
anchor: List[List[int]]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class LayerConfg:
|
|
16
|
+
args: Dict
|
|
17
|
+
source: Union[int, str, List[int]]
|
|
18
|
+
tags: str
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class BlockConfig:
|
|
23
|
+
block: List[Dict[str, LayerConfg]]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class ModelConfig:
|
|
28
|
+
name: Optional[str]
|
|
29
|
+
anchor: AnchorConfig
|
|
30
|
+
model: Dict[str, BlockConfig]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass
|
|
34
|
+
class DownloadDetail:
|
|
35
|
+
url: str
|
|
36
|
+
file_size: int
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
class DownloadOptions:
|
|
41
|
+
details: Dict[str, DownloadDetail]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass
|
|
45
|
+
class DatasetConfig:
|
|
46
|
+
path: str
|
|
47
|
+
class_num: int
|
|
48
|
+
class_list: List[str]
|
|
49
|
+
auto_download: Optional[DownloadOptions]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass
|
|
53
|
+
class DataConfig:
|
|
54
|
+
shuffle: bool
|
|
55
|
+
batch_size: int
|
|
56
|
+
pin_memory: bool
|
|
57
|
+
cpu_num: int
|
|
58
|
+
image_size: List[int]
|
|
59
|
+
data_augment: Dict[str, int]
|
|
60
|
+
source: Optional[Union[str, int]]
|
|
61
|
+
dynamic_shape: Optional[bool]
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@dataclass
|
|
65
|
+
class OptimizerArgs:
|
|
66
|
+
lr: float
|
|
67
|
+
weight_decay: float
|
|
68
|
+
momentum: float
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass
|
|
72
|
+
class OptimizerConfig:
|
|
73
|
+
type: str
|
|
74
|
+
args: OptimizerArgs
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@dataclass
|
|
78
|
+
class MatcherConfig:
|
|
79
|
+
iou: str
|
|
80
|
+
topk: int
|
|
81
|
+
factor: Dict[str, int]
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@dataclass
|
|
85
|
+
class LossConfig:
|
|
86
|
+
objective: Dict[str, int]
|
|
87
|
+
aux: Union[bool, float]
|
|
88
|
+
matcher: MatcherConfig
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@dataclass
|
|
92
|
+
class SchedulerConfig:
|
|
93
|
+
type: str
|
|
94
|
+
warmup: Dict[str, Union[int, float]]
|
|
95
|
+
args: Dict[str, Any]
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@dataclass
|
|
99
|
+
class EMAConfig:
|
|
100
|
+
enable: bool
|
|
101
|
+
decay: float
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@dataclass
|
|
105
|
+
class NMSConfig:
|
|
106
|
+
min_confidence: float
|
|
107
|
+
min_iou: float
|
|
108
|
+
max_bbox: int
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
@dataclass
|
|
112
|
+
class InferenceConfig:
|
|
113
|
+
task: str
|
|
114
|
+
nms: NMSConfig
|
|
115
|
+
data: DataConfig
|
|
116
|
+
fast_inference: Optional[None]
|
|
117
|
+
save_predict: bool
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@dataclass
|
|
121
|
+
class ValidationConfig:
|
|
122
|
+
task: str
|
|
123
|
+
nms: NMSConfig
|
|
124
|
+
data: DataConfig
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@dataclass
|
|
128
|
+
class TrainConfig:
|
|
129
|
+
task: str
|
|
130
|
+
epoch: int
|
|
131
|
+
data: DataConfig
|
|
132
|
+
optimizer: OptimizerConfig
|
|
133
|
+
loss: LossConfig
|
|
134
|
+
scheduler: SchedulerConfig
|
|
135
|
+
ema: EMAConfig
|
|
136
|
+
validation: ValidationConfig
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@dataclass
|
|
140
|
+
class Config:
|
|
141
|
+
task: Union[TrainConfig, InferenceConfig, ValidationConfig]
|
|
142
|
+
dataset: DatasetConfig
|
|
143
|
+
model: ModelConfig
|
|
144
|
+
name: str
|
|
145
|
+
|
|
146
|
+
device: Union[str, int, List[int]]
|
|
147
|
+
cpu_num: int
|
|
148
|
+
|
|
149
|
+
image_size: List[int]
|
|
150
|
+
|
|
151
|
+
out_path: str
|
|
152
|
+
exist_ok: bool
|
|
153
|
+
|
|
154
|
+
lucky_number: 10
|
|
155
|
+
use_wandb: bool
|
|
156
|
+
use_tensorboard: bool
|
|
157
|
+
|
|
158
|
+
weight: Optional[str]
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
@dataclass
|
|
162
|
+
class YOLOLayer(nn.Module):
|
|
163
|
+
source: Union[int, str, List[int]]
|
|
164
|
+
output: bool
|
|
165
|
+
tags: str
|
|
166
|
+
layer_type: str
|
|
167
|
+
usable: bool
|
|
168
|
+
external: Optional[dict]
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
""" Yolo mit base detector class. """
|
|
5
|
+
|
|
6
|
+
# Importing basic libraries
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import supervision as sv
|
|
10
|
+
import numpy as np
|
|
11
|
+
from PIL import Image
|
|
12
|
+
import wget
|
|
13
|
+
import torch
|
|
14
|
+
|
|
15
|
+
from ..base_detector import BaseDetector
|
|
16
|
+
from ....data import datasets as pw_data
|
|
17
|
+
|
|
18
|
+
import sys
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
from lightning import Trainer
|
|
22
|
+
import yaml
|
|
23
|
+
from omegaconf import OmegaConf
|
|
24
|
+
|
|
25
|
+
project_root = Path(__file__).resolve().parent
|
|
26
|
+
sys.path.append(str(project_root))
|
|
27
|
+
|
|
28
|
+
from yolo import create_model, create_converter, PostProcess, AugmentationComposer
|
|
29
|
+
|
|
30
|
+
class YOLOMITBase(BaseDetector):
|
|
31
|
+
"""
|
|
32
|
+
Base detector class for YOLO MIT framework. This class provides utility methods for
|
|
33
|
+
loading the model, generating results, and performing single and batch image detections.
|
|
34
|
+
"""
|
|
35
|
+
def __init__(self, weights=None, device="cpu", url=None):
|
|
36
|
+
"""
|
|
37
|
+
Initialize the YOLO MIT detector.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
weights (str, optional):
|
|
41
|
+
Path to the model weights. Defaults to None.
|
|
42
|
+
device (str, optional):
|
|
43
|
+
Device for model inference. Defaults to "cpu".
|
|
44
|
+
url (str, optional):
|
|
45
|
+
URL to fetch the model weights. Defaults to None.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
self.cfg = self._load_cfg()
|
|
49
|
+
self.transform = AugmentationComposer([], self.cfg.image_size, self.cfg.image_size[0])
|
|
50
|
+
self.weights = weights
|
|
51
|
+
self.device = device
|
|
52
|
+
self.url = url
|
|
53
|
+
super(YOLOMITBase, self).__init__(weights=self.weights, device=self.device, url=self.url)
|
|
54
|
+
|
|
55
|
+
def _load_cfg(self):
|
|
56
|
+
if self.MODEL_NAME == "MDV6-mit-yolov9-c.ckpt":
|
|
57
|
+
if not os.path.exists(os.path.join(torch.hub.get_dir(), "checkpoints", "config_v9s.yaml")):
|
|
58
|
+
os.makedirs(os.path.join(torch.hub.get_dir(), "checkpoints"), exist_ok=True)
|
|
59
|
+
url = "https://zenodo.org/records/15178680/files/config_v9s.yaml?download=1"
|
|
60
|
+
config_path = wget.download(url, out=os.path.join(torch.hub.get_dir(), "checkpoints"))
|
|
61
|
+
else:
|
|
62
|
+
config_path = os.path.join(torch.hub.get_dir(), "checkpoints", "config_v9s.yaml")
|
|
63
|
+
elif self.MODEL_NAME == "MDV6-mit-yolov9-e.ckpt":
|
|
64
|
+
if not os.path.exists(os.path.join(torch.hub.get_dir(), "checkpoints", "config_v9c.yaml")):
|
|
65
|
+
os.makedirs(os.path.join(torch.hub.get_dir(), "checkpoints"), exist_ok=True)
|
|
66
|
+
url = "https://zenodo.org/records/15178680/files/config_v9c.yaml?download=1"
|
|
67
|
+
config_path = wget.download(url, out=os.path.join(torch.hub.get_dir(), "checkpoints"))
|
|
68
|
+
else:
|
|
69
|
+
config_path = os.path.join(torch.hub.get_dir(), "checkpoints", "config_v9c.yaml")
|
|
70
|
+
|
|
71
|
+
with open(config_path, 'r') as f:
|
|
72
|
+
cfg_dict = yaml.safe_load(f)
|
|
73
|
+
|
|
74
|
+
return OmegaConf.create(cfg_dict)
|
|
75
|
+
|
|
76
|
+
def _load_model(self, weights=None, device="cpu", url=None):
|
|
77
|
+
"""
|
|
78
|
+
Load the YOLO MIT model weights.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
weights (str, optional):
|
|
82
|
+
Path to the model weights. Defaults to None.
|
|
83
|
+
device (str, optional):
|
|
84
|
+
Device for model inference. Defaults to "cpu".
|
|
85
|
+
url (str, optional):
|
|
86
|
+
URL to fetch the model weights. Defaults to None.
|
|
87
|
+
Raises:
|
|
88
|
+
Exception: If weights are not provided.
|
|
89
|
+
"""
|
|
90
|
+
if url:
|
|
91
|
+
if not os.path.exists(os.path.join(torch.hub.get_dir(), "checkpoints", self.MODEL_NAME)):
|
|
92
|
+
os.makedirs(os.path.join(torch.hub.get_dir(), "checkpoints"), exist_ok=True)
|
|
93
|
+
weights = wget.download(url, out=os.path.join(torch.hub.get_dir(), "checkpoints"))
|
|
94
|
+
else:
|
|
95
|
+
weights = os.path.join(torch.hub.get_dir(), "checkpoints", self.MODEL_NAME)
|
|
96
|
+
else:
|
|
97
|
+
raise Exception("Need weights for inference.")
|
|
98
|
+
|
|
99
|
+
self.cfg.image_size = [self.IMAGE_SIZE, self.IMAGE_SIZE]
|
|
100
|
+
self.model = create_model(self.cfg.model, weight_path=weights, class_num=3).to(self.device)
|
|
101
|
+
self.converter = create_converter(self.cfg.model.name, self.model, self.cfg.model.anchor, self.cfg.image_size, self.device)
|
|
102
|
+
self.post_proccess = PostProcess(self.converter, self.cfg.task.nms)
|
|
103
|
+
|
|
104
|
+
def results_generation(self, preds, img_id, id_strip=None):
|
|
105
|
+
"""
|
|
106
|
+
Generate results for detection based on model predictions.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
preds (List[torch.Tensor]):
|
|
110
|
+
Model predictions.
|
|
111
|
+
img_id (str):
|
|
112
|
+
Image identifier.
|
|
113
|
+
id_strip (str, optional):
|
|
114
|
+
Strip specific characters from img_id. Defaults to None.
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
dict: Dictionary containing image ID, detections, and labels.
|
|
118
|
+
"""
|
|
119
|
+
#preds: [cls, x1, y1, x2, y2, conf]
|
|
120
|
+
class_id = preds[0][:,0].cpu().numpy().astype(int)
|
|
121
|
+
xyxy = preds[0][:,1:5].cpu().numpy()
|
|
122
|
+
confidence = preds[0][:,5].cpu().numpy()
|
|
123
|
+
|
|
124
|
+
results = {"img_id": str(img_id).strip(id_strip)}
|
|
125
|
+
results["detections"] = sv.Detections(
|
|
126
|
+
xyxy=xyxy,
|
|
127
|
+
confidence=confidence,
|
|
128
|
+
class_id=class_id
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
results["labels"] = [
|
|
132
|
+
f"{self.CLASS_NAMES[class_id]} {confidence:0.2f}"
|
|
133
|
+
for _, _, confidence, class_id, _, _ in results["detections"]
|
|
134
|
+
]
|
|
135
|
+
results
|
|
136
|
+
return results
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def single_image_detection(self, img, img_path=None, det_conf_thres=0.2, id_strip=None):
|
|
140
|
+
"""
|
|
141
|
+
Perform detection on a single image.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
img (str or ndarray):
|
|
145
|
+
Image path or ndarray of images.
|
|
146
|
+
img_path (str, optional):
|
|
147
|
+
Image path or identifier.
|
|
148
|
+
det_conf_thres (float, optional):
|
|
149
|
+
Confidence threshold for predictions. Defaults to 0.2.
|
|
150
|
+
id_strip (str, optional):
|
|
151
|
+
Characters to strip from img_id. Defaults to None.
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
dict: Detection results.
|
|
155
|
+
"""
|
|
156
|
+
self.cfg.task.data.source = img_path
|
|
157
|
+
self.cfg.task.nms.min_confidence = det_conf_thres
|
|
158
|
+
self._load_model(weights=self.weights, device=self.device, url=self.url)
|
|
159
|
+
|
|
160
|
+
if type(img) == str:
|
|
161
|
+
if img_path is None:
|
|
162
|
+
img_path = img
|
|
163
|
+
im_pil = Image.open(img_path).convert('RGB')
|
|
164
|
+
else:
|
|
165
|
+
im_pil = Image.fromarray(img)
|
|
166
|
+
|
|
167
|
+
image, bbox, rev_tensor = self.transform(im_pil)
|
|
168
|
+
image = image.to(self.device)[None]
|
|
169
|
+
rev_tensor = rev_tensor.to(self.device)[None]
|
|
170
|
+
|
|
171
|
+
with torch.no_grad():
|
|
172
|
+
predict = self.model(image)
|
|
173
|
+
det_results = self.post_proccess(predict, rev_tensor) #pred_box: [cls, x1, y1, x2, y2, conf]
|
|
174
|
+
|
|
175
|
+
return self.results_generation(det_results, img_path, id_strip)
|
|
176
|
+
|
|
177
|
+
def batch_image_detection(self, data_path, batch_size=16, det_conf_thres=0.2, id_strip=None):
|
|
178
|
+
"""
|
|
179
|
+
Perform detection on a batch of images.
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
data_path (str):
|
|
183
|
+
Path containing all images for inference.
|
|
184
|
+
batch_size (int, optional):
|
|
185
|
+
Batch size for inference. Defaults to 16.
|
|
186
|
+
det_conf_thres (float, optional):
|
|
187
|
+
Confidence threshold for predictions. Defaults to 0.2.
|
|
188
|
+
id_strip (str, optional):
|
|
189
|
+
Characters to strip from img_id. Defaults to None.
|
|
190
|
+
extension (str, optional):
|
|
191
|
+
Image extension to search for. Defaults to "JPG"
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
list: List of detection results for all images.
|
|
195
|
+
"""
|
|
196
|
+
self.cfg.task.data.source = data_path
|
|
197
|
+
self.cfg.task.nms.min_confidence = det_conf_thres
|
|
198
|
+
self._load_model(weights=self.weights, device=self.device, url=self.url)
|
|
199
|
+
|
|
200
|
+
dataset = pw_data.DetectionImageFolder(
|
|
201
|
+
data_path,
|
|
202
|
+
transform=self.transform,
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
results = []
|
|
206
|
+
for i in range(len(dataset.images)):
|
|
207
|
+
res = self.single_image_detection(dataset.images[i], img_path=dataset.images[i], det_conf_thres=det_conf_thres, id_strip=id_strip)
|
|
208
|
+
# Upload the original image and get the size in the format (height, width)
|
|
209
|
+
img = Image.open(dataset.images[i])
|
|
210
|
+
img = np.asarray(img)
|
|
211
|
+
size = img.shape[:2]
|
|
212
|
+
# Normalize the coordinates for timelapse compatibility
|
|
213
|
+
normalized_coords = [[x1 / size[1], y1 / size[0], x2 / size[1], y2 / size[0]] for x1, y1, x2, y2 in res["detections"].xyxy]
|
|
214
|
+
res["normalized_coords"] = normalized_coords
|
|
215
|
+
results.append(res)
|
|
216
|
+
|
|
217
|
+
return results
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PytorchWildlife
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.4
|
|
4
4
|
Summary: a PyTorch Collaborative Deep Learning Framework for Conservation.
|
|
5
5
|
Home-page: https://github.com/microsoft/CameraTraps/
|
|
6
6
|
Author: Andres Hernandez, Zhongqi Miao, Daniela Ruiz Lopez, Isai Daniel Chacon Silva
|
|
7
|
-
Author-email: v-
|
|
7
|
+
Author-email: v-hernandres@microsoft.com, zhongqimiao@microsoft.com, v-druizlopez@microsoft.com, v-ichaconsil@microsoft.com
|
|
8
8
|
License: MIT
|
|
9
9
|
Keywords: pytorch_wildlife,pytorch,wildlife,megadetector,conservation,animal,detection,classification
|
|
10
10
|
Classifier: Development Status :: 3 - Alpha
|
|
@@ -63,16 +63,46 @@ Dynamic: summary
|
|
|
63
63
|
|
|
64
64
|
## 📣 Announcements
|
|
65
65
|
|
|
66
|
-
###
|
|
66
|
+
### 🚀 We’re Open for Contributions!
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
We’re excited to announce that **Pytorch-Wildlife** is now open to community contributions!
|
|
69
|
+
If you’d like to get involved and help improve the project, we’d love to have you on board.
|
|
69
70
|
|
|
70
|
-
|
|
71
|
+
👉 **Check out our Contribution Guidelines:**
|
|
71
72
|
|
|
72
|
-
|
|
73
|
+
[📚 How to Participate](https://microsoft.github.io/CameraTraps/contribute/#how-to-participate)
|
|
73
74
|
|
|
74
|
-
|
|
75
|
+
You’ll find everything you need there — from how to pick an issue, to submitting your first pull request.
|
|
76
|
+
Let’s build this together! 🐾🌱
|
|
75
77
|
|
|
78
|
+
### V 1.2.4
|
|
79
|
+
|
|
80
|
+
The inference code for the MIT YOLO and Apache RT‑DETR models is now available! To use either one, just load it like any other PyTorch‑Wildlife model:
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from pw_detection import MegaDetectorV6MIT, MegaDetectorV6Apache
|
|
84
|
+
|
|
85
|
+
# MIT YOLO
|
|
86
|
+
detector = MegaDetectorV6MIT(
|
|
87
|
+
device=DEVICE,
|
|
88
|
+
pretrained=True,
|
|
89
|
+
version="MDV6-mit-yolov9-e"
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
# Apache RT‑DETR
|
|
93
|
+
detector = MegaDetectorV6Apache(
|
|
94
|
+
device=DEVICE,
|
|
95
|
+
pretrained=True,
|
|
96
|
+
version="MDV6-apa-rtdetr-e"
|
|
97
|
+
)
|
|
98
|
+
```
|
|
99
|
+
Valid versions:
|
|
100
|
+
- MDV6-mit-yolov9-c
|
|
101
|
+
- MDV6-mit-yolov9-e
|
|
102
|
+
- MDV6-apa-rtdetr-c
|
|
103
|
+
- MDV6-apa-rtdetr-e
|
|
104
|
+
|
|
105
|
+
You can also try out the full pipeline using the `detection_classification_pipeline_demo.py` script in the demo folder.
|
|
76
106
|
|
|
77
107
|
#### Previous versions:
|
|
78
108
|
- [What's New](https://microsoft.github.io/CameraTraps/releases/release_notes/)
|
|
@@ -38,6 +38,9 @@ PytorchWildlife/models/detection/herdnet/animaloc/data/types.py
|
|
|
38
38
|
PytorchWildlife/models/detection/herdnet/animaloc/eval/__init__.py
|
|
39
39
|
PytorchWildlife/models/detection/herdnet/animaloc/eval/lmds.py
|
|
40
40
|
PytorchWildlife/models/detection/herdnet/animaloc/eval/stitchers.py
|
|
41
|
+
PytorchWildlife/models/detection/rtdetr_apache/__init__.py
|
|
42
|
+
PytorchWildlife/models/detection/rtdetr_apache/megadetectorv6_apache.py
|
|
43
|
+
PytorchWildlife/models/detection/rtdetr_apache/rtdetr_apache_base.py
|
|
41
44
|
PytorchWildlife/models/detection/ultralytics_based/Deepfaune.py
|
|
42
45
|
PytorchWildlife/models/detection/ultralytics_based/__init__.py
|
|
43
46
|
PytorchWildlife/models/detection/ultralytics_based/megadetectorv5.py
|
|
@@ -46,6 +49,11 @@ PytorchWildlife/models/detection/ultralytics_based/megadetectorv6_distributed.py
|
|
|
46
49
|
PytorchWildlife/models/detection/ultralytics_based/yolov5_base.py
|
|
47
50
|
PytorchWildlife/models/detection/ultralytics_based/yolov8_base.py
|
|
48
51
|
PytorchWildlife/models/detection/ultralytics_based/yolov8_distributed.py
|
|
52
|
+
PytorchWildlife/models/detection/yolo_mit/__init__.py
|
|
53
|
+
PytorchWildlife/models/detection/yolo_mit/megadetectorv6_mit.py
|
|
54
|
+
PytorchWildlife/models/detection/yolo_mit/yolo_mit_base.py
|
|
55
|
+
PytorchWildlife/models/detection/yolo_mit/yolo/__init__.py
|
|
56
|
+
PytorchWildlife/models/detection/yolo_mit/yolo/config.py
|
|
49
57
|
PytorchWildlife/utils/__init__.py
|
|
50
58
|
PytorchWildlife/utils/misc.py
|
|
51
59
|
PytorchWildlife/utils/post_process.py
|
|
@@ -20,16 +20,46 @@
|
|
|
20
20
|
|
|
21
21
|
## 📣 Announcements
|
|
22
22
|
|
|
23
|
-
###
|
|
23
|
+
### 🚀 We’re Open for Contributions!
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
We’re excited to announce that **Pytorch-Wildlife** is now open to community contributions!
|
|
26
|
+
If you’d like to get involved and help improve the project, we’d love to have you on board.
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
👉 **Check out our Contribution Guidelines:**
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
[📚 How to Participate](https://microsoft.github.io/CameraTraps/contribute/#how-to-participate)
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
You’ll find everything you need there — from how to pick an issue, to submitting your first pull request.
|
|
33
|
+
Let’s build this together! 🐾🌱
|
|
32
34
|
|
|
35
|
+
### V 1.2.4
|
|
36
|
+
|
|
37
|
+
The inference code for the MIT YOLO and Apache RT‑DETR models is now available! To use either one, just load it like any other PyTorch‑Wildlife model:
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from pw_detection import MegaDetectorV6MIT, MegaDetectorV6Apache
|
|
41
|
+
|
|
42
|
+
# MIT YOLO
|
|
43
|
+
detector = MegaDetectorV6MIT(
|
|
44
|
+
device=DEVICE,
|
|
45
|
+
pretrained=True,
|
|
46
|
+
version="MDV6-mit-yolov9-e"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# Apache RT‑DETR
|
|
50
|
+
detector = MegaDetectorV6Apache(
|
|
51
|
+
device=DEVICE,
|
|
52
|
+
pretrained=True,
|
|
53
|
+
version="MDV6-apa-rtdetr-e"
|
|
54
|
+
)
|
|
55
|
+
```
|
|
56
|
+
Valid versions:
|
|
57
|
+
- MDV6-mit-yolov9-c
|
|
58
|
+
- MDV6-mit-yolov9-e
|
|
59
|
+
- MDV6-apa-rtdetr-c
|
|
60
|
+
- MDV6-apa-rtdetr-e
|
|
61
|
+
|
|
62
|
+
You can also try out the full pipeline using the `detection_classification_pipeline_demo.py` script in the demo folder.
|
|
33
63
|
|
|
34
64
|
#### Previous versions:
|
|
35
65
|
- [What's New](https://microsoft.github.io/CameraTraps/releases/release_notes/)
|
|
@@ -4,12 +4,12 @@ with open('README.md', encoding="utf8") as file:
|
|
|
4
4
|
long_description = file.read()
|
|
5
5
|
setup(
|
|
6
6
|
name='PytorchWildlife',
|
|
7
|
-
version='1.2.
|
|
7
|
+
version='1.2.4',
|
|
8
8
|
packages=find_packages(),
|
|
9
9
|
url='https://github.com/microsoft/CameraTraps/',
|
|
10
10
|
license='MIT',
|
|
11
11
|
author='Andres Hernandez, Zhongqi Miao, Daniela Ruiz Lopez, Isai Daniel Chacon Silva',
|
|
12
|
-
author_email='v-
|
|
12
|
+
author_email='v-hernandres@microsoft.com, zhongqimiao@microsoft.com, v-druizlopez@microsoft.com, v-ichaconsil@microsoft.com',
|
|
13
13
|
description='a PyTorch Collaborative Deep Learning Framework for Conservation.',
|
|
14
14
|
long_description=long_description,
|
|
15
15
|
long_description_content_type='text/markdown',
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/classification/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/base_detector.py
RENAMED
|
File without changes
|
{pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/herdnet/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/herdnet/dla.py
RENAMED
|
File without changes
|
{pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/herdnet/herdnet.py
RENAMED
|
File without changes
|
{pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife/models/detection/herdnet/model.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytorchwildlife-1.2.3 → pytorchwildlife-1.2.4}/PytorchWildlife.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|