ibbi 0.0.0__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.
- ibbi-0.0.0/LICENSE +21 -0
- ibbi-0.0.0/PKG-INFO +200 -0
- ibbi-0.0.0/README.md +179 -0
- ibbi-0.0.0/pyproject.toml +84 -0
- ibbi-0.0.0/src/ibbi/__init__.py +68 -0
- ibbi-0.0.0/src/ibbi/data/__init__.py +0 -0
- ibbi-0.0.0/src/ibbi/data/dataset_info.py +0 -0
- ibbi-0.0.0/src/ibbi/data/transforms.py +0 -0
- ibbi-0.0.0/src/ibbi/models/__init__.py +6 -0
- ibbi-0.0.0/src/ibbi/models/_factory.py +0 -0
- ibbi-0.0.0/src/ibbi/models/_pretrained.py +0 -0
- ibbi-0.0.0/src/ibbi/models/_registry.py +24 -0
- ibbi-0.0.0/src/ibbi/models/classification.py +102 -0
- ibbi-0.0.0/src/ibbi/models/detection.py +103 -0
- ibbi-0.0.0/src/ibbi/utils/__init__.py +0 -0
- ibbi-0.0.0/src/ibbi/utils/hub.py +18 -0
- ibbi-0.0.0/src/ibbi/utils/torch_utils.py +0 -0
ibbi-0.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Chris
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
ibbi-0.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: ibbi
|
|
3
|
+
Version: 0.0.0
|
|
4
|
+
Summary: A package for bark and ambrosia beetle identification.
|
|
5
|
+
License: MIT
|
|
6
|
+
Author: G. Christopher Marais
|
|
7
|
+
Requires-Python: >=3.11,<4.0
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Requires-Dist: huggingface-hub (>=0.32.3,<0.33.0)
|
|
14
|
+
Requires-Dist: ipywidgets (>=8.1.7,<9.0.0)
|
|
15
|
+
Requires-Dist: numpy (>=2.2.6,<3.0.0)
|
|
16
|
+
Requires-Dist: pandas (>=2.3.0,<3.0.0)
|
|
17
|
+
Requires-Dist: pillow (>=11.2.1,<12.0.0)
|
|
18
|
+
Requires-Dist: ultralytics (==8.3.139)
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# Intelligent Bark Beetle Identifier (IBBI)
|
|
22
|
+
|
|
23
|
+
<!-- [](https://joss.theoj.org/papers/10.21105/joss.01234) -->
|
|
24
|
+
[](https://badge.fury.io/py/ibbi)
|
|
25
|
+
[](https://opensource.org/licenses/MIT)
|
|
26
|
+
|
|
27
|
+
**IBBI** is a Python package that provides a simple and unified interface for detecting and classifying bark and ambrosia beetles from images using state-of-the-art computer vision models.
|
|
28
|
+
|
|
29
|
+
This package is designed to support entomological research by automating the laborious task of beetle identification, enabling high-throughput data analysis for ecological studies, pest management, and biodiversity monitoring. The core models are built on multiple different architectures and are made easily accessible through a simple Python API.
|
|
30
|
+
|
|
31
|
+
### Motivation
|
|
32
|
+
|
|
33
|
+
The ability to accurately identify bark and ambrosia beetles is critical for forest health and pest management. However, traditional methods face significant challenges:
|
|
34
|
+
|
|
35
|
+
* **They are slow and time-consuming.**
|
|
36
|
+
* **They require highly specialized expertise.**
|
|
37
|
+
* **They create a bottleneck for large-scale research.**
|
|
38
|
+
|
|
39
|
+
The IBBI package provides a powerful, modern solution to overcome these obstacles:
|
|
40
|
+
|
|
41
|
+
* It uses **pre-trained, open-source models** for rapid analysis.
|
|
42
|
+
* It **automates both detection and classification** from images.
|
|
43
|
+
* It **lowers the barrier to entry**, enabling faster and more extensive data collection for all researchers.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Table of Contents
|
|
48
|
+
|
|
49
|
+
- [Intelligent Bark Beetle Identifier (IBBI)](#intelligent-bark-beetle-identifier-ibbi)
|
|
50
|
+
- [Motivation](#motivation)
|
|
51
|
+
- [Table of Contents](#table-of-contents)
|
|
52
|
+
- [Installation](#installation)
|
|
53
|
+
- [Quick Start](#quick-start)
|
|
54
|
+
- [Available Models](#available-models)
|
|
55
|
+
- [Model Training Workflow](#model-training-workflow)
|
|
56
|
+
- [How to Contribute](#how-to-contribute)
|
|
57
|
+
- [License](#license)
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Installation
|
|
62
|
+
|
|
63
|
+
This package requires PyTorch. For compatibility with your specific hardware (e.g., CUDA-enabled GPU), please install PyTorch *before* installing `ibbi`.
|
|
64
|
+
|
|
65
|
+
**1. Install PyTorch**
|
|
66
|
+
|
|
67
|
+
Follow the official instructions at **[pytorch.org](https://pytorch.org/get-started/locally/)** to install the correct version for your system (OS, package manager, and CUDA version).
|
|
68
|
+
|
|
69
|
+
**2. Install IBBI**
|
|
70
|
+
|
|
71
|
+
Once PyTorch is installed, you can install the package directly from PyPI:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install ibbi
|
|
75
|
+
````
|
|
76
|
+
|
|
77
|
+
-----
|
|
78
|
+
|
|
79
|
+
## Quick Start
|
|
80
|
+
|
|
81
|
+
Using IBBI is straightforward. You can load a pre-trained model for either detection or classification and immediately use it for inference on your images.
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
import ibbi
|
|
85
|
+
from PIL import Image
|
|
86
|
+
|
|
87
|
+
# Load an image
|
|
88
|
+
image = Image.open("path/to/your/beetle_image.jpg")
|
|
89
|
+
|
|
90
|
+
# 1. Load a pretrained object detection model or a classification model
|
|
91
|
+
detector = ibbi.create_model("yolov10x_bb_detect_model", pretrained=True)
|
|
92
|
+
classifier = ibbi.create_model("yolov10x_bb_classify_model", pretrained=True)
|
|
93
|
+
|
|
94
|
+
# 2. Run prediction to get class probabilities and/or bounding boxes
|
|
95
|
+
# The results will be the detected bounding box coordinates, confidence scores, and class labels
|
|
96
|
+
detection_results = detector.predict(image)
|
|
97
|
+
classification_results = classifier.predict(image)
|
|
98
|
+
|
|
99
|
+
# 3. You can also extract deep features from all models for other tasks
|
|
100
|
+
# The results will be a tensor of features
|
|
101
|
+
features = classifier.extract_features(image)
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
For a more detailed, hands-on demonstration, please see the example notebook located in the repository: `notebooks/example.ipynb`.
|
|
106
|
+
|
|
107
|
+
-----
|
|
108
|
+
|
|
109
|
+
## Available Models
|
|
110
|
+
|
|
111
|
+
The package provides a factory function `create_model()` to access the following pre-trained models from Huggingface Hub:
|
|
112
|
+
|
|
113
|
+
| Model Name | Task | Pretrained Weights Repository | Model Size (Params) | mAP@0.5 | mAP@[.5:.95] |
|
|
114
|
+
|----------------------------|------------------|--------------------------------------------|---------------------|---------|--------------|
|
|
115
|
+
| yolov10x_bb_detect_model | Object Detection | ChristopherMarais/ibbi_yolov10_od_20250601 | 29.5M | N/A | N/A |
|
|
116
|
+
| yolov10x_bb_classify_model | Classification | ChristopherMarais/ibbi_yolov10_c_20250608 | 29.5M | N/A | N/A |
|
|
117
|
+
|
|
118
|
+
A detailed list of available models and their Hugging Face repositories can be found in the [ibbi_model_summary.csv](./docs/assets/data/ibbi_model_summary.csv) file.
|
|
119
|
+
|
|
120
|
+
-----
|
|
121
|
+
|
|
122
|
+
## Model Training Workflow
|
|
123
|
+
|
|
124
|
+
The models included in this package were trained using a standardized data flow on a dataset of bark and ambrosia beetle images from multiple different sources to include 63 different species. A list of all the species the current set of classification models were trained on can be found in the [ibbi_species_table.csv](./docs/assets/data/ibbi_species_table.csv) file.
|
|
125
|
+
|
|
126
|
+
<p align="center">
|
|
127
|
+
<img src="./docs/assets/images/data_flow_ibbi.png" alt="My training workflow">
|
|
128
|
+
</p>
|
|
129
|
+
|
|
130
|
+
**1. Data Collection & Aggregation:**
|
|
131
|
+
|
|
132
|
+
* An initial dataset of 54,421 images was compiled from diverse sources, including field photography from [barkbeetles.info](https://www.barkbeetles.info), lab-based specimen photography, and images from iNaturalist.
|
|
133
|
+
* This aggregated dataset contained a mix of labeled and unlabeled images. Initially, 17,689 images had species-level labels, while 36,732 had no annotations.
|
|
134
|
+
|
|
135
|
+
**2. Annotation with Human-in-the-Loop:**
|
|
136
|
+
|
|
137
|
+
* To create high-quality localization data, a zero-shot object detection model (GroundingDINO) was first used to generate preliminary bounding boxes for the beetles in the images.
|
|
138
|
+
* Crucially, these automated annotations were then manually reviewed and refined by experts to ensure their accuracy and consistency, creating a reliable ground truth for training.
|
|
139
|
+
|
|
140
|
+
**3. Dataset Preparation and Splitting:**
|
|
141
|
+
|
|
142
|
+
* A dedicated test set of 2,031 images was created by selecting images only from species with at least 50 representatives. This ensures a balanced and fair evaluation.
|
|
143
|
+
* The remaining annotated data was split into two distinct training sets based on the task:
|
|
144
|
+
* Object Detection Training Set (35,274 images): All images with verified bounding boxes (excluding the test set) were used to train the general beetle detection models. This larger dataset helps the models learn to accurately localize beetles under various conditions.
|
|
145
|
+
* Classification Training Set (11,507 images): A filtered subset containing images with both verified bounding boxes and species-level labels was used to train the fine-grained classification models.
|
|
146
|
+
|
|
147
|
+
**4. Model Training and Fine-Tuning:**
|
|
148
|
+
|
|
149
|
+
* Pre-trained model architectures were fine-tuned for each specific task:
|
|
150
|
+
* Object Detection models were trained on the larger localization dataset to become expert beetle detectors.
|
|
151
|
+
* Classification models were trained on the fully labeled dataset to specialize in identifying different beetle species.
|
|
152
|
+
* Data augmentation techniques, including random rotations, scaling, color jitter, and mosaic augmentation, were used throughout training to improve model robustness and prevent over-fitting.
|
|
153
|
+
|
|
154
|
+
**5. Evaluation and Deployment:**
|
|
155
|
+
|
|
156
|
+
* The performance of all trained models was rigorously measured against the held-out test set to ensure high accuracy for both detection and classification tasks.
|
|
157
|
+
* The final, best-performing model weights were saved and uploaded to Hugging Face Hub, from where the `ibbi` package automatically downloads them, making them easily accessible to researchers via a simple API.
|
|
158
|
+
|
|
159
|
+
-----
|
|
160
|
+
|
|
161
|
+
## How to Contribute
|
|
162
|
+
|
|
163
|
+
Contributions are welcome\! If you would like to improve IBBI, please follow these steps:
|
|
164
|
+
|
|
165
|
+
1. Clone this repository.
|
|
166
|
+
2. Create a Conda environment and activate it:
|
|
167
|
+
```bash
|
|
168
|
+
conda env create -f environment.yml
|
|
169
|
+
conda activate IBBI
|
|
170
|
+
```
|
|
171
|
+
3. Install dependencies using Poetry and set up pre-commit hooks:
|
|
172
|
+
```bash
|
|
173
|
+
pip install torch torchvision torchaudio # Ensure PyTorch is installed first
|
|
174
|
+
poetry config virtualenvs.create false --local
|
|
175
|
+
poetry install
|
|
176
|
+
poetry run pre-commit install
|
|
177
|
+
```
|
|
178
|
+
4. Create a new branch for your feature or bug fix.
|
|
179
|
+
5. Commit your changes and open a pull request.
|
|
180
|
+
|
|
181
|
+
To add new dependencies, use `poetry add <package-name>` for the main package or `poetry add --group dev <package-name>` for development dependencies.
|
|
182
|
+
|
|
183
|
+
-----
|
|
184
|
+
|
|
185
|
+
<!-- ## Citing IBBI
|
|
186
|
+
|
|
187
|
+
If you use IBBI in your research, please cite the JOSS paper.
|
|
188
|
+
|
|
189
|
+
**(Placeholder) To be added upon acceptance:**
|
|
190
|
+
|
|
191
|
+
> Marais, C., et al., (2025). IBBI: Intelligent Bark Beetle Identifier. Journal of Open Source Software, X(XX), XXXX. https://www.google.com/search?q=https://doi.org/XX.XXXXX/joss.XXXXX
|
|
192
|
+
|
|
193
|
+
You can also cite the specific version of the software archive using the DOI provided by Zenodo/figshare.
|
|
194
|
+
|
|
195
|
+
----- -->
|
|
196
|
+
|
|
197
|
+
## License
|
|
198
|
+
|
|
199
|
+
This project is licensed under the terms of the MIT License. See the `LICENSE` file for details.
|
|
200
|
+
|
ibbi-0.0.0/README.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Intelligent Bark Beetle Identifier (IBBI)
|
|
2
|
+
|
|
3
|
+
<!-- [](https://joss.theoj.org/papers/10.21105/joss.01234) -->
|
|
4
|
+
[](https://badge.fury.io/py/ibbi)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
**IBBI** is a Python package that provides a simple and unified interface for detecting and classifying bark and ambrosia beetles from images using state-of-the-art computer vision models.
|
|
8
|
+
|
|
9
|
+
This package is designed to support entomological research by automating the laborious task of beetle identification, enabling high-throughput data analysis for ecological studies, pest management, and biodiversity monitoring. The core models are built on multiple different architectures and are made easily accessible through a simple Python API.
|
|
10
|
+
|
|
11
|
+
### Motivation
|
|
12
|
+
|
|
13
|
+
The ability to accurately identify bark and ambrosia beetles is critical for forest health and pest management. However, traditional methods face significant challenges:
|
|
14
|
+
|
|
15
|
+
* **They are slow and time-consuming.**
|
|
16
|
+
* **They require highly specialized expertise.**
|
|
17
|
+
* **They create a bottleneck for large-scale research.**
|
|
18
|
+
|
|
19
|
+
The IBBI package provides a powerful, modern solution to overcome these obstacles:
|
|
20
|
+
|
|
21
|
+
* It uses **pre-trained, open-source models** for rapid analysis.
|
|
22
|
+
* It **automates both detection and classification** from images.
|
|
23
|
+
* It **lowers the barrier to entry**, enabling faster and more extensive data collection for all researchers.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Table of Contents
|
|
28
|
+
|
|
29
|
+
- [Intelligent Bark Beetle Identifier (IBBI)](#intelligent-bark-beetle-identifier-ibbi)
|
|
30
|
+
- [Motivation](#motivation)
|
|
31
|
+
- [Table of Contents](#table-of-contents)
|
|
32
|
+
- [Installation](#installation)
|
|
33
|
+
- [Quick Start](#quick-start)
|
|
34
|
+
- [Available Models](#available-models)
|
|
35
|
+
- [Model Training Workflow](#model-training-workflow)
|
|
36
|
+
- [How to Contribute](#how-to-contribute)
|
|
37
|
+
- [License](#license)
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Installation
|
|
42
|
+
|
|
43
|
+
This package requires PyTorch. For compatibility with your specific hardware (e.g., CUDA-enabled GPU), please install PyTorch *before* installing `ibbi`.
|
|
44
|
+
|
|
45
|
+
**1. Install PyTorch**
|
|
46
|
+
|
|
47
|
+
Follow the official instructions at **[pytorch.org](https://pytorch.org/get-started/locally/)** to install the correct version for your system (OS, package manager, and CUDA version).
|
|
48
|
+
|
|
49
|
+
**2. Install IBBI**
|
|
50
|
+
|
|
51
|
+
Once PyTorch is installed, you can install the package directly from PyPI:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install ibbi
|
|
55
|
+
````
|
|
56
|
+
|
|
57
|
+
-----
|
|
58
|
+
|
|
59
|
+
## Quick Start
|
|
60
|
+
|
|
61
|
+
Using IBBI is straightforward. You can load a pre-trained model for either detection or classification and immediately use it for inference on your images.
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
import ibbi
|
|
65
|
+
from PIL import Image
|
|
66
|
+
|
|
67
|
+
# Load an image
|
|
68
|
+
image = Image.open("path/to/your/beetle_image.jpg")
|
|
69
|
+
|
|
70
|
+
# 1. Load a pretrained object detection model or a classification model
|
|
71
|
+
detector = ibbi.create_model("yolov10x_bb_detect_model", pretrained=True)
|
|
72
|
+
classifier = ibbi.create_model("yolov10x_bb_classify_model", pretrained=True)
|
|
73
|
+
|
|
74
|
+
# 2. Run prediction to get class probabilities and/or bounding boxes
|
|
75
|
+
# The results will be the detected bounding box coordinates, confidence scores, and class labels
|
|
76
|
+
detection_results = detector.predict(image)
|
|
77
|
+
classification_results = classifier.predict(image)
|
|
78
|
+
|
|
79
|
+
# 3. You can also extract deep features from all models for other tasks
|
|
80
|
+
# The results will be a tensor of features
|
|
81
|
+
features = classifier.extract_features(image)
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
For a more detailed, hands-on demonstration, please see the example notebook located in the repository: `notebooks/example.ipynb`.
|
|
86
|
+
|
|
87
|
+
-----
|
|
88
|
+
|
|
89
|
+
## Available Models
|
|
90
|
+
|
|
91
|
+
The package provides a factory function `create_model()` to access the following pre-trained models from Huggingface Hub:
|
|
92
|
+
|
|
93
|
+
| Model Name | Task | Pretrained Weights Repository | Model Size (Params) | mAP@0.5 | mAP@[.5:.95] |
|
|
94
|
+
|----------------------------|------------------|--------------------------------------------|---------------------|---------|--------------|
|
|
95
|
+
| yolov10x_bb_detect_model | Object Detection | ChristopherMarais/ibbi_yolov10_od_20250601 | 29.5M | N/A | N/A |
|
|
96
|
+
| yolov10x_bb_classify_model | Classification | ChristopherMarais/ibbi_yolov10_c_20250608 | 29.5M | N/A | N/A |
|
|
97
|
+
|
|
98
|
+
A detailed list of available models and their Hugging Face repositories can be found in the [ibbi_model_summary.csv](./docs/assets/data/ibbi_model_summary.csv) file.
|
|
99
|
+
|
|
100
|
+
-----
|
|
101
|
+
|
|
102
|
+
## Model Training Workflow
|
|
103
|
+
|
|
104
|
+
The models included in this package were trained using a standardized data flow on a dataset of bark and ambrosia beetle images from multiple different sources to include 63 different species. A list of all the species the current set of classification models were trained on can be found in the [ibbi_species_table.csv](./docs/assets/data/ibbi_species_table.csv) file.
|
|
105
|
+
|
|
106
|
+
<p align="center">
|
|
107
|
+
<img src="./docs/assets/images/data_flow_ibbi.png" alt="My training workflow">
|
|
108
|
+
</p>
|
|
109
|
+
|
|
110
|
+
**1. Data Collection & Aggregation:**
|
|
111
|
+
|
|
112
|
+
* An initial dataset of 54,421 images was compiled from diverse sources, including field photography from [barkbeetles.info](https://www.barkbeetles.info), lab-based specimen photography, and images from iNaturalist.
|
|
113
|
+
* This aggregated dataset contained a mix of labeled and unlabeled images. Initially, 17,689 images had species-level labels, while 36,732 had no annotations.
|
|
114
|
+
|
|
115
|
+
**2. Annotation with Human-in-the-Loop:**
|
|
116
|
+
|
|
117
|
+
* To create high-quality localization data, a zero-shot object detection model (GroundingDINO) was first used to generate preliminary bounding boxes for the beetles in the images.
|
|
118
|
+
* Crucially, these automated annotations were then manually reviewed and refined by experts to ensure their accuracy and consistency, creating a reliable ground truth for training.
|
|
119
|
+
|
|
120
|
+
**3. Dataset Preparation and Splitting:**
|
|
121
|
+
|
|
122
|
+
* A dedicated test set of 2,031 images was created by selecting images only from species with at least 50 representatives. This ensures a balanced and fair evaluation.
|
|
123
|
+
* The remaining annotated data was split into two distinct training sets based on the task:
|
|
124
|
+
* Object Detection Training Set (35,274 images): All images with verified bounding boxes (excluding the test set) were used to train the general beetle detection models. This larger dataset helps the models learn to accurately localize beetles under various conditions.
|
|
125
|
+
* Classification Training Set (11,507 images): A filtered subset containing images with both verified bounding boxes and species-level labels was used to train the fine-grained classification models.
|
|
126
|
+
|
|
127
|
+
**4. Model Training and Fine-Tuning:**
|
|
128
|
+
|
|
129
|
+
* Pre-trained model architectures were fine-tuned for each specific task:
|
|
130
|
+
* Object Detection models were trained on the larger localization dataset to become expert beetle detectors.
|
|
131
|
+
* Classification models were trained on the fully labeled dataset to specialize in identifying different beetle species.
|
|
132
|
+
* Data augmentation techniques, including random rotations, scaling, color jitter, and mosaic augmentation, were used throughout training to improve model robustness and prevent over-fitting.
|
|
133
|
+
|
|
134
|
+
**5. Evaluation and Deployment:**
|
|
135
|
+
|
|
136
|
+
* The performance of all trained models was rigorously measured against the held-out test set to ensure high accuracy for both detection and classification tasks.
|
|
137
|
+
* The final, best-performing model weights were saved and uploaded to Hugging Face Hub, from where the `ibbi` package automatically downloads them, making them easily accessible to researchers via a simple API.
|
|
138
|
+
|
|
139
|
+
-----
|
|
140
|
+
|
|
141
|
+
## How to Contribute
|
|
142
|
+
|
|
143
|
+
Contributions are welcome\! If you would like to improve IBBI, please follow these steps:
|
|
144
|
+
|
|
145
|
+
1. Clone this repository.
|
|
146
|
+
2. Create a Conda environment and activate it:
|
|
147
|
+
```bash
|
|
148
|
+
conda env create -f environment.yml
|
|
149
|
+
conda activate IBBI
|
|
150
|
+
```
|
|
151
|
+
3. Install dependencies using Poetry and set up pre-commit hooks:
|
|
152
|
+
```bash
|
|
153
|
+
pip install torch torchvision torchaudio # Ensure PyTorch is installed first
|
|
154
|
+
poetry config virtualenvs.create false --local
|
|
155
|
+
poetry install
|
|
156
|
+
poetry run pre-commit install
|
|
157
|
+
```
|
|
158
|
+
4. Create a new branch for your feature or bug fix.
|
|
159
|
+
5. Commit your changes and open a pull request.
|
|
160
|
+
|
|
161
|
+
To add new dependencies, use `poetry add <package-name>` for the main package or `poetry add --group dev <package-name>` for development dependencies.
|
|
162
|
+
|
|
163
|
+
-----
|
|
164
|
+
|
|
165
|
+
<!-- ## Citing IBBI
|
|
166
|
+
|
|
167
|
+
If you use IBBI in your research, please cite the JOSS paper.
|
|
168
|
+
|
|
169
|
+
**(Placeholder) To be added upon acceptance:**
|
|
170
|
+
|
|
171
|
+
> Marais, C., et al., (2025). IBBI: Intelligent Bark Beetle Identifier. Journal of Open Source Software, X(XX), XXXX. https://www.google.com/search?q=https://doi.org/XX.XXXXX/joss.XXXXX
|
|
172
|
+
|
|
173
|
+
You can also cite the specific version of the software archive using the DOI provided by Zenodo/figshare.
|
|
174
|
+
|
|
175
|
+
----- -->
|
|
176
|
+
|
|
177
|
+
## License
|
|
178
|
+
|
|
179
|
+
This project is licensed under the terms of the MIT License. See the `LICENSE` file for details.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "ibbi"
|
|
3
|
+
version = "0.0.0"
|
|
4
|
+
description = "A package for bark and ambrosia beetle identification."
|
|
5
|
+
authors = ["G. Christopher Marais"]
|
|
6
|
+
license = "MIT"
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
packages = [{ include = "ibbi", from = "src" }]
|
|
9
|
+
|
|
10
|
+
[tool.poetry.dependencies]
|
|
11
|
+
python = ">=3.11,<4.0"
|
|
12
|
+
huggingface-hub = ">=0.32.3,<0.33.0"
|
|
13
|
+
ultralytics = "8.3.139"
|
|
14
|
+
pandas = "^2.3.0"
|
|
15
|
+
numpy = "^2.2.6"
|
|
16
|
+
pillow = "^11.2.1"
|
|
17
|
+
ipywidgets = "^8.1.7"
|
|
18
|
+
|
|
19
|
+
[tool.poetry.group.dev.dependencies]
|
|
20
|
+
ruff = "^0.11.10"
|
|
21
|
+
pyright = "^1.1.401"
|
|
22
|
+
pytest = "^8.3.5"
|
|
23
|
+
pre-commit = "^4.2.0"
|
|
24
|
+
mkdocs = "^1.6.1"
|
|
25
|
+
mkdocs-material = "^9.6.14"
|
|
26
|
+
jupyterlab = "^4.4.2"
|
|
27
|
+
isort = "^6.0.1"
|
|
28
|
+
black = "^25.1.0"
|
|
29
|
+
notebook = "^7.4.2"
|
|
30
|
+
ipykernel = "^6.29.5"
|
|
31
|
+
ipywidgets = "^8.1.7"
|
|
32
|
+
mkdocstrings = "^0.29.1"
|
|
33
|
+
mkdocstrings-python = "^1.16.12"
|
|
34
|
+
poetry-dynamic-versioning = "^1.8.2"
|
|
35
|
+
|
|
36
|
+
[build-system]
|
|
37
|
+
requires = ["poetry-core>=1.0.0", "poetry-dynamic-versioning"]
|
|
38
|
+
build-backend = "poetry.core.masonry.api"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# --- Tool Configurations ---
|
|
42
|
+
|
|
43
|
+
[tool.ruff]
|
|
44
|
+
line-length = 120
|
|
45
|
+
|
|
46
|
+
[tool.ruff.lint]
|
|
47
|
+
select = ["A", "B", "C4", "E", "W", "F", "I", "UP", "RUF"]
|
|
48
|
+
ignore = [
|
|
49
|
+
"B007",
|
|
50
|
+
"E721",
|
|
51
|
+
"RUF015",
|
|
52
|
+
"UP038",
|
|
53
|
+
"C401",
|
|
54
|
+
"C408",
|
|
55
|
+
"C409",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
[tool.ruff.format]
|
|
59
|
+
quote-style = "double"
|
|
60
|
+
|
|
61
|
+
[tool.ruff.lint.isort]
|
|
62
|
+
known-first-party = ["ibbi"]
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
[tool.pyright]
|
|
66
|
+
include = ["src/ibbi", "tests"]
|
|
67
|
+
exclude = ["**/node_modules", "**/__pycache__"]
|
|
68
|
+
stubPath = "src/stubs"
|
|
69
|
+
reportMissingImports = true
|
|
70
|
+
pythonVersion = "3.11"
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
[tool.pytest.ini_options]
|
|
74
|
+
minversion = "6.0"
|
|
75
|
+
addopts = "-ra -q"
|
|
76
|
+
testpaths = [
|
|
77
|
+
"tests",
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
[tool.poetry-dynamic-versioning]
|
|
81
|
+
enable = true
|
|
82
|
+
vcs = "git"
|
|
83
|
+
style = "pep440"
|
|
84
|
+
format-latest = "{base}.dev{distance}"
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# src/ibbi/__init__.py
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Main initialization file for the ibbi package.
|
|
5
|
+
|
|
6
|
+
This file exposes the primary user-facing function, `create_model`, which acts as a
|
|
7
|
+
factory for instantiating various beetle detection and classification models.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import Any, Union
|
|
11
|
+
|
|
12
|
+
# --- IMPORTANT ---
|
|
13
|
+
# Import the model definition files first.
|
|
14
|
+
# This ensures that the @register_model decorator runs and populates
|
|
15
|
+
# the model_registry before we try to use it.
|
|
16
|
+
from .models import classification, detection # noqa: F401
|
|
17
|
+
|
|
18
|
+
# Now, import the registry that has been populated.
|
|
19
|
+
from .models._registry import model_registry
|
|
20
|
+
from .models.classification import YOLOv10BeetleClassifier
|
|
21
|
+
from .models.detection import YOLOv10BeetleDetector
|
|
22
|
+
|
|
23
|
+
# Define a type hint for the models that can be returned
|
|
24
|
+
ModelType = Union[YOLOv10BeetleDetector, YOLOv10BeetleClassifier]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def create_model(model_name: str, pretrained: bool = False, **kwargs: Any) -> ModelType:
|
|
28
|
+
"""
|
|
29
|
+
Creates a model from a name.
|
|
30
|
+
|
|
31
|
+
This factory function is the main entry point for users of the package.
|
|
32
|
+
It looks up the requested model in the registry, downloads pretrained
|
|
33
|
+
weights from the Hugging Face Hub if requested, and returns an
|
|
34
|
+
instantiated model object.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
model_name (str): Name of the model to create.
|
|
38
|
+
pretrained (bool): Whether to load pretrained weights from the Hugging Face Hub.
|
|
39
|
+
Defaults to False.
|
|
40
|
+
**kwargs (Any): Extra arguments to pass to the model-creating function.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
ModelType: An instance of the requested model (e.g., YOLOv10BeetleDetector or
|
|
44
|
+
YOLOv10BeetleClassifier).
|
|
45
|
+
|
|
46
|
+
Raises:
|
|
47
|
+
KeyError: If the requested `model_name` is not found in the model registry.
|
|
48
|
+
|
|
49
|
+
Example:
|
|
50
|
+
```python
|
|
51
|
+
import ibbi
|
|
52
|
+
|
|
53
|
+
# Create a pretrained detection model
|
|
54
|
+
detector = ibbi.create_model("yolov10x_bb_detect_model", pretrained=True)
|
|
55
|
+
|
|
56
|
+
# Create a pretrained classification model
|
|
57
|
+
classifier = ibbi.create_model("yolov10x_bb_classify_model", pretrained=True)
|
|
58
|
+
```
|
|
59
|
+
"""
|
|
60
|
+
if model_name not in model_registry:
|
|
61
|
+
available = ", ".join(model_registry.keys())
|
|
62
|
+
raise KeyError(f"Model '{model_name}' not found. Available models: [{available}]")
|
|
63
|
+
|
|
64
|
+
# Look up the factory function in the registry and call it
|
|
65
|
+
model_factory = model_registry[model_name]
|
|
66
|
+
model = model_factory(pretrained=pretrained, **kwargs)
|
|
67
|
+
|
|
68
|
+
return model
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# 1. The registry itself: a dictionary to hold your models.
|
|
2
|
+
model_registry = {}
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def register_model(fn):
|
|
6
|
+
"""
|
|
7
|
+
# 2. A decorator function to easily add models to the registry.
|
|
8
|
+
|
|
9
|
+
This function takes a model-creating function (like your
|
|
10
|
+
`yolov10x_bb_detect_model` function) and adds it to the
|
|
11
|
+
`model_registry` dictionary. The function's name becomes the key.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
fn: The model-creating function to register.
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
The original function, after it has been registered.
|
|
18
|
+
"""
|
|
19
|
+
model_name = fn.__name__
|
|
20
|
+
if model_name in model_registry:
|
|
21
|
+
raise ValueError(f"Model {model_name} is already registered.")
|
|
22
|
+
|
|
23
|
+
model_registry[model_name] = fn
|
|
24
|
+
return fn
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# src/ibbi/models/classification.py
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Beetle classification models.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import torch
|
|
8
|
+
from ultralytics import YOLO
|
|
9
|
+
|
|
10
|
+
from ..utils.hub import download_from_hf_hub
|
|
11
|
+
from ._registry import register_model
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class YOLOv10BeetleClassifier:
|
|
15
|
+
"""
|
|
16
|
+
A wrapper class for the YOLOv10 beetle classifier model.
|
|
17
|
+
|
|
18
|
+
Provides a clean interface for image classification and feature extraction.
|
|
19
|
+
|
|
20
|
+
Attributes:
|
|
21
|
+
model (YOLO): The underlying `ultralytics.YOLO` model instance.
|
|
22
|
+
device (str): The compute device ('cuda' or 'cpu') the model is loaded on.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, model_path: str):
|
|
26
|
+
"""
|
|
27
|
+
Initializes the YOLOv10BeetleClassifier.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
model_path (str): The local path to the .pt model file.
|
|
31
|
+
"""
|
|
32
|
+
self.model = YOLO(model_path)
|
|
33
|
+
self.device = "cuda" if torch.cuda.is_available() else "cpu"
|
|
34
|
+
self.model.to(self.device)
|
|
35
|
+
print(f"Model loaded on device: {self.device}")
|
|
36
|
+
|
|
37
|
+
def predict(self, image, **kwargs):
|
|
38
|
+
"""
|
|
39
|
+
Performs image classification on an image.
|
|
40
|
+
|
|
41
|
+
This method takes an image and returns the predicted class probabilities.
|
|
42
|
+
Accepts any arguments that the `ultralytics.YOLO.predict` method accepts.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
image: The input image(s). Can be a path, URL, numpy array, PIL image, etc.
|
|
46
|
+
**kwargs: Additional keyword arguments to pass to the underlying
|
|
47
|
+
`predict` method of the YOLO model.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
A list of `ultralytics.engine.results.Results` objects containing the
|
|
51
|
+
predicted class probabilities.
|
|
52
|
+
"""
|
|
53
|
+
print("Running image classification (predict)...")
|
|
54
|
+
return self.model.predict(image, **kwargs)
|
|
55
|
+
|
|
56
|
+
def extract_features(self, image, **kwargs):
|
|
57
|
+
"""
|
|
58
|
+
Extracts deep features from the backbone of the model for an image.
|
|
59
|
+
|
|
60
|
+
This is useful for downstream tasks like clustering or similarity search.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
image: The input image(s).
|
|
64
|
+
**kwargs: Additional keyword arguments to pass to the underlying
|
|
65
|
+
`embed` method of the YOLO model.
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
A tensor of features if successful, otherwise None.
|
|
69
|
+
"""
|
|
70
|
+
print("Extracting features (embed)...")
|
|
71
|
+
features = self.model.embed(image, **kwargs)
|
|
72
|
+
if features:
|
|
73
|
+
return features[0]
|
|
74
|
+
return None
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@register_model
|
|
78
|
+
def yolov10x_bb_classify_model(pretrained: bool = False, **kwargs):
|
|
79
|
+
"""
|
|
80
|
+
Factory function for the YOLOv10 beetle classifier.
|
|
81
|
+
|
|
82
|
+
Instantiates a `YOLOv10BeetleClassifier` model. If `pretrained` is True,
|
|
83
|
+
it downloads the official weights from the Hugging Face Hub.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
pretrained (bool): If True, downloads pretrained weights.
|
|
87
|
+
Defaults to False.
|
|
88
|
+
**kwargs: Additional arguments (not currently used).
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
YOLOv10BeetleClassifier: An instance of the classifier class.
|
|
92
|
+
"""
|
|
93
|
+
if pretrained:
|
|
94
|
+
repo_id = "ChristopherMarais/ibbi_yolov10_c_20250608"
|
|
95
|
+
filename = "model.pt"
|
|
96
|
+
local_weights_path = download_from_hf_hub(repo_id=repo_id, filename=filename)
|
|
97
|
+
else:
|
|
98
|
+
# Note: A non-pretrained YOLOv10x model is not meaningful for this task,
|
|
99
|
+
# but this path is kept for API consistency.
|
|
100
|
+
local_weights_path = "yolov10x.pt"
|
|
101
|
+
|
|
102
|
+
return YOLOv10BeetleClassifier(model_path=local_weights_path)
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# src/ibbi/models/detection.py
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Beetle detection models.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import torch
|
|
8
|
+
from ultralytics import YOLO
|
|
9
|
+
|
|
10
|
+
from ..utils.hub import download_from_hf_hub
|
|
11
|
+
from ._registry import register_model
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class YOLOv10BeetleDetector:
|
|
15
|
+
"""
|
|
16
|
+
A wrapper class for YOLOv10 beetle detection models.
|
|
17
|
+
|
|
18
|
+
This class provides a clean interface for performing object detection inference
|
|
19
|
+
and extracting deep features from images.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
model (YOLO): The underlying `ultralytics.YOLO` model instance.
|
|
23
|
+
device (str): The compute device ('cuda' or 'cpu') the model is loaded on.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self, model_path: str):
|
|
27
|
+
"""
|
|
28
|
+
Initializes the YOLOv10BeetleDetector.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
model_path (str): The local path to the pretrained `.pt` model file.
|
|
32
|
+
"""
|
|
33
|
+
self.model = YOLO(model_path)
|
|
34
|
+
self.device = "cuda" if torch.cuda.is_available() else "cpu"
|
|
35
|
+
self.model.to(self.device)
|
|
36
|
+
print(f"Model loaded on device: {self.device}")
|
|
37
|
+
|
|
38
|
+
def predict(self, image, **kwargs):
|
|
39
|
+
"""
|
|
40
|
+
Performs object detection inference on an image.
|
|
41
|
+
|
|
42
|
+
This method takes an image and returns the bounding box predictions.
|
|
43
|
+
Accepts any arguments that the `ultralytics.YOLO.predict` method accepts.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
image: The input image(s). Can be a path, URL, numpy array, PIL image, etc.
|
|
47
|
+
**kwargs: Additional keyword arguments to pass to the underlying
|
|
48
|
+
`predict` method of the YOLO model.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
A list of `ultralytics.engine.results.Results` objects containing the
|
|
52
|
+
detected bounding boxes, confidence scores, and class labels.
|
|
53
|
+
"""
|
|
54
|
+
print("Running object detection (predict)...")
|
|
55
|
+
return self.model.predict(image, **kwargs)
|
|
56
|
+
|
|
57
|
+
def extract_features(self, image, **kwargs):
|
|
58
|
+
"""
|
|
59
|
+
Extracts deep features from the backbone of the model for an image.
|
|
60
|
+
|
|
61
|
+
This is useful for downstream tasks like clustering or similarity search.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
image: The input image(s).
|
|
65
|
+
**kwargs: Additional keyword arguments to pass to the underlying
|
|
66
|
+
`embed` method of the YOLO model.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
A tensor of features if successful, otherwise None.
|
|
70
|
+
"""
|
|
71
|
+
print("Extracting features (embed)...")
|
|
72
|
+
features = self.model.embed(image, **kwargs)
|
|
73
|
+
if features:
|
|
74
|
+
return features[0]
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@register_model
|
|
79
|
+
def yolov10x_bb_detect_model(pretrained: bool = False, **kwargs):
|
|
80
|
+
"""
|
|
81
|
+
Factory function for the YOLOv10 beetle detector.
|
|
82
|
+
|
|
83
|
+
Instantiates a `YOLOv10BeetleDetector` model. If `pretrained` is True,
|
|
84
|
+
it downloads the official weights from the Hugging Face Hub.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
pretrained (bool): If True, downloads pretrained weights.
|
|
88
|
+
Defaults to False.
|
|
89
|
+
**kwargs: Additional arguments (not currently used).
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
YOLOv10BeetleDetector: An instance of the detector class.
|
|
93
|
+
"""
|
|
94
|
+
if pretrained:
|
|
95
|
+
repo_id = "ChristopherMarais/ibbi_yolov10_od_20250601"
|
|
96
|
+
filename = "model.pt"
|
|
97
|
+
local_weights_path = download_from_hf_hub(repo_id=repo_id, filename=filename)
|
|
98
|
+
else:
|
|
99
|
+
# Note: A non-pretrained YOLOv10x model is not meaningful for this task,
|
|
100
|
+
# but this path is kept for API consistency.
|
|
101
|
+
local_weights_path = "yolov10x.pt"
|
|
102
|
+
|
|
103
|
+
return YOLOv10BeetleDetector(model_path=local_weights_path)
|
|
File without changes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from huggingface_hub import hf_hub_download
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def download_from_hf_hub(repo_id: str, filename: str) -> str:
|
|
5
|
+
"""
|
|
6
|
+
Downloads a model file from a Hugging Face Hub repository.
|
|
7
|
+
|
|
8
|
+
Args:
|
|
9
|
+
repo_id (str): The ID of the repository (e.g., "your-username/my-model").
|
|
10
|
+
filename (str): The name of the file to download from the repo.
|
|
11
|
+
|
|
12
|
+
Returns:
|
|
13
|
+
str: The local path to the downloaded file.
|
|
14
|
+
"""
|
|
15
|
+
print(f"Downloading {filename} from Hugging Face hub repository '{repo_id}'...")
|
|
16
|
+
local_model_path = hf_hub_download(repo_id=repo_id, filename=filename)
|
|
17
|
+
print("Download complete. Model cached at:", local_model_path)
|
|
18
|
+
return local_model_path
|
|
File without changes
|