Rodiyah commited on
Commit
023e61d
·
verified ·
1 Parent(s): cc10294

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +24 -31
app.py CHANGED
@@ -40,49 +40,37 @@ transform = transforms.Compose([
40
  ])
41
 
42
  # -----------------------
43
- # Helper: basic fundus check
44
  # -----------------------
45
  def looks_like_fundus(image):
46
  """
47
- Heuristic to check if an image is likely a retinal fundus scan.
48
 
49
- Assumptions:
50
- - Fundus images usually have a bright circular central region (retina)
51
- and a darker outer border (background).
52
- - Non-fundus images (documents, labels, screens) tend to have
53
- similar brightness across the whole frame.
54
  """
55
- # Grayscale + resize for consistency
56
  img = np.array(image.convert("L").resize((224, 224)))
57
 
58
- # Central square (potential retina)
59
  center = img[40:184, 40:184]
60
 
61
- # Border = everything outside the center
62
  border_mask = np.ones_like(img, dtype=bool)
63
  border_mask[40:184, 40:184] = False
64
  border_pixels = img[border_mask]
65
 
66
- # Safety: if something weird happens, don't block it
67
  if border_pixels.size == 0:
68
  return True
69
 
70
  center_mean = center.mean()
71
  border_mean = border_pixels.mean()
72
 
73
- # Ratios of dark/bright pixels
74
- border_dark_ratio = np.mean(border_pixels < 40) # dark background
75
- center_bright_ratio = np.mean(center > 80) # bright retina
76
 
77
- # Conditions (tunable):
78
- # 1) Center clearly brighter than border
79
- cond_contrast = center_mean - border_mean > 25
80
-
81
- # 2) Most of the border is dark
82
- cond_border_dark = border_dark_ratio > 0.5
83
-
84
- # 3) A good portion of the center is bright
85
- cond_center_bright = center_bright_ratio > 0.4
86
 
87
  return cond_contrast and cond_border_dark and cond_center_bright
88
 
@@ -91,14 +79,16 @@ def looks_like_fundus(image):
91
  # Predict and save
92
  # -----------------------
93
  def predict_retinopathy(image):
94
- # 1. Block non-retina images BEFORE model / Grad-CAM
95
- if not looks_like_fundus(image):
96
- raise gr.Error(
97
- "The uploaded image does not appear to be a retinal fundus scan. "
98
- "Please upload a valid ophthalmic retinal image for Diabetic Retinopathy assessment."
 
 
99
  )
100
 
101
- # 2. Normal pipeline for valid retinal images
102
  timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
103
  img = image.convert("RGB").resize((224, 224))
104
  img_tensor = transform(img).unsqueeze(0).to(device)
@@ -125,7 +115,9 @@ def predict_retinopathy(image):
125
  filename = f"{timestamp}_{label}_{confidence:.2f}.png"
126
  cam_pil.save(os.path.join(save_dir, filename))
127
 
128
- return cam_pil, f"{label} (Confidence: {confidence:.2f})"
 
 
129
 
130
 
131
  # -----------------------
@@ -145,7 +137,8 @@ demo = gr.Interface(
145
  ),
146
  article=(
147
  "⚕️ **OpthaDetect** is an AI-powered ophthalmic decision-support tool. "
148
- "It highlights retinal risk regions using Grad-CAM for better clinical interpretability."
 
149
  )
150
  )
151
 
 
40
  ])
41
 
42
  # -----------------------
43
+ # Helper: soft fundus check
44
  # -----------------------
45
  def looks_like_fundus(image):
46
  """
47
+ Very lightweight heuristic to guess if an image looks like a retinal fundus scan.
48
 
49
+ This is NOT a medical-grade classifier – it is only used to show a warning
50
+ if the image is very unlikely to be a retina.
 
 
 
51
  """
 
52
  img = np.array(image.convert("L").resize((224, 224)))
53
 
54
+ # Central square (potential retina) vs border
55
  center = img[40:184, 40:184]
56
 
 
57
  border_mask = np.ones_like(img, dtype=bool)
58
  border_mask[40:184, 40:184] = False
59
  border_pixels = img[border_mask]
60
 
61
+ # Safety fallback
62
  if border_pixels.size == 0:
63
  return True
64
 
65
  center_mean = center.mean()
66
  border_mean = border_pixels.mean()
67
 
68
+ border_dark_ratio = np.mean(border_pixels < 40) # dark background
69
+ center_bright_ratio = np.mean(center > 80) # bright retina
 
70
 
71
+ cond_contrast = center_mean - border_mean > 15
72
+ cond_border_dark = border_dark_ratio > 0.3
73
+ cond_center_bright = center_bright_ratio > 0.25
 
 
 
 
 
 
74
 
75
  return cond_contrast and cond_border_dark and cond_center_bright
76
 
 
79
  # Predict and save
80
  # -----------------------
81
  def predict_retinopathy(image):
82
+ # 1. Soft validation (no blocking just warning text)
83
+ if looks_like_fundus(image):
84
+ warning = ""
85
+ else:
86
+ warning = (
87
+ "⚠️ The uploaded image may not be a retinal fundus scan. "
88
+ "This system is intended for use with ophthalmic retinal images only.\n\n"
89
  )
90
 
91
+ # 2. Normal pipeline
92
  timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
93
  img = image.convert("RGB").resize((224, 224))
94
  img_tensor = transform(img).unsqueeze(0).to(device)
 
115
  filename = f"{timestamp}_{label}_{confidence:.2f}.png"
116
  cam_pil.save(os.path.join(save_dir, filename))
117
 
118
+ prediction_text = f"{label} (Confidence: {confidence:.2f})"
119
+
120
+ return cam_pil, warning + prediction_text
121
 
122
 
123
  # -----------------------
 
137
  ),
138
  article=(
139
  "⚕️ **OpthaDetect** is an AI-powered ophthalmic decision-support tool. "
140
+ "It highlights retinal risk regions using Grad-CAM for better clinical interpretability. "
141
+ "This tool does not replace clinical judgement and should be used alongside professional assessment."
142
  )
143
  )
144