Skip to content

Commit edc87f3

Browse files
committed
Add BirdNET-Gemodel 3.0
1 parent 85f788b commit edc87f3

15 files changed

Lines changed: 1013 additions & 1 deletion

File tree

docs/birdnet.geo_models.v3_0.rst

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
birdnet.geo\_models.v3\_0 package
2+
=================================
3+
4+
Submodules
5+
----------
6+
7+
birdnet.geo\_models.v3\_0.model module
8+
--------------------------------------
9+
10+
.. automodule:: birdnet.geo_models.v3_0.model
11+
:members:
12+
:show-inheritance:
13+
:undoc-members:
14+
15+
birdnet.geo\_models.v3\_0.tf module
16+
------------------------------------
17+
18+
.. automodule:: birdnet.geo_models.v3_0.tf
19+
:members:
20+
:show-inheritance:
21+
:undoc-members:
22+
23+
Module contents
24+
---------------
25+
26+
.. automodule:: birdnet.geo_models.v3_0
27+
:members:
28+
:show-inheritance:
29+
:undoc-members:
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
from __future__ import annotations
2+
3+
from pathlib import Path
4+
from typing import Any, final
5+
6+
from ordered_set import OrderedSet
7+
8+
from birdnet.core.backends import (
9+
BackendLoader,
10+
VersionedGeoBackendProtocol,
11+
)
12+
from birdnet.geo.inference.prediction_result import GeoPredictionResult
13+
from birdnet.geo.inference.session import GeoPredictionSession
14+
from birdnet.geo.models.base import GeoModelBase
15+
from birdnet.globals import (
16+
GEO_MODEL_VERSION_V3_0,
17+
GEO_MODEL_VERSIONS,
18+
MODEL_TYPE_GEO,
19+
MODEL_TYPES,
20+
)
21+
from birdnet.utils.helper import validate_species_list
22+
23+
24+
class GeoDownloaderBaseV3_0:
25+
AVAILABLE_LANGUAGES: OrderedSet[str] = OrderedSet(
26+
(
27+
"af",
28+
"ar",
29+
"cs",
30+
"da",
31+
"de",
32+
"en_uk",
33+
"en_us",
34+
"es",
35+
"fi",
36+
"fr",
37+
"hu",
38+
"it",
39+
"ja",
40+
"ko",
41+
"nl",
42+
"no",
43+
"pl",
44+
"pt",
45+
"ro",
46+
"ru",
47+
"sk",
48+
"sl",
49+
"sv",
50+
"th",
51+
"tr",
52+
"uk",
53+
"zh",
54+
)
55+
)
56+
57+
58+
class GeoModelV3_0(GeoModelBase):
59+
def __init__(
60+
self,
61+
model_path: Path,
62+
species_list: OrderedSet[str],
63+
is_custom_model: bool,
64+
backend_type: type[VersionedGeoBackendProtocol],
65+
backend_kwargs: dict[str, Any],
66+
) -> None:
67+
super().__init__(
68+
model_path, species_list, is_custom_model, backend_type, backend_kwargs
69+
)
70+
71+
@classmethod
72+
def load(
73+
cls,
74+
model_path: Path,
75+
species_list: OrderedSet[str],
76+
backend_type: type[VersionedGeoBackendProtocol],
77+
backend_kwargs: dict[str, Any],
78+
) -> GeoModelV3_0:
79+
result = GeoModelV3_0(
80+
model_path,
81+
species_list,
82+
is_custom_model=False,
83+
backend_type=backend_type,
84+
backend_kwargs=backend_kwargs,
85+
)
86+
return result
87+
88+
@classmethod
89+
def load_custom(
90+
cls,
91+
model_path: Path,
92+
species_list: Path,
93+
backend_type: type[VersionedGeoBackendProtocol],
94+
backend_kwargs: dict[str, Any],
95+
check_validity: bool,
96+
) -> GeoModelV3_0:
97+
assert model_path.exists()
98+
assert species_list.is_file()
99+
100+
loaded_species_list = validate_species_list(species_list)
101+
102+
if check_validity:
103+
n_species_in_model = BackendLoader.check_model_can_be_loaded(
104+
model_path, backend_type, backend_kwargs
105+
)
106+
107+
if n_species_in_model != len(loaded_species_list):
108+
raise ValueError(
109+
f"Model '{model_path.absolute()}' has {n_species_in_model} outputs, "
110+
f"but species list '{species_list.absolute()}' "
111+
f"has {len(loaded_species_list)} species!"
112+
)
113+
114+
result = GeoModelV3_0(
115+
model_path,
116+
loaded_species_list,
117+
is_custom_model=True,
118+
backend_type=backend_type,
119+
backend_kwargs=backend_kwargs,
120+
)
121+
return result
122+
123+
@classmethod
124+
@final
125+
def get_version(cls) -> GEO_MODEL_VERSIONS:
126+
return GEO_MODEL_VERSION_V3_0
127+
128+
@classmethod
129+
@final
130+
def get_model_type(cls) -> MODEL_TYPES:
131+
return MODEL_TYPE_GEO
132+
133+
def predict_session(
134+
self,
135+
/,
136+
*,
137+
min_confidence: float = 0.03,
138+
half_precision: bool = False,
139+
device: str = "CPU",
140+
) -> GeoPredictionSession:
141+
return GeoPredictionSession(
142+
species_list=self.species_list,
143+
model_path=self.model_path,
144+
model_is_custom=self.is_custom_model,
145+
model_version=self.get_version(),
146+
model_backend_type=self.backend_type,
147+
model_backend_custom_kwargs=self.backend_kwargs,
148+
min_confidence=min_confidence,
149+
half_precision=half_precision,
150+
device=device,
151+
)
152+
153+
def predict(
154+
self,
155+
latitude: float,
156+
longitude: float,
157+
/,
158+
*,
159+
week: int | None = None,
160+
min_confidence: float = 0.03,
161+
half_precision: bool = False,
162+
device: str = "CPU",
163+
) -> GeoPredictionResult:
164+
with self.predict_session(
165+
min_confidence=min_confidence,
166+
half_precision=half_precision,
167+
device=device,
168+
) as session:
169+
return session.run(
170+
latitude,
171+
longitude,
172+
week=week,
173+
)

0 commit comments

Comments
 (0)