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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -32
app.py CHANGED
@@ -1,7 +1,8 @@
1
  import gradio as gr
2
  import tensorflow as tf
3
  import numpy as np
4
- from PIL import Image
 
5
 
6
  # 🧠 Load your TFLite model
7
  interpreter = tf.lite.Interpreter(model_path="stool_model.tflite")
@@ -13,7 +14,7 @@ output_details = interpreter.get_output_details()
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.",
@@ -24,78 +25,95 @@ diagnosis_advice = {
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
 
 
1
  import gradio as gr
2
  import tensorflow as tf
3
  import numpy as np
4
+ from PIL import Image, ImageStat
5
+ import cv2
6
 
7
  # 🧠 Load your TFLite model
8
  interpreter = tf.lite.Interpreter(model_path="stool_model.tflite")
 
14
  # 🏷️ Labels of your stool model
15
  labels = ["bloody", "hard stool", "normal", "parasite", "watery"]
16
 
17
+ # 💬 Diagnosis summaries
18
  diagnosis_advice = {
19
  "bloody": "Possible hemorrhagic gastroenteritis. ⚠️ Visit a vet immediately as it may indicate internal bleeding or infection.",
20
  "hard stool": "Your pet may be constipated. 💧 Encourage hydration and increase dietary fiber intake.",
 
25
  "Uncertain / unclear stool image": "⚠️ The image is unclear or confidence is low. Try retaking the photo in better lighting."
26
  }
27
 
28
+ # 🧩 Image preprocessing for the TFLite model
29
  def preprocess_image(img: Image.Image):
30
  img = img.convert("RGB").resize((128, 128))
31
  arr = np.asarray(img).astype(np.float32) / 255.0
32
  arr = np.expand_dims(arr, axis=0)
33
  return arr
34
 
35
+ # 🚫 Strict non-stool detection
36
  def is_not_stool_image(image):
37
+ """Multi-layer detection for non-stool photos"""
38
+ np_img = np.array(image.convert("RGB"))
39
+ stat = ImageStat.Stat(image)
40
+
41
+ # 🧠 1️⃣ Brightness & contrast checks
42
+ brightness = stat.mean[0]
43
+ contrast = stat.stddev[0]
44
+ if brightness > 210 or brightness < 30:
45
+ return True # too bright or dark
46
  if contrast < 25:
47
  return True # too flat / no texture
48
+
49
+ # 🧠 2️⃣ Dominant color detection (stool tends to be brownish)
50
+ avg_color = np.mean(np_img.reshape(-1, 3), axis=0)
51
+ r, g, b = avg_color
52
+
53
+ # Detect unnatural colors (too blue, green, or red)
54
+ if (r > 200 and g < 100 and b < 100) or (g > 180 and r < 100) or (b > 180):
55
+ return True
56
+
57
+ # 🧠 3️⃣ Color tone validation — real stool is usually brown (RGB ratios)
58
+ brownish_score = (r * 0.5 + g * 0.3 + b * 0.2)
59
+ grayish_score = abs(r - g) + abs(g - b)
60
+ if brownish_score < 60 or grayish_score > 80:
61
+ return True
62
+
63
+ # 🧠 4️⃣ Texture detection with OpenCV
64
+ gray = cv2.cvtColor(np_img, cv2.COLOR_RGB2GRAY)
65
+ lap_var = cv2.Laplacian(gray, cv2.CV_64F).var() # blur measure
66
+ if lap_var < 50:
67
+ return True # image too smooth or blurry (likely not stool)
68
+
69
+ return False # passes all checks, likely stool
70
+
71
+ # 🧠 Main classifier
72
  def classify_image(image):
73
  try:
74
+ # 🧩 Step 1: Reject non-stool images first
75
  if is_not_stool_image(image):
76
  return {"Not stool image": 1.0}, diagnosis_advice["Not stool image"]
77
 
78
+ # 🧩 Step 2: Run TFLite model
79
  input_data = preprocess_image(image)
80
  interpreter.set_tensor(input_details[0]['index'], input_data)
81
  interpreter.invoke()
82
  output_data = interpreter.get_tensor(output_details[0]['index'])[0]
83
 
84
+ # 🧩 Step 3: Sort predictions
85
  results = {labels[i]: float(output_data[i]) for i in range(len(labels))}
86
  sorted_results = dict(sorted(results.items(), key=lambda x: x[1], reverse=True))
87
  top_label, top_score = list(sorted_results.items())[0]
88
 
89
+ # 🧩 Step 4: Handle low-confidence predictions
90
+ if top_score < 0.45:
91
  return {"Uncertain / unclear stool image": top_score}, diagnosis_advice["Uncertain / unclear stool image"]
92
 
93
+ # 🧩 Step 5: Add readable confidence %
94
  formatted_results = {
95
  f"{label} ({score * 100:.2f}%)": score for label, score in sorted_results.items()
96
  }
97
 
98
+ # 🩺 Step 6: Generate human-readable advice
99
  advice = diagnosis_advice.get(top_label, "No advice available for this diagnosis.")
100
  return formatted_results, advice
101
 
102
  except Exception as e:
103
+ return {"Error": 0.0}, f"⚠️ Error: {str(e)}"
104
 
105
  # 🎨 Gradio Interface
106
  demo = gr.Interface(
107
  fn=classify_image,
108
+ inputs=gr.Image(type="pil", label="📸 Upload Stool Image"),
109
  outputs=[
110
  gr.Label(num_top_classes=3, label="Predicted Diagnosis & Confidence"),
111
  gr.Textbox(label="💬 Diagnosis Summary", lines=3),
112
  ],
113
+ title="🐾 Pet Stool Diagnosis AI (Strict Validation)",
114
  description=(
115
+ "Upload a stool image for AI-based diagnosis. The system will first verify if it's a real stool photo, "
116
+ "then predict the stool type and give a simple health summary."
117
  ),
118
  )
119