sowmyaiyer21 commited on
Commit
fe3fd9c
·
verified ·
1 Parent(s): 782d979

Upload folder using huggingface_hub

Browse files
.gitattributes CHANGED
@@ -1,35 +1,36 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ *.keras filter=lfs diff=lfs merge=lfs -text
Dockerfile ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.13.5-slim
2
+
3
+ WORKDIR /app
4
+
5
+ RUN apt-get update && apt-get install -y \
6
+ build-essential \
7
+ curl \
8
+ git \
9
+ && rm -rf /var/lib/apt/lists/*
10
+
11
+ COPY requirements.txt ./
12
+ COPY src/ ./src/
13
+
14
+ RUN pip3 install -r requirements.txt
15
+
16
+ EXPOSE 8501
17
+
18
+ HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health
19
+
20
+ ENTRYPOINT ["streamlit", "run", "src/streamlit_app.py", "--server.port=8501", "--server.address=0.0.0.0"]
README.md CHANGED
@@ -1,3 +1,20 @@
1
  ---
 
 
 
 
 
 
 
 
 
 
2
  license: apache-2.0
3
  ---
 
 
 
 
 
 
 
 
1
  ---
2
+ title: My Streamlit App
3
+ emoji: 🚀
4
+ colorFrom: red
5
+ colorTo: red
6
+ sdk: docker
7
+ app_port: 8501
8
+ tags:
9
+ - streamlit
10
+ pinned: false
11
+ short_description: tetanus web interface
12
  license: apache-2.0
13
  ---
14
+
15
+ # Welcome to Streamlit!
16
+
17
+ Edit `/src/streamlit_app.py` to customize this app to your heart's desire. :heart:
18
+
19
+ If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
20
+ forums](https://discuss.streamlit.io).
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ altair
2
+ pandas
3
+ streamlit
src/app.py ADDED
@@ -0,0 +1,627 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import warnings
3
+ warnings.filterwarnings('ignore', category=UserWarning)
4
+ os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
5
+
6
+ import streamlit as st
7
+ import tensorflow as tf
8
+ from tensorflow.keras.models import load_model
9
+ from tensorflow.keras.preprocessing import image
10
+ import numpy as np
11
+ import matplotlib.pyplot as plt
12
+ from PIL import Image
13
+ import io
14
+ import plotly.express as px
15
+ import plotly.graph_objects as go
16
+ from plotly.subplots import make_subplots
17
+
18
+ # ====== Page Configuration ======
19
+ st.set_page_config(
20
+ page_title="Tetanus Risk Classifier",
21
+ page_icon="🩺",
22
+ layout="wide",
23
+ initial_sidebar_state="expanded"
24
+ )
25
+
26
+ # ====== Custom CSS for Modern UI ======
27
+ st.markdown("""
28
+ <style>
29
+ /* Import Google Fonts */
30
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
31
+
32
+ /* Global Styling */
33
+ .main {
34
+ font-family: 'Inter', sans-serif;
35
+ background: linear-gradient(135deg, #fffaf0 0%, #fdf6e3 100%);
36
+ min-height: 100vh;
37
+ }
38
+
39
+ .stApp {
40
+ background: #fefcf7;
41
+ color: #3a3a3a;
42
+ }
43
+
44
+ /* Header Styling */
45
+ .main-title {
46
+ font-size: 3rem;
47
+ font-weight: 700;
48
+ text-align: center;
49
+ color: #2b2b2b;
50
+ margin-bottom: 0.5rem;
51
+ text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
52
+ }
53
+
54
+ .sub-title {
55
+ font-size: 1.2rem;
56
+ text-align: center;
57
+ color: #7a6a4f;
58
+ margin-bottom: 3rem;
59
+ font-weight: 400;
60
+ }
61
+
62
+ /* Card Styling */
63
+ .custom-card {
64
+ background: #fffdf8;
65
+ border-radius: 16px;
66
+ padding: 2rem;
67
+ box-shadow: 0 6px 18px rgba(0,0,0,0.08);
68
+ border: 1px solid #f1e7d0;
69
+ margin-bottom: 2rem;
70
+ }
71
+
72
+ .upload-card {
73
+ background: #fffef9;
74
+ border-radius: 16px;
75
+ padding: 2rem;
76
+ text-align: center;
77
+ border: 2px dashed #e0d6b8;
78
+ transition: all 0.3s ease;
79
+ margin: 1rem 0;
80
+ }
81
+
82
+ .upload-card:hover {
83
+ border-color: #b08968;
84
+ transform: translateY(-2px);
85
+ box-shadow: 0 12px 25px rgba(0,0,0,0.1);
86
+ }
87
+
88
+ /* Risk Level Indicators */
89
+ .risk-badge-high {
90
+ background: #fbe9e7;
91
+ color: #c62828;
92
+ padding: 1rem 2rem;
93
+ border-radius: 12px;
94
+ text-align: center;
95
+ font-size: 1.2rem;
96
+ font-weight: 700;
97
+ margin: 1rem 0;
98
+ border: 1px solid #ef9a9a;
99
+ }
100
+
101
+ .risk-badge-mid {
102
+ background: #fff8e1;
103
+ color: #b37400;
104
+ padding: 1rem 2rem;
105
+ border-radius: 12px;
106
+ text-align: center;
107
+ font-size: 1.2rem;
108
+ font-weight: 700;
109
+ margin: 1rem 0;
110
+ border: 1px solid #ffd54f;
111
+ }
112
+
113
+ .risk-badge-low {
114
+ background: #f1fbe9;
115
+ color: #2e7d32;
116
+ padding: 1rem 2rem;
117
+ border-radius: 12px;
118
+ text-align: center;
119
+ font-size: 1.2rem;
120
+ font-weight: 700;
121
+ margin: 1rem 0;
122
+ border: 1px solid #a5d6a7;
123
+ }
124
+
125
+ /* Section Headers */
126
+ .section-header {
127
+ font-size: 1.5rem;
128
+ font-weight: 700;
129
+ color: #5c4d36;
130
+ margin: 2rem 0 1rem 0;
131
+ padding-bottom: 0.5rem;
132
+ border-bottom: 2px solid #e0d6b8;
133
+ text-align: center;
134
+ }
135
+
136
+ /* Metrics Styling */
137
+ .metric-container {
138
+ background: #fffdf6;
139
+ border-radius: 12px;
140
+ padding: 1.2rem;
141
+ text-align: center;
142
+ border: 1px solid #e7dbc2;
143
+ margin: 1rem 0;
144
+ color: #3a3a3a;
145
+ }
146
+
147
+ /* Recommendations */
148
+ .recommendation-box {
149
+ padding: 1.5rem;
150
+ margin: 1.5rem 0;
151
+ border-radius: 12px;
152
+ border-left: 5px solid;
153
+ background: #fffdf9;
154
+ box-shadow: 0 6px 12px rgba(0,0,0,0.05);
155
+ }
156
+
157
+ .recommendation-high {
158
+ border-left-color: #c62828;
159
+ }
160
+
161
+ .recommendation-mid {
162
+ border-left-color: #b37400;
163
+ }
164
+
165
+ .recommendation-low {
166
+ border-left-color: #2e7d32;
167
+ }
168
+
169
+ /* Sidebar Styling */
170
+ .sidebar .sidebar-content {
171
+ background: #fffef9;
172
+ border-radius: 12px;
173
+ padding: 1rem;
174
+ margin: 0.5rem 0;
175
+ box-shadow: 0 4px 8px rgba(0,0,0,0.05);
176
+ border: 1px solid #f1e7d0;
177
+ }
178
+
179
+ /* Hide Streamlit branding */
180
+ .stDeployButton, footer {
181
+ display: none !important;
182
+ }
183
+
184
+ /* Custom info boxes */
185
+ .info-box {
186
+ background: #fffdf6;
187
+ border-radius: 10px;
188
+ padding: 1.2rem;
189
+ margin: 1rem 0;
190
+ border-left: 4px solid #b08968;
191
+ color: #3a3a3a;
192
+ }
193
+
194
+ .info-title {
195
+ font-weight: 700;
196
+ color: #7a6a4f;
197
+ font-size: 1.1rem;
198
+ margin-bottom: 0.8rem;
199
+ }
200
+
201
+ /* Progress bars */
202
+ .stProgress > div > div > div > div {
203
+ background: linear-gradient(90deg, #b08968, #d4a373);
204
+ border-radius: 6px;
205
+ }
206
+
207
+ /* Upload button styling */
208
+ .stFileUploader label {
209
+ background: #f1e3cf !important;
210
+ color: #3a3a3a !important;
211
+ border-radius: 10px !important;
212
+ border: 1px solid #d9c9a8 !important;
213
+ padding: 0.8rem 1.5rem !important;
214
+ font-weight: 600 !important;
215
+ transition: all 0.3s ease !important;
216
+ }
217
+
218
+ .stFileUploader label:hover {
219
+ background: #e6d3b3 !important;
220
+ transform: translateY(-2px) !important;
221
+ box-shadow: 0 6px 12px rgba(0,0,0,0.15) !important;
222
+ }
223
+ .stAlert div {
224
+ color: black !important;
225
+ }
226
+ </style>
227
+
228
+
229
+
230
+ """, unsafe_allow_html=True)
231
+
232
+ # ====== Main Title ======
233
+ st.markdown('<h1 class="main-title">Tetanus Risk Assessment System</h1>', unsafe_allow_html=True)
234
+ st.markdown('<p class="sub-title">AI-powered medical imaging analysis for tetanus risk evaluation</p>', unsafe_allow_html=True)
235
+
236
+ # ====== Enhanced Sidebar Configuration ======
237
+ with st.sidebar:
238
+ st.markdown('<div class="sidebar-content">', unsafe_allow_html=True)
239
+ st.markdown("## Configuration")
240
+
241
+ # Model path input with better styling
242
+ model_path = st.text_input(
243
+ "Model File Path",
244
+ value="final_tetanus_model.keras",
245
+ help="Enter the path to your trained .keras model file"
246
+ )
247
+
248
+ st.markdown("---")
249
+
250
+ # Risk categories with enhanced presentation
251
+ st.markdown("## Risk Categories")
252
+
253
+ col1, col2 = st.columns([1, 3])
254
+ with col1:
255
+ st.markdown("●", unsafe_allow_html=True)
256
+ st.markdown("●", unsafe_allow_html=True)
257
+ st.markdown("●", unsafe_allow_html=True)
258
+ with col2:
259
+ st.markdown("**High Risk** - Immediate medical attention")
260
+ st.markdown("**Moderate Risk** - Clinical evaluation needed")
261
+ st.markdown("**Low Risk** - Standard wound care")
262
+
263
+ st.markdown("---")
264
+
265
+ # Enhanced risk information
266
+ with st.expander("Detailed Risk Information"):
267
+ st.markdown("""
268
+ **High Risk Indicators:**
269
+ - Deep puncture wounds
270
+ - Contaminated wounds
271
+ - Foreign object presence
272
+ - Rusty metal exposure
273
+
274
+ **Moderate Risk Indicators:**
275
+ - Minor cuts with debris
276
+ - Moderate depth wounds
277
+ - Delayed treatment (>6 hours)
278
+ - Animal bites
279
+
280
+ **Low Risk Indicators:**
281
+ - Superficial cuts
282
+ - Clean wounds
283
+ - Fresh injuries (<1 hour)
284
+ - Proper wound cleaning
285
+ """)
286
+
287
+ st.markdown("---")
288
+
289
+ # System info
290
+ st.markdown("## System Info")
291
+ st.info("**Model Status:** Ready for analysis")
292
+ st.info("**Processing:** Real-time inference")
293
+ st.info("**Accuracy:** Clinical-grade assessment")
294
+
295
+ st.markdown('</div>', unsafe_allow_html=True)
296
+
297
+ # ====== Model Loading Function ======
298
+ @st.cache_resource
299
+ def load_tetanus_model(model_path):
300
+ """Load the trained model with enhanced error handling"""
301
+ try:
302
+ if os.path.exists(model_path):
303
+ model = load_model(model_path)
304
+ return model, None
305
+ else:
306
+ return None, f"Model file not found at: {model_path}"
307
+ except Exception as e:
308
+ return None, f"Error loading model: {str(e)}"
309
+
310
+ # ====== Enhanced Image Preprocessing ======
311
+ def preprocess_image(img):
312
+ """Enhanced image preprocessing with validation"""
313
+ if img.mode != 'RGB':
314
+ img = img.convert('RGB')
315
+
316
+ # Store original size for display
317
+ original_size = img.size
318
+
319
+ # Resize for model
320
+ img = img.resize((224, 224))
321
+ img_array = image.img_to_array(img)
322
+ img_array = np.expand_dims(img_array, axis=0)
323
+ img_array = img_array / 255.0
324
+
325
+ return img_array, original_size
326
+
327
+ # ====== Enhanced Prediction Function ======
328
+
329
+
330
+ def make_prediction(model, img_array):
331
+ """Make prediction with detailed probability analysis"""
332
+ try:
333
+ risk_categories = ['High Risk', 'Mid Risk', 'Low Risk']
334
+
335
+ # 🔥 Use actual model prediction instead of mock
336
+ prediction = model.predict(img_array, verbose=0)
337
+
338
+ predicted_index = np.argmax(prediction)
339
+ predicted_label = risk_categories[predicted_index]
340
+ confidence = prediction[0][predicted_index] * 100
341
+ all_probabilities = prediction[0] * 100
342
+
343
+ return predicted_label, confidence, all_probabilities, None
344
+ except Exception as e:
345
+ return None, None, None, f"Error making prediction: {str(e)}"
346
+
347
+ # ====== Enhanced Visualization Functions ======
348
+ def create_confidence_chart(confidence):
349
+ """Create an enhanced confidence visualization"""
350
+ fig = go.Figure(go.Indicator(
351
+ mode = "gauge+number+delta",
352
+ value = confidence,
353
+ domain = {'x': [0, 1], 'y': [0, 1]},
354
+ title = {'text': "Confidence Level"},
355
+ delta = {'reference': 80},
356
+ gauge = {
357
+ 'axis': {'range': [None, 100]},
358
+ 'bar': {'color': "#4f46e5"},
359
+ 'steps': [
360
+ {'range': [0, 50], 'color': "#fee2e2"},
361
+ {'range': [50, 80], 'color': "#fef3c7"},
362
+ {'range': [80, 100], 'color': "#d1fae5"}],
363
+ 'threshold': {
364
+ 'line': {'color': "red", 'width': 4},
365
+ 'thickness': 0.75,
366
+ 'value': 90}}))
367
+
368
+ fig.update_layout(
369
+ height=300,
370
+ font={'color': "#4f46e5", 'family': "Inter"},
371
+ paper_bgcolor="rgba(0,0,0,0)",
372
+ plot_bgcolor="rgba(0,0,0,0)"
373
+ )
374
+ return fig
375
+
376
+ def create_probability_chart(probabilities, categories):
377
+ """Create enhanced probability visualization"""
378
+ colors = ['#ef4444', '#f59e0b', '#10b981']
379
+
380
+ fig = go.Figure(data=[
381
+ go.Bar(
382
+ x=categories,
383
+ y=probabilities,
384
+ marker_color=colors,
385
+ text=[f'{p:.1f}%' for p in probabilities],
386
+ textposition='auto',
387
+ )
388
+ ])
389
+
390
+ fig.update_layout(
391
+ title="Risk Probability Distribution",
392
+ xaxis_title="Risk Categories",
393
+ yaxis_title="Probability (%)",
394
+ font={'color': "#374151", 'family': "Inter"},
395
+ paper_bgcolor="rgba(0,0,0,0)",
396
+ plot_bgcolor="rgba(0,0,0,0)",
397
+ height=400
398
+ )
399
+
400
+ return fig
401
+
402
+ # ====== Main Application ======
403
+ def main():
404
+ # Load model with enhanced feedback
405
+ with st.spinner("Loading AI model..."):
406
+ model, error = load_tetanus_model(model_path)
407
+
408
+ if error:
409
+ st.error(f"**Model Loading Error:** {error}")
410
+ st.info("**Tip:** Please verify the model path in the sidebar configuration.")
411
+ st.stop()
412
+
413
+ # Success message with animation
414
+ st.info("**AI Model loaded successfully!** Ready for medical image analysis.")
415
+
416
+ # Create enhanced layout
417
+ col1, col2 = st.columns([1.2, 1], gap="large")
418
+
419
+ with col1:
420
+ # Enhanced upload section
421
+ st.markdown('<div class="custom-card">', unsafe_allow_html=True)
422
+ st.markdown('<h2 class="section-header">Upload or Capture Medical Image</h2>', unsafe_allow_html=True)
423
+
424
+ # File uploader
425
+ uploaded_file = st.file_uploader(
426
+ "Upload Medical Image",
427
+ type=['png', 'jpg', 'jpeg', 'bmp', 'tiff'],
428
+ help="Upload a clear, high-quality image of the wound for analysis",
429
+ label_visibility="collapsed"
430
+ )
431
+
432
+ # Camera input
433
+ camera_file = st.camera_input(
434
+ "Capture Medical Image",
435
+ label_visibility="collapsed"
436
+ )
437
+
438
+ # Pick whichever is used
439
+ final_file = uploaded_file if uploaded_file is not None else camera_file
440
+
441
+ if final_file is not None:
442
+ # Display image with enhanced presentation
443
+ img = Image.open(final_file)
444
+ st.image(img, caption="Medical Image for Analysis", use_container_width=True)
445
+
446
+ # Enhanced image metadata
447
+ img_array, original_size = preprocess_image(img)
448
+
449
+ col_meta1, col_meta2, col_meta3 = st.columns(3)
450
+ with col_meta1:
451
+ st.markdown('<div class="metric-container">', unsafe_allow_html=True)
452
+ st.metric("Dimensions", f"{original_size[0]} × {original_size[1]}")
453
+ st.markdown('</div>', unsafe_allow_html=True)
454
+
455
+ with col_meta2:
456
+ st.markdown('<div class="metric-container">', unsafe_allow_html=True)
457
+ st.metric("Format", img.format if hasattr(img, 'format') else 'Unknown')
458
+ st.markdown('</div>', unsafe_allow_html=True)
459
+
460
+ with col_meta3:
461
+ st.markdown('<div class="metric-container">', unsafe_allow_html=True)
462
+ file_size = len(final_file.getvalue()) / 1024 # KB
463
+ st.metric("Size", f"{file_size:.1f} KB")
464
+ st.markdown('</div>', unsafe_allow_html=True)
465
+ else:
466
+ # Enhanced empty state
467
+ st.markdown("### Drop your medical image here or capture using the camera")
468
+ st.markdown("Supported formats: PNG, JPG, JPEG, BMP, TIFF")
469
+ st.markdown("Maximum file size: 10MB")
470
+ st.markdown('</div>', unsafe_allow_html=True)
471
+
472
+ st.markdown('</div>', unsafe_allow_html=True)
473
+
474
+
475
+ with col2:
476
+ # Enhanced results section
477
+ st.markdown('<div class="custom-card">', unsafe_allow_html=True)
478
+ st.markdown('<h2 class="section-header">Results</h2>', unsafe_allow_html=True)
479
+
480
+ if uploaded_file is not None or camera_file is not None:
481
+ # Choose file priority (uploaded > captured)
482
+ file_source = uploaded_file if uploaded_file is not None else camera_file
483
+ img = Image.open(file_source)
484
+ img_array, _ = preprocess_image(img)
485
+
486
+ # Processing with enhanced feedback
487
+ with st.spinner("Analyzing image with AI model..."):
488
+ predicted_label, confidence, all_probabilities, pred_error = make_prediction(model, img_array)
489
+
490
+ if pred_error:
491
+ st.error(f"❌ **Prediction Error:** {pred_error}")
492
+ st.markdown('</div>', unsafe_allow_html=True)
493
+ st.stop()
494
+
495
+ # Enhanced risk level display
496
+ if predicted_label == "High Risk":
497
+ st.markdown('<div class="risk-badge-high">HIGH RISK DETECTED</div>', unsafe_allow_html=True)
498
+ elif predicted_label == "Mid Risk":
499
+ st.markdown('<div class="risk-badge-mid">MODERATE RISK DETECTED</div>', unsafe_allow_html=True)
500
+ else:
501
+ st.markdown('<div class="risk-badge-low">LOW RISK DETECTED</div>', unsafe_allow_html=True)
502
+
503
+ # Enhanced confidence display
504
+ st.markdown("### Confidence Analysis")
505
+ confidence_chart = create_confidence_chart(confidence)
506
+ st.plotly_chart(confidence_chart, use_container_width=True)
507
+
508
+ else:
509
+ # Enhanced empty state for results
510
+ st.markdown("""
511
+ <div style="text-align: center; padding: 3rem; color: #9ca3af;">
512
+ <div style="font-size: 4rem; margin-bottom: 1rem;">⚕</div>
513
+ <h3>Ready for Analysis</h3>
514
+ <p>Upload or capture a medical image to begin AI-powered risk assessment</p>
515
+ </div>
516
+ """, unsafe_allow_html=True)
517
+
518
+ st.markdown('</div>', unsafe_allow_html=True)
519
+
520
+ # Enhanced detailed analysis section (full width)
521
+ if (uploaded_file is not None or camera_file is not None) and 'predicted_label' in locals():
522
+ st.markdown('<div class="custom-card">', unsafe_allow_html=True)
523
+ st.markdown('<h2 class="section-header">Detailed Probability Analysis</h2>', unsafe_allow_html=True)
524
+
525
+ # Create probability visualization
526
+ risk_categories = ['High Risk', 'Mid Risk', 'Low Risk']
527
+ prob_chart = create_probability_chart(all_probabilities, risk_categories)
528
+ st.plotly_chart(prob_chart, use_container_width=True)
529
+
530
+ # Detailed breakdown
531
+ col1, col2, col3 = st.columns(3)
532
+ categories = ['High Risk', 'Mid Risk', 'Low Risk']
533
+ colors = ['#ef4444', '#f59e0b', '#10b981']
534
+
535
+ for i, (col, category, color, prob) in enumerate(zip([col1, col2, col3], categories, colors, all_probabilities)):
536
+ with col:
537
+ st.markdown(f"""
538
+ <div style="text-align: center; padding: 1rem; background: rgba(255,255,255,0.8); border-radius: 10px; margin: 0.5rem 0;">
539
+ <div style="width: 20px; height: 20px; background-color: {color}; border-radius: 50%; margin: 0 auto 0.5rem;"></div>
540
+ <div style="font-weight: 700; font-size: 1.2rem;">{category}</div>
541
+ <div style="font-size: 1.5rem; font-weight: 600; color: #4f46e5;">{prob:.1f}%</div>
542
+ </div>
543
+ """, unsafe_allow_html=True)
544
+
545
+ st.markdown('</div>', unsafe_allow_html=True)
546
+
547
+ # Enhanced recommendations section
548
+ st.markdown('<div class="custom-card">', unsafe_allow_html=True)
549
+ st.markdown('<h2 class="section-header">Medical Recommendations</h2>', unsafe_allow_html=True)
550
+
551
+ if predicted_label == "High Risk":
552
+ st.markdown("""
553
+ <div class="recommendation-box recommendation-high">
554
+ <h3 style="color: #dc2626; font-size: 1.5rem; margin-bottom: 1rem;">IMMEDIATE MEDICAL ATTENTION REQUIRED</h3>
555
+ <ul style="font-size: 1.1rem; line-height: 1.8;">
556
+ <li style="color:black;"><strong>Seek emergency medical care immediately</strong></li>
557
+ <li style="color:black;" >Do not delay professional treatment</li>
558
+ <li style="color:black;">Verify tetanus vaccination status with healthcare provider</li>
559
+ <li style="color:black;">Clean wound with sterile saline if available</li>
560
+ <li style="color:black;">Avoid home remedies - professional care is essential</li>
561
+ <li style="color:black;">Monitor for signs of infection or tetanus symptoms</li>
562
+ </ul>
563
+ </div>
564
+ """, unsafe_allow_html=True)
565
+ elif predicted_label == "Mid Risk":
566
+ st.markdown("""
567
+ <div class="recommendation-box recommendation-mid">
568
+ <h3 style="color: #d97706; font-size: 1.5rem; margin-bottom: 1rem;">CLINICAL EVALUATION RECOMMENDED</h3>
569
+ <ul style="font-size: 1.1rem; line-height: 1.8;">
570
+ <li style="color:black;"><strong>Clean wound thoroughly with soap and water</strong></li>
571
+ <li style="color:black;">Monitor for signs of infection (redness, swelling, warmth)</li>
572
+ <li style="color:black;">Consult healthcare provider within 24 hours</li>
573
+ <li style="color:black;">Update tetanus vaccination if necessary (>5 years)</li>
574
+ <li style="color:black;">Apply clean dressing and change regularly</li>
575
+ <li style="color:black;">Take photos to track healing progress</li>
576
+ </ul>
577
+ </div>
578
+ """, unsafe_allow_html=True)
579
+ else:
580
+ st.markdown("""
581
+ <div class="recommendation-box recommendation-low">
582
+ <h3 style="color: #059669; font-size: 1.5rem; margin-bottom: 1rem;">STANDARD WOUND CARE PROTOCOL</h3>
583
+ <ul style="font-size: 1.1rem; line-height: 1.8; color:black;">
584
+ <li style="color:black;"><strong>Clean wound gently with soap and water</strong></li>
585
+ <li style="color:black;">Apply antiseptic and clean bandage</li>
586
+ <li style="color:black;">Monitor for changes or infection signs</li>
587
+ <li style="color:black;">Keep wound clean and dry</li>
588
+ <li style="color:black;">Consider tetanus booster if >5 years since last vaccination</li>
589
+ <li style="color:black;">Follow up if wound doesn't heal properly</li>
590
+ </ul>
591
+ </div>
592
+ """, unsafe_allow_html=True)
593
+
594
+ st.markdown('</div>', unsafe_allow_html=True)
595
+
596
+ # Enhanced information section
597
+ st.markdown("---")
598
+
599
+ info_col1, info_col2 = st.columns(2)
600
+
601
+ with info_col1:
602
+ st.markdown("""
603
+ <div class="info-box">
604
+ <div class="info-title">System Overview</div>
605
+ <p><strong>AI Technology:</strong> Convolutional Neural Networks</p>
606
+ <p><strong>Processing:</strong> Real-time image analysis</p>
607
+ <p><strong>Classification:</strong> Three-tier risk assessment</p>
608
+ <p><strong>Guidelines:</strong> Evidence-based medical protocols</p>
609
+ </div>
610
+ """, unsafe_allow_html=True)
611
+
612
+ with info_col2:
613
+ st.markdown("""
614
+ <div class="info-box">
615
+ <div class="info-title">Technical Specs</div>
616
+ <p><strong>Model Architecture:</strong> Deep CNN</p>
617
+ <p><strong>Input Resolution:</strong> 224×224 pixels</p>
618
+ <p><strong>Framework:</strong> TensorFlow/Keras</p>
619
+ <p><strong>Inference Time:</strong> <2 seconds</p>
620
+ </div>
621
+ """, unsafe_allow_html=True)
622
+
623
+
624
+
625
+ # ====== Run Application ======
626
+ if __name__ == "__main__":
627
+ main()
src/final_tetanus_model.keras ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e3fffc4af4a1f85c78cc2d27fffbb82aea0856736544ea8d0a045c981dca3999
3
+ size 5276886
src/requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ streamlit>=1.25.0
2
+ tensorflow
3
+ Pillow>=9.0.0
4
+ matplotlib>=3.5.0
5
+ numpy>=1.21.0
src/streamlit_app.py ADDED
@@ -0,0 +1,627 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import warnings
3
+ warnings.filterwarnings('ignore', category=UserWarning)
4
+ os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
5
+
6
+ import streamlit as st
7
+ import tensorflow as tf
8
+ from tensorflow.keras.models import load_model
9
+ from tensorflow.keras.preprocessing import image
10
+ import numpy as np
11
+ import matplotlib.pyplot as plt
12
+ from PIL import Image
13
+ import io
14
+ import plotly.express as px
15
+ import plotly.graph_objects as go
16
+ from plotly.subplots import make_subplots
17
+
18
+ # ====== Page Configuration ======
19
+ st.set_page_config(
20
+ page_title="Tetanus Risk Classifier",
21
+ page_icon="🩺",
22
+ layout="wide",
23
+ initial_sidebar_state="expanded"
24
+ )
25
+
26
+ # ====== Custom CSS for Modern UI ======
27
+ st.markdown("""
28
+ <style>
29
+ /* Import Google Fonts */
30
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
31
+
32
+ /* Global Styling */
33
+ .main {
34
+ font-family: 'Inter', sans-serif;
35
+ background: linear-gradient(135deg, #fffaf0 0%, #fdf6e3 100%);
36
+ min-height: 100vh;
37
+ }
38
+
39
+ .stApp {
40
+ background: #fefcf7;
41
+ color: #3a3a3a;
42
+ }
43
+
44
+ /* Header Styling */
45
+ .main-title {
46
+ font-size: 3rem;
47
+ font-weight: 700;
48
+ text-align: center;
49
+ color: #2b2b2b;
50
+ margin-bottom: 0.5rem;
51
+ text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
52
+ }
53
+
54
+ .sub-title {
55
+ font-size: 1.2rem;
56
+ text-align: center;
57
+ color: #7a6a4f;
58
+ margin-bottom: 3rem;
59
+ font-weight: 400;
60
+ }
61
+
62
+ /* Card Styling */
63
+ .custom-card {
64
+ background: #fffdf8;
65
+ border-radius: 16px;
66
+ padding: 2rem;
67
+ box-shadow: 0 6px 18px rgba(0,0,0,0.08);
68
+ border: 1px solid #f1e7d0;
69
+ margin-bottom: 2rem;
70
+ }
71
+
72
+ .upload-card {
73
+ background: #fffef9;
74
+ border-radius: 16px;
75
+ padding: 2rem;
76
+ text-align: center;
77
+ border: 2px dashed #e0d6b8;
78
+ transition: all 0.3s ease;
79
+ margin: 1rem 0;
80
+ }
81
+
82
+ .upload-card:hover {
83
+ border-color: #b08968;
84
+ transform: translateY(-2px);
85
+ box-shadow: 0 12px 25px rgba(0,0,0,0.1);
86
+ }
87
+
88
+ /* Risk Level Indicators */
89
+ .risk-badge-high {
90
+ background: #fbe9e7;
91
+ color: #c62828;
92
+ padding: 1rem 2rem;
93
+ border-radius: 12px;
94
+ text-align: center;
95
+ font-size: 1.2rem;
96
+ font-weight: 700;
97
+ margin: 1rem 0;
98
+ border: 1px solid #ef9a9a;
99
+ }
100
+
101
+ .risk-badge-mid {
102
+ background: #fff8e1;
103
+ color: #b37400;
104
+ padding: 1rem 2rem;
105
+ border-radius: 12px;
106
+ text-align: center;
107
+ font-size: 1.2rem;
108
+ font-weight: 700;
109
+ margin: 1rem 0;
110
+ border: 1px solid #ffd54f;
111
+ }
112
+
113
+ .risk-badge-low {
114
+ background: #f1fbe9;
115
+ color: #2e7d32;
116
+ padding: 1rem 2rem;
117
+ border-radius: 12px;
118
+ text-align: center;
119
+ font-size: 1.2rem;
120
+ font-weight: 700;
121
+ margin: 1rem 0;
122
+ border: 1px solid #a5d6a7;
123
+ }
124
+
125
+ /* Section Headers */
126
+ .section-header {
127
+ font-size: 1.5rem;
128
+ font-weight: 700;
129
+ color: #5c4d36;
130
+ margin: 2rem 0 1rem 0;
131
+ padding-bottom: 0.5rem;
132
+ border-bottom: 2px solid #e0d6b8;
133
+ text-align: center;
134
+ }
135
+
136
+ /* Metrics Styling */
137
+ .metric-container {
138
+ background: #fffdf6;
139
+ border-radius: 12px;
140
+ padding: 1.2rem;
141
+ text-align: center;
142
+ border: 1px solid #e7dbc2;
143
+ margin: 1rem 0;
144
+ color: #3a3a3a;
145
+ }
146
+
147
+ /* Recommendations */
148
+ .recommendation-box {
149
+ padding: 1.5rem;
150
+ margin: 1.5rem 0;
151
+ border-radius: 12px;
152
+ border-left: 5px solid;
153
+ background: #fffdf9;
154
+ box-shadow: 0 6px 12px rgba(0,0,0,0.05);
155
+ }
156
+
157
+ .recommendation-high {
158
+ border-left-color: #c62828;
159
+ }
160
+
161
+ .recommendation-mid {
162
+ border-left-color: #b37400;
163
+ }
164
+
165
+ .recommendation-low {
166
+ border-left-color: #2e7d32;
167
+ }
168
+
169
+ /* Sidebar Styling */
170
+ .sidebar .sidebar-content {
171
+ background: #fffef9;
172
+ border-radius: 12px;
173
+ padding: 1rem;
174
+ margin: 0.5rem 0;
175
+ box-shadow: 0 4px 8px rgba(0,0,0,0.05);
176
+ border: 1px solid #f1e7d0;
177
+ }
178
+
179
+ /* Hide Streamlit branding */
180
+ .stDeployButton, footer {
181
+ display: none !important;
182
+ }
183
+
184
+ /* Custom info boxes */
185
+ .info-box {
186
+ background: #fffdf6;
187
+ border-radius: 10px;
188
+ padding: 1.2rem;
189
+ margin: 1rem 0;
190
+ border-left: 4px solid #b08968;
191
+ color: #3a3a3a;
192
+ }
193
+
194
+ .info-title {
195
+ font-weight: 700;
196
+ color: #7a6a4f;
197
+ font-size: 1.1rem;
198
+ margin-bottom: 0.8rem;
199
+ }
200
+
201
+ /* Progress bars */
202
+ .stProgress > div > div > div > div {
203
+ background: linear-gradient(90deg, #b08968, #d4a373);
204
+ border-radius: 6px;
205
+ }
206
+
207
+ /* Upload button styling */
208
+ .stFileUploader label {
209
+ background: #f1e3cf !important;
210
+ color: #3a3a3a !important;
211
+ border-radius: 10px !important;
212
+ border: 1px solid #d9c9a8 !important;
213
+ padding: 0.8rem 1.5rem !important;
214
+ font-weight: 600 !important;
215
+ transition: all 0.3s ease !important;
216
+ }
217
+
218
+ .stFileUploader label:hover {
219
+ background: #e6d3b3 !important;
220
+ transform: translateY(-2px) !important;
221
+ box-shadow: 0 6px 12px rgba(0,0,0,0.15) !important;
222
+ }
223
+ .stAlert div {
224
+ color: black !important;
225
+ }
226
+ </style>
227
+
228
+
229
+
230
+ """, unsafe_allow_html=True)
231
+
232
+ # ====== Main Title ======
233
+ st.markdown('<h1 class="main-title">Tetanus Risk Assessment System</h1>', unsafe_allow_html=True)
234
+ st.markdown('<p class="sub-title">AI-powered medical imaging analysis for tetanus risk evaluation</p>', unsafe_allow_html=True)
235
+
236
+ # ====== Enhanced Sidebar Configuration ======
237
+ with st.sidebar:
238
+ st.markdown('<div class="sidebar-content">', unsafe_allow_html=True)
239
+ st.markdown("## Configuration")
240
+
241
+ # Model path input with better styling
242
+ model_path = st.text_input(
243
+ "Model File Path",
244
+ value="final_tetanus_model.keras",
245
+ help="Enter the path to your trained .keras model file"
246
+ )
247
+
248
+ st.markdown("---")
249
+
250
+ # Risk categories with enhanced presentation
251
+ st.markdown("## Risk Categories")
252
+
253
+ col1, col2 = st.columns([1, 3])
254
+ with col1:
255
+ st.markdown("●", unsafe_allow_html=True)
256
+ st.markdown("●", unsafe_allow_html=True)
257
+ st.markdown("●", unsafe_allow_html=True)
258
+ with col2:
259
+ st.markdown("**High Risk** - Immediate medical attention")
260
+ st.markdown("**Moderate Risk** - Clinical evaluation needed")
261
+ st.markdown("**Low Risk** - Standard wound care")
262
+
263
+ st.markdown("---")
264
+
265
+ # Enhanced risk information
266
+ with st.expander("Detailed Risk Information"):
267
+ st.markdown("""
268
+ **High Risk Indicators:**
269
+ - Deep puncture wounds
270
+ - Contaminated wounds
271
+ - Foreign object presence
272
+ - Rusty metal exposure
273
+
274
+ **Moderate Risk Indicators:**
275
+ - Minor cuts with debris
276
+ - Moderate depth wounds
277
+ - Delayed treatment (>6 hours)
278
+ - Animal bites
279
+
280
+ **Low Risk Indicators:**
281
+ - Superficial cuts
282
+ - Clean wounds
283
+ - Fresh injuries (<1 hour)
284
+ - Proper wound cleaning
285
+ """)
286
+
287
+ st.markdown("---")
288
+
289
+ # System info
290
+ st.markdown("## System Info")
291
+ st.info("**Model Status:** Ready for analysis")
292
+ st.info("**Processing:** Real-time inference")
293
+ st.info("**Accuracy:** Clinical-grade assessment")
294
+
295
+ st.markdown('</div>', unsafe_allow_html=True)
296
+
297
+ # ====== Model Loading Function ======
298
+ @st.cache_resource
299
+ def load_tetanus_model(model_path):
300
+ """Load the trained model with enhanced error handling"""
301
+ try:
302
+ if os.path.exists(model_path):
303
+ model = load_model(model_path)
304
+ return model, None
305
+ else:
306
+ return None, f"Model file not found at: {model_path}"
307
+ except Exception as e:
308
+ return None, f"Error loading model: {str(e)}"
309
+
310
+ # ====== Enhanced Image Preprocessing ======
311
+ def preprocess_image(img):
312
+ """Enhanced image preprocessing with validation"""
313
+ if img.mode != 'RGB':
314
+ img = img.convert('RGB')
315
+
316
+ # Store original size for display
317
+ original_size = img.size
318
+
319
+ # Resize for model
320
+ img = img.resize((224, 224))
321
+ img_array = image.img_to_array(img)
322
+ img_array = np.expand_dims(img_array, axis=0)
323
+ img_array = img_array / 255.0
324
+
325
+ return img_array, original_size
326
+
327
+ # ====== Enhanced Prediction Function ======
328
+
329
+
330
+ def make_prediction(model, img_array):
331
+ """Make prediction with detailed probability analysis"""
332
+ try:
333
+ risk_categories = ['High Risk', 'Mid Risk', 'Low Risk']
334
+
335
+ # 🔥 Use actual model prediction instead of mock
336
+ prediction = model.predict(img_array, verbose=0)
337
+
338
+ predicted_index = np.argmax(prediction)
339
+ predicted_label = risk_categories[predicted_index]
340
+ confidence = prediction[0][predicted_index] * 100
341
+ all_probabilities = prediction[0] * 100
342
+
343
+ return predicted_label, confidence, all_probabilities, None
344
+ except Exception as e:
345
+ return None, None, None, f"Error making prediction: {str(e)}"
346
+
347
+ # ====== Enhanced Visualization Functions ======
348
+ def create_confidence_chart(confidence):
349
+ """Create an enhanced confidence visualization"""
350
+ fig = go.Figure(go.Indicator(
351
+ mode = "gauge+number+delta",
352
+ value = confidence,
353
+ domain = {'x': [0, 1], 'y': [0, 1]},
354
+ title = {'text': "Confidence Level"},
355
+ delta = {'reference': 80},
356
+ gauge = {
357
+ 'axis': {'range': [None, 100]},
358
+ 'bar': {'color': "#4f46e5"},
359
+ 'steps': [
360
+ {'range': [0, 50], 'color': "#fee2e2"},
361
+ {'range': [50, 80], 'color': "#fef3c7"},
362
+ {'range': [80, 100], 'color': "#d1fae5"}],
363
+ 'threshold': {
364
+ 'line': {'color': "red", 'width': 4},
365
+ 'thickness': 0.75,
366
+ 'value': 90}}))
367
+
368
+ fig.update_layout(
369
+ height=300,
370
+ font={'color': "#4f46e5", 'family': "Inter"},
371
+ paper_bgcolor="rgba(0,0,0,0)",
372
+ plot_bgcolor="rgba(0,0,0,0)"
373
+ )
374
+ return fig
375
+
376
+ def create_probability_chart(probabilities, categories):
377
+ """Create enhanced probability visualization"""
378
+ colors = ['#ef4444', '#f59e0b', '#10b981']
379
+
380
+ fig = go.Figure(data=[
381
+ go.Bar(
382
+ x=categories,
383
+ y=probabilities,
384
+ marker_color=colors,
385
+ text=[f'{p:.1f}%' for p in probabilities],
386
+ textposition='auto',
387
+ )
388
+ ])
389
+
390
+ fig.update_layout(
391
+ title="Risk Probability Distribution",
392
+ xaxis_title="Risk Categories",
393
+ yaxis_title="Probability (%)",
394
+ font={'color': "#374151", 'family': "Inter"},
395
+ paper_bgcolor="rgba(0,0,0,0)",
396
+ plot_bgcolor="rgba(0,0,0,0)",
397
+ height=400
398
+ )
399
+
400
+ return fig
401
+
402
+ # ====== Main Application ======
403
+ def main():
404
+ # Load model with enhanced feedback
405
+ with st.spinner("Loading AI model..."):
406
+ model, error = load_tetanus_model(model_path)
407
+
408
+ if error:
409
+ st.error(f"**Model Loading Error:** {error}")
410
+ st.info("**Tip:** Please verify the model path in the sidebar configuration.")
411
+ st.stop()
412
+
413
+ # Success message with animation
414
+ st.info("**AI Model loaded successfully!** Ready for medical image analysis.")
415
+
416
+ # Create enhanced layout
417
+ col1, col2 = st.columns([1.2, 1], gap="large")
418
+
419
+ with col1:
420
+ # Enhanced upload section
421
+ st.markdown('<div class="custom-card">', unsafe_allow_html=True)
422
+ st.markdown('<h2 class="section-header">Upload or Capture Medical Image</h2>', unsafe_allow_html=True)
423
+
424
+ # File uploader
425
+ uploaded_file = st.file_uploader(
426
+ "Upload Medical Image",
427
+ type=['png', 'jpg', 'jpeg', 'bmp', 'tiff'],
428
+ help="Upload a clear, high-quality image of the wound for analysis",
429
+ label_visibility="collapsed"
430
+ )
431
+
432
+ # Camera input
433
+ camera_file = st.camera_input(
434
+ "Capture Medical Image",
435
+ label_visibility="collapsed"
436
+ )
437
+
438
+ # Pick whichever is used
439
+ final_file = uploaded_file if uploaded_file is not None else camera_file
440
+
441
+ if final_file is not None:
442
+ # Display image with enhanced presentation
443
+ img = Image.open(final_file)
444
+ st.image(img, caption="Medical Image for Analysis", use_container_width=True)
445
+
446
+ # Enhanced image metadata
447
+ img_array, original_size = preprocess_image(img)
448
+
449
+ col_meta1, col_meta2, col_meta3 = st.columns(3)
450
+ with col_meta1:
451
+ st.markdown('<div class="metric-container">', unsafe_allow_html=True)
452
+ st.metric("Dimensions", f"{original_size[0]} × {original_size[1]}")
453
+ st.markdown('</div>', unsafe_allow_html=True)
454
+
455
+ with col_meta2:
456
+ st.markdown('<div class="metric-container">', unsafe_allow_html=True)
457
+ st.metric("Format", img.format if hasattr(img, 'format') else 'Unknown')
458
+ st.markdown('</div>', unsafe_allow_html=True)
459
+
460
+ with col_meta3:
461
+ st.markdown('<div class="metric-container">', unsafe_allow_html=True)
462
+ file_size = len(final_file.getvalue()) / 1024 # KB
463
+ st.metric("Size", f"{file_size:.1f} KB")
464
+ st.markdown('</div>', unsafe_allow_html=True)
465
+ else:
466
+ # Enhanced empty state
467
+ st.markdown("### Drop your medical image here or capture using the camera")
468
+ st.markdown("Supported formats: PNG, JPG, JPEG, BMP, TIFF")
469
+ st.markdown("Maximum file size: 10MB")
470
+ st.markdown('</div>', unsafe_allow_html=True)
471
+
472
+ st.markdown('</div>', unsafe_allow_html=True)
473
+
474
+
475
+ with col2:
476
+ # Enhanced results section
477
+ st.markdown('<div class="custom-card">', unsafe_allow_html=True)
478
+ st.markdown('<h2 class="section-header">Results</h2>', unsafe_allow_html=True)
479
+
480
+ if uploaded_file is not None or camera_file is not None:
481
+ # Choose file priority (uploaded > captured)
482
+ file_source = uploaded_file if uploaded_file is not None else camera_file
483
+ img = Image.open(file_source)
484
+ img_array, _ = preprocess_image(img)
485
+
486
+ # Processing with enhanced feedback
487
+ with st.spinner("Analyzing image with AI model..."):
488
+ predicted_label, confidence, all_probabilities, pred_error = make_prediction(model, img_array)
489
+
490
+ if pred_error:
491
+ st.error(f"❌ **Prediction Error:** {pred_error}")
492
+ st.markdown('</div>', unsafe_allow_html=True)
493
+ st.stop()
494
+
495
+ # Enhanced risk level display
496
+ if predicted_label == "High Risk":
497
+ st.markdown('<div class="risk-badge-high">HIGH RISK DETECTED</div>', unsafe_allow_html=True)
498
+ elif predicted_label == "Mid Risk":
499
+ st.markdown('<div class="risk-badge-mid">MODERATE RISK DETECTED</div>', unsafe_allow_html=True)
500
+ else:
501
+ st.markdown('<div class="risk-badge-low">LOW RISK DETECTED</div>', unsafe_allow_html=True)
502
+
503
+ # Enhanced confidence display
504
+ st.markdown("### Confidence Analysis")
505
+ confidence_chart = create_confidence_chart(confidence)
506
+ st.plotly_chart(confidence_chart, use_container_width=True)
507
+
508
+ else:
509
+ # Enhanced empty state for results
510
+ st.markdown("""
511
+ <div style="text-align: center; padding: 3rem; color: #9ca3af;">
512
+ <div style="font-size: 4rem; margin-bottom: 1rem;">⚕</div>
513
+ <h3>Ready for Analysis</h3>
514
+ <p>Upload or capture a medical image to begin AI-powered risk assessment</p>
515
+ </div>
516
+ """, unsafe_allow_html=True)
517
+
518
+ st.markdown('</div>', unsafe_allow_html=True)
519
+
520
+ # Enhanced detailed analysis section (full width)
521
+ if (uploaded_file is not None or camera_file is not None) and 'predicted_label' in locals():
522
+ st.markdown('<div class="custom-card">', unsafe_allow_html=True)
523
+ st.markdown('<h2 class="section-header">Detailed Probability Analysis</h2>', unsafe_allow_html=True)
524
+
525
+ # Create probability visualization
526
+ risk_categories = ['High Risk', 'Mid Risk', 'Low Risk']
527
+ prob_chart = create_probability_chart(all_probabilities, risk_categories)
528
+ st.plotly_chart(prob_chart, use_container_width=True)
529
+
530
+ # Detailed breakdown
531
+ col1, col2, col3 = st.columns(3)
532
+ categories = ['High Risk', 'Mid Risk', 'Low Risk']
533
+ colors = ['#ef4444', '#f59e0b', '#10b981']
534
+
535
+ for i, (col, category, color, prob) in enumerate(zip([col1, col2, col3], categories, colors, all_probabilities)):
536
+ with col:
537
+ st.markdown(f"""
538
+ <div style="text-align: center; padding: 1rem; background: rgba(255,255,255,0.8); border-radius: 10px; margin: 0.5rem 0;">
539
+ <div style="width: 20px; height: 20px; background-color: {color}; border-radius: 50%; margin: 0 auto 0.5rem;"></div>
540
+ <div style="font-weight: 700; font-size: 1.2rem;">{category}</div>
541
+ <div style="font-size: 1.5rem; font-weight: 600; color: #4f46e5;">{prob:.1f}%</div>
542
+ </div>
543
+ """, unsafe_allow_html=True)
544
+
545
+ st.markdown('</div>', unsafe_allow_html=True)
546
+
547
+ # Enhanced recommendations section
548
+ st.markdown('<div class="custom-card">', unsafe_allow_html=True)
549
+ st.markdown('<h2 class="section-header">Medical Recommendations</h2>', unsafe_allow_html=True)
550
+
551
+ if predicted_label == "High Risk":
552
+ st.markdown("""
553
+ <div class="recommendation-box recommendation-high">
554
+ <h3 style="color: #dc2626; font-size: 1.5rem; margin-bottom: 1rem;">IMMEDIATE MEDICAL ATTENTION REQUIRED</h3>
555
+ <ul style="font-size: 1.1rem; line-height: 1.8;">
556
+ <li style="color:black;"><strong>Seek emergency medical care immediately</strong></li>
557
+ <li style="color:black;" >Do not delay professional treatment</li>
558
+ <li style="color:black;">Verify tetanus vaccination status with healthcare provider</li>
559
+ <li style="color:black;">Clean wound with sterile saline if available</li>
560
+ <li style="color:black;">Avoid home remedies - professional care is essential</li>
561
+ <li style="color:black;">Monitor for signs of infection or tetanus symptoms</li>
562
+ </ul>
563
+ </div>
564
+ """, unsafe_allow_html=True)
565
+ elif predicted_label == "Mid Risk":
566
+ st.markdown("""
567
+ <div class="recommendation-box recommendation-mid">
568
+ <h3 style="color: #d97706; font-size: 1.5rem; margin-bottom: 1rem;">CLINICAL EVALUATION RECOMMENDED</h3>
569
+ <ul style="font-size: 1.1rem; line-height: 1.8;">
570
+ <li style="color:black;"><strong>Clean wound thoroughly with soap and water</strong></li>
571
+ <li style="color:black;">Monitor for signs of infection (redness, swelling, warmth)</li>
572
+ <li style="color:black;">Consult healthcare provider within 24 hours</li>
573
+ <li style="color:black;">Update tetanus vaccination if necessary (>5 years)</li>
574
+ <li style="color:black;">Apply clean dressing and change regularly</li>
575
+ <li style="color:black;">Take photos to track healing progress</li>
576
+ </ul>
577
+ </div>
578
+ """, unsafe_allow_html=True)
579
+ else:
580
+ st.markdown("""
581
+ <div class="recommendation-box recommendation-low">
582
+ <h3 style="color: #059669; font-size: 1.5rem; margin-bottom: 1rem;">STANDARD WOUND CARE PROTOCOL</h3>
583
+ <ul style="font-size: 1.1rem; line-height: 1.8; color:black;">
584
+ <li style="color:black;"><strong>Clean wound gently with soap and water</strong></li>
585
+ <li style="color:black;">Apply antiseptic and clean bandage</li>
586
+ <li style="color:black;">Monitor for changes or infection signs</li>
587
+ <li style="color:black;">Keep wound clean and dry</li>
588
+ <li style="color:black;">Consider tetanus booster if >5 years since last vaccination</li>
589
+ <li style="color:black;">Follow up if wound doesn't heal properly</li>
590
+ </ul>
591
+ </div>
592
+ """, unsafe_allow_html=True)
593
+
594
+ st.markdown('</div>', unsafe_allow_html=True)
595
+
596
+ # Enhanced information section
597
+ st.markdown("---")
598
+
599
+ info_col1, info_col2 = st.columns(2)
600
+
601
+ with info_col1:
602
+ st.markdown("""
603
+ <div class="info-box">
604
+ <div class="info-title">System Overview</div>
605
+ <p><strong>AI Technology:</strong> Convolutional Neural Networks</p>
606
+ <p><strong>Processing:</strong> Real-time image analysis</p>
607
+ <p><strong>Classification:</strong> Three-tier risk assessment</p>
608
+ <p><strong>Guidelines:</strong> Evidence-based medical protocols</p>
609
+ </div>
610
+ """, unsafe_allow_html=True)
611
+
612
+ with info_col2:
613
+ st.markdown("""
614
+ <div class="info-box">
615
+ <div class="info-title">Technical Specs</div>
616
+ <p><strong>Model Architecture:</strong> Deep CNN</p>
617
+ <p><strong>Input Resolution:</strong> 224×224 pixels</p>
618
+ <p><strong>Framework:</strong> TensorFlow/Keras</p>
619
+ <p><strong>Inference Time:</strong> <2 seconds</p>
620
+ </div>
621
+ """, unsafe_allow_html=True)
622
+
623
+
624
+
625
+ # ====== Run Application ======
626
+ if __name__ == "__main__":
627
+ main()