SF_THRESH config
This commit is contained in:
@@ -11,6 +11,7 @@ SITE_NAME=""
|
|||||||
#______________________used for detecting bird audio.__________________________#
|
#______________________used for detecting bird audio.__________________________#
|
||||||
|
|
||||||
MODEL=BirdNET_6K_GLOBAL_MODEL
|
MODEL=BirdNET_6K_GLOBAL_MODEL
|
||||||
|
SF_THRESH=0.5
|
||||||
|
|
||||||
#--------------------- Required: Latitude, and Longitude ----------------------#
|
#--------------------- Required: Latitude, and Longitude ----------------------#
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ if(isset($_GET["latitude"])){
|
|||||||
$language = $_GET["language"];
|
$language = $_GET["language"];
|
||||||
$timezone = $_GET["timezone"];
|
$timezone = $_GET["timezone"];
|
||||||
$model = $_GET["model"];
|
$model = $_GET["model"];
|
||||||
|
$sf_thresh = $_GET["sf_thresh"];
|
||||||
|
|
||||||
if(isset($_GET['apprise_notify_each_detection'])) {
|
if(isset($_GET['apprise_notify_each_detection'])) {
|
||||||
$apprise_notify_each_detection = 1;
|
$apprise_notify_each_detection = 1;
|
||||||
@@ -135,6 +136,7 @@ if(isset($_GET["latitude"])){
|
|||||||
$contents = preg_replace("/FLICKR_FILTER_EMAIL=.*/", "FLICKR_FILTER_EMAIL=$flickr_filter_email", $contents);
|
$contents = preg_replace("/FLICKR_FILTER_EMAIL=.*/", "FLICKR_FILTER_EMAIL=$flickr_filter_email", $contents);
|
||||||
$contents = preg_replace("/APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES=.*/", "APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES=$minimum_time_limit", $contents);
|
$contents = preg_replace("/APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES=.*/", "APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES=$minimum_time_limit", $contents);
|
||||||
$contents = preg_replace("/MODEL=.*/", "MODEL=$model", $contents);
|
$contents = preg_replace("/MODEL=.*/", "MODEL=$model", $contents);
|
||||||
|
$contents = preg_replace("/SF_THRESH=.*/", "SF_THRESH=$sf_thresh", $contents);
|
||||||
|
|
||||||
$contents2 = file_get_contents("./scripts/thisrun.txt");
|
$contents2 = file_get_contents("./scripts/thisrun.txt");
|
||||||
$contents2 = preg_replace("/SITE_NAME=.*/", "SITE_NAME=\"$site_name\"", $contents2);
|
$contents2 = preg_replace("/SITE_NAME=.*/", "SITE_NAME=\"$site_name\"", $contents2);
|
||||||
@@ -152,6 +154,8 @@ if(isset($_GET["latitude"])){
|
|||||||
$contents2 = preg_replace("/FLICKR_FILTER_EMAIL=.*/", "FLICKR_FILTER_EMAIL=$flickr_filter_email", $contents2);
|
$contents2 = preg_replace("/FLICKR_FILTER_EMAIL=.*/", "FLICKR_FILTER_EMAIL=$flickr_filter_email", $contents2);
|
||||||
$contents2 = preg_replace("/APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES=.*/", "APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES=$minimum_time_limit", $contents2);
|
$contents2 = preg_replace("/APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES=.*/", "APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES=$minimum_time_limit", $contents2);
|
||||||
$contents2 = preg_replace("/MODEL=.*/", "MODEL=$model", $contents2);
|
$contents2 = preg_replace("/MODEL=.*/", "MODEL=$model", $contents2);
|
||||||
|
$contents2 = preg_replace("/SF_THRESH=.*/", "SF_THRESH=$sf_thresh", $contents2);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if($site_name != $config["SITE_NAME"]) {
|
if($site_name != $config["SITE_NAME"]) {
|
||||||
@@ -342,6 +346,10 @@ function sendTestNotification(e) {
|
|||||||
?>
|
?>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<label for="latitude">Species occurance frequency threshold: </label>
|
||||||
|
<p>This value is used by the model to constrain the list of possible species that it will try to detect, given the minimum occurence frequency. A 0.05 threshold means that the species is seen on average at least 5% of the time, from historically collected data for your lat/lon.<br>If you'd like to tinker with this value and see the species list output, you can run the following command:<pre class="bash">~/BirdNET-Pi/birdnet/bin/python3 species.py --threshold 0.7</pre></p>
|
||||||
|
<input name="latitude" type="number" max="90" min="-90" step="0.0001" value="<?php print($config['LATITUDE']);?>" required/><br>
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt>BirdNET_6K_GLOBAL_MODEL (2020)</dt><br>
|
<dt>BirdNET_6K_GLOBAL_MODEL (2020)</dt><br>
|
||||||
<dd id="ddnewline">This model comes from BirdNET-Lite, with bird sound recognition for more than 6,000 species worldwide. This is the default option and will generally work very well for most use cases.</dd>
|
<dd id="ddnewline">This model comes from BirdNET-Lite, with bird sound recognition for more than 6,000 species worldwide. This is the default option and will generally work very well for most use cases.</dd>
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ LONGITUDE=$(curl -s4 ifconfig.co/json | jq .longitude)
|
|||||||
#______________________used for detecting bird audio.__________________________#
|
#______________________used for detecting bird audio.__________________________#
|
||||||
|
|
||||||
MODEL=BirdNET_6K_GLOBAL_MODEL
|
MODEL=BirdNET_6K_GLOBAL_MODEL
|
||||||
|
SF_THRESH=0.5
|
||||||
|
|
||||||
#--------------------- BirdWeather Station Information -----------------------#
|
#--------------------- BirdWeather Station Information -----------------------#
|
||||||
#_____________The variable below can be set to have your BirdNET-Pi____________#
|
#_____________The variable below can be set to have your BirdNET-Pi____________#
|
||||||
|
|||||||
@@ -0,0 +1,139 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
from tzlocal import get_localzone
|
||||||
|
import datetime
|
||||||
|
import sqlite3
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
import math
|
||||||
|
import numpy as np
|
||||||
|
import librosa
|
||||||
|
import operator
|
||||||
|
import socket
|
||||||
|
import threading
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import argparse
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
try:
|
||||||
|
import tflite_runtime.interpreter as tflite
|
||||||
|
except BaseException:
|
||||||
|
from tensorflow import lite as tflite
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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_3K_V2.2_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):
|
||||||
|
|
||||||
|
global M_INTERPRETER
|
||||||
|
|
||||||
|
# Does interpreter exist?
|
||||||
|
try:
|
||||||
|
if M_INTERPRETER == None:
|
||||||
|
loadMetaModel()
|
||||||
|
except Exception as e:
|
||||||
|
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):
|
||||||
|
|
||||||
|
# Make filter prediction
|
||||||
|
l_filter = predictFilter(lat, lon, week)
|
||||||
|
|
||||||
|
# Apply threshold
|
||||||
|
l_filter = np.where(l_filter >= 0.03, 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)
|
||||||
|
|
||||||
|
# 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'
|
||||||
|
with open(userDir + '/BirdNET-Pi/scripts/thisrun.txt', 'r') as f:
|
||||||
|
|
||||||
|
this_run = f.readlines()
|
||||||
|
lat = str(str(str([i for i in this_run if i.startswith('LATITUDE')]).split('=')[1]).split('\\')[0])
|
||||||
|
lon = str(str(str([i for i in this_run if i.startswith('LONGITUDE')]).split('=')[1]).split('\\')[0])
|
||||||
|
|
||||||
|
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('--o', default='/home/pi/BirdNET-Pi/include_species_list.txt', help='Path to output file or folder. If this is a folder, file will be named \'species_list.txt\'.')
|
||||||
|
#parser.add_argument('--lat', type=float, default=##, help='Recording location latitude. Set -1 to ignore.')
|
||||||
|
#parser.add_argument('--lon', type=float, default=##, help='Recording location longitude. Set -1 to ignore.')
|
||||||
|
#parser.add_argument('--week', type=int, default=dayofweek, help='Week of the year when the recording was made. Values in [1, 48] (4 weeks per month). Set -1 for year-round species list.')
|
||||||
|
parser.add_argument('--threshold', type=float, default=0.05, help='Occurrence frequency threshold. Defaults to 0.05.')
|
||||||
|
#parser.add_argument('--sortby', default='freq', help='Sort species by occurrence frequency or alphabetically. Values in [\'freq\', \'alpha\']. Defaults to \'freq\'.')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
LOCATION_FILTER_THRESHOLD = args.threshold
|
||||||
|
|
||||||
|
# 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("\nThe above species list describes all of the species that have been historically observed at the specified lat/long ("+lat+", "+lon+") for this week of the year. The frequency threshold is the percentage of submitted eBird checklists that the species appeared on, meaning a higher threshold means that the species is more common.")
|
||||||
|
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)")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -147,6 +147,9 @@ fi
|
|||||||
if ! grep MODEL /etc/birdnet/birdnet.conf &>/dev/null;then
|
if ! grep MODEL /etc/birdnet/birdnet.conf &>/dev/null;then
|
||||||
sudo -u$USER echo "MODEL=BirdNET_6K_GLOBAL_MODEL" >> /etc/birdnet/birdnet.conf
|
sudo -u$USER echo "MODEL=BirdNET_6K_GLOBAL_MODEL" >> /etc/birdnet/birdnet.conf
|
||||||
fi
|
fi
|
||||||
|
if ! grep SF_THRESH /etc/birdnet/birdnet.conf &>/dev/null;then
|
||||||
|
sudo -u$USER echo "SF_THRESH=0.5" >> /etc/birdnet/birdnet.conf
|
||||||
|
fi
|
||||||
|
|
||||||
sudo systemctl daemon-reload
|
sudo systemctl daemon-reload
|
||||||
restart_services.sh
|
restart_services.sh
|
||||||
|
|||||||
Reference in New Issue
Block a user