phiaaa commited on
Commit
b1b16f3
·
verified ·
1 Parent(s): 3bb9819

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -25
app.py CHANGED
@@ -10,72 +10,93 @@ interpreter.allocate_tensors()
10
  input_details = interpreter.get_input_details()
11
  output_details = interpreter.get_output_details()
12
 
13
- # 🏷️ Define your classes
14
  labels = ["bloody", "hard stool", "normal", "parasite", "watery"]
15
 
16
- # 🧩 Image preprocessing
 
 
 
 
 
 
 
 
 
 
 
17
  def preprocess_image(img: Image.Image):
18
  img = img.convert("RGB").resize((128, 128))
19
  arr = np.asarray(img).astype(np.float32) / 255.0
20
  arr = np.expand_dims(arr, axis=0)
21
  return arr
22
 
23
- # 🚫 Detect if the uploaded image is NOT a stool image
24
  def is_not_stool_image(image):
25
  arr = np.asarray(image.convert("RGB")).astype(np.float32)
26
  brightness = arr.mean()
27
  contrast = arr.std()
28
  avg_color = arr.mean(axis=(0, 1))
29
 
30
- # 🧠 Basic heuristic checks
31
- # These values are adjustable based on your dataset
32
  if brightness > 220 or brightness < 25:
33
- return True # too bright or dark
34
  if contrast < 25:
35
- return True # too flat / low texture
36
  if avg_color[0] > 180 and avg_color[1] < 80 and avg_color[2] < 80:
37
- return True # too red
38
- if avg_color[0] < 50 and avg_color[1] > 180:
39
  return True # too greenish
40
  if avg_color[2] > 200:
41
- return True # too blueish
42
-
43
  return False
44
 
45
- # 🧠 Classification function
46
  def classify_image(image):
47
  try:
48
- # 🚫 Check if this is not stool
49
  if is_not_stool_image(image):
50
- return {"Not stool image": 1.0}
51
 
52
- # Proceed with model prediction
53
  input_data = preprocess_image(image)
54
  interpreter.set_tensor(input_details[0]['index'], input_data)
55
  interpreter.invoke()
56
  output_data = interpreter.get_tensor(output_details[0]['index'])[0]
57
 
58
- # Sort predictions
59
  results = {labels[i]: float(output_data[i]) for i in range(len(labels))}
60
  sorted_results = dict(sorted(results.items(), key=lambda x: x[1], reverse=True))
61
-
62
- # Extra sanity rule: if top score < 0.4, label as uncertain
63
  top_label, top_score = list(sorted_results.items())[0]
 
 
64
  if top_score < 0.4:
65
- return {"Uncertain / unclear stool image": top_score}
 
 
 
 
 
66
 
67
- return sorted_results
 
 
68
 
69
  except Exception as e:
70
- return {"Error": str(e)}
71
 
72
- # 🎨 Gradio UI
73
  demo = gr.Interface(
74
  fn=classify_image,
75
  inputs=gr.Image(type="pil", label="📸 Upload stool image"),
76
- outputs=gr.Label(num_top_classes=3, label="Predicted diagnosis"),
77
- title="🐾 Stool Diagnosis AI",
78
- description="Upload a stool image for analysis. The model predicts stool type or rejects unrelated photos."
 
 
 
 
 
 
79
  )
80
 
81
  if __name__ == "__main__":
 
10
  input_details = interpreter.get_input_details()
11
  output_details = interpreter.get_output_details()
12
 
13
+ # 🏷️ Labels of your stool model
14
  labels = ["bloody", "hard stool", "normal", "parasite", "watery"]
15
 
16
+ # 💬 Diagnosis summaries for each label
17
+ diagnosis_advice = {
18
+ "bloody": "Possible hemorrhagic gastroenteritis. ⚠️ Visit a vet immediately as it may indicate internal bleeding or infection.",
19
+ "hard stool": "Your pet may be constipated. 💧 Encourage hydration and increase dietary fiber intake.",
20
+ "normal": "✅ Healthy stool detected. Your pet appears to be in good digestive health.",
21
+ "parasite": "⚠️ Possible tapeworm or other parasite infection. Schedule deworming and a vet check-up.",
22
+ "watery": "Possible diarrhea. 💧 Ensure hydration and monitor for dehydration or weakness.",
23
+ "Not stool image": "❌ This image doesn’t appear to be a stool sample. Please upload a clearer photo of stool.",
24
+ "Uncertain / unclear stool image": "⚠️ The image is unclear or confidence is low. Try retaking the photo in better lighting."
25
+ }
26
+
27
+ # 🧩 Preprocess image for TFLite
28
  def preprocess_image(img: Image.Image):
29
  img = img.convert("RGB").resize((128, 128))
30
  arr = np.asarray(img).astype(np.float32) / 255.0
31
  arr = np.expand_dims(arr, axis=0)
32
  return arr
33
 
34
+ # 🚫 Detection filter for non-stool images
35
  def is_not_stool_image(image):
36
  arr = np.asarray(image.convert("RGB")).astype(np.float32)
37
  brightness = arr.mean()
38
  contrast = arr.std()
39
  avg_color = arr.mean(axis=(0, 1))
40
 
 
 
41
  if brightness > 220 or brightness < 25:
42
+ return True # too bright or too dark
43
  if contrast < 25:
44
+ return True # too flat / no texture
45
  if avg_color[0] > 180 and avg_color[1] < 80 and avg_color[2] < 80:
46
+ return True # too reddish
47
+ if avg_color[1] > 200 and avg_color[0] < 100:
48
  return True # too greenish
49
  if avg_color[2] > 200:
50
+ return True # too bluish
 
51
  return False
52
 
53
+ # 🧠 Main classification logic
54
  def classify_image(image):
55
  try:
56
+ # Step 1: Validate stool image
57
  if is_not_stool_image(image):
58
+ return {"Not stool image": 1.0}, diagnosis_advice["Not stool image"]
59
 
60
+ # Step 2: Run TFLite model
61
  input_data = preprocess_image(image)
62
  interpreter.set_tensor(input_details[0]['index'], input_data)
63
  interpreter.invoke()
64
  output_data = interpreter.get_tensor(output_details[0]['index'])[0]
65
 
66
+ # Step 3: Sort predictions by confidence
67
  results = {labels[i]: float(output_data[i]) for i in range(len(labels))}
68
  sorted_results = dict(sorted(results.items(), key=lambda x: x[1], reverse=True))
 
 
69
  top_label, top_score = list(sorted_results.items())[0]
70
+
71
+ # Step 4: Handle low confidence
72
  if top_score < 0.4:
73
+ return {"Uncertain / unclear stool image": top_score}, diagnosis_advice["Uncertain / unclear stool image"]
74
+
75
+ # Step 5: Add readable confidence percentages
76
+ formatted_results = {
77
+ f"{label} ({score * 100:.2f}%)": score for label, score in sorted_results.items()
78
+ }
79
 
80
+ # Step 6: Return label + human diagnosis
81
+ advice = diagnosis_advice.get(top_label, "No advice available for this diagnosis.")
82
+ return formatted_results, advice
83
 
84
  except Exception as e:
85
+ return {"Error": str(e)}, f"⚠️ Error encountered: {str(e)}"
86
 
87
+ # 🎨 Gradio Interface
88
  demo = gr.Interface(
89
  fn=classify_image,
90
  inputs=gr.Image(type="pil", label="📸 Upload stool image"),
91
+ outputs=[
92
+ gr.Label(num_top_classes=3, label="Predicted Diagnosis & Confidence"),
93
+ gr.Textbox(label="💬 Diagnosis Summary", lines=3),
94
+ ],
95
+ title="🐾 Pet Stool Diagnosis AI (with Confidence & Advice)",
96
+ description=(
97
+ "Upload a stool image to get an AI-based diagnosis with confidence scores and health advice. "
98
+ "This tool checks image validity, identifies stool condition, and provides next-step guidance."
99
+ ),
100
  )
101
 
102
  if __name__ == "__main__":