File size: 3,169 Bytes
c466de2
eb6aa3b
9800007
eb6aa3b
 
 
20ebb8b
 
eb6aa3b
 
 
 
 
9800007
eb6aa3b
 
 
 
 
 
 
 
 
9800007
 
 
 
 
 
 
 
 
 
eb6aa3b
9800007
 
eb6aa3b
 
 
 
 
 
 
 
 
 
9800007
 
 
9d63e55
9800007
 
 
 
 
 
 
 
 
 
 
 
 
 
 
eb6aa3b
 
 
9800007
 
 
 
eb6aa3b
 
 
9800007
 
 
 
 
 
 
 
eb6aa3b
 
9800007
eb6aa3b
 
 
 
9800007
 
 
 
 
eb6aa3b
 
 
 
9800007
eb6aa3b
 
 
 
 
9800007
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
"""Fish Species Classification — CNN & Transfer Learning (combined Streamlit app)."""

import json
import sys
from pathlib import Path

import streamlit as st

if "/opt/anaconda3" in sys.executable:
    st.set_page_config(page_title="Python ortam hatasi", page_icon="⚠️")
    st.error(
        "Bu uygulama Anaconda Python ile calismaz (segmentation fault).\n\n"
        f"```bash\ncd \"{Path(__file__).resolve().parent}\"\n"
        f"~/venvs/tensorflow/bin/streamlit run {Path(__file__).name}\n```"
    )
    st.stop()

import numpy as np
import tensorflow as tf
from PIL import Image

ROOT = Path(__file__).resolve().parent

MODEL_CONFIG = {
    "Convolutional Neural Networks": {
        "stem": "fish_cnn",
        "notebook": "FishClassificationNew.ipynb",
    },
    "Transfer Learning": {
        "stem": "fish_tl",
        "notebook": "FishClassificationNew.ipynb",
    },
}


def get_preprocess(backbone: str):
    if backbone == "VGG16":
        from tensorflow.keras.applications.vgg16 import preprocess_input
        return preprocess_input
    if backbone == "ResNet50":
        from tensorflow.keras.applications.resnet50 import preprocess_input
        return preprocess_input
    from tensorflow.keras.applications.xception import preprocess_input
    return preprocess_input


@st.cache_resource
def load_artifacts(model_key: str):
    stem = MODEL_CONFIG[model_key]["stem"]
    models_dir = ROOT
    for ext in (".h5", ".keras"):
        path = models_dir / f"{stem}{ext}"
        if path.is_file():
            model = tf.keras.models.load_model(path)
            break
    else:
        raise FileNotFoundError(
            f"Model not found for {model_key}. Run {MODEL_CONFIG[model_key]['notebook']} first."
        )
    meta_path = models_dir / f"{stem}_meta.json"
    meta = json.loads(meta_path.read_text(encoding="utf-8"))
    return model, meta


def prepare_image(img: Image.Image, meta: dict, model_key: str) -> np.ndarray:
    size = tuple(meta["img_size"])
    arr = np.array(img.convert("RGB").resize(size), dtype=np.float32)
    arr = np.expand_dims(arr, axis=0)
    if model_key == "Convolutional Neural Networks":
        arr = arr / 255.0
    else:
        arr = get_preprocess(meta.get("backbone", "Xception"))(arr)
    return arr


st.set_page_config(page_title="Fish Species Classification", page_icon="🐟")
st.title("Fish Species Classification")

model_type = st.radio(
    "Model",
    list(MODEL_CONFIG.keys()),
    horizontal=True,
)

try:
    model, meta = load_artifacts(model_type)
except FileNotFoundError as e:
    st.error(str(e))
    st.stop()

if model_type == "Transfer Learning":
    st.caption(f"Backbone: {meta.get('backbone', 'Xception')}")
else:
    st.caption("Custom CNN")

uploaded = st.file_uploader("Upload image (jpg/png)", type=["jpg", "jpeg", "png"])
if uploaded:
    img = Image.open(uploaded)
    st.image(img, use_container_width=True)
    batch = prepare_image(img, meta, model_type)
    probs = model.predict(batch, verbose=0)[0]
    idx = int(np.argmax(probs))
    label = meta["class_names"][idx]
    st.success(f"Prediction: **{label}**")
    st.write(f"Confidence: {probs[idx]:.2%}")