kmunzwa commited on
Commit
770b5e4
·
verified ·
1 Parent(s): 139f05e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +7 -57
app.py CHANGED
@@ -15,54 +15,33 @@ from PIL import Image
15
  # LOAD THE MODEL
16
  # ------------------------------------
17
 
18
- # load the float32 TFLite model
19
  interpreter = Interpreter(model_path="resnet50_float32.tflite")
20
-
21
- # allocate memory for the model's input and output tensors
22
  interpreter.allocate_tensors()
23
 
24
- # get input and output tensor details
25
  input_details = interpreter.get_input_details()
26
  output_details = interpreter.get_output_details()
27
 
28
- # image size ResNet50 expects
29
  INPUT_SIZE = (224, 224)
30
 
31
  print("Gatekeeper model loaded successfully")
32
 
33
 
34
  # ------------------------------------
35
- # THRESHOLDS
36
  # ------------------------------------
37
 
38
- # minimum probability for cervix to be accepted as a positive detection
39
  CERVIX_THRESHOLD = 0.55
40
 
41
- # minimum gap between cervix and non-cervix probabilities
42
- # if the gap is smaller than this the prediction is too uncertain to trust
43
- CONFIDENCE_GAP = 0.15
44
-
45
- # minimum image brightness - images below this are too dark to classify
46
- MIN_BRIGHTNESS = 30
47
-
48
- # minimum image contrast - images below this are blank or uniform
49
- MIN_STD = 20
50
-
51
 
52
  # ------------------------------------
53
  # IMAGE PREPROCESSING FUNCTION
54
  # ------------------------------------
55
 
56
  def preprocess_image(image):
57
- # convert numpy array to PIL Image in RGB format and resize
58
  img = Image.fromarray(image).convert("RGB").resize(INPUT_SIZE)
59
-
60
- # convert to float32 numpy array and normalise to [0, 1]
61
  img = np.array(img, dtype=np.float32) / 255.0
62
-
63
- # add batch dimension: (224, 224, 3) → (1, 224, 224, 3)
64
  img = np.expand_dims(img, axis=0)
65
-
66
  return img
67
 
68
 
@@ -71,50 +50,27 @@ def preprocess_image(image):
71
  # ------------------------------------
72
 
73
  def classify_image(image):
74
- # if the user submits without an image return a warning
75
  if image is None:
76
  return None, "Please upload an image first"
77
 
78
- # Option 3: Basic image sanity checks
79
- img_array = np.array(image)
80
-
81
- # reject images that are too dark to analyse reliably
82
- if img_array.mean() < MIN_BRIGHTNESS:
83
- return None, "Image is too dark - please upload a clearer photo"
84
-
85
- # reject images that are blank, uniformly coloured, or plain screenshots
86
- if img_array.std() < MIN_STD:
87
- return None, "Image appears blank or uniform - please upload a real photo"
88
-
89
- # preprocess the image
90
  processed = preprocess_image(image)
91
-
92
- # load the preprocessed image into the model's input tensor
93
  interpreter.set_tensor(input_details[0]['index'], processed)
94
-
95
- # run inference
96
  interpreter.invoke()
97
-
98
- # read the output tensor
99
  output = interpreter.get_tensor(output_details[0]['index'])
 
100
  print(f"Raw model output: {output}")
101
 
102
- # extract individual class probabilities
103
  prob_non_cervix = float(output[0][0])
104
  prob_cervix = float(output[0][1])
105
 
106
  print(f"Non-Cervix: {prob_non_cervix:.4f} | Cervix: {prob_cervix:.4f}")
107
 
108
- # Option 1: Confidence threshold + gap check
109
- gap = prob_cervix - prob_non_cervix
110
-
111
- if prob_cervix >= CERVIX_THRESHOLD and gap >= CONFIDENCE_GAP:
112
  prediction_text = "Cervix Detected"
113
- elif prob_non_cervix >= CERVIX_THRESHOLD and gap <= -CONFIDENCE_GAP:
114
- prediction_text = "Non-Cervix"
115
  else:
116
- # not confident enough either way - temporary misclassification safety net
117
- prediction_text = "Uncertain - please retake or upload a clearer image"
118
 
119
  scores = {
120
  "Cervix": round(prob_cervix, 4),
@@ -173,12 +129,6 @@ with gr.Blocks(theme=gr.themes.Soft()) as app:
173
  | 0 | Non-Cervix | Image does NOT contain cervix |
174
  | 1 | Cervix | Image contains cervix |
175
 
176
- ---
177
- **How predictions work:**
178
- - **Cervix Detected** - model scored >= 0.55 with a gap of >= 0.15 over Non-Cervix
179
- - **Non-Cervix** - model scored >= 0.55 with a gap of >= 0.15 over Cervix
180
- - **Uncertain** - model was not confident enough; retake the image
181
-
182
  ---
183
  Disclaimer: This tool is for research purposes only.
184
  It is not intended for clinical diagnosis or medical use.
 
15
  # LOAD THE MODEL
16
  # ------------------------------------
17
 
 
18
  interpreter = Interpreter(model_path="resnet50_float32.tflite")
 
 
19
  interpreter.allocate_tensors()
20
 
 
21
  input_details = interpreter.get_input_details()
22
  output_details = interpreter.get_output_details()
23
 
 
24
  INPUT_SIZE = (224, 224)
25
 
26
  print("Gatekeeper model loaded successfully")
27
 
28
 
29
  # ------------------------------------
30
+ # THRESHOLD
31
  # ------------------------------------
32
 
33
+ # cervix must score at least 0.55 to be accepted as a positive detection
34
  CERVIX_THRESHOLD = 0.55
35
 
 
 
 
 
 
 
 
 
 
 
36
 
37
  # ------------------------------------
38
  # IMAGE PREPROCESSING FUNCTION
39
  # ------------------------------------
40
 
41
  def preprocess_image(image):
 
42
  img = Image.fromarray(image).convert("RGB").resize(INPUT_SIZE)
 
 
43
  img = np.array(img, dtype=np.float32) / 255.0
 
 
44
  img = np.expand_dims(img, axis=0)
 
45
  return img
46
 
47
 
 
50
  # ------------------------------------
51
 
52
  def classify_image(image):
 
53
  if image is None:
54
  return None, "Please upload an image first"
55
 
56
+ # preprocess and run inference
 
 
 
 
 
 
 
 
 
 
 
57
  processed = preprocess_image(image)
 
 
58
  interpreter.set_tensor(input_details[0]['index'], processed)
 
 
59
  interpreter.invoke()
 
 
60
  output = interpreter.get_tensor(output_details[0]['index'])
61
+
62
  print(f"Raw model output: {output}")
63
 
 
64
  prob_non_cervix = float(output[0][0])
65
  prob_cervix = float(output[0][1])
66
 
67
  print(f"Non-Cervix: {prob_non_cervix:.4f} | Cervix: {prob_cervix:.4f}")
68
 
69
+ # simple threshold check
70
+ if prob_cervix >= CERVIX_THRESHOLD:
 
 
71
  prediction_text = "Cervix Detected"
 
 
72
  else:
73
+ prediction_text = "Non-Cervix"
 
74
 
75
  scores = {
76
  "Cervix": round(prob_cervix, 4),
 
129
  | 0 | Non-Cervix | Image does NOT contain cervix |
130
  | 1 | Cervix | Image contains cervix |
131
 
 
 
 
 
 
 
132
  ---
133
  Disclaimer: This tool is for research purposes only.
134
  It is not intended for clinical diagnosis or medical use.