Sefat33 commited on
Commit
82be6ad
Β·
verified Β·
1 Parent(s): 5b24bc2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +66 -112
app.py CHANGED
@@ -7,6 +7,7 @@ from lime import lime_image
7
  from skimage.segmentation import mark_boundaries
8
  from keras.layers import BatchNormalization, DepthwiseConv2D, TFSMLayer
9
  import os
 
10
 
11
  # --- Fix deserialization issues ---
12
  original_bn = BatchNormalization.from_config
@@ -26,6 +27,30 @@ IMG_SIZE = (224, 224)
26
  CLASS_NAMES = ['Normal', 'Diabetes', 'Glaucoma', 'Cataract', 'AMD', 'Hypertension', 'Myopia', 'Others']
27
  LIME_EXPLAINER = lime_image.LimeImageExplainer()
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  @st.cache_resource
30
  def load_model():
31
  model_path = "Model"
@@ -56,11 +81,8 @@ def preprocess_with_steps(img):
56
  resized = cv2.resize(sharp, IMG_SIZE) / 255.0
57
 
58
  fig, axs = plt.subplots(1, 4, figsize=(20, 5))
59
- for ax, image, title in zip(
60
- axs,
61
- [img, circ, clahe_img, resized],
62
- ["Original", "Circular Crop", "CLAHE", "Sharpen + Resize"],
63
- ):
64
  ax.imshow(image)
65
  ax.set_title(title)
66
  ax.axis("off")
@@ -86,116 +108,29 @@ def show_lime(img, model, pred_idx, pred_label):
86
  label=pred_idx, positive_only=True, num_features=10, hide_rest=False
87
  )
88
 
89
- # --- Enhanced LIME Explanation Dictionary ---
90
- # --- Easy Language LIME Explanation Dictionary with Color Tags ---
91
- explanation_text = {
92
- 'Normal': """βœ… **<span style='color:green'>Normal</span>**
93
- The model predicted <span style='color:green'><strong>Normal</strong></span> because everything looks healthy:
94
-
95
- - 🟒 **Overall Look**: Clear retina, no spots or damage
96
- - 🩺 **Blood Vessels**: Normal size and shape
97
- - πŸ‘ **Optic Disc & Macula**: Clean, no swelling or dark areas
98
-
99
- <span style='color:green'>βœ”οΈ The eye appears completely healthy.</span>""",
100
-
101
- 'Diabetes': """πŸ’‰ **<span style='color:orange'>Diabetes</span>**
102
- The model predicted <span style='color:orange'><strong>Diabetes</strong></span> due to signs of diabetic eye disease:
103
-
104
- - πŸ”Ά **Overall Look**: Tiny spots, bleeding, or swelling
105
- - 🩸 **Blood Vessels**: Damaged or swollen
106
- - πŸ‘ **Optic Disc & Macula**: Swelling or fluid may be present
107
-
108
- <span style='color:orange'>⚠️ Signs of diabetic retinopathy.</span>""",
109
-
110
- 'Glaucoma': """πŸ‘ **<span style='color:red'>Glaucoma</span>**
111
- The model predicted <span style='color:red'><strong>Glaucoma</strong></span> by detecting optic nerve changes:
112
-
113
- - πŸ”΄ **Overall Look**: Some nerve areas look damaged
114
- - πŸ’‰ **Blood Vessels**: Mostly normal
115
- - πŸ‘ **Optic Disc & Macula**: Disc cupping, nerve fiber loss
116
-
117
- <span style='color:red'>πŸ”΄ Serious conditionβ€”can lead to vision loss.</span>""",
118
-
119
- 'Cataract': """🌫 **<span style='color:gray'>Cataract</span>**
120
- The model predicted <span style='color:gray'><strong>Cataract</strong></span> based on blurry image quality:
121
-
122
- - 🌫 **Overall Look**: Image appears cloudy or foggy
123
- - πŸ‘ **Blood Vessels**: Hard to see clearly
124
- - πŸ” **Optic Disc & Macula**: Low contrast and unclear
125
-
126
- <span style='color:gray'>⚠️ Likely due to a cloudy lens (cataract).</span>""",
127
-
128
- 'AMD': """πŸ§“ **<span style='color:red'>AMD (Macular Degeneration)</span>**
129
- The model predicted <span style='color:red'><strong>AMD</strong></span> by focusing on the center of the retina:
130
-
131
- - πŸ”΄ **Overall Look**: Mostly clear except center
132
- - 🩺 **Blood Vessels**: Usually look fine
133
- - πŸ‘ **Optic Disc & Macula**: Yellow spots or damage in macula
134
-
135
- <span style='color:red'>⚠️ Early signs of age-related vision loss.</span>""",
136
-
137
- 'Hypertension': """⚠️ **<span style='color:orange'>Hypertension</span>**
138
- The model predicted <span style='color:orange'><strong>Hypertension</strong></span> due to blood vessel changes:
139
-
140
- - πŸ”Ά **Overall Look**: Small bleeds or spots
141
- - 🩸 **Blood Vessels**: Narrowed or twisted
142
- - πŸ‘ **Optic Disc & Macula**: Swelling or star patterns
143
-
144
- <span style='color:orange'>⚠️ May be caused by high blood pressure.</span>""",
145
-
146
- 'Myopia': """πŸ‘“ **<span style='color:blue'>Myopia</span>**
147
- The model predicted <span style='color:blue'><strong>Myopia</strong></span> based on eye structure:
148
-
149
- - πŸ”΅ **Overall Look**: Stretched or thin retina edges
150
- - 🩺 **Blood Vessels**: Usually normal
151
- - πŸ‘ **Optic Disc & Macula**: Tilted disc, outer damage
152
-
153
- <span style='color:blue'>ℹ️ Common in people with nearsightedness.</span>""",
154
-
155
- 'Others': """πŸ”Ž **<span style='color:gray'>Others</span>**
156
- The model predicted <span style='color:gray'><strong>Others</strong></span> due to unknown or rare changes:
157
-
158
- - βšͺ **Overall Look**: Mixed or unusual patterns
159
- - 🩸 **Blood Vessels**: Varies by case
160
- - πŸ‘ **Optic Disc & Macula**: Random changes
161
-
162
- <span style='color:gray'>❓ May indicate a rare or mixed eye condition.</span>"""
163
- }
164
-
165
- }
166
-
167
- # --- Side-by-side layout ---
168
- col1, col2 = st.columns([1, 2]) # left for image, right for text
169
-
170
- with col1:
171
- fig, ax = plt.subplots(figsize=(3, 3))
172
- ax.imshow(mark_boundaries(temp, mask))
173
- ax.axis("off")
174
- ax.text(
175
- 5, 20,
176
- f"LIME: {pred_label}",
177
- color="black",
178
- fontsize=10,
179
- bbox=dict(facecolor='white', alpha=0.7, pad=2)
180
- )
181
- st.pyplot(fig)
182
- plt.close(fig)
183
-
184
- with col2:
185
- st.markdown("#### πŸ‘ Detailed LIME Explanation")
186
- st.markdown(explanation_text.get(pred_label, "No explanation available."))
187
-
188
-
189
- # --- UI ---
190
- st.set_page_config(page_title="πŸ‘ Retina Classifier - Multi Image LIME", layout="wide")
191
- st.title("πŸ‘ Retina Disease Classifier with LIME Explanation")
192
 
 
193
  model = load_model()
194
 
195
  with st.sidebar:
196
- uploaded_files = st.file_uploader(
197
- "πŸ“‚ Upload retinal images", type=["jpg", "jpeg", "png"], accept_multiple_files=True
198
- )
199
  selected_filename = None
200
  if uploaded_files:
201
  filenames = [f.name for f in uploaded_files]
@@ -217,4 +152,23 @@ if uploaded_files and selected_filename:
217
  confidence = np.max(preds) * 100
218
 
219
  st.success(f"βœ… Prediction: **{pred_label}** ({confidence:.2f}%)")
220
- show_lime(preprocessed, model, pred_idx, pred_label)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  from skimage.segmentation import mark_boundaries
8
  from keras.layers import BatchNormalization, DepthwiseConv2D, TFSMLayer
9
  import os
10
+ from io import BytesIO
11
 
12
  # --- Fix deserialization issues ---
13
  original_bn = BatchNormalization.from_config
 
27
  CLASS_NAMES = ['Normal', 'Diabetes', 'Glaucoma', 'Cataract', 'AMD', 'Hypertension', 'Myopia', 'Others']
28
  LIME_EXPLAINER = lime_image.LimeImageExplainer()
29
 
30
+ # --- Enhanced LIME Explanation Dictionary (HTML + Icons + Colors) ---
31
+ explanation_text = {
32
+ 'Normal': """βœ… **<span style='color:green'>Normal</span>**\nThe model predicted <span style='color:green'><strong>Normal</strong></span> because everything looks healthy:\n- 🟒 **Overall Look**: Clear retina, no spots or damage \n- 🩺 **Blood Vessels**: Normal size and shape \n- πŸ‘ **Optic Disc & Macula**: Clean, no swelling or dark areas \n<span style='color:green'>βœ”οΈ The eye appears completely healthy.</span>""",
33
+ 'Diabetes': """πŸ’‰ **<span style='color:orange'>Diabetes</span>**\nThe model predicted <span style='color:orange'><strong>Diabetes</strong></span> due to signs of diabetic eye disease:\n- πŸ”Ά **Overall Look**: Tiny spots, bleeding, or swelling \n- 🩸 **Blood Vessels**: Damaged or swollen \n- πŸ‘ **Optic Disc & Macula**: Swelling or fluid may be present \n<span style='color:orange'>⚠️ Signs of diabetic retinopathy.</span>""",
34
+ 'Glaucoma': """πŸ‘ **<span style='color:red'>Glaucoma</span>**\nThe model predicted <span style='color:red'><strong>Glaucoma</strong></span> by detecting optic nerve changes:\n- πŸ”΄ **Overall Look**: Some nerve areas look damaged \n- πŸ’‰ **Blood Vessels**: Mostly normal \n- πŸ‘ **Optic Disc & Macula**: Disc cupping, nerve fiber loss \n<span style='color:red'>πŸ”΄ Serious conditionβ€”can lead to vision loss.</span>""",
35
+ 'Cataract': """🌫 **<span style='color:gray'>Cataract</span>**\nThe model predicted <span style='color:gray'><strong>Cataract</strong></span> based on blurry image quality:\n- 🌫 **Overall Look**: Image appears cloudy or foggy \n- πŸ‘ **Blood Vessels**: Hard to see clearly \n- πŸ” **Optic Disc & Macula**: Low contrast and unclear \n<span style='color:gray'>⚠️ Likely due to a cloudy lens (cataract).</span>""",
36
+ 'AMD': """πŸ§“ **<span style='color:red'>AMD (Macular Degeneration)</span>**\nThe model predicted <span style='color:red'><strong>AMD</strong></span> by focusing on the center of the retina:\n- πŸ”΄ **Overall Look**: Mostly clear except center \n- 🩺 **Blood Vessels**: Usually look fine \n- πŸ‘ **Optic Disc & Macula**: Yellow spots or damage in macula \n<span style='color:red'>⚠️ Early signs of age-related vision loss.</span>""",
37
+ 'Hypertension': """⚠️ **<span style='color:orange'>Hypertension</span>**\nThe model predicted <span style='color:orange'><strong>Hypertension</strong></span> due to blood vessel changes:\n- πŸ”Ά **Overall Look**: Small bleeds or spots \n- 🩸 **Blood Vessels**: Narrowed or twisted \n- πŸ‘ **Optic Disc & Macula**: Swelling or star patterns \n<span style='color:orange'>⚠️ May be caused by high blood pressure.</span>""",
38
+ 'Myopia': """πŸ‘“ **<span style='color:blue'>Myopia</span>**\nThe model predicted <span style='color:blue'><strong>Myopia</strong></span> based on eye structure:\n- πŸ”΅ **Overall Look**: Stretched or thin retina edges \n- 🩺 **Blood Vessels**: Usually normal \n- πŸ‘ **Optic Disc & Macula**: Tilted disc, outer damage \n<span style='color:blue'>ℹ️ Common in people with nearsightedness.</span>""",
39
+ 'Others': """πŸ”Ž **<span style='color:gray'>Others</span>**\nThe model predicted <span style='color:gray'><strong>Others</strong></span> due to unknown or rare changes:\n- βšͺ **Overall Look**: Mixed or unusual patterns \n- 🩸 **Blood Vessels**: Varies by case \n- πŸ‘ **Optic Disc & Macula**: Random changes \n<span style='color:gray'>❓ May indicate a rare or mixed eye condition.</span>"""
40
+ }
41
+
42
+ # --- Streamlit Setup ---
43
+ st.set_page_config(page_title="πŸ‘ Retina Classifier - Multi Image LIME", layout="wide")
44
+ st.title("πŸ‘ Retina Disease Classifier with LIME Explanation")
45
+ st.markdown("""
46
+ <style>
47
+ .lime-text {
48
+ color: var(--text-color);
49
+ font-size: 16px;
50
+ }
51
+ </style>
52
+ """, unsafe_allow_html=True)
53
+
54
  @st.cache_resource
55
  def load_model():
56
  model_path = "Model"
 
81
  resized = cv2.resize(sharp, IMG_SIZE) / 255.0
82
 
83
  fig, axs = plt.subplots(1, 4, figsize=(20, 5))
84
+ for ax, image, title in zip(axs, [img, circ, clahe_img, resized],
85
+ ["Original", "Circular Crop", "CLAHE", "Sharpen + Resize"]):
 
 
 
86
  ax.imshow(image)
87
  ax.set_title(title)
88
  ax.axis("off")
 
108
  label=pred_idx, positive_only=True, num_features=10, hide_rest=False
109
  )
110
 
111
+ fig, ax = plt.subplots(figsize=(3, 3))
112
+ ax.imshow(mark_boundaries(temp, mask))
113
+ ax.axis("off")
114
+ ax.text(5, 20, f"LIME: {pred_label}", color="black", fontsize=10,
115
+ bbox=dict(facecolor='white', alpha=0.7, pad=2))
116
+ st.pyplot(fig)
117
+
118
+ buf = BytesIO()
119
+ fig.savefig(buf, format="png")
120
+ st.download_button("πŸ“₯ Download LIME Image", buf.getvalue(), file_name=f"{pred_label}_LIME.png", mime="image/png")
121
+ plt.close(fig)
122
+
123
+ st.markdown("#### πŸ‘ Detailed LIME Explanation")
124
+ st.markdown(
125
+ f"<div class='lime-text'>{explanation_text.get(pred_label, 'No explanation available.')}</div>",
126
+ unsafe_allow_html=True
127
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
 
129
+ # --- Sidebar + File Upload ---
130
  model = load_model()
131
 
132
  with st.sidebar:
133
+ uploaded_files = st.file_uploader("πŸ“‚ Upload retinal images", type=["jpg", "jpeg", "png"], accept_multiple_files=True)
 
 
134
  selected_filename = None
135
  if uploaded_files:
136
  filenames = [f.name for f in uploaded_files]
 
152
  confidence = np.max(preds) * 100
153
 
154
  st.success(f"βœ… Prediction: **{pred_label}** ({confidence:.2f}%)")
155
+
156
+ # Show probability chart
157
+ st.markdown("#### πŸ“Š Class Probabilities")
158
+ prob_dict = {label: float(preds[0][i]) for i, label in enumerate(CLASS_NAMES)}
159
+ prob_chart_data = sorted(prob_dict.items(), key=lambda x: x[1], reverse=True)
160
+
161
+ prob_labels = [k for k, _ in prob_chart_data]
162
+ prob_values = [v for _, v in prob_chart_data]
163
+
164
+ fig_bar, ax_bar = plt.subplots(figsize=(8, 3))
165
+ bars = ax_bar.barh(prob_labels, prob_values, color="skyblue")
166
+ ax_bar.set_xlim(0, 1)
167
+ ax_bar.invert_yaxis()
168
+ ax_bar.set_xlabel("Confidence Score")
169
+ for bar in bars:
170
+ ax_bar.text(bar.get_width() + 0.01, bar.get_y() + 0.25, f"{bar.get_width()*100:.1f}%", color='black')
171
+ st.pyplot(fig_bar)
172
+ plt.close(fig_bar)
173
+
174
+ show_lime(preprocessed, model, pred_idx, pred_label)