File size: 3,688 Bytes
1582553 f16709f 1582553 f532fdf 1582553 f16709f 1582553 f532fdf 1582553 f16709f 1582553 f16709f fc72c3a f16709f 1582553 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
from pathlib import Path
import numpy as np
from iSparrow.sparrow_model_base import ModelBase
# from iSparrow import utils
class Model(ModelBase):
"""
Model Model class representing the the default birdnet model. Does currently not support custom species list or species prediction based on coordinates.
"""
def __init__(
self,
model_path: str,
num_threads: int = 1,
sigmoid_sensitivity: float = 1.0,
species_list_file: str = None,
**kwargs
):
"""
__init__ Create a new model instance that uses birdnet-analyzer models for bird species classification
Args:
model_path (str): Path to the location of the model file to be loaded
num_threads (int, optional): Number of threads used for inference. Defaults to 1.
sigmoid_sensitivity (float, optional): Parameter of the sigmoid function used to compute probabilities. Defaults to 1.0.
Raises:
AnalyzerConfigurationError: The model file 'model.tflite' doesn't exist at the given path.
AnalyzerConfigurationError: The labels file 'labels.txt' doesn't exist at the given path.
"""
labels_path = str(Path(model_path) / "labels.txt")
model_path = str(Path(model_path) / "model.tflite")
# base class loads the model and labels
super().__init__(
"birdnet_default",
model_path,
labels_path,
num_threads=num_threads,
**kwargs
)
self.sigmoid_sensitivity = sigmoid_sensitivity
# store input and output index to not have to retrieve them each time an inference is made
input_details = self.model.get_input_details()
output_details = self.model.get_output_details()
# Get input tensor index
self.input_layer_index = input_details[0]["index"]
# Get classification output or feature embeddings as output, depending on presence fo custom classifier
self.output_layer_index = output_details[0]["index"]
def load_species_list(self):
# TODO
pass
def predict(self, sample: np.array) -> np.array:
"""
predict Make inference about the bird species for the preprocessed data passed to this function as arguments.
Args:
data (np.array): list of preprocessed data chunks
Returns:
list: List of (label, inferred_probability)
"""
data = np.array([sample], dtype="float32")
self.model.resize_tensor_input(
self.input_layer_index, [len(data), *data[0].shape]
)
self.model.allocate_tensors()
# Make a prediction (Audio only for now)
self.model.set_tensor(self.input_layer_index, np.array(data, dtype="float32"))
self.model.invoke()
prediction = self.model.get_tensor(self.output_layer_index)
confidence = self._sigmoid(
np.array(prediction), sigmoid_sensitivity=-self.sigmoid_sensitivity
)
return confidence
@classmethod
def from_cfg(cls, sparrow_folder: str, cfg: dict):
"""
from_cfg Create a new instance from a dictionary containing keyword arguments. Usually loaded from a config file.
Args:
sparrow_dir (str): Installation directory of the Sparrow package
cfg (dict): Dictionary containing the keyword arguments
Returns:
Model: New model instance created with the supplied kwargs.
"""
cfg["model_path"] = str(
Path(sparrow_folder) / Path("models") / cfg["model_path"]
)
return cls(**cfg)
|