Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import numpy as np | |
| from PIL import Image | |
| import tensorflow as tf | |
| from tensorflow.keras.models import load_model | |
| from tensorflow.keras.applications.resnet50 import preprocess_input | |
| # ----------------------------------------------------------- | |
| # 1. Config | |
| # ----------------------------------------------------------- | |
| IMG_SIZE = (128, 128) # zelfde als bij training | |
| MODEL_PATH = "indian_birds_resnet50.h5" # <-- pas aan indien nodig | |
| # VUL HIER JOUW LABELS IN (dezelfde volgorde als tijdens training) | |
| labels = [ | |
| "Asian Green Bee-Eater", | |
| "Brown-Headed Barbet", | |
| "Cattle Egret", | |
| "Common Kingfisher", | |
| "Common Myna", | |
| "Common Rosefinch", | |
| "Common Tailorbird", | |
| "Coppersmith Barbet", | |
| "Forest Wagtail", | |
| "Gray Wagtail", | |
| "Hoopoe", | |
| "House Crow", | |
| "Indian Grey Hornbill", | |
| "Indian Peafowl", | |
| "Indian Pitta", | |
| "Indian Roller", | |
| "Jungle Babbler", | |
| "Northern Lapwing", | |
| "Red Wattled Lapwing", | |
| "Ruddy Shelduck", | |
| "Rufous Treepie", | |
| "Sarus Crane", | |
| "White Wagtail", | |
| "White-Breasted Kingfisher", | |
| "White-Breasted Waterhen" | |
| ] | |
| label_map = {name: i for i, name in enumerate(labels)} | |
| inv_label_map = {v: k for k, v in label_map.items()} | |
| # ----------------------------------------------------------- | |
| # 2. Model laden (gecached) | |
| # ----------------------------------------------------------- | |
| def load_bird_model(): | |
| model = load_model(MODEL_PATH) | |
| return model | |
| model = load_bird_model() | |
| # ----------------------------------------------------------- | |
| # 3. Hulpfuncties | |
| # ----------------------------------------------------------- | |
| def preprocess_image(img: Image.Image) -> np.ndarray: | |
| """Resize + preprocess zoals bij training.""" | |
| img = img.convert("RGB").resize(IMG_SIZE) | |
| x = np.array(img).astype("float32") | |
| x = preprocess_input(x) # ResNet50 preprocessing | |
| x = np.expand_dims(x, axis=0) # batch-dimensie | |
| return x | |
| def predict_image(img: Image.Image): | |
| x = preprocess_image(img) | |
| probs = model.predict(x, verbose=0)[0] # vorm (25,) | |
| pred_id = int(np.argmax(probs)) | |
| pred_label = inv_label_map[pred_id] | |
| pred_prob = float(probs[pred_id]) | |
| # top-3 | |
| top3_ids = probs.argsort()[-3:][::-1] | |
| top3 = [(inv_label_map[int(i)], float(probs[i])) for i in top3_ids] | |
| return pred_label, pred_prob, top3 | |
| # ----------------------------------------------------------- | |
| # 4. Streamlit UI | |
| # ----------------------------------------------------------- | |
| st.set_page_config(page_title="Indian Bird Classifier", layout="centered") | |
| st.title("🕊️ Indian Bird Species Classifier") | |
| st.write( | |
| "Upload een vogelafbeelding uit de *25 Indian Bird Species* dataset " | |
| "en het model (ResNet50) voorspelt de soort." | |
| ) | |
| uploaded_file = st.file_uploader( | |
| "Kies een afbeelding (.jpg, .png)", | |
| type=["jpg", "jpeg", "png"] | |
| ) | |
| if uploaded_file is not None: | |
| # Afbeelding tonen | |
| image = Image.open(uploaded_file) | |
| st.image(image, caption="Geüploade afbeelding", use_column_width=True) | |
| if st.button("🔮 Voorspel vogelsoort"): | |
| with st.spinner("Model is aan het voorspellen..."): | |
| pred_label, pred_prob, top3 = predict_image(image) | |
| st.success(f"Voorspelling: **{pred_label}** ({pred_prob:.2%} zekerheid)") | |
| st.subheader("Top 3 voorspellingen") | |
| for name, p in top3: | |
| st.write(f"- {name}: **{p:.2%}**") | |
| else: | |
| st.info("Upload een afbeelding om te starten.") | |