Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
3b25828
Add onboarding task
ohwenyi Mar 15, 2026
9dae747
Updated Onboarding Task with Dinh Kim Thanh Nguyen
ndktwork Mar 21, 2026
6ada96d
Merge branch 'main' into EE/Dinh/UpdateOnboardingTask
ndktwork Mar 21, 2026
a32a185
Updated Onboarding Task with OF
AlphaArcturus Mar 22, 2026
f908b43
Moved and renamed onboarding notebook
AlphaArcturus Mar 22, 2026
201fc4f
Update onboarding notebook
AlphaArcturus Mar 22, 2026
d3c0c85
Restore onboarding template notebook
AlphaArcturus Mar 22, 2026
900460b
Complete onboarding task
Mar 22, 2026
681127a
Completed onboarding task
Kunalanand077 Mar 22, 2026
8878f80
Updated Onboarding Task with YZ
223089688 Mar 24, 2026
834be07
Completed onboarding task - added bird descriptions
Vamshi-Gollapelly Apr 2, 2026
1344288
Merge branch 'main' into EHMI/VG/onboarding-task
Vamshi-Gollapelly Apr 2, 2026
1a9d98b
Merge branch 'main' into EE/YZ/OnboardingTask
s223089688 Apr 4, 2026
aa57913
Validation of calibration method on optimal models
dinalfer-wq Apr 5, 2026
b71aca1
calibration validation
dinalfer-wq Apr 5, 2026
609f67a
Merge branch 'main' into EHMI/VG/onboarding-task
Vamshi-Gollapelly Apr 7, 2026
1047b00
Merge branch 'main' into EHMI/VG/onboarding-task
Vamshi-Gollapelly Apr 15, 2026
61748bd
Merge branch 'main' into EE/YZ/OnboardingTask
s223089688 Apr 17, 2026
0a0154f
Merge branch 'main' into EHMI/VG/onboarding-task
Vamshi-Gollapelly Apr 26, 2026
57b1ae6
Sprint 2: augmentation benchmarking notebook
kiran497 May 2, 2026
5180d70
Updated Sprint 2 notebook
kiran497 May 3, 2026
f8a59e0
Add Sprint 2 augmentation benchmarking README
kiran497 May 3, 2026
5649d51
Add Sprint 2 update for calibration research
223089688 May 9, 2026
ff64542
Merge branch 'main' into EE/YZ/Task2.1-CalibrationResearch-Sprint2
s223089688 May 9, 2026
833742f
Fix IoT engine integration and add edge inference support
mraula May 13, 2026
1aed1dd
Merge branch 'main' into EE/RM/iot-engine-integration
mraula May 13, 2026
30aa067
Added error_analysis
jackhatesgravity May 14, 2026
32bf6a5
Merge branch 'main' into EHMI/VG/onboarding-task
Vamshi-Gollapelly May 15, 2026
b8381b6
Sprint 2: Add API status badge, environment detection, and env setup …
kimmynoto May 15, 2026
baee05c
Merge branch 'main' into EE/YZ/Task2.1-CalibrationResearch-Sprint2
s223089688 May 15, 2026
24fdac9
feat(frontend): Task 7 — shared UI utilities, loading states, retry h…
Vamshi-Gollapelly May 16, 2026
009f490
Merge branch 'main' into feature/task7-shared-ui-utilities
Vamshi-Gollapelly May 16, 2026
48269a0
Merge branch 'main' into EHMI/kn/sprint2-api-status
kimmynoto May 16, 2026
253e5be
Merge pull request #906 from DataBytes-Organisation/feature/task7-sha…
KishanFW May 16, 2026
a6b4225
Merge branch 'main' into EHMI/kn/sprint2-api-status
KishanFW May 16, 2026
260494b
Merge branch 'main' into EE/JMP/error_analysis
KishanFW May 16, 2026
f2f843d
Merge pull request #904 from DataBytes-Organisation/EE/JMP/error_anal…
KishanFW May 16, 2026
88f20c2
Merge branch 'main' into EE/RM/iot-engine-integration
KishanFW May 16, 2026
a1eefe2
Merge branch 'main' into EE/YZ/Task2.1-CalibrationResearch-Sprint2
KishanFW May 16, 2026
28104c0
Merge pull request #901 from DataBytes-Organisation/EE/YZ/Task2.1-Cal…
KishanFW May 16, 2026
1c098ba
Merge branch 'main' into sprint2-augmentation
KishanFW May 16, 2026
65ebf57
Merge pull request #897 from DataBytes-Organisation/sprint2-augmentation
KishanFW May 16, 2026
0c6853d
Merge branch 'main' into EHMI/kn/sprint2-api-status
KishanFW May 16, 2026
2181306
Merge branch 'main' into EE/Dinal/Task2.3
KishanFW May 16, 2026
a3bb245
Merge pull request #905 from DataBytes-Organisation/EHMI/kn/sprint2-a…
KishanFW May 16, 2026
ac4f142
Merge pull request #903 from DataBytes-Organisation/EE/RM/iot-engine-…
KishanFW May 16, 2026
e22ae20
Merge branch 'main' into EE/Dinal/Task2.3
KishanFW May 16, 2026
3ff96b5
Merge pull request #884 from DataBytes-Organisation/EE/Dinal/Task2.3
KishanFW May 16, 2026
c93e10a
Merge branch 'main' into EHMI/VG/onboarding-task
KishanFW May 16, 2026
eb9f623
Merge branch 'main' into EE/Dinh/UpdateOnboardingTask
KishanFW May 16, 2026
e990a62
Merge pull request #872 from DataBytes-Organisation/EE/Dinh/UpdateOnb…
KishanFW May 16, 2026
9185df6
Merge branch 'main' into EE/YZ/OnboardingTask
KishanFW May 16, 2026
e7da3a6
Merge pull request #876 from DataBytes-Organisation/EE/YZ/OnboardingTask
KishanFW May 16, 2026
f246b50
Merge branch 'main' into EHMI/ow/onboarding-task
KishanFW May 16, 2026
33b350f
Merge branch 'main' into EHMI/VG/onboarding-task
KishanFW May 16, 2026
14f98ec
Merge branch 'main' into EE/OF/Onboarding-Task
KishanFW May 16, 2026
3b45231
Merge pull request #874 from DataBytes-Organisation/EE/OF/Onboarding-…
KishanFW May 16, 2026
148a61d
Merge branch 'main' into EHMI/VG/onboarding-task
KishanFW May 17, 2026
ec5e367
Merge pull request #879 from DataBytes-Organisation/EHMI/VG/onboardin…
KishanFW May 17, 2026
1e54fa3
Merge branch 'main' into EHMI/ow/onboarding-task
KishanFW May 17, 2026
cee976b
Merge pull request #875 from DataBytes-Organisation/EHMI/ow/onboardin…
KishanFW May 17, 2026
07f662a
Add engine maintainability guide and handover workbook
AlphaArcturus May 17, 2026
e682b6d
Merge branch 'main' into EE/OF/maintainability-guide
KishanFW May 17, 2026
29a2522
Merge pull request #907 from DataBytes-Organisation/EE/OF/maintainabi…
KishanFW May 17, 2026
8392d8e
Added Sprint 2 Task 4 dataset readiness workflow
May 17, 2026
284355c
Merge branch 'main' into EE/DS/Dataset-Readiness
KishanFW May 17, 2026
e0bfc4b
Merge pull request #909 from DataBytes-Organisation/EE/DS/Dataset-Rea…
KishanFW May 17, 2026
404483d
Added ALA label mapping validation workflow
ManaswiniNookala May 17, 2026
57c75af
Moved dataset readiness notebook to torch implementation folder
May 17, 2026
0c37d4b
Moved notebook to torch_impl folder
May 17, 2026
b2a692c
Merge pull request #914 from DataBytes-Organisation/EE/DS/Dataset-Rea…
KishanFW May 17, 2026
b506e4d
Added ALA label mapping validation workflow
ManaswiniNookala May 17, 2026
2199aef
Add Sprint 2 Task 2 deliverable: calibration evaluation report
dinalfer-wq May 17, 2026
ff0b30f
Standardise calibrated confidence output in engine
Kunalanand077 May 17, 2026
ac68d5f
Merge branch 'main' into EE/MN/ALA-Label-Mapping
KishanFW May 18, 2026
b644e2e
Merge pull request #913 from DataBytes-Organisation/EE/MN/ALA-Label-M…
KishanFW May 18, 2026
4fbc224
Merge pull request #915 from DataBytes-Organisation/EE/Dinal/task2-co…
KishanFW May 18, 2026
32ce9f7
Create Error Analysis Report.pdf
jackhatesgravity May 18, 2026
3429a4b
Merge branch 'main' into EE/JMP/error_analysis
jackhatesgravity May 18, 2026
85bbc3c
Merge pull request #919 from DataBytes-Organisation/EE/JMP/error_anal…
KishanFW May 23, 2026
1d3d83a
Merge branch 'main' into EE/KA/calibrated-confidence-standardisation
KishanFW May 23, 2026
c0ae3f5
Merge pull request #921 from Kunalanandd/EE/KA/calibrated-confidence-…
KishanFW May 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
216 changes: 134 additions & 82 deletions Echo/__init__.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
import logging, os
import logging
import os

