KPrashanth commited on
Commit
ef29459
·
verified ·
1 Parent(s): 893d4a2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +47 -38
app.py CHANGED
@@ -1,5 +1,8 @@
1
  # app.py
2
 
 
 
 
3
  import gradio as gr
4
  from PIL import Image
5
 
@@ -12,54 +15,64 @@ cbc = SmartCBC() # loads YOLO + classifier once
12
 
13
 
14
  # -------------------------------------------------
15
- # Helper to normalize Gallery input
16
  # -------------------------------------------------
17
- def _normalize_gallery_images(images):
18
  """
19
- Gradio Gallery (type='pil') can return:
20
- - list[PIL.Image]
21
- - or list[(PIL.Image, metadata_dict)]
 
 
22
 
23
- This function strips metadata if present and returns a flat list of images.
24
  """
25
- if images is None:
26
- return []
27
-
28
- normalized = []
29
- for item in images:
30
- # Sometimes (media, metadata), sometimes media only
31
- if isinstance(item, tuple):
32
- media = item[0]
 
 
 
 
 
33
  else:
34
- media = item
35
- normalized.append(media)
36
- return normalized
 
 
 
 
 
 
37
 
38
 
39
  # -------------------------------------------------
40
  # Core Gradio wrapper
41
  # -------------------------------------------------
42
- def analyze_images(images, age, gender, output_mode):
43
  """
44
  Wrapper for SmartCBC.analyze().
45
 
46
- - Accepts one or multiple images from a Gradio Gallery.
47
- - Delegates to SmartCBC.analyze(), which auto-routes to analyze_batch()
48
- if a list of images is provided.
49
  - Returns either a human-readable text report or full JSON.
50
  """
51
- # No images
52
- if images is None or len(images) == 0:
53
  return "Please upload at least one image.", None
54
 
55
- # Normalize gallery output (strip metadata if any)
56
- img_list = _normalize_gallery_images(images)
57
 
58
- # If single image, send just that; if multiple, send list → analyze_batch
59
- if len(img_list) == 1:
60
- image_input = img_list[0]
61
  else:
62
- image_input = img_list
63
 
64
  # Run SmartCBC pipeline
65
  result = cbc.analyze(
@@ -70,15 +83,13 @@ def analyze_images(images, age, gender, output_mode):
70
 
71
  # Choose output mode
72
  if output_mode == "Text Report":
73
- # result["report_text"] is produced by build_api_response()
74
  return result.get("report_text", "No report generated."), None
75
  else:
76
- # Show full structured JSON
77
  return None, result
78
 
79
 
80
  # -------------------------------------------------
81
- # Gradio UI Layout
82
  # -------------------------------------------------
83
  with gr.Blocks(title="SmartCBC - Multimodal Blood Analysis") as demo:
84
 
@@ -96,13 +107,11 @@ with gr.Blocks(title="SmartCBC - Multimodal Blood Analysis") as demo:
96
  )
97
 
98
  with gr.Row():
99
- img_in = gr.Gallery(
 
100
  label="Upload 1 or Multiple Blood Smear Images (FOVs)",
101
- columns=3,
102
- height="auto",
103
- allow_preview=True,
104
- type="pil", # works with gradio==4.44.1
105
- file_types=["image"] # ensure only images are selectable
106
  )
107
 
108
  with gr.Column():
 
1
  # app.py
2
 
3
+ import os
4
+ from typing import List, Any
5
+
6
  import gradio as gr
7
  from PIL import Image
8
 
 
15
 
16
 
17
  # -------------------------------------------------
18
+ # Helper: convert uploaded files to PIL Images
19
  # -------------------------------------------------
20
+ def files_to_pil_list(files: List[Any]) -> List[Image.Image]:
21
  """
22
+ Gradio Files (file_count='multiple') returns a list of file objects or dicts.
23
+
24
+ Each item commonly looks like:
25
+ - {"name": "/tmp/....png", "orig_name": "...", ...}
26
+ - or a file-like object with .name
27
 
28
+ This helper normalizes them into a list of RGB PIL Images.
29
  """
30
+ pil_list: List[Image.Image] = []
31
+
32
+ if files is None:
33
+ return pil_list
34
+
35
+ for f in files:
36
+ # Newer gradio often returns dicts with "name"
37
+ if isinstance(f, dict) and "name" in f:
38
+ path = f["name"]
39
+ # Older style: File object with .name
40
+ elif hasattr(f, "name"):
41
+ path = f.name
42
+ # Fallback: assume it's already a path-like
43
  else:
44
+ path = str(f)
45
+
46
+ if not os.path.isfile(path):
47
+ raise FileNotFoundError(f"Uploaded file not found on disk: {path}")
48
+
49
+ img = Image.open(path).convert("RGB")
50
+ pil_list.append(img)
51
+
52
+ return pil_list
53
 
54
 
55
  # -------------------------------------------------
56
  # Core Gradio wrapper
57
  # -------------------------------------------------
58
+ def analyze_images(files, age, gender, output_mode):
59
  """
60
  Wrapper for SmartCBC.analyze().
61
 
62
+ - Accepts one or multiple images from a Gradio Files input.
63
+ - If a single image -> sends a single PIL.Image
64
+ If multiple -> sends a list[Image.Image] (SmartCBC can route to analyze_batch).
65
  - Returns either a human-readable text report or full JSON.
66
  """
67
+ if files is None or len(files) == 0:
 
68
  return "Please upload at least one image.", None
69
 
70
+ pil_images = files_to_pil_list(files)
 
71
 
72
+ if len(pil_images) == 1:
73
+ image_input = pil_images[0]
 
74
  else:
75
+ image_input = pil_images
76
 
77
  # Run SmartCBC pipeline
78
  result = cbc.analyze(
 
83
 
84
  # Choose output mode
85
  if output_mode == "Text Report":
 
86
  return result.get("report_text", "No report generated."), None
87
  else:
 
88
  return None, result
89
 
90
 
91
  # -------------------------------------------------
92
+ # Gradio UI Layout (compatible with Gradio 4.0.0)
93
  # -------------------------------------------------
94
  with gr.Blocks(title="SmartCBC - Multimodal Blood Analysis") as demo:
95
 
 
107
  )
108
 
109
  with gr.Row():
110
+ # Use Files for multi-image upload (works on Gradio 4.0.0)
111
+ img_in = gr.Files(
112
  label="Upload 1 or Multiple Blood Smear Images (FOVs)",
113
+ file_count="multiple",
114
+ file_types=["image"],
 
 
 
115
  )
116
 
117
  with gr.Column():