File size: 4,748 Bytes
5319594
df3daa4
5319594
df3daa4
14b0860
5319594
 
51331b7
b5211d5
51331b7
57e1e06
3dfae4b
14b0860
 
 
 
 
51331b7
14b0860
f00cc48
51331b7
 
 
 
14b0860
 
 
831c624
 
 
51331b7
 
831c624
77a7518
51331b7
 
 
14b0860
 
 
5319594
51331b7
3dfae4b
51331b7
 
 
14b0860
 
 
51331b7
3dfae4b
51331b7
14b0860
 
 
51331b7
9ef3ae0
 
 
14b0860
51331b7
9ef3ae0
51331b7
9ef3ae0
14b0860
51331b7
9ef3ae0
14b0860
51331b7
 
14b0860
 
51331b7
9ef3ae0
51331b7
 
a6acdd3
 
 
 
 
 
51331b7
69ac75a
ba2e954
 
 
 
 
69ac75a
 
 
 
 
 
51331b7
69ac75a
51331b7
 
 
a6acdd3
51331b7
a6acdd3
 
 
 
51331b7
 
 
 
 
 
 
a6acdd3
51331b7
 
 
 
a6acdd3
 
 
51331b7
 
 
a6acdd3
51331b7
a6acdd3
 
 
 
69ac75a
a6acdd3
51331b7
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import gradio as gr
import numpy as np
import onnxruntime
import librosa
import os

# Load the ONNX model
sess = onnxruntime.InferenceSession('weightsgru.onnx')

# Define a function to extract MFCC features from an audio file
utterance_length = 384
def extract_mfcc(file_path, utterance_length):
    """
    Extracts MFCC features from an audio file and pads/truncates them
    to a fixed utterance length.
    """
    try:
        # Get raw .wav data and sampling rate from librosa's load function
        raw_w, sampling_rate = librosa.load(file_path, sr=None)

        # Obtain MFCC Features from raw data
        mfcc_features = librosa.feature.mfcc(y=raw_w, sr=sampling_rate, n_mfcc=40, hop_length=512)

        # Adjust the utterance length
        if mfcc_features.shape[1] > utterance_length:
            mfcc_features_new = mfcc_features[:, :utterance_length]
        else:
            mfcc_features_new = np.pad(
                mfcc_features,
                ((0, 0), (0, utterance_length - mfcc_features.shape[1])),
                mode='constant',
                constant_values=0
            )

        # Transpose the matrix for the desired shape
        mfcc_features_new = mfcc_features_new.T
        return mfcc_features_new
    except Exception as e:
        print(f"Error extracting MFCC: {e}")
        return None

# Define a function to classify audio using the ONNX model
def classify_audio(audio_file):
    """
    Classifies an audio file of a bird call and returns the two most likely species.
    """
    if audio_file is None:
        return "Please upload an audio file.", "No second label."
        
    utterance_length = 384
    mfcc_features = extract_mfcc(audio_file, utterance_length)

    if mfcc_features is None:
        return "Error processing audio file.", "No second label."

    # Split the features into 6 segments for the GRU model
    features = np.split(mfcc_features, 6)
    inputs = [np.expand_dims(segment, axis=0) for segment in features]
    classes = np.zeros((1, 10))

    # Run each segment through the ONNX model and sum the outputs
    for input_data in inputs:
        output = sess.run(None, {'gru_input': input_data.astype(np.float32)})[0]
        classes += output

    # Get the indices of the top two predictions
    pred_final1 = np.argmax(classes)
    sorted_indices = np.argsort(classes.flatten())
    
    # The second highest prediction is the second to last element in the sorted array
    pred_final2 = sorted_indices[-2]

    # Map the indices to human-readable labels
    bird_labels = {
        0: 'crow', 1: 'duck', 2: 'owl', 3: 'goaway', 4: 'peafowl',
        5: 'sparrow', 6: 'bluejay', 7: 'Asiankoel', 8: 'lapwing', 9: 'woodpeewe'
    }
    highest_bird_label = bird_labels[pred_final1]
    second_highest_bird_label = bird_labels[pred_final2]

    return highest_bird_label, second_highest_bird_label

# Gradio interface definition
inputs = gr.Audio(type="filepath", label="Upload an audio file (.wav)")
# outputs = [gr.Label(label="Bird Label 1"), gr.Label(label="Bird Label 2")]
outputs = [
    gr.Textbox(label="Bird Label 1"),
    gr.Textbox(label="Bird Label 2")
]

interface = gr.Interface(
    fn=classify_audio,
    inputs=inputs,
    outputs=outputs,
    title="Multi-label Bird Call Identification from Field Recordings",
    description="The multi-label bird call identification system is designed to classify 10 different bird species: House Crow, Mallard Duck, Eurasian Owl, Grey Go-away, Indian Peafowl, House Sparrow, Blue Jay, Asian Koel, Red Lapwing, and Western Wood Pewee. This system utilizes the MFCC-GRU model and is trained on data obtained from the Xeno-Canto bird sound database.",
    css="""
    body {
        background-color: #f0f8ff; /* Light sky blue background */
    }
    .gradio-container {
        background: linear-gradient(135deg, #e0f7fa, #b2ebf2); /* A nice gradient for the container */
        border-radius: 15px;
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
        padding: 20px;
    }
    h1 {
        color: #00796b; /* Dark cyan for the title */
        text-align: center;
    }
    .markdown-heading {
        color: #004d40; /* Even darker shade for markdown headings */
    }
    .gr-button {
        background-color: #009688; /* Teal color for buttons */
        color: white;
        border: none;
        border-radius: 10px;
        font-weight: bold;
        transition: background-color 0.3s ease;
    }
    .gr-button:hover {
        background-color: #00796b; /* Darker teal on hover */
    }
    .gr-textbox {
        background-color: #e0f2f1; /* Light cyan background for textboxes */
        border-radius: 10px;
        border: 1px solid #b2dfdb;
    }
"""
)

# Launch the app
interface.launch()