CoolFace
Apppublic

Natzi21/malaria-cell-detection

sourceHugging Faceupdated 3mo agoView on Hugging Face
0likes
streamlit_app.py311 linesDownload Raw Back to src
1"""2Malaria Detection - Streamlit App3===================================4AI-powered blood smear analysis.5Run with: streamlit run app.py6"""7 8import streamlit as st9import tensorflow as tf10import numpy as np11from PIL import Image12import time13import datetime14 15# ─────────────────────────────────────────────16#  PAGE CONFIG17# ─────────────────────────────────────────────18st.set_page_config(19    page_title="Malaria Detection System",20    page_icon="🦟",21    layout="centered"22)23 24# ─────────────────────────────────────────────25#  CUSTOM CSS26# ─────────────────────────────────────────────27st.markdown("""28<style>29    @import url('https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=Inter:wght@300;400;600;700&display=swap');30 31    html, body, [class*="css"] {32        font-family: 'Inter', sans-serif;33    }34 35    .stApp {36        background-color: #0d1117;37        color: #e6edf3;38    }39 40    .main-header {41        text-align: center;42        padding: 2rem 0 1rem;43    }44 45    .badge {46        display: inline-block;47        background: linear-gradient(90deg, #238636, #2ea043);48        color: white;49        padding: 4px 16px;50        border-radius: 20px;51        font-size: 0.75rem;52        font-weight: 700;53        letter-spacing: 2px;54        margin-bottom: 12px;55        font-family: 'Space Mono', monospace;56    }57 58    .main-title {59        font-size: 2.2rem;60        font-weight: 700;61        color: #e6edf3;62        margin: 0;63    }64 65    .subtitle {66        color: #8b949e;67        font-size: 0.95rem;68        margin-top: 8px;69    }70 71    .stat-container {72        background: #161b22;73        border: 1px solid #30363d;74        border-radius: 12px;75        padding: 1.2rem;76        text-align: center;77        margin-bottom: 1rem;78    }79 80    .stat-value {81        font-size: 1.6rem;82        font-weight: 700;83        color: #58a6ff;84        font-family: 'Space Mono', monospace;85    }86 87    .stat-label {88        font-size: 0.72rem;89        color: #8b949e;90        margin-top: 4px;91        letter-spacing: 0.5px;92    }93 94    .result-infected {95        background: rgba(248, 81, 73, 0.1);96        border: 1px solid rgba(248, 81, 73, 0.4);97        border-radius: 12px;98        padding: 1.5rem;99        text-align: center;100    }101 102    .result-healthy {103        background: rgba(46, 160, 67, 0.1);104        border: 1px solid rgba(46, 160, 67, 0.4);105        border-radius: 12px;106        padding: 1.5rem;107        text-align: center;108    }109 110    .result-title {111        font-size: 1.4rem;112        font-weight: 700;113        margin: 0.5rem 0;114    }115 116    .result-infected .result-title { color: #f85149; }117    .result-healthy  .result-title { color: #2ea043; }118 119    .result-meta {120        color: #8b949e;121        font-size: 0.85rem;122        font-family: 'Space Mono', monospace;123    }124 125    .history-item {126        background: #161b22;127        border: 1px solid #30363d;128        border-radius: 8px;129        padding: 0.75rem 1rem;130        margin-bottom: 0.5rem;131        display: flex;132        justify-content: space-between;133        font-size: 0.85rem;134    }135 136    .stButton > button {137        background: linear-gradient(90deg, #1f6feb, #388bfd) !important;138        color: white !important;139        border: none !important;140        border-radius: 8px !important;141        font-weight: 600 !important;142        padding: 0.6rem 2rem !important;143        width: 100% !important;144        font-size: 1rem !important;145    }146 147    .divider {148        border: none;149        border-top: 1px solid #21262d;150        margin: 1.5rem 0;151    }152</style>153""", unsafe_allow_html=True)154 155# ─────────────────────────────────────────────156#  SESSION STATE157# ─────────────────────────────────────────────158if "history" not in st.session_state:159    st.session_state.history = []160if "total_latency" not in st.session_state:161    st.session_state.total_latency = 0162 163# ─────────────────────────────────────────────164#  LOAD MODEL (cached so it only loads once)165# ─────────────────────────────────────────────166@st.cache_resource167def load_model():168    from keras.layers import Dense169 170    class PatchedDense(Dense):171        def __init__(self, *args, **kwargs):172            kwargs.pop('quantization_config', None)173            super().__init__(*args, **kwargs)174 175    model = tf.keras.models.load_model(176        'malaria_model_final.h5',177        custom_objects={'Dense': PatchedDense},178        compile=False179    )180    return model181 182IMG_SIZE = (128, 128)183 184# ─────────────────────────────────────────────185#  HEADER186# ─────────────────────────────────────────────187st.markdown("""188<div class="main-header">189    <div class="badge">⚡ 5G ENABLED</div>190    <div class="main-title">🦟 Malaria Detection System</div>191    <div class="subtitle">AI-powered blood smear analysis · MobileNetV2</div>192</div>193""", unsafe_allow_html=True)194 195# ─────────────────────────────────────────────196#  STATS BAR197# ─────────────────────────────────────────────198total = len(st.session_state.history)199avg_latency = round(st.session_state.total_latency / total) if total > 0 else 0200 201col1, col2, col3, col4 = st.columns(4)202with col1:203    st.markdown('<div class="stat-container"><div class="stat-value">94.3%</div><div class="stat-label">MODEL ACCURACY</div></div>', unsafe_allow_html=True)204with col2:205    st.markdown('<div class="stat-container"><div class="stat-value">0.9846</div><div class="stat-label">AUC-ROC SCORE</div></div>', unsafe_allow_html=True)206with col3:207    st.markdown(f'<div class="stat-container"><div class="stat-value">{total}</div><div class="stat-label">TOTAL PREDICTIONS</div></div>', unsafe_allow_html=True)208with col4:209    latency_display = f"{avg_latency}ms" if total > 0 else "—"210    st.markdown(f'<div class="stat-container"><div class="stat-value">{latency_display}</div><div class="stat-label">AVG LATENCY</div></div>', unsafe_allow_html=True)211 212st.markdown('<hr class="divider">', unsafe_allow_html=True)213 214# ─────────────────────────────────────────────215#  UPLOAD + PREDICT216# ─────────────────────────────────────────────217st.markdown("#### 🔬 Upload Blood Smear Image")218uploaded_file = st.file_uploader(219    "Choose a cell image (PNG or JPG)",220    type=["png", "jpg", "jpeg"],221    label_visibility="collapsed"222)223 224if uploaded_file:225    col_img, col_info = st.columns([1, 2])226    with col_img:227        img = Image.open(uploaded_file).convert("RGB")228        st.image(img, caption="Uploaded image", use_container_width=True)229    with col_info:230        st.markdown(f"""231        **File:** `{uploaded_file.name}`  232        **Size:** `{img.size[0]} × {img.size[1]} px`  233        **Format:** `{uploaded_file.type}`234        """)235        st.markdown(" ")236        analyze = st.button("🚀 Analyze via 5G Network")237 238    if analyze:239        model = load_model()240 241        with st.spinner("Transmitting over 5G network... Running AI analysis..."):242            start = time.time()243 244            img_resized = img.resize(IMG_SIZE)245            img_array = np.array(img_resized) / 255.0246            img_array = np.expand_dims(img_array, axis=0)247 248            prob = float(model.predict(img_array, verbose=0)[0][0])249            latency_ms = round((time.time() - start) * 1000)250 251        prediction = "Parasitized" if prob > 0.5 else "Uninfected"252        confidence = prob if prob > 0.5 else 1 - prob253        timestamp = datetime.datetime.now().strftime("%H:%M:%S")254 255        st.session_state.history.insert(0, {256            "prediction": prediction,257            "confidence": f"{confidence:.1%}",258            "latency_ms": latency_ms,259            "timestamp": timestamp,260        })261        st.session_state.total_latency += latency_ms262 263        st.markdown('<hr class="divider">', unsafe_allow_html=True)264 265        if prediction == "Parasitized":266            st.markdown(f"""267            <div class="result-infected">268                <div style="font-size:3rem">🦟</div>269                <div class="result-title">Malaria Detected — Parasitized</div>270                <div class="result-meta">Confidence: {confidence:.1%} &nbsp;·&nbsp; Latency: {latency_ms}ms &nbsp;·&nbsp; {timestamp}</div>271            </div>272            """, unsafe_allow_html=True)273        else:274            st.markdown(f"""275            <div class="result-healthy">276                <div style="font-size:3rem">✅</div>277                <div class="result-title">No Malaria — Uninfected</div>278                <div class="result-meta">Confidence: {confidence:.1%} &nbsp;·&nbsp; Latency: {latency_ms}ms &nbsp;·&nbsp; {timestamp}</div>279            </div>280            """, unsafe_allow_html=True)281 282        st.markdown(" ")283        st.progress(confidence, text=f"Confidence: {confidence:.1%}")284 285        st.rerun()286 287# ─────────────────────────────────────────────288#  PREDICTION HISTORY289# ─────────────────────────────────────────────290st.markdown('<hr class="divider">', unsafe_allow_html=True)291st.markdown("#### 📋 Prediction History")292 293if not st.session_state.history:294    st.markdown('<p style="color:#8b949e; font-size:0.9rem;">No predictions yet. Upload an image to begin.</p>', unsafe_allow_html=True)295else:296    for entry in st.session_state.history:297        is_infected = entry["prediction"] == "Parasitized"298        dot_color = "#f85149" if is_infected else "#2ea043"299        label = "🦟 Parasitized" if is_infected else "✅ Uninfected"300        st.markdown(f"""301        <div class="history-item">302            <span>303                <span style="display:inline-block;width:10px;height:10px;border-radius:50%;304                      background:{dot_color};margin-right:8px;vertical-align:middle;"></span>305                <strong>{label}</strong>306            </span>307            <span style="color:#8b949e;">{entry['confidence']} confidence</span>308            <span style="color:#8b949e;font-family:'Space Mono',monospace;">{entry['latency_ms']}ms</span>309            <span style="color:#6e7681;">{entry['timestamp']}</span>310        </div>311        """, unsafe_allow_html=True)