logging.disable(logging.WARNING)
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"

import keras
import ffmpeg
from keras.models import load_model as lm
import tfimm
from pydub import AudioSegment, effects
import keras
import tensorflow as tf
import tensorflow_io as tfio
from os.path import isfile, join
import tfimm
from keras.models import load_model as lm
from os import listdir
from os.path import isfile, join
from pydub import AudioSegment, effects

target_classes = ['nightjar', 'skylark', 'yellow-faced honeyeater', 'feral goat',
'sambar deer', 'grey shrikethrush', 'australian raven', 'fallow deer',
'yellow robin', 'cat', 'whistler', 'white-plumed honeyeater',
'brown rat', 'pied currawong', 'wild pig']
target_classes = [
'nightjar', 'skylark', 'yellow-faced honeyeater', 'feral goat',
'sambar deer', 'grey shrikethrush', 'australian raven', 'fallow deer',
'yellow robin', 'cat', 'whistler', 'white-plumed honeyeater',
'brown rat', 'pied currawong', 'wild pig'
]

########################################################################################
# MODEL PARAMETERS
Expand All @@ -31,26 +35,32 @@
class EchoClassifierLayer(tf.keras.layers.Layer):
def __init__(self):
super(EchoClassifierLayer, self).__init__()

dropout=0.5

