VaneshDev commited on
Commit
ccdb749
·
verified ·
1 Parent(s): aa3be18

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +116 -38
app.py CHANGED
@@ -15,27 +15,82 @@ DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
15
  MODEL = xrv.models.get_model("densenet121-res224-all").to(DEVICE).eval()
16
  LABELS = MODEL.pathologies
17
 
18
- # --- Image Preprocessing ---
19
- def preprocess_image(pil_img: Image.Image) -> torch.Tensor:
20
- """Convert to grayscale, normalize, and resize for model."""
21
- if pil_img.mode != "L":
22
- pil_img = pil_img.convert("L")
23
-
24
- img_array = np.array(pil_img).astype(np.float32)
25
- img_array = xrv.datasets.normalize(img_array, 255) # normalize [-1024, 1024]
26
- img_array = img_array[None, ...] # [1, H, W]
27
-
28
- # Apply center crop and resize
29
- transform = transforms.Compose([
30
- xrv.datasets.XRayCenterCrop(),
31
- xrv.datasets.XRayResizer(224)
32
- ])
33
- img_array = transform(img_array)
34
-
35
- tensor = torch.from_numpy(img_array).unsqueeze(0).to(DEVICE)
36
- return tensor
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
- # --- Medical Recommendations ---
39
  ADVICE = {
40
  "Pneumonia": "Possible infection. Recommend antibiotics and pulmonology consult.",
41
  "Cardiomegaly": "Enlarged heart. Recommend echocardiography and cardiologist review.",
@@ -47,27 +102,54 @@ ADVICE = {
47
  def get_advice(label):
48
  return ADVICE.get(label, "Please consult a radiologist for further evaluation.")
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  # --- X-ray Analysis (No CAM) ---
51
  def analyse_xray(img: Image.Image):
52
  try:
53
  if img is None:
54
  return "Please upload an X-ray image.", None
55
-
56
  x = preprocess_image(img)
57
  with torch.no_grad():
58
  output = MODEL(x)
59
- probs = torch.sigmoid(output)[0] * 100 # convert to percent
60
-
61
  topk = torch.topk(probs, 5)
62
- html = "<h3>🩺 Top 5 Predictions</h3><table border='1'><tr><th>Condition</th><th>Confidence</th></tr>"
 
63
  for idx in topk.indices:
64
- html += f"<tr><td>{LABELS[idx]}</td><td>{probs[idx]:.1f}%</td></tr>"
65
- html += "</table><br>"
 
 
 
 
 
66
 
67
  top_label = LABELS[topk.indices[0].item()]
68
- html += f"<b>Recommended Action for '{top_label}':</b> {get_advice(top_label)}"
69
 
70
- return html, img.resize((224, 224)) # return resized image for display
71
  except Exception as e:
72
  return f"Error processing image: {str(e)}", None
73
 
@@ -76,41 +158,38 @@ def analyse_report(file):
76
  try:
77
  if file is None:
78
  return "Please upload a PDF report."
79
-
80
  doc = fitz.open(file.name)
81
  text = "\n".join(page.get_text() for page in doc)
82
  doc.close()
83
-
84
  found = []
85
  for label in LABELS:
86
  if re.search(rf"\b{label.lower()}\b", text.lower()):
87
  found.append(label)
88
-
89
  if found:
90
  html = "<h3>📃 Findings Detected in Report:</h3><ul>"
91
  for label in found:
92
- html += f"<li><b>{label}</b>: {get_advice(label)}</li>"
93
  html += "</ul>"
94
  else:
95
  html = "<p>No known conditions detected from report text.</p>"
96
-
97
  return html
98
  except Exception as e:
99
  return f"Error processing PDF: {str(e)}"
100
 
101
  # --- Gradio UI ---
102
  with gr.Blocks(title="🩻 RadiologyScan AI") as demo:
103
- gr.Markdown("## 🩻 RadiologyScan AI\nPerform fast AI-based analysis of Chest X-rays and medical reports")
104
-
 
 
 
105
  with gr.Tabs():
106
  with gr.Tab("🔍 X-ray Analysis"):
107
  x_input = gr.Image(label="Upload Chest X-ray", type="pil")
108
  x_out_html = gr.HTML()
109
  x_out_image = gr.Image(label="Resized X-ray (224x224)")
110
-
111
  analyze_btn = gr.Button("Analyze X-ray")
112
  clear_btn = gr.Button("Clear")
113
-
114
  analyze_btn.click(analyse_xray, inputs=x_input, outputs=[x_out_html, x_out_image])
115
  clear_btn.click(lambda: (None, "", None), None, [x_input, x_out_html, x_out_image])
116
 
@@ -119,7 +198,6 @@ with gr.Blocks(title="🩻 RadiologyScan AI") as demo:
119
  pdf_output = gr.HTML()
120
  analyze_pdf_btn = gr.Button("Analyze Report")
121
  clear_pdf_btn = gr.Button("Clear")
122
-
123
  analyze_pdf_btn.click(analyse_report, inputs=pdf_input, outputs=pdf_output)
124
  clear_pdf_btn.click(lambda: (None, ""), None, [pdf_input, pdf_output])
125
 
 
15
  MODEL = xrv.models.get_model("densenet121-res224-all").to(DEVICE).eval()
16
  LABELS = MODEL.pathologies
17
 
18
+ # --- Extended Medical Information ---
19
+ DISEASE_INFO = {
20
+ "Atelectasis": {
21
+ "description":"Collapse of part or all of a lung, reducing oxygen exchange.",
22
+ "cause":"Blocked airway, lung compression, post-surgery.",
23
+ "recommendation":"Deep breathing exercises, possibly bronchoscopy or physiotherapy.",
24
+ },
25
+ "Cardiomegaly": {
26
+ "description":"Enlargement of the heart, seen as a broad silhouette.",
27
+ "cause":"High blood pressure, valve disease, cardiomyopathy.",
28
+ "recommendation":"Echocardiogram, consult a cardiologist.",
29
+ },
30
+ "Consolidation": {
31
+ "description":"Lung region filled with liquid instead of air.",
32
+ "cause":"Often from pneumonia (bacterial or viral).",
33
+ "recommendation":"Consult a physician; likely antibiotics and follow-up chest X-ray.",
34
+ },
35
+ "Edema": {
36
+ "description":"Fluid accumulation in the lungs.",
37
+ "cause":"Heart failure, kidney issues.",
38
+ "recommendation":"Treat underlying cause, may need diuretics, consult cardiology.",
39
+ },
40
+ "Effusion": {
41
+ "description":"Fluid buildup between lung and chest wall.",
42
+ "cause":"Infection, heart failure, cancer.",
43
+ "recommendation":"May need drainage (thoracentesis), see a pulmonologist.",
44
+ },
45
+ "Emphysema": {
46
+ "description":"Damage and enlargement of lung air sacs (alveoli).",
47
+ "cause":"Mainly smoking.",
48
+ "recommendation":"Quit smoking, pulmonary rehab, inhalers.",
49
+ },
50
+ "Fibrosis": {
51
+ "description":"Scarring of lung tissue, making breathing difficult.",
52
+ "cause":"Longstanding inflammation, auto-immune disease, occupational exposure.",
53
+ "recommendation":"Pulmonologist consult, immunosuppression/antifibrotic therapy.",
54
+ },
55
+ "Fracture": {
56
+ "description":"Break/crack in a bone (commonly ribs).",
57
+ "cause":"Trauma, accident, fall.",
58
+ "recommendation":"Pain management, monitor for organ injury, orthopedic consult if severe.",
59
+ },
60
+ "Infiltration": {
61
+ "description":"Something abnormal (cells/fluid) in the lungs.",
62
+ "cause":"Most often infection, sometimes inflammation or cancer.",
63
+ "recommendation":"See physician, further tests to clarify cause.",
64
+ },
65
+ "Mass": {
66
+ "description":"Lump or growth seen on X-ray.",
67
+ "cause":"Could be benign or malignant tumor.",
68
+ "recommendation":"Consult pulmonologist or oncologist, consider CT/biopsy.",
69
+ },
70
+ "Nodule": {
71
+ "description":"Small round or oval spot in the lung.",
72
+ "cause":"Old infection, benign, or early cancer.",
73
+ "recommendation":"May need CT and follow-up scans, discuss with doctor.",
74
+ },
75
+ "Pleural_Thickening": {
76
+ "description":"Thickening of chest lining.",
77
+ "cause":"Old infection, asbestos exposure.",
78
+ "recommendation":"Pulmonology follow-up; rarely needs intervention.",
79
+ },
80
+ "Pneumonia": {
81
+ "description":"Infection causing inflammation in the lungs.",
82
+ "cause":"Bacteria, viruses, or fungus.",
83
+ "recommendation":"Antibiotics/antivirals if needed. Seek prompt medical attention.",
84
+ },
85
+ "Pneumothorax": {
86
+ "description":"Collapsed lung (air leaks into chest cavity).",
87
+ "cause":"Trauma, rupture, sometimes spontaneous.",
88
+ "recommendation":"May need emergency care to remove air; consult ER.",
89
+ },
90
+ # Add more if you want to extend—see LABELS for all possible findings
91
+ }
92
 
93
+ # --- Recommendations for top-line advice ---
94
  ADVICE = {
95
  "Pneumonia": "Possible infection. Recommend antibiotics and pulmonology consult.",
96
  "Cardiomegaly": "Enlarged heart. Recommend echocardiography and cardiologist review.",
 
102
  def get_advice(label):
103
  return ADVICE.get(label, "Please consult a radiologist for further evaluation.")
104
 
105
+ def get_disease_info(label):
106
+ d = DISEASE_INFO.get(label)
107
+ if d:
108
+ return (
109
+ f"<b>{label}</b>: {d['description']}<br>"
110
+ f"<b>Possible Causes:</b> {d['cause']}<br>"
111
+ f"<b>Recommendation:</b> {d['recommendation']}"
112
+ )
113
+ return f"<b>{label}</b>: No extra info available. Please consult a radiologist."
114
+
115
+ # --- Image Preprocessing ---
116
+ def preprocess_image(pil_img: Image.Image) -> torch.Tensor:
117
+ """Convert to grayscale, normalize, and resize for model."""
118
+ if pil_img.mode != "L":
119
+ pil_img = pil_img.convert("L")
120
+ img_array = np.array(pil_img).astype(np.float32)
121
+ img_array = xrv.datasets.normalize(img_array, 255)
122
+ img_array = img_array[None, ...] # [1, H, W]
123
+ img_array = xrv.datasets.XRayCenterCrop()(img_array)
124
+ img_array = xrv.datasets.XRayResizer(224)(img_array)
125
+ tensor = torch.from_numpy(img_array).unsqueeze(0).to(DEVICE)
126
+ return tensor
127
+
128
  # --- X-ray Analysis (No CAM) ---
129
  def analyse_xray(img: Image.Image):
130
  try:
131
  if img is None:
132
  return "Please upload an X-ray image.", None
 
133
  x = preprocess_image(img)
134
  with torch.no_grad():
135
  output = MODEL(x)
136
+ probs = torch.sigmoid(output)[0] * 100
 
137
  topk = torch.topk(probs, 5)
138
+
139
+ html = "<h3>🩺 Top 5 Predictions</h3><table border='1'><tr><th>Condition</th><th>Confidence</th><th>Details</th></tr>"
140
  for idx in topk.indices:
141
+ label = LABELS[idx]
142
+ html += (
143
+ f"<tr><td>{label}</td>"
144
+ f"<td>{probs[idx]:.1f}%</td>"
145
+ f"<td>{get_disease_info(label)}</td></tr>"
146
+ )
147
+ html += "</table>"
148
 
149
  top_label = LABELS[topk.indices[0].item()]
150
+ html += f"<br><b>Recommended Action for '{top_label}':</b> {get_advice(top_label)}"
151
 
152
+ return html, img.resize((224, 224))
153
  except Exception as e:
154
  return f"Error processing image: {str(e)}", None
155
 
 
158
  try:
159
  if file is None:
160
  return "Please upload a PDF report."
 
161
  doc = fitz.open(file.name)
162
  text = "\n".join(page.get_text() for page in doc)
163
  doc.close()
 
164
  found = []
165
  for label in LABELS:
166
  if re.search(rf"\b{label.lower()}\b", text.lower()):
167
  found.append(label)
 
168
  if found:
169
  html = "<h3>📃 Findings Detected in Report:</h3><ul>"
170
  for label in found:
171
+ html += f"<li>{get_disease_info(label)}</li>"
172
  html += "</ul>"
173
  else:
174
  html = "<p>No known conditions detected from report text.</p>"
 
175
  return html
176
  except Exception as e:
177
  return f"Error processing PDF: {str(e)}"
178
 
179
  # --- Gradio UI ---
180
  with gr.Blocks(title="🩻 RadiologyScan AI") as demo:
181
+ gr.Markdown(
182
+ "## 🩻 RadiologyScan AI\n"
183
+ "Perform fast AI-based analysis of Chest X-rays and medical reports\n"
184
+ "<em>This tool provides informative summaries for common radiological findings. Not a substitute for a professional medical opinion.</em>"
185
+ )
186
  with gr.Tabs():
187
  with gr.Tab("🔍 X-ray Analysis"):
188
  x_input = gr.Image(label="Upload Chest X-ray", type="pil")
189
  x_out_html = gr.HTML()
190
  x_out_image = gr.Image(label="Resized X-ray (224x224)")
 
191
  analyze_btn = gr.Button("Analyze X-ray")
192
  clear_btn = gr.Button("Clear")
 
193
  analyze_btn.click(analyse_xray, inputs=x_input, outputs=[x_out_html, x_out_image])
194
  clear_btn.click(lambda: (None, "", None), None, [x_input, x_out_html, x_out_image])
195
 
 
198
  pdf_output = gr.HTML()
199
  analyze_pdf_btn = gr.Button("Analyze Report")
200
  clear_pdf_btn = gr.Button("Clear")
 
201
  analyze_pdf_btn.click(analyse_report, inputs=pdf_input, outputs=pdf_output)
202
  clear_pdf_btn.click(lambda: (None, ""), None, [pdf_input, pdf_output])
203