luigi12345
commited on
Commit
β’
c73c262
1
Parent(s):
4234218
app.py
CHANGED
@@ -183,30 +183,58 @@ def save_results(results, original_images):
|
|
183 |
def main():
|
184 |
st.set_page_config(layout="wide", page_title="Glaucoma Screening Tool")
|
185 |
|
|
|
|
|
186 |
st.markdown("""
|
187 |
<h1 style='text-align: center;'>Glaucoma Screening from Retinal Fundus Images</h1>
|
188 |
<p style='text-align: center; color: gray;'>Upload retinal images for automated glaucoma detection and optic disc/cup segmentation</p>
|
189 |
""", unsafe_allow_html=True)
|
190 |
|
191 |
-
#
|
192 |
-
st.sidebar.markdown("### Upload Settings")
|
193 |
-
uploaded_files = st.sidebar.file_uploader("Upload Retinal Images",
|
194 |
-
type=['png', 'jpeg', 'jpg'],
|
195 |
-
accept_multiple_files=True,
|
196 |
-
help="Support multiple images in PNG, JPEG formats")
|
197 |
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
204 |
|
205 |
if uploaded_files:
|
206 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
207 |
|
208 |
-
#
|
209 |
-
|
|
|
|
|
|
|
|
|
210 |
|
211 |
# Prepare images data
|
212 |
images_data = []
|
@@ -228,20 +256,44 @@ def main():
|
|
228 |
results = process_batch(model, images_data, progress_bar)
|
229 |
|
230 |
if results:
|
231 |
-
#
|
232 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
233 |
|
234 |
-
#
|
235 |
-
st.
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
)
|
241 |
|
242 |
-
#
|
243 |
-
|
244 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
245 |
cols = st.columns(3)
|
246 |
with cols[0]:
|
247 |
st.image(result['processed_image'], caption="Segmentation", use_column_width=True)
|
@@ -254,3 +306,37 @@ def main():
|
|
254 |
st.write(f"VCDR: {result['vcdr']:.3f}")
|
255 |
st.write(f"Cup Confidence: {result['cup_conf']:.1f}%")
|
256 |
st.write(f"Disc Confidence: {result['disc_conf']:.1f}%")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
183 |
def main():
|
184 |
st.set_page_config(layout="wide", page_title="Glaucoma Screening Tool")
|
185 |
|
186 |
+
print("Starting app...") # Debug print
|
187 |
+
|
188 |
st.markdown("""
|
189 |
<h1 style='text-align: center;'>Glaucoma Screening from Retinal Fundus Images</h1>
|
190 |
<p style='text-align: center; color: gray;'>Upload retinal images for automated glaucoma detection and optic disc/cup segmentation</p>
|
191 |
""", unsafe_allow_html=True)
|
192 |
|
193 |
+
print("Header rendered...") # Debug print
|
|
|
|
|
|
|
|
|
|
|
194 |
|
195 |
+
# Add session state for better state management
|
196 |
+
if 'processed_count' not in st.session_state:
|
197 |
+
st.session_state.processed_count = 0
|
198 |
+
|
199 |
+
# Add a more informative sidebar
|
200 |
+
with st.sidebar:
|
201 |
+
st.markdown("### π€ Upload Images")
|
202 |
+
uploaded_files = st.file_uploader(
|
203 |
+
"Upload Retinal Images",
|
204 |
+
type=['png', 'jpeg', 'jpg'],
|
205 |
+
accept_multiple_files=True,
|
206 |
+
help="Support multiple images in PNG, JPEG formats"
|
207 |
+
)
|
208 |
+
|
209 |
+
st.markdown("### π Processing Stats")
|
210 |
+
if 'processed_count' in st.session_state:
|
211 |
+
st.metric("Images Processed", st.session_state.processed_count)
|
212 |
+
|
213 |
+
st.markdown("---")
|
214 |
+
|
215 |
+
# Add batch size limit
|
216 |
+
max_batch = st.number_input("Max Batch Size",
|
217 |
+
min_value=1,
|
218 |
+
max_value=100,
|
219 |
+
value=20,
|
220 |
+
help="Maximum number of images to process in one batch")
|
221 |
|
222 |
if uploaded_files:
|
223 |
+
# Validate batch size
|
224 |
+
if len(uploaded_files) > max_batch:
|
225 |
+
st.warning(f"β οΈ Please upload maximum {max_batch} images at once. Current: {len(uploaded_files)}")
|
226 |
+
return
|
227 |
+
|
228 |
+
# Add loading animation
|
229 |
+
with st.spinner('π Initializing model...'):
|
230 |
+
model = GlaucomaModel(device=torch.device("cuda:0" if torch.cuda.is_available() else "cpu"))
|
231 |
|
232 |
+
# Add summary metrics at the top
|
233 |
+
col1, col2 = st.columns(2)
|
234 |
+
with col1:
|
235 |
+
st.info(f"π Total images: {len(uploaded_files)}")
|
236 |
+
with col2:
|
237 |
+
st.info(f"βοΈ Using: {'GPU' if torch.cuda.is_available() else 'CPU'}")
|
238 |
|
239 |
# Prepare images data
|
240 |
images_data = []
|
|
|
256 |
results = process_batch(model, images_data, progress_bar)
|
257 |
|
258 |
if results:
|
259 |
+
# Add summary statistics
|
260 |
+
st.markdown("### π Summary Statistics")
|
261 |
+
glaucoma_count = sum(1 for r in results if r['diagnosis'] == 'Glaucoma')
|
262 |
+
normal_count = len(results) - glaucoma_count
|
263 |
+
|
264 |
+
cols = st.columns(4)
|
265 |
+
with cols[0]:
|
266 |
+
st.metric("Total Processed", len(results))
|
267 |
+
with cols[1]:
|
268 |
+
st.metric("Glaucoma Detected", glaucoma_count)
|
269 |
+
with cols[2]:
|
270 |
+
st.metric("Normal", normal_count)
|
271 |
+
with cols[3]:
|
272 |
+
avg_conf = sum(r['confidence'] for r in results) / len(results)
|
273 |
+
st.metric("Avg Confidence", f"{avg_conf:.1f}%")
|
274 |
|
275 |
+
# Add filter options
|
276 |
+
st.markdown("### π Filter Results")
|
277 |
+
show_only = st.multiselect(
|
278 |
+
"Show cases:",
|
279 |
+
["All", "Glaucoma", "Normal"],
|
280 |
+
default=["All"]
|
281 |
)
|
282 |
|
283 |
+
# Filter results based on selection
|
284 |
+
filtered_results = results
|
285 |
+
if "All" not in show_only:
|
286 |
+
filtered_results = [
|
287 |
+
r for r in results
|
288 |
+
if (r['diagnosis'] == 'Glaucoma' and 'Glaucoma' in show_only) or
|
289 |
+
(r['diagnosis'] == 'Normal' and 'Normal' in show_only)
|
290 |
+
]
|
291 |
+
|
292 |
+
# Display filtered results
|
293 |
+
for result in filtered_results:
|
294 |
+
with st.expander(
|
295 |
+
f"π {result['file_name']} - {result['diagnosis']} ({result['confidence']:.1f}% confidence)"
|
296 |
+
):
|
297 |
cols = st.columns(3)
|
298 |
with cols[0]:
|
299 |
st.image(result['processed_image'], caption="Segmentation", use_column_width=True)
|
|
|
306 |
st.write(f"VCDR: {result['vcdr']:.3f}")
|
307 |
st.write(f"Cup Confidence: {result['cup_conf']:.1f}%")
|
308 |
st.write(f"Disc Confidence: {result['disc_conf']:.1f}%")
|
309 |
+
|
310 |
+
# Update session state
|
311 |
+
st.session_state.processed_count += len(results)
|
312 |
+
|
313 |
+
# Add export options
|
314 |
+
st.markdown("### π₯ Export Options")
|
315 |
+
col1, col2 = st.columns(2)
|
316 |
+
with col1:
|
317 |
+
st.download_button(
|
318 |
+
label="π₯ Download All Results (ZIP)",
|
319 |
+
data=zip_data,
|
320 |
+
file_name=f"glaucoma_screening_{datetime.now().strftime('%Y%m%d_%H%M%S')}.zip",
|
321 |
+
mime="application/zip"
|
322 |
+
)
|
323 |
+
with col2:
|
324 |
+
# Add CSV-only download
|
325 |
+
csv_data = pd.DataFrame([{
|
326 |
+
'File': r['file_name'],
|
327 |
+
'Diagnosis': r['diagnosis'],
|
328 |
+
'Confidence': r['confidence'],
|
329 |
+
'VCDR': r['vcdr']
|
330 |
+
} for r in results]).to_csv(index=False)
|
331 |
+
|
332 |
+
st.download_button(
|
333 |
+
label="π Download Report (CSV)",
|
334 |
+
data=csv_data,
|
335 |
+
file_name=f"glaucoma_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv",
|
336 |
+
mime="text/csv"
|
337 |
+
)
|
338 |
+
|
339 |
+
# Add this at the end of the file
|
340 |
+
if __name__ == "__main__":
|
341 |
+
print("Running main...") # Debug print
|
342 |
+
main()
|