self.fc1 = tf.keras.layers.Dense(128,
kernel_regularizer=tf.keras.regularizers.L2(0.01),
activation=tf.keras.activations.relu)

self.fc2 = tf.keras.layers.Dense(128,
kernel_regularizer=tf.keras.regularizers.L2(0.01),
activation=tf.keras.activations.relu)

self.do2 = tf.keras.layers.Dropout(dropout)

self.out = tf.keras.layers.Dense(15,
activation=tf.keras.activations.linear)

dropout = 0.5

self.fc1 = tf.keras.layers.Dense(
128,
kernel_regularizer=tf.keras.regularizers.L2(0.01),
activation=tf.keras.activations.relu
)

self.fc2 = tf.keras.layers.Dense(
128,
kernel_regularizer=tf.keras.regularizers.L2(0.01),
activation=tf.keras.activations.relu
)

self.do2 = tf.keras.layers.Dropout(dropout)

self.out = tf.keras.layers.Dense(
15,
activation=tf.keras.activations.linear
)

def call(self, inputs):
x = self.fc1(inputs)
x = self.fc2(x)
x = self.do2(x)
x = self.fc1(inputs)
x = self.fc2(x)
x = self.do2(x)
x = self.out(x)
return x

Expand All @@ -59,91 +69,123 @@ def call(self, inputs):
# CLASSIFIER MODEL - leveraging EfficientNetV2
########################################################################################
class EchoTfimmModel(tf.keras.Model):

def __init__(self, *args, **kwargs):
def __init__(self, *args, **kwargs):
super(EchoTfimmModel, self).__init__(*args, **kwargs)

