Pengusir-Hama-Burung-Otomatis/tugas akhir/realtime.py

220 lines
6.9 KiB
Python

import sounddevice as sd
import numpy as np
import librosa
import joblib
import firebase_admin
import time
from firebase_admin import credentials, db
# =====================================================
# FIREBASE SETUP
# =====================================================
cred = credentials.Certificate("serviceAccountKey.json")
firebase_admin.initialize_app(cred, {
'databaseURL': 'https://tugas-akhir-9947b-default-rtdb.asia-southeast1.firebasedatabase.app/'
})
ref = db.reference("/Kebun")
# =====================================================
# LOAD MODEL & LABEL
# =====================================================
model = joblib.load("model_burung.pkl")
label_map = {
10: "manusia",
20: "burung"
}
# =====================================================
# PARAMETER
# =====================================================
duration = 2.0
fs = 22050
MIN_VOLUME = 0.06
MIN_CONFIDENCE = 0.75
MAX_DISTANCE = 300
# =====================================================
# HOLD DETEKSI & TIMER
# =====================================================
DETECTION_HOLD = 5
last_detection_time = 0
last_result = "tidak dikenal"
last_firebase_update = 0
firebase_interval = 2
print("===================================")
print("AI KNN BURUNG AKTIF")
print("Listening...")
print("===================================")
# =====================================================
# LOOP
# =====================================================
while True:
try:
# =============================================
# AMBIL SENSOR FIREBASE
# =============================================
jarak = 0
suara_sensor = 0
try:
sensor_data = ref.child("Sensor").get()
if sensor_data:
if "Jarak" in sensor_data:
jarak = int(sensor_data["Jarak"])
if "Suara_dB" in sensor_data:
suara_sensor = float(sensor_data["Suara_dB"])
except Exception as e:
print("Gagal baca sensor:", e)
# =============================================
# RECORD AUDIO
# =============================================
audio = sd.rec(
int(duration * fs),
samplerate=fs,
channels=1,
device=1,
dtype='float32'
)
sd.wait()
audio = audio.flatten()
# =============================================
# HITUNG VOLUME & KONVERSI dB
# =============================================
volume = np.max(np.abs(audio))
db_value = int(volume * 85)
if db_value < 30:
db_value = 30
if db_value > 85:
db_value = 85
print("Volume:", round(volume, 4))
print("dB:", db_value)
# =============================================
# DEFAULT
# =============================================
hasil = "tidak dikenal"
confidence = 0.0
# =============================================
# DEBUG FILTER
# =============================================
print("========== FILTER ==========")
print("Volume :", round(volume, 4))
print("Min Volume :", MIN_VOLUME)
print("Jarak :", jarak)
print("Max Jarak :", MAX_DISTANCE)
if volume < MIN_VOLUME:
print("SKIP -> Volume terlalu kecil")
if suara_sensor < 60:
print("SKIP -> Suara sensor ESP32 kurang dari 60 dB")
if jarak <= 2:
print("SKIP -> Jarak terlalu dekat")
if jarak > MAX_DISTANCE:
print("SKIP -> Jarak terlalu jauh")
# =============================================
# FILTER NOISE & PREDIKSI
# =============================================
if (volume >= MIN_VOLUME and suara_sensor >= 60 and jarak > 2 and jarak <= MAX_DISTANCE):
# NORMALISASI & MFCC
audio = librosa.util.normalize(audio)
mfcc = librosa.feature.mfcc(y=audio, sr=fs, n_mfcc=13)
mfcc_scaled = np.mean(mfcc.T, axis=0).reshape(1, -1)
# PREDIKSI
proba = model.predict_proba(mfcc_scaled)[0]
prediksi = model.predict(mfcc_scaled)[0]
print("Probabilitas :", proba)
confidence = float(np.max(proba))
predicted_label = label_map.get(prediksi, "tidak dikenal")
print("Raw Prediksi :", prediksi)
print("Label :", predicted_label)
print("Confidence :", round(confidence, 2))
# =========================================
# VALIDASI HASIL AI (Sudah di dalam posisi Indentasi yang Benar)
# =========================================
sorted_proba = np.sort(proba)
highest = sorted_proba[-1]
second = sorted_proba[-2]
selisih = highest - second
print("Selisih Proba :", round(selisih, 2))
if (confidence >= 0.75 and selisih >= 0.20 and predicted_label in ["manusia", "burung"]):
hasil = predicted_label
else:
hasil = "tidak dikenal"
# =============================================
# HOLD HASIL DETEKSI
# =============================================
current_time = time.time()
if hasil in ["manusia", "burung"]:
last_result = hasil
last_detection_time = current_time
# TAHAN HASIL
if (current_time - last_detection_time) < DETECTION_HOLD:
hasil_tampil = last_result
else:
hasil_tampil = "tidak dikenal"
# =============================================
# DEBUG TAMPILAN
# =============================================
print("Confidence:", round(confidence, 2))
print("Hasil AI:", hasil)
print("Tampil:", hasil_tampil)
print("Jarak Firebase:", jarak)
print("Suara Sensor:", suara_sensor)
print("----------------")
# =============================================
# UPDATE FIREBASE
# =============================================
if (current_time - last_firebase_update) >= firebase_interval:
last_firebase_update = current_time
ref.update({
"AI": {
"Klasifikasi": hasil_tampil,
"Confidence": round(confidence, 2),
"Volume": round(float(volume), 4)
}
})
# =============================================
# DELAY
# =============================================
time.sleep(0.3)
except Exception as e:
print("ERROR:", e)
try:
ref.update({
"AI": {
"Klasifikasi": "error",
"Confidence": 0,
"Volume": 0
}
})
except:
pass
time.sleep(1)