New Model Implementation

This commit is contained in:
ehpersonal38
2023-01-14 15:22:39 -05:00
parent e2062362b8
commit 84763bf5b7
13 changed files with 177 additions and 9 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
*.pyc
*.flac
.vscode
model/*
datasets/
birdnet.conf
IdentifiedSoFar.txt
+5
View File
@@ -6,6 +6,11 @@
SITE_NAME=""
#--------------------------------- Model --------------------------------------#
#_____________The variable below configures which BirdNET model is_____________#
#______________________used for detecting bird audio.__________________________#
MODEL=BirdNET_6K_GLOBAL_MODEL
#--------------------- Required: Latitude, and Longitude ----------------------#
+1 -1
View File
@@ -17,7 +17,7 @@ body::-webkit-scrollbar {
display:none
}
</style>
<link rel="stylesheet" href="style.css?v=8.05.22">
<link rel="stylesheet" href="style.css?v=1.14.23">
<link rel="stylesheet" type="text/css" href="static/dialog-polyfill.css" />
<body>
<div class="banner">
+4
View File
@@ -811,4 +811,8 @@ pre#timer.bash {
line-height:5px;
padding:3px;
background-color:#9fe29b
}
#ddnewline::before {
content: none;
}
+1 -1
View File
@@ -21,7 +21,7 @@ if (file_exists('./scripts/thisrun.txt')) {
$config = parse_ini_file('./scripts/firstrun.ini');
}
?>
<link rel="stylesheet" href="style.css?v=8.05.22">
<link rel="stylesheet" href="style.css?v=1.14.23">
<style>
body::-webkit-scrollbar {
display:none
Binary file not shown.
Binary file not shown.
Binary file not shown.
+52
View File
@@ -34,6 +34,7 @@ if(isset($_GET["latitude"])){
$flickr_filter_email = $_GET["flickr_filter_email"];
$language = $_GET["language"];
$timezone = $_GET["timezone"];
$model = $_GET["model"];
if(isset($_GET['apprise_notify_each_detection'])) {
$apprise_notify_each_detection = 1;
@@ -100,6 +101,23 @@ if(isset($_GET["latitude"])){
syslog(LOG_INFO, "Successfully changed language to '$language'");
}
if ($model != $lang_config['MODEL']){
$user = trim(shell_exec("awk -F: '/1000/{print $1}' /etc/passwd"));
$home = trim(shell_exec("awk -F: '/1000/{print $6}' /etc/passwd"));
// Archive old language file
syslog_shell_exec("cp -f $home/BirdNET-Pi/model/labels.txt $home/BirdNET-Pi/model/labels.txt.old", $user);
if($model == "BirdNET_GLOBAL_3K_V2.2_Model_FP16"){
// Install new language label file
syslog_shell_exec("$home/BirdNET-Pi/scripts/install_language_label_nm.sh -l $language", $user);
} else {
syslog_shell_exec("$home/BirdNET-Pi/scripts/install_language_label.sh -l $language", $user);
}
syslog(LOG_INFO, "Successfully changed language to '$language'");
}
$contents = file_get_contents("/etc/birdnet/birdnet.conf");
$contents = preg_replace("/SITE_NAME=.*/", "SITE_NAME=\"$site_name\"", $contents);
@@ -116,6 +134,7 @@ if(isset($_GET["latitude"])){
$contents = preg_replace("/DATABASE_LANG=.*/", "DATABASE_LANG=$language", $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("/MODEL=.*/", "MODEL=$model", $contents);
$contents2 = file_get_contents("./scripts/thisrun.txt");
$contents2 = preg_replace("/SITE_NAME=.*/", "SITE_NAME=\"$site_name\"", $contents2);
@@ -132,6 +151,7 @@ if(isset($_GET["latitude"])){
$contents2 = preg_replace("/DATABASE_LANG=.*/", "DATABASE_LANG=$language", $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("/MODEL=.*/", "MODEL=$model", $contents2);
if($site_name != $config["SITE_NAME"]) {
@@ -304,6 +324,38 @@ function sendTestNotification(e) {
xmlHttp.send(null);
}
</script>
<table class="settingstable"><tr><td>
<h2>Model</h2>
<label for="model">Select a Model: </label>
<select name="model">
<?php
$models = array("BirdNET_6K_GLOBAL_MODEL", "BirdNET_GLOBAL_3K_V2.2_Model_FP16");
foreach($models as $modelName){
$isSelected = "";
if($config['MODEL'] == $modelName){
$isSelected = 'selected="selected"';
}
echo "<option value='{$modelName}' $isSelected>$modelName</option>";
}
?>
</select>
<dl>
<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>
<dt>BirdNET_GLOBAL_3K_V2.2_Model_FP16 (2022+)</dt>
<dd id="ddnewline">This model comes from BirdNET-Analyzer, a newer work-in-progress project with aims to improve on the old model. Currently it only supports about 3,500 species worldwide, so for users in North America, this model is generally much more accurate than the above model, but elsewhere it will be less accurate and possibly useless.</dd>
</dl>
</td></tr></table><br>
<table class="settingstable"><tr><td>
<h2>BirdWeather</h2>
<label for="birdweather_id">BirdWeather ID: </label>
<input name="birdweather_id" type="text" value="<?php print($config['BIRDWEATHER_ID']);?>" /><br>
<p><a href="https://app.birdweather.com" target="_blank">BirdWeather.com</a> is a weather map for bird sounds. Stations around the world supply audio and video streams to BirdWeather where they are then analyzed by BirdNET and compared to eBird Grid data. BirdWeather catalogues the bird audio and spectrogram visualizations so that you can listen to, view, and read about birds throughout the world. <a href="mailto:tim@birdweather.com?subject=Request%20BirdWeather%20ID&body=<?php include('./scripts/birdweather_request.php'); ?>" target="_blank">Email Tim</a> to request a BirdWeather ID</p>
</td></tr></table><br>
<table class="settingstable"><tr><td>
<h2>Location</h2>
+6
View File
@@ -27,6 +27,12 @@ SITE_NAME="$HOSTNAME"
LATITUDE=$(curl -s4 ifconfig.co/json | jq .latitude)
LONGITUDE=$(curl -s4 ifconfig.co/json | jq .longitude)
#--------------------------------- Model --------------------------------------#
#_____________The variable below configures which BirdNET model is_____________#
#______________________used for detecting bird audio.__________________________#
MODEL=BirdNET_6K_GLOBAL_MODEL
#--------------------- BirdWeather Station Information -----------------------#
#_____________The variable below can be set to have your BirdNET-Pi____________#
#__________________also act as a BirdWeather listening station_________________#
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
usage() { echo "Usage: $0 -l <language i18n id>" 1>&2; exit 1; }
while getopts "l:" o; do
case "${o}" in
l)
lang=${OPTARG}
;;
*)
usage
;;
esac
done
shift $((OPTIND-1))
HOME=$(awk -F: '/1000/ {print $6}' /etc/passwd)
label_file_name="labels_${lang}.txt"
unzip -o $HOME/BirdNET-Pi/model/labels_nm.zip $label_file_name \
-d $HOME/BirdNET-Pi/model \
&& mv -f $HOME/BirdNET-Pi/model/$label_file_name $HOME/BirdNET-Pi/model/labels.txt \
&& logger "[$0] Changed language label file to '$label_file_name'";
exit 0
+77 -6
View File
@@ -35,6 +35,7 @@ DISCONNECT_MESSAGE = "!DISCONNECT"
userDir = os.path.expanduser('~')
DB_PATH = userDir + '/BirdNET-Pi/scripts/birds.db'
PREDICTED_SPECIES_LIST = []
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
@@ -51,7 +52,7 @@ with open(userDir + '/BirdNET-Pi/scripts/thisrun.txt', 'r') as f:
this_run = f.readlines()
audiofmt = "." + str(str(str([i for i in this_run if i.startswith('AUDIOFMT')]).split('=')[1]).split('\\')[0])
priv_thresh = float("." + str(str(str([i for i in this_run if i.startswith('PRIVACY_THRESHOLD')]).split('=')[1]).split('\\')[0])) / 10
model = str(str(str([i for i in this_run if i.startswith('MODEL')]).split('=')[1]).split('\\')[0])
def loadModel():
@@ -63,7 +64,8 @@ def loadModel():
print('LOADING TF LITE MODEL...', end=' ')
# Load TFLite model and allocate tensors.
modelpath = userDir + '/BirdNET-Pi/model/BirdNET_6K_GLOBAL_MODEL.tflite'
# model will either be BirdNET_GLOBAL_3K_V2.2_MData_Model_FP16 (new) or BirdNET_6K_GLOBAL_MODEL (old)
modelpath = userDir + '/BirdNET-Pi/model/'+model+'.tflite'
myinterpreter = tflite.Interpreter(model_path=modelpath, num_threads=2)
myinterpreter.allocate_tensors()
@@ -73,7 +75,8 @@ def loadModel():
# Get input tensor index
INPUT_LAYER_INDEX = input_details[0]['index']
MDATA_INPUT_INDEX = input_details[1]['index']
if model == "BirdNET_6K_GLOBAL_MODEL":
MDATA_INPUT_INDEX = input_details[1]['index']
OUTPUT_LAYER_INDEX = output_details[0]['index']
# Load labels
@@ -87,6 +90,68 @@ def loadModel():
return myinterpreter
def loadMetaModel():
global M_INTERPRETER
global M_INPUT_LAYER_INDEX
global M_OUTPUT_LAYER_INDEX
# 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']
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 predictSpeciesList(lat, lon, week):
l_filter = explore(lat, lon, week)
for s in l_filter:
if s[0] >= 0.03:
PREDICTED_SPECIES_LIST.append(s[1])
def loadCustomSpeciesList(path):
@@ -162,7 +227,8 @@ def predict(sample, sensitivity):
global INTERPRETER
# Make a prediction
INTERPRETER.set_tensor(INPUT_LAYER_INDEX, np.array(sample[0], dtype='float32'))
INTERPRETER.set_tensor(MDATA_INPUT_INDEX, np.array(sample[1], dtype='float32'))
if model == "BirdNET_6K_GLOBAL_MODEL":
INTERPRETER.set_tensor(MDATA_INPUT_INDEX, np.array(sample[1], dtype='float32'))
INTERPRETER.invoke()
prediction = INTERPRETER.get_tensor(OUTPUT_LAYER_INDEX)[0]
@@ -197,6 +263,11 @@ def analyzeAudioData(chunks, lat, lon, week, sensitivity, overlap,):
start = time.time()
print('ANALYZING AUDIO...', end=' ', flush=True)
if model == "BirdNET_GLOBAL_3K_V2.2_MData_Model_FP16":
if len(PREDICTED_SPECIES_LIST) == 0:
predictSpeciesList(lat,lon,week)
# Convert and prepare metadata
mdata = convertMetadata(np.array([lat, lon, week]))
mdata = np.expand_dims(mdata, 0)
@@ -242,7 +313,7 @@ def writeResultsToFile(detections, min_conf, path):
rfile.write('Start (s);End (s);Scientific name;Common name;Confidence\n')
for d in detections:
for entry in detections[d]:
if entry[1] >= min_conf and ((entry[0] in INCLUDE_LIST or len(INCLUDE_LIST) == 0) and (entry[0] not in EXCLUDE_LIST or len(EXCLUDE_LIST) == 0)):
if entry[1] >= min_conf and ((entry[0] in INCLUDE_LIST or len(INCLUDE_LIST) == 0) and (entry[0] not in EXCLUDE_LIST or len(EXCLUDE_LIST) == 0) and (entry[0] in PREDICTED_SPECIES_LIST or len(PREDICTED_SPECIES_LIST) == 0) ):
rfile.write(d + ';' + entry[0].replace('_', ';') + ';' + str(entry[1]) + '\n')
rcnt += 1
print('DONE! WROTE', rcnt, 'RESULTS.')
@@ -364,7 +435,7 @@ def handle_client(conn, addr):
species_apprised_this_run = []
for entry in detections[d]:
if entry[1] >= min_conf and ((entry[0] in INCLUDE_LIST or len(INCLUDE_LIST) == 0)
and (entry[0] not in EXCLUDE_LIST or len(EXCLUDE_LIST) == 0)):
and (entry[0] not in EXCLUDE_LIST or len(EXCLUDE_LIST) == 0) and (entry[0] in PREDICTED_SPECIES_LIST or len(PREDICTED_SPECIES_LIST) == 0) ):
# Write to text file.
rfile.write(str(current_date) + ';' + str(current_time) + ';' + entry[0].replace('_', ';') + ';'
+ str(entry[1]) + ";" + str(args.lat) + ';' + str(args.lon) + ';' + str(min_conf) + ';' + str(week) + ';'
+4
View File
@@ -144,5 +144,9 @@ if ! grep HEARTBEAT_URL /etc/birdnet/birdnet.conf &>/dev/null;then
sudo -u$USER echo "HEARTBEAT_URL=" >> /etc/birdnet/birdnet.conf
fi
if ! grep MODEL /etc/birdnet/birdnet.conf &>/dev/null;then
sudo -u$USER echo "MODEL=BirdNET_6K_GLOBAL_MODEL" >> /etc/birdnet/birdnet.conf
fi
sudo systemctl daemon-reload
restart_services.sh