Spaces:
Sleeping
Sleeping
| import tensorflow as tf | |
| import gradio as gr | |
| import numpy as np | |
| from PIL import Image | |
| import base64 | |
| import io | |
| import re | |
| # 1. UPDATE LABEL (Wajib urut abjad sesuai folder di Colab tadi) | |
| # Pastikan urutannya benar! | |
| LABELS = ["botol_kaca", "botol_plastik", "karton", "kertas", "non_sampah"] | |
| # 2. SETTING THRESHOLD | |
| # Jika keyakinan model di bawah angka ini, anggap tidak dikenal | |
| THRESHOLD = 0.70 | |
| # === Load model TFLite === | |
| # Pastikan nama file model di Hugging Face sesuai dengan ini | |
| model_path = "model_sampah_final.tflite" | |
| try: | |
| interpreter = tf.lite.Interpreter(model_path=model_path) | |
| interpreter.allocate_tensors() | |
| input_details = interpreter.get_input_details() | |
| output_details = interpreter.get_output_details() | |
| INPUT_HEIGHT = input_details[0]['shape'][1] | |
| INPUT_WIDTH = input_details[0]['shape'][2] | |
| print("✅ Model berhasil dimuat!") | |
| except Exception as e: | |
| print(f"❌ Error load model: {e}") | |
| def predict(base64_data_uri): | |
| try: | |
| # --- DECODE BASE64 (Sama seperti kode lama) --- | |
| if "," in base64_data_uri: | |
| base64_str = re.sub(r'^data:image/.+;base64,', '', base64_data_uri) | |
| else: | |
| base64_str = base64_data_uri | |
| img_bytes = base64.b64decode(base64_str) | |
| img = Image.open(io.BytesIO(img_bytes)) | |
| if img.mode == 'RGBA': | |
| img = img.convert('RGB') | |
| # --- PREPROCESSING --- | |
| img = img.resize((INPUT_WIDTH, INPUT_HEIGHT)) | |
| img_array = np.array(img, dtype=np.float32) | |
| img_array = np.expand_dims(img_array, axis=0) | |
| img_array = img_array / 255.0 | |
| # --- PREDIKSI --- | |
| interpreter.set_tensor(input_details[0]["index"], img_array) | |
| interpreter.invoke() | |
| output_data = interpreter.get_tensor(output_details[0]["index"]) | |
| # Ambil hasil probabilitas | |
| predictions = output_data[0] # Contoh: [0.1, 0.8, 0.05, 0.0, 0.05] | |
| max_score = np.max(predictions) # Score tertinggi: 0.8 | |
| predicted_index = np.argmax(predictions) # Index juara | |
| predicted_label = LABELS[predicted_index] # Nama label juara | |
| # --- LOGIKA CERDAS (FILTER) --- | |
| # Cek 1: Apakah score di bawah Threshold? | |
| if max_score < THRESHOLD: | |
| # Kirim sinyal ke Flutter bahwa ini tidak dikenal | |
| return "tidak_dikenal" | |
| # Cek 2: Apakah terdeteksi sebagai 'non_sampah'? | |
| if predicted_label == "non_sampah": | |
| # Kirim sinyal ke Flutter bahwa ini bukan sampah | |
| return "bukan_sampah" | |
| # Cek 3: Lolos seleksi -> Kirim nama sampah asli | |
| return predicted_label | |
| except Exception as e: | |
| return f"Error: {str(e)}" | |
| # --------------------------------------------- | |
| iface = gr.Interface( | |
| fn=predict, | |
| inputs=gr.Textbox(label="Base64 Data URI Input"), | |
| outputs="text", | |
| title="EcoQuest API v2 (Robust)", | |
| description="API Deteksi Sampah dengan filter Threshold & Non-Sampah." | |
| ) | |
| iface.launch() |