Spaces:
Sleeping
Sleeping
Completed other pages and added dataset page
Browse files- app.py +30 -6
- pages/Dataset.py +62 -0
- pages/Model_Evaluation.py +31 -0
- pages/Upload_and_Predict.py +138 -9
app.py
CHANGED
@@ -3,20 +3,44 @@ from PIL import Image
|
|
3 |
|
4 |
def main():
|
5 |
st.set_page_config(page_title="DR Assistive Tool", layout="centered")
|
6 |
-
|
7 |
st.markdown("<h1 style='text-align: center; color: #2E86C1;'>DR Assistive Tool</h1>", unsafe_allow_html=True)
|
8 |
|
9 |
st.markdown("""
|
10 |
-
<h4 style='text-align: center; color: grey;'>
|
|
|
|
|
11 |
""", unsafe_allow_html=True)
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
st.markdown("""
|
14 |
---
|
15 |
### π Features:
|
16 |
-
- **Upload
|
17 |
-
- **Evaluate** the model using real test datasets
|
18 |
-
|
19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
""")
|
21 |
|
22 |
if __name__ == '__main__':
|
|
|
3 |
|
4 |
def main():
|
5 |
st.set_page_config(page_title="DR Assistive Tool", layout="centered")
|
6 |
+
|
7 |
st.markdown("<h1 style='text-align: center; color: #2E86C1;'>DR Assistive Tool</h1>", unsafe_allow_html=True)
|
8 |
|
9 |
st.markdown("""
|
10 |
+
<h4 style='text-align: center; color: grey;'>
|
11 |
+
An AI-powered assistant for early detection of Diabetic Retinopathy
|
12 |
+
</h4>
|
13 |
""", unsafe_allow_html=True)
|
14 |
|
15 |
+
st.markdown("""---""")
|
16 |
+
|
17 |
+
st.markdown("""
|
18 |
+
### π§ What is DR Assistive Tool?
|
19 |
+
**DR Assistive Tool** is a user-friendly web application built for early and accurate detection of **Diabetic Retinopathy (DR)**βa diabetes-related eye disease that can lead to blindness if not diagnosed in time. This tool uses **AI and deep learning models** trained on retinal images to help healthcare professionals, students, and researchers identify the severity stage of DR.
|
20 |
+
|
21 |
+
By simply uploading a retinal image, the model will:
|
22 |
+
- Analyze the image using advanced machine learning techniques
|
23 |
+
- Predict the stage of Diabetic Retinopathy (No DR, Mild, Moderate, Severe, Proliferative DR)
|
24 |
+
- Provide a quick, reliable, and cost-efficient second opinion for screening
|
25 |
+
|
26 |
+
The app also offers evaluation options to test the model's performance using real datasets, ensuring its credibility and practical usability.
|
27 |
+
""")
|
28 |
+
|
29 |
st.markdown("""
|
30 |
---
|
31 |
### π Features:
|
32 |
+
- π€ **Upload retinal images** for DR stage prediction
|
33 |
+
- π **Evaluate** the model using real test datasets
|
34 |
+
- π **View results** with interpretation and confidence score
|
35 |
+
- π **Analyze model performance** using accuracy, precision, confusion matrix, and more (in evaluation mode)
|
36 |
+
|
37 |
+
---
|
38 |
+
### π How to Use:
|
39 |
+
1. Use the **sidebar** to select a feature (e.g., Predict or Evaluate).
|
40 |
+
2. In **Evaluate**, to check model accuracy.
|
41 |
+
3. In **Predict**, choose an DR image in sample images to predict or upload a high-quality retinal image (JPEG or PNG).
|
42 |
+
|
43 |
+
β οΈ *Note: This tool is not a diagnostic tool. This is an assistive tool for Doctors.*
|
44 |
""")
|
45 |
|
46 |
if __name__ == '__main__':
|
pages/Dataset.py
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import pandas as pd
|
3 |
+
import os
|
4 |
+
from PIL import Image
|
5 |
+
|
6 |
+
st.set_page_config(layout="wide")
|
7 |
+
st.title("π Dataset Information")
|
8 |
+
|
9 |
+
# Introduction
|
10 |
+
st.markdown("""
|
11 |
+
### π§Ύ Dataset Overview
|
12 |
+
|
13 |
+
## Dataset Descrption
|
14 |
+
|
15 |
+
### DDR dataset contains 13,673 fundus images from 147 hospitals, covering 23 provinces in China. The images are classified into 5 classes according to DR severity: none, mild, moderate, severe, and proliferative DR. There is a sixth category which indicates the images with poor quality. The dataset presented here does not include the images with poor quality (sixth category) and all images have been preprocessed to delete the black background. https://www.kaggle.com/datasets/mariaherrerot/ddrdataset
|
16 |
+
|
17 |
+
- **No_DR**
|
18 |
+
- **Mild**
|
19 |
+
- **Moderate**
|
20 |
+
- **Severe**
|
21 |
+
- **Proliferative_DR**
|
22 |
+
""")
|
23 |
+
|
24 |
+
# Dataset preparation explanation
|
25 |
+
st.markdown("""
|
26 |
+
### π§ͺ Data Preparation & Splitting
|
27 |
+
|
28 |
+
The original dataset was preprocessed and resized to **224x224 pixels**. It was then split into three sets:
|
29 |
+
|
30 |
+
- **Training Set**: Used to train the model.
|
31 |
+
- **Validation Set** *(optional)*: Used to fine-tune hyperparameters.
|
32 |
+
- **Testing Set**: Used for final model evaluation.
|
33 |
+
|
34 |
+
We used an 80-20 stratified split:
|
35 |
+
- **80%** of the data was used for training.
|
36 |
+
- **20%** was reserved for testing, ensuring each class was proportionally represented.
|
37 |
+
|
38 |
+
A CSV file (`test_labels.csv`) was created for the test set, containing the filenames and their corresponding class labels.
|
39 |
+
""")
|
40 |
+
|
41 |
+
# Visualizing the test dataset
|
42 |
+
st.markdown("### πΈ Sample Images from Test Dataset")
|
43 |
+
|
44 |
+
csv_path = "D:/DR_Classification/splits/test_labels.csv"
|
45 |
+
img_dir = "D:/DR_Classification/splits/test"
|
46 |
+
|
47 |
+
try:
|
48 |
+
df = pd.read_csv(csv_path)
|
49 |
+
class_names = df.iloc[:, 1].unique()
|
50 |
+
|
51 |
+
for class_name in class_names:
|
52 |
+
st.subheader(f"π Class: {class_name}")
|
53 |
+
class_samples = df[df.iloc[:, 1] == class_name].head(3)
|
54 |
+
cols = st.columns(len(class_samples))
|
55 |
+
|
56 |
+
for i, row in enumerate(class_samples.itertuples()):
|
57 |
+
img_path = os.path.join(img_dir, row[1])
|
58 |
+
if os.path.exists(img_path):
|
59 |
+
image = Image.open(img_path).convert('RGB')
|
60 |
+
cols[i].image(image, caption=row[1], use_column_width=True)
|
61 |
+
except Exception as e:
|
62 |
+
st.error(f"Error loading dataset: {e}")
|
pages/Model_Evaluation.py
CHANGED
@@ -129,6 +129,37 @@ with col2:
|
|
129 |
if st.session_state.evaluation_done:
|
130 |
reevaluate_col, download_col = st.columns([1, 1])
|
131 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
# ---- Evaluation Logic ----
|
133 |
if st.session_state.trigger_eval:
|
134 |
st.markdown("### β±οΈ Evaluation Results")
|
|
|
129 |
if st.session_state.evaluation_done:
|
130 |
reevaluate_col, download_col = st.columns([1, 1])
|
131 |
|
132 |
+
# ---- Description for Model Evaluation ----
|
133 |
+
with st.expander("βΉοΈ **What is Model Evaluation?**", expanded=True):
|
134 |
+
st.markdown("""
|
135 |
+
<div style='font-size:16px;'>
|
136 |
+
The **Model Evaluation** section tests how well the trained AI model performs on the unseen <strong>test set</strong> of retinal images. This provides insights into the reliability and performance of the model when deployed in real scenarios.
|
137 |
+
|
138 |
+
#### π What It Does:
|
139 |
+
- Loads the test dataset of labeled retinal images
|
140 |
+
- Runs the model to predict labels
|
141 |
+
- Compares predictions vs. true labels
|
142 |
+
- Computes:
|
143 |
+
- π **Classification Report** (Precision, Recall, F1-Score)
|
144 |
+
- π§ **Confusion Matrix**
|
145 |
+
- π **Multi-class ROC Curve**
|
146 |
+
- β **Misclassified Image Samples**
|
147 |
+
- Saves the full report as a downloadable PDF
|
148 |
+
|
149 |
+
#### π§ How to Use:
|
150 |
+
1. Click **π Start Evaluation** to begin analyzing the modelβs performance.
|
151 |
+
2. Wait for the evaluation to finish (shows progress bar and batch updates).
|
152 |
+
3. Once done:
|
153 |
+
- Check performance scores for each DR class
|
154 |
+
- View visual summaries like confusion matrix and ROC curve
|
155 |
+
- See the top 5 misclassified examples
|
156 |
+
4. Optionally, download the full evaluation report via **π Download PDF**
|
157 |
+
|
158 |
+
β οΈ <i>Note: This evaluation runs on the full test set and might take several seconds depending on hardware.</i>
|
159 |
+
</div>
|
160 |
+
""", unsafe_allow_html=True)
|
161 |
+
|
162 |
+
|
163 |
# ---- Evaluation Logic ----
|
164 |
if st.session_state.trigger_eval:
|
165 |
st.markdown("### β±οΈ Evaluation Results")
|
pages/Upload_and_Predict.py
CHANGED
@@ -3,11 +3,75 @@ import torch
|
|
3 |
from torchvision import transforms, models
|
4 |
from PIL import Image
|
5 |
import numpy as np
|
|
|
|
|
|
|
6 |
|
|
|
7 |
st.markdown("<h2 style='color: #2E86C1;'>π· Upload & Predict</h2>", unsafe_allow_html=True)
|
8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
class_names = ['No DR', 'Mild', 'Moderate', 'Severe', 'Proliferative DR']
|
10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
@st.cache_resource
|
12 |
def load_model():
|
13 |
model = models.densenet121(pretrained=False)
|
@@ -16,6 +80,7 @@ def load_model():
|
|
16 |
model.eval()
|
17 |
return model
|
18 |
|
|
|
19 |
transform = transforms.Compose([
|
20 |
transforms.Resize(256),
|
21 |
transforms.CenterCrop(224),
|
@@ -23,6 +88,7 @@ transform = transforms.Compose([
|
|
23 |
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
|
24 |
])
|
25 |
|
|
|
26 |
def predict_image(model, image):
|
27 |
img_tensor = transform(image).unsqueeze(0)
|
28 |
with torch.no_grad():
|
@@ -31,14 +97,77 @@ def predict_image(model, image):
|
|
31 |
prob = torch.nn.functional.softmax(outputs, dim=1)[0][pred].item() * 100
|
32 |
return class_names[pred.item()], prob
|
33 |
|
34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
|
36 |
-
if uploaded_file is not None:
|
37 |
-
|
38 |
-
|
39 |
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
|
|
3 |
from torchvision import transforms, models
|
4 |
from PIL import Image
|
5 |
import numpy as np
|
6 |
+
import pandas as pd
|
7 |
+
from collections import defaultdict
|
8 |
+
import os
|
9 |
|
10 |
+
# Title
|
11 |
st.markdown("<h2 style='color: #2E86C1;'>π· Upload & Predict</h2>", unsafe_allow_html=True)
|
12 |
|
13 |
+
st.markdown("""
|
14 |
+
### π About This Feature: Upload & Predict
|
15 |
+
|
16 |
+
This section of the **DR Assistive Tool** allows users to upload retinal images and get an AI-based prediction of the **Diabetic Retinopathy stage**. It uses a fine-tuned **DenseNet-121** model trained specifically for detecting DR severity levels.
|
17 |
+
|
18 |
+
The model classifies the uploaded image into one of the five classes:
|
19 |
+
- **No DR**
|
20 |
+
- **Mild**
|
21 |
+
- **Moderate**
|
22 |
+
- **Severe**
|
23 |
+
- **Proliferative DR**
|
24 |
+
|
25 |
+
This is especially helpful for:
|
26 |
+
- Students learning about AI in healthcare
|
27 |
+
- Researchers testing model robustness
|
28 |
+
- Clinicians exploring AI-assisted screening tools
|
29 |
+
|
30 |
+
The tool also shows **sample images from the test set** for each class. You can use these images to test the modelβs performance and understand what different DR stages look like.
|
31 |
+
|
32 |
+
---
|
33 |
+
### π§ How to Use:
|
34 |
+
1. π **View sample images** from the test set grouped by DR stage.
|
35 |
+
- Click the **"π Predict"** button under a sample image to test how the model classifies it.
|
36 |
+
2. π **Upload your own retinal image** (in JPG or PNG format) using the file uploader.
|
37 |
+
3. π§ Click the **"Predict"** button after uploading.
|
38 |
+
- The model will analyze the image and display:
|
39 |
+
- π― **Predicted DR Stage**
|
40 |
+
- π **Model confidence score (in %)**
|
41 |
+
|
42 |
+
β οΈ *Make sure your image is a clear, centered fundus photograph for best results.*
|
43 |
+
|
44 |
+
---
|
45 |
+
### π Behind the Scenes:
|
46 |
+
- β
Model: Pretrained **DenseNet-121**
|
47 |
+
- πΌ Input size: Images are resized to 224Γ224 pixels
|
48 |
+
- π Normalization: Matches ImageNet pretraining stats
|
49 |
+
- π¦ Output: Highest probability class from 5 DR categories using **softmax**
|
50 |
+
|
51 |
+
*This tool is for educational and research purposes only β not for clinical use.*
|
52 |
+
""", unsafe_allow_html=True)
|
53 |
+
|
54 |
+
|
55 |
+
# DR class names
|
56 |
class_names = ['No DR', 'Mild', 'Moderate', 'Severe', 'Proliferative DR']
|
57 |
|
58 |
+
# Load sample images from CSV with proper label mapping
|
59 |
+
@st.cache_data
|
60 |
+
def load_sample_images_from_csv(csv_path=r'D:\\DR_Classification\\splits\\test_labels.csv'):
|
61 |
+
df = pd.read_csv(csv_path)
|
62 |
+
samples = defaultdict(list)
|
63 |
+
|
64 |
+
for i in range(5):
|
65 |
+
class_name = class_names[i]
|
66 |
+
class_samples = df[df['label'] == i].head(5)
|
67 |
+
for _, row in class_samples.iterrows():
|
68 |
+
img_path = row['new_path']
|
69 |
+
if os.path.exists(img_path):
|
70 |
+
samples[class_name].append(img_path)
|
71 |
+
|
72 |
+
return samples
|
73 |
+
|
74 |
+
# Load pretrained model
|
75 |
@st.cache_resource
|
76 |
def load_model():
|
77 |
model = models.densenet121(pretrained=False)
|
|
|
80 |
model.eval()
|
81 |
return model
|
82 |
|
83 |
+
# Image transform function
|
84 |
transform = transforms.Compose([
|
85 |
transforms.Resize(256),
|
86 |
transforms.CenterCrop(224),
|
|
|
88 |
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
|
89 |
])
|
90 |
|
91 |
+
# Prediction function
|
92 |
def predict_image(model, image):
|
93 |
img_tensor = transform(image).unsqueeze(0)
|
94 |
with torch.no_grad():
|
|
|
97 |
prob = torch.nn.functional.softmax(outputs, dim=1)[0][pred].item() * 100
|
98 |
return class_names[pred.item()], prob
|
99 |
|
100 |
+
# Create two tabs for better separation of features
|
101 |
+
tab1, tab2 = st.tabs(["π§ͺ Sample Images", "π€ Upload & Predict"])
|
102 |
+
|
103 |
+
with tab1:
|
104 |
+
st.markdown("### π§ͺ Sample Images from Test Set")
|
105 |
+
|
106 |
+
st.markdown("""
|
107 |
+
#### π About This Feature: Sample Images
|
108 |
+
In this tab, you can explore sample retinal images from the test set, grouped by their **Diabetic Retinopathy (DR)** stage. This helps you:
|
109 |
+
- Understand the **visual differences** between DR stages
|
110 |
+
- Test the modelβs performance on known data
|
111 |
+
- Get familiar with the modelβs prediction behavior
|
112 |
+
|
113 |
+
#### π§ How to Use:
|
114 |
+
1. Browse the sample images under each DR class.
|
115 |
+
2. Click **π Predict** under an image to let the AI model analyze it.
|
116 |
+
3. The result will show:
|
117 |
+
- π― **Predicted DR stage**
|
118 |
+
- π **Confidence score**
|
119 |
+
|
120 |
+
> *Ideal for researchers and students testing the model with known data.*
|
121 |
+
""", unsafe_allow_html=True)
|
122 |
+
|
123 |
+
sample_images = load_sample_images_from_csv()
|
124 |
+
|
125 |
+
for class_name in class_names:
|
126 |
+
if class_name in sample_images and sample_images[class_name]:
|
127 |
+
cols = st.columns(5)
|
128 |
+
for i, img_path in enumerate(sample_images[class_name]):
|
129 |
+
with cols[i]:
|
130 |
+
st.image(img_path, use_container_width=True)
|
131 |
+
|
132 |
+
if st.button("π Predict", key=f"predict_{img_path}_{i}"):
|
133 |
+
image = Image.open(img_path).convert('RGB')
|
134 |
+
model = load_model()
|
135 |
+
pred_class, prob = predict_image(model, image)
|
136 |
+
st.success(f"π― Prediction: **{pred_class}** ({prob:.2f}% confidence)")
|
137 |
+
else:
|
138 |
+
st.warning(f"β οΈ No images found for **{class_name}**")
|
139 |
+
|
140 |
+
with tab2:
|
141 |
+
st.markdown("### π€ Upload & Predict")
|
142 |
+
|
143 |
+
st.markdown("""
|
144 |
+
#### π About This Feature: Upload & Predict
|
145 |
+
This tool allows you to upload a **retinal image** and get an **AI-based prediction** of the DR stage using a fine-tuned **DenseNet-121** model.
|
146 |
+
|
147 |
+
The model classifies the image into one of:
|
148 |
+
- No DR
|
149 |
+
- Mild
|
150 |
+
- Moderate
|
151 |
+
- Severe
|
152 |
+
- Proliferative DR
|
153 |
+
|
154 |
+
#### π§ How to Use:
|
155 |
+
1. π Upload a **clear fundus image** (JPG or PNG).
|
156 |
+
2. π§ Click **Predict** to let the model analyze it.
|
157 |
+
3. β
You'll see:
|
158 |
+
- π― The predicted DR stage
|
159 |
+
- π Confidence level (in percentage)
|
160 |
+
|
161 |
+
""", unsafe_allow_html=True)
|
162 |
+
|
163 |
+
uploaded_file = st.file_uploader("π Upload Retinal Image", type=["jpg", "png"])
|
164 |
|
165 |
+
if uploaded_file is not None:
|
166 |
+
image = Image.open(uploaded_file).convert('RGB')
|
167 |
+
st.image(image, caption='πΌ Uploaded Image', use_container_width=True)
|
168 |
|
169 |
+
if st.button("π§ Predict"):
|
170 |
+
with st.spinner('Analyzing image...'):
|
171 |
+
model = load_model()
|
172 |
+
pred_class, prob = predict_image(model, image)
|
173 |
+
st.success(f"π― Prediction: **{pred_class}** ({prob:.2f}% confidence)")
|