From d8d0d5aa0993ef6ec59c43e8676de93f396f39f8 Mon Sep 17 00:00:00 2001 From: frederik Date: Sat, 8 Nov 2025 14:59:49 +0100 Subject: [PATCH] use models.py, add support for data model V2 --- scripts/species.py | 137 +++++++++------------------------------------ 1 file changed, 26 insertions(+), 111 deletions(-) diff --git a/scripts/species.py b/scripts/species.py index 56be8be..477e698 100644 --- a/scripts/species.py +++ b/scripts/species.py @@ -2,123 +2,38 @@ import argparse import datetime import os -import numpy as np +from utils.helpers import get_settings, MODEL_PATH +from utils.models import MDataModel1, MDataModel2 -from utils.helpers import get_settings - -try: - import tflite_runtime.interpreter as tflite -except BaseException: - from tensorflow import lite as tflite - -M_INTERPRETER, M_INPUT_LAYER_INDEX, M_OUTPUT_LAYER_INDEX, CLASSES = (None, None, None, None) - - -def loadMetaModel(): - global M_INTERPRETER - global M_INPUT_LAYER_INDEX - global M_OUTPUT_LAYER_INDEX - global CLASSES - - # Load TFLite model and allocate tensors. - M_INTERPRETER = tflite.Interpreter(model_path=userDir + '/BirdNET-Pi/model/BirdNET_GLOBAL_6K_V2.4_MData_Model_FP16.tflite') - M_INTERPRETER.allocate_tensors() - - # Get input and output tensors. - input_details = M_INTERPRETER.get_input_details() - output_details = M_INTERPRETER.get_output_details() - - # Get input tensor index - M_INPUT_LAYER_INDEX = input_details[0]['index'] - M_OUTPUT_LAYER_INDEX = output_details[0]['index'] - - # Load labels - CLASSES = [] - labelspath = userDir + '/BirdNET-Pi/model/labels.txt' - with open(labelspath, 'r') as lfile: - for line in lfile.readlines(): - CLASSES.append(line.replace('\n', '')) - - print("loaded META model") - - -def predictFilter(lat, lon, week): - # Does interpreter exist? - try: - if M_INTERPRETER is None: - loadMetaModel() - except Exception: - loadMetaModel() - - # Prepare mdata as sample - sample = np.expand_dims(np.array([lat, lon, week], dtype='float32'), 0) - - # Run inference - M_INTERPRETER.set_tensor(M_INPUT_LAYER_INDEX, sample) - M_INTERPRETER.invoke() - - return M_INTERPRETER.get_tensor(M_OUTPUT_LAYER_INDEX)[0] - - -def explore(lat, lon, week, threshold): - - # Make filter prediction - l_filter = predictFilter(lat, lon, week) - - # Apply threshold - l_filter = np.where(l_filter >= threshold, l_filter, 0) - - # Zip with labels - l_filter = list(zip(l_filter, CLASSES)) - - # Sort by filter value - l_filter = sorted(l_filter, key=lambda x: x[0], reverse=True) - - return l_filter - - -def getSpeciesList(lat, lon, week, threshold=0.05, sort=False): - - print('Getting species list for {}/{}, Week {}...'.format(lat, lon, week), end='', flush=True) - - # Extract species from model - pred = explore(lat, lon, week, threshold) - - # Make species list - slist = [] - for p in pred: - if p[0] >= threshold: - slist.append([p[1], p[0]]) - - return slist - - -userDir = os.path.expanduser('~') -DB_PATH = userDir + '/BirdNET-Pi/scripts/birds.db' - -conf = get_settings() -lat = conf.getfloat('LATITUDE') -lon = conf.getfloat('LONGITUDE') - -weekofyear = datetime.datetime.today().isocalendar()[1] if __name__ == '__main__': - - # Parse arguments parser = argparse.ArgumentParser( description='Get list of species for a given location with BirdNET. Sorted by occurrence frequency.' ) - parser.add_argument('--threshold', type=float, default=0.05, help='Occurrence frequency threshold. Defaults to 0.05.') - + parser.add_argument('--threshold', type=float, default=0.05, + help='Occurrence frequency threshold. Defaults to 0.05.') args = parser.parse_args() - LOCATION_FILTER_THRESHOLD = args.threshold + conf = get_settings() + lat = conf.getfloat('LATITUDE') + lon = conf.getfloat('LONGITUDE') + week = datetime.datetime.today().isocalendar()[1] - # Get species list - species_list = getSpeciesList(lat, lon, weekofyear, LOCATION_FILTER_THRESHOLD, False) - for x in range(len(species_list)): - print(species_list[x][0] + " - " + str(species_list[x][1])) + print(f'Getting species list for {lat}/{lon}, Week {week}...', flush=True) + labels_path = os.path.join(MODEL_PATH, 'labels.txt') + with open(labels_path, 'r') as lfile: + labels = [line.strip() for line in lfile] - print("\nThe above species list describes all the species that the model will attempt to detect. \ - If you don't see a species you want detected on this list, decrease your threshold.") - print("\nNOTE: no actual changes to your BirdNET-Pi species list were made by running this command. \ - To set your desired frequency threshold, do it through the BirdNET-Pi web interface (Tools -> Settings -> Model)") + model = MDataModel1(args.threshold) if conf.getint('DATA_MODEL_VERSION') == 1 else MDataModel2(args.threshold) + model.set_meta_data(lat, lon, week) + species_list = model.get_species_list_details(labels) + + for species in species_list: + print(f'{species[1]} - {species[0]:.4f}') + + print(""" +The above species list describes all the species that the model will attempt to detect. +If you don't see a species you want detected on this list, decrease your threshold. + +NOTE: no actual changes to your BirdNET-Pi species list were made by running this command. +To set your desired frequency threshold, do it through the BirdNET-Pi web interface (Tools -> Settings -> Model) +""")