self.fm = tfimm.create_model("efficientnet_v2_s_in21k", pretrained=True, in_channels=MODEL_INPUT_IMAGE_CHANNELS)
self.flat = tf.keras.layers.Flatten()

self.fm = tfimm.create_model(
"efficientnet_v2_s_in21k",
pretrained=False,
in_channels=MODEL_INPUT_IMAGE_CHANNELS
)
self.flat = tf.keras.layers.Flatten()
self.classifier = EchoClassifierLayer()

def call(self, inputs, training=False):
x = self.fm.forward_features(inputs)
def call(self, inputs, training=False):
x = self.fm.forward_features(inputs)
x = self.flat(x)
x = self.classifier(x)
x = self.classifier(x)
return x


########################################################################################
# LOAD MODEL
########################################################################################
def load_model():
PATH_TO_MODEL = os.path.join(os.getcwd(), 'Echo', 'Models', 'baseline_timm_model_dataset_2_15_classes.hdf5')

test_model = EchoTfimmModel()
test_model.build([None, 224, 224, 1])
test_model.load_weights(PATH_TO_MODEL)
test_model = tf.keras.models.load_model(
r"C:\Users\vamsh\Desktop\Project-Echo\echo_model\1"
)
return test_model


########################################################################################
# AUDIO PROCESSING
########################################################################################
def process_raw_audio(_model_, path_to_audio_file, sr: int = 16000):
NFFT = 512
WINDOW = 512
STRIDE = 512
SAMPLE_RATE = int(44100/2)
SAMPLE_RATE = int(44100 / 2)
MELS = 128
FMIN = 0
FMAX = int(SAMPLE_RATE)/2
FMAX = int(SAMPLE_RATE) / 2
CLIP_LENGTH = 5000
BITRATE = '32k'

_ret_data_ = []

if not os.path.exists(path_to_audio_file): raise ValueError('Audio file does not exist')
if not os.path.exists(path_to_audio_file):
raise ValueError('Audio file does not exist')

def dataset_transforms(image, _model_):
# reshape into standard 3 channels
def dataset_transforms(image, _model_):
image = tf.expand_dims(image, -1)

image = tf.ensure_shape(image, [216, 128, 1])
image = tf.image.resize(image,
(MODEL_INPUT_IMAGE_HEIGHT,
MODEL_INPUT_IMAGE_WIDTH),
method=tf.image.ResizeMethod.NEAREST_NEIGHBOR)

# rescale to range [0,1]
image = image - tf.reduce_min(image)
image = image / (tf.reduce_max(image)+tf.keras.backend.epsilon())
image = tf.image.resize(
image,
(MODEL_INPUT_IMAGE_HEIGHT, MODEL_INPUT_IMAGE_WIDTH),
method=tf.image.ResizeMethod.NEAREST_NEIGHBOR
)

image = image - tf.reduce_min(image)
image = image / (tf.reduce_max(image) + tf.keras.backend.epsilon())

return image

raw_sound = AudioSegment.from_file(path_to_audio_file, format=path_to_audio_file.split('.')[-1])
raw_sound = AudioSegment.from_file(
path_to_audio_file,
format=path_to_audio_file.split('.')[-1]
)
raw_sound = effects.normalize(raw_sound)

arr_split_file = [raw_sound[idx:idx + CLIP_LENGTH] for idx in range(0, len(raw_sound), CLIP_LENGTH)]
arr_split_file = [
raw_sound[idx:idx + CLIP_LENGTH]
for idx in range(0, len(raw_sound), CLIP_LENGTH)
]

for count_sample, sample in enumerate(arr_split_file):
# padding audio < 5s
if len(sample) < CLIP_LENGTH:
silence = AudioSegment.silent(duration=((CLIP_LENGTH-len(sample))))
sample = sample + silence # Adding silence after the audio
silence = AudioSegment.silent(duration=(CLIP_LENGTH - len(sample)))
sample = sample + silence

sample.export(os.path.join(os.getcwd(), 'o.flac'), format='flac', bitrate=BITRATE, parameters = [])
sample.export(
os.path.join(os.getcwd(), 'o.flac'),
format='flac',
bitrate=BITRATE,
parameters=[]
)

_tmp_path_ = os.path.join(os.getcwd(), 'o.flac')
file_contents=tf.io.read_file(_tmp_path_)
file_contents = tf.io.read_file(_tmp_path_)

try:
tmp_audio_t = tfio.audio.decode_flac(input=file_contents, dtype=tf.int16)
except:
tmp_audio_t = tfio.audio.decode_flac(input=file_contents, dtype=tf.int32)

tmp_audio_t = tf.cast(tmp_audio_t, tf.float32)

tmp_audio_t = tfio.audio.resample(tmp_audio_t, tfio.audio.AudioIOTensor(_tmp_path_)._rate.numpy(), SAMPLE_RATE)
os.remove(_tmp_path_)

tmp_audio_t = tfio.audio.resample(
tmp_audio_t,
tfio.audio.AudioIOTensor(_tmp_path_)._rate.numpy(),
SAMPLE_RATE
)
os.remove(_tmp_path_)

# Convert to spectrogram
spectrogram = tfio.audio.spectrogram(
tmp_audio_t[:, 0], nfft=NFFT, window=WINDOW, stride=STRIDE)
tmp_audio_t[:, 0],
nfft=NFFT,
window=WINDOW,
stride=STRIDE
)

mel_spectrogram = tfio.audio.melscale(
spectrogram, rate=SAMPLE_RATE, mels=MELS, fmin=FMIN, fmax=FMAX)

spectrogram,
rate=SAMPLE_RATE,
mels=MELS,
fmin=FMIN,
fmax=FMAX
)

_tmp_path_ = os.path.join(os.getcwd(), 'o.pt')
tf.io.write_file(_tmp_path_, tf.io.serialize_tensor(mel_spectrogram))

Expand All @@ -154,16 +196,18 @@ def dataset_transforms(image, _model_):

_ret_data_.append(_mod_data_)
os.remove(_tmp_path_)

return _ret_data_

return _ret_data_

def predict(_model_, path_to_file, traverse_path:bool = False):

########################################################################################
# PREDICTION
########################################################################################
def predict(_model_, path_to_file, traverse_path: bool = False):
def translate_results(result):
target_index = tf.argmax(tf.squeeze(result)).numpy()
target_class = target_classes[target_index]
target_proba = 100.0*tf.nn.softmax(result)[0,target_index].numpy()
target_class = target_classes[target_index]
target_proba = 100.0 * tf.nn.softmax(result)[0, target_index].numpy()
target_proba = str(round(target_proba, 2))

return target_class, target_proba
Expand All @@ -172,17 +216,25 @@ def translate_results(result):
_predict_data_ = process_raw_audio(_model_, path_to_file)

print(f'Your audio file is: {os.path.split(path_to_file)[-1]}')
print(f'Your file is split into {len(_predict_data_)} windows of 5 seconds width per window. For each sliding window, we found:')
print(
f'Your file is split into {len(_predict_data_)} windows of 5 seconds width per window. '
f'For each sliding window, we found:'
)

for x in _predict_data_:
_ret = translate_results(_model_.predict(x, verbose = 0))
_ret = translate_results(_model_.predict(x, verbose=0))
print(f' A {_ret[0]} with a confidence of {_ret[1]}%')

else:
for _file_ in [f for f in listdir(path_to_file) if isfile(join(path_to_file, f))]:
_predict_data_ = process_raw_audio(_model_, os.path.join(path_to_file, _file_))

print(f'Your audio file is: {os.path.split(os.path.join(path_to_file, _file_))[-1]}')
print(f'Your file is split into {len(_predict_data_)} windows of 5 seconds width per window. For each sliding window, we found:')
print(
f'Your file is split into {len(_predict_data_)} windows of 5 seconds width per window. '
f'For each sliding window, we found:'
)

for x in _predict_data_:
_ret = translate_results(_model_.predict(x, verbose = 0))
print(f' A {_ret[0]} with a confidence of {_ret[1]}%')

_ret = translate_results(_model_.predict(x, verbose=0))
print(f' A {_ret[0]} with a confidence of {_ret[1]}%')
Loading