New Model Implementation
This commit is contained in:
+1
-1
@@ -1,7 +1,7 @@
|
||||
*.pyc
|
||||
*.flac
|
||||
.vscode
|
||||
model/*
|
||||
|
||||
datasets/
|
||||
birdnet.conf
|
||||
IdentifiedSoFar.txt
|
||||
|
||||
@@ -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
@@ -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">
|
||||
|
||||
@@ -812,3 +812,7 @@ pre#timer.bash {
|
||||
padding:3px;
|
||||
background-color:#9fe29b
|
||||
}
|
||||
|
||||
#ddnewline::before {
|
||||
content: none;
|
||||
}
|
||||
+1
-1
@@ -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.
@@ -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>
|
||||
|
||||
@@ -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_________________#
|
||||
|
||||
@@ -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
@@ -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) + ';'
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user