Sefat33 commited on
Commit
39c3e47
Β·
verified Β·
1 Parent(s): 82be6ad

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +85 -63
app.py CHANGED
@@ -27,30 +27,6 @@ IMG_SIZE = (224, 224)
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,8 +57,11 @@ def preprocess_with_steps(img):
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")
@@ -95,6 +74,65 @@ def predict(images, model):
95
  preds = model.predict(images, verbose=0)
96
  return list(preds.values())[0] if isinstance(preds, dict) else preds
97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  def show_lime(img, model, pred_idx, pred_label):
99
  with st.spinner("🟑 LIME explanation is loading..."):
100
  explanation = LIME_EXPLAINER.explain_instance(
@@ -108,25 +146,28 @@ def show_lime(img, model, pred_idx, pred_label):
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:
@@ -152,23 +193,4 @@ if uploaded_files and selected_filename:
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)
 
27
  CLASS_NAMES = ['Normal', 'Diabetes', 'Glaucoma', 'Cataract', 'AMD', 'Hypertension', 'Myopia', 'Others']
28
  LIME_EXPLAINER = lime_image.LimeImageExplainer()
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  @st.cache_resource
31
  def load_model():
32
  model_path = "Model"
 
57
  resized = cv2.resize(sharp, IMG_SIZE) / 255.0
58
 
59
  fig, axs = plt.subplots(1, 4, figsize=(20, 5))
60
+ for ax, image, title in zip(
61
+ axs,
62
+ [img, circ, clahe_img, resized],
63
+ ["Original", "Circular Crop", "CLAHE", "Sharpen + Resize"],
64
+ ):
65
  ax.imshow(image)
66
  ax.set_title(title)
67
  ax.axis("off")
 
74
  preds = model.predict(images, verbose=0)
75
  return list(preds.values())[0] if isinstance(preds, dict) else preds
76
 
77
+ # --- Easy Language LIME Explanation Dictionary ---
78
+ explanation_text = {
79
+ 'Normal': """βœ… **<span style='color:green'>Normal</span>**<br>
80
+ The model predicted <strong>Normal</strong> because everything looks healthy:<br>
81
+ - 🟒 Overall retina looks clear, no spots or damage<br>
82
+ - 🩺 Blood vessels have normal size and shape<br>
83
+ - πŸ‘ Optic disc and macula are clean and well-defined<br>
84
+ <span style='color:green'>βœ”οΈ This is a healthy eye.</span>""",
85
+
86
+ 'Diabetes': """πŸ’‰ **<span style='color:orange'>Diabetes</span>**<br>
87
+ The model detected signs of diabetic eye disease:<br>
88
+ - πŸ”Ά Tiny red spots, bleeding, or swelling<br>
89
+ - 🩸 Blood vessels appear damaged or thickened<br>
90
+ - πŸ‘ Macula may show fluid or swelling<br>
91
+ <span style='color:orange'>⚠️ Diabetic retinopathy detected.</span>""",
92
+
93
+ 'Glaucoma': """πŸ‘ **<span style='color:red'>Glaucoma</span>**<br>
94
+ The model noticed optic nerve damage patterns:<br>
95
+ - πŸ”΄ Some nerve areas seem thin or missing<br>
96
+ - πŸ’‰ Blood vessels are mostly normal<br>
97
+ - πŸ‘ Disc cupping and nerve fiber loss<br>
98
+ <span style='color:red'>πŸ”΄ May cause permanent vision loss if untreated.</span>""",
99
+
100
+ 'Cataract': """🌫 **<span style='color:gray'>Cataract</span>**<br>
101
+ The image quality was affected by lens clouding:<br>
102
+ - 🌫 Whole image looks hazy or foggy<br>
103
+ - πŸ‘ Blood vessels are not clearly visible<br>
104
+ - πŸ” Macula and disc are blurry<br>
105
+ <span style='color:gray'>⚠️ Cataract is likely reducing image clarity.</span>""",
106
+
107
+ 'AMD': """πŸ§“ **<span style='color:red'>AMD (Macular Degeneration)</span>**<br>
108
+ The model found damage in the central retina (macula):<br>
109
+ - πŸ”΄ Center of retina shows yellow spots or damage<br>
110
+ - 🩺 Blood vessels usually look fine<br>
111
+ - πŸ‘ Macula shows signs of age-related change<br>
112
+ <span style='color:red'>⚠️ Early signs of macular degeneration.</span>""",
113
+
114
+ 'Hypertension': """⚠️ **<span style='color:orange'>Hypertension</span>**<br>
115
+ The model found signs of high blood pressure in the retina:<br>
116
+ - πŸ”Ά Small bleeds or bright spots in retina<br>
117
+ - 🩸 Blood vessels narrowed or twisted<br>
118
+ - πŸ‘ Possible swelling or star patterns<br>
119
+ <span style='color:orange'>⚠️ Hypertensive retinopathy suspected.</span>""",
120
+
121
+ 'Myopia': """πŸ‘“ **<span style='color:blue'>Myopia</span>**<br>
122
+ The model identified signs of nearsightedness:<br>
123
+ - πŸ”΅ Retinal edges look stretched or thin<br>
124
+ - 🩺 Blood vessels are mostly normal<br>
125
+ - πŸ‘ Tilted optic disc, possible outer damage<br>
126
+ <span style='color:blue'>ℹ️ Common in high myopia cases.</span>""",
127
+
128
+ 'Others': """πŸ”Ž **<span style='color:gray'>Others</span>**<br>
129
+ Mixed or unclear patterns seen in retina:<br>
130
+ - βšͺ Random spots or patches<br>
131
+ - 🩸 Blood vessel features vary<br>
132
+ - πŸ‘ Disc or macula changes are not typical<br>
133
+ <span style='color:gray'>❓ Could be a rare or unclassified condition.</span>"""
134
+ }
135
+
136
  def show_lime(img, model, pred_idx, pred_label):
137
  with st.spinner("🟑 LIME explanation is loading..."):
138
  explanation = LIME_EXPLAINER.explain_instance(
 
146
  label=pred_idx, positive_only=True, num_features=10, hide_rest=False
147
  )
148
 
149
+ col1, col2 = st.columns([1, 2])
150
+
151
+ with col1:
152
+ fig, ax = plt.subplots(figsize=(4, 4))
153
+ ax.imshow(mark_boundaries(temp, mask))
154
+ ax.axis("off")
155
+ ax.set_title("πŸ“ LIME Highlighted Areas", fontsize=12)
156
+ st.pyplot(fig)
157
+
158
+ buf = BytesIO()
159
+ fig.savefig(buf, format="png")
160
+ st.download_button("πŸ“₯ Download LIME Image", buf.getvalue(), file_name=f"{pred_label}_LIME.png", mime="image/png")
161
+ plt.close(fig)
162
+
163
+ with col2:
164
+ st.markdown("### 🧠 Model's Reasoning")
165
+ st.markdown(explanation_text.get(pred_label, "No explanation available."), unsafe_allow_html=True)
166
+
167
+ # --- UI ---
168
+ st.set_page_config(page_title="πŸ‘ Retina Classifier - Multi Image LIME", layout="wide")
169
+ st.title("πŸ‘ Retina Disease Classifier with LIME Explanation")
170
 
 
171
  model = load_model()
172
 
173
  with st.sidebar:
 
193
  confidence = np.max(preds) * 100
194
 
195
  st.success(f"βœ… Prediction: **{pred_label}** ({confidence:.2f}%)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  show_lime(preprocessed, model, pred_idx, pred_label)