Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -2,6 +2,7 @@ import gradio as gr
|
|
| 2 |
from PIL import Image
|
| 3 |
import torch
|
| 4 |
from torchvision import models, transforms
|
|
|
|
| 5 |
import logging
|
| 6 |
import os
|
| 7 |
|
|
@@ -52,7 +53,7 @@ def preprocess_image(image):
|
|
| 52 |
def predict_xray(image):
|
| 53 |
try:
|
| 54 |
if image is None:
|
| 55 |
-
return "Error: No image uploaded.", ""
|
| 56 |
|
| 57 |
image_tensor = preprocess_image(image)
|
| 58 |
with torch.no_grad():
|
|
@@ -60,19 +61,61 @@ def predict_xray(image):
|
|
| 60 |
probs = torch.nn.functional.softmax(outputs, dim=1)[0] # Softmax over all conditions
|
| 61 |
results = {conditions[i]: float(probs[i].cpu().numpy()) * 100 for i in range(len(conditions))}
|
| 62 |
|
| 63 |
-
#
|
| 64 |
most_likely_condition = max(results, key=results.get)
|
| 65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
|
| 67 |
-
# Display
|
| 68 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
|
| 70 |
logger.info(f"Prediction: {most_likely_condition} with confidence {confidence:.2f}%")
|
| 71 |
-
return summary
|
| 72 |
|
| 73 |
except Exception as e:
|
| 74 |
logger.error(f"Error in predict_xray: {str(e)}")
|
| 75 |
-
return f"Error: {str(e)}", ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
|
| 77 |
# Gradio Interface with enhanced UI
|
| 78 |
def create_interface():
|
|
@@ -83,6 +126,9 @@ def create_interface():
|
|
| 83 |
.gradio-button { background-color: #3B82F6; color: white; border-radius: 10px; padding: 15px 30px; font-size: 16px; transition: background-color 0.3s; }
|
| 84 |
.gradio-button:hover { background-color: #2563EB; }
|
| 85 |
.result-box { background-color: #ffffff; border-radius: 10px; padding: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); margin-top: 20px; max-width: 100%; }
|
|
|
|
|
|
|
|
|
|
| 86 |
"""
|
| 87 |
|
| 88 |
gr.Markdown("<h1 class='title'>RadiologyScan AI</h1>")
|
|
@@ -91,18 +137,28 @@ def create_interface():
|
|
| 91 |
with gr.Row():
|
| 92 |
with gr.Column(scale=1):
|
| 93 |
xray_input = gr.Image(label="Upload X-ray", type="pil", elem_id="xray-input")
|
|
|
|
|
|
|
| 94 |
|
| 95 |
with gr.Row():
|
| 96 |
predict_button = gr.Button("Analyze X-ray", elem_classes="gradio-button")
|
|
|
|
| 97 |
|
| 98 |
with gr.Column():
|
| 99 |
-
xray_output = gr.HTML(label="Diagnosis Summary", elem_classes="result-box")
|
|
|
|
|
|
|
|
|
|
| 100 |
|
| 101 |
predict_button.click(
|
| 102 |
fn=predict_xray,
|
| 103 |
inputs=xray_input,
|
| 104 |
-
outputs=xray_output
|
| 105 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 106 |
|
| 107 |
return demo
|
| 108 |
|
|
|
|
| 2 |
from PIL import Image
|
| 3 |
import torch
|
| 4 |
from torchvision import models, transforms
|
| 5 |
+
import PyPDF2
|
| 6 |
import logging
|
| 7 |
import os
|
| 8 |
|
|
|
|
| 53 |
def predict_xray(image):
|
| 54 |
try:
|
| 55 |
if image is None:
|
| 56 |
+
return "Error: No image uploaded.", "", ""
|
| 57 |
|
| 58 |
image_tensor = preprocess_image(image)
|
| 59 |
with torch.no_grad():
|
|
|
|
| 61 |
probs = torch.nn.functional.softmax(outputs, dim=1)[0] # Softmax over all conditions
|
| 62 |
results = {conditions[i]: float(probs[i].cpu().numpy()) * 100 for i in range(len(conditions))}
|
| 63 |
|
| 64 |
+
# Handle case where predicted class might not be in our list of conditions
|
| 65 |
most_likely_condition = max(results, key=results.get)
|
| 66 |
+
|
| 67 |
+
# Ensure the predicted condition is in the valid conditions list
|
| 68 |
+
if most_likely_condition not in conditions:
|
| 69 |
+
most_likely_condition = "Other"
|
| 70 |
+
confidence = 0.0
|
| 71 |
+
else:
|
| 72 |
+
confidence = results[most_likely_condition]
|
| 73 |
+
|
| 74 |
+
# Create a detailed summary of results
|
| 75 |
+
summary = f"**Summary**: Based on the X-ray analysis, the most likely diagnosis is: <b>{most_likely_condition}</b> with a confidence of <b>{confidence:.2f}%</b>."
|
| 76 |
+
|
| 77 |
+
# Enhanced condition details for each disease/condition
|
| 78 |
+
condition_details = {
|
| 79 |
+
"Normal": {"description": "No abnormal signs detected.", "recommendation": "Routine check-ups recommended."},
|
| 80 |
+
"Pneumonia": {"description": "Lung inflammation detected, possibly infectious.", "recommendation": "Seek medical attention for treatment."},
|
| 81 |
+
"Cancer": {"description": "Suspicious masses suggest cancer; further imaging needed.", "recommendation": "Consult an oncologist."},
|
| 82 |
+
"TB": {"description": "Cavitary lesions indicate tuberculosis.", "recommendation": "Immediate medical evaluation required."},
|
| 83 |
+
"Other": {"description": "Unclear abnormality; further investigation needed.", "recommendation": "Consult a radiologist."},
|
| 84 |
+
"Fractures": {"description": "Bone break detected.", "recommendation": "Orthopedic evaluation."},
|
| 85 |
+
"COPD": {"description": "Lung damage from COPD observed.", "recommendation": "Pulmonary consultation."},
|
| 86 |
+
# Add the rest of the conditions as needed...
|
| 87 |
+
}
|
| 88 |
|
| 89 |
+
# Display results in a clear format
|
| 90 |
+
detailed_results = "<ul class='result-list'>"
|
| 91 |
+
for condition, prob in results.items():
|
| 92 |
+
detailed_results += f"<li><b>{condition}:</b> {prob:.2f}%</li>"
|
| 93 |
+
detailed_results += "</ul>"
|
| 94 |
+
|
| 95 |
+
additional_feedback = f"<div class='feedback-box'><b>Description:</b> {condition_details[most_likely_condition]['description']}<br><b>Recommendation:</b> {condition_details[most_likely_condition]['recommendation']}</div>"
|
| 96 |
|
| 97 |
logger.info(f"Prediction: {most_likely_condition} with confidence {confidence:.2f}%")
|
| 98 |
+
return summary, detailed_results, additional_feedback
|
| 99 |
|
| 100 |
except Exception as e:
|
| 101 |
logger.error(f"Error in predict_xray: {str(e)}")
|
| 102 |
+
return f"Error: {str(e)}", "", ""
|
| 103 |
+
|
| 104 |
+
# Define function to read and analyze patient reports (PDFs)
|
| 105 |
+
def analyze_report(file):
|
| 106 |
+
text = ""
|
| 107 |
+
if file and file.name.endswith(".pdf"):
|
| 108 |
+
try:
|
| 109 |
+
pdf_reader = PyPDF2.PdfReader(file)
|
| 110 |
+
for page in pdf_reader.pages:
|
| 111 |
+
text += page.extract_text() or ""
|
| 112 |
+
report_summary = f"Patient Report (Preview): {text[:300]}..." if text else "No readable text found in the PDF."
|
| 113 |
+
except Exception as e:
|
| 114 |
+
logger.error(f"Error reading PDF: {str(e)}")
|
| 115 |
+
report_summary = f"Error processing PDF: {str(e)}"
|
| 116 |
+
else:
|
| 117 |
+
report_summary = "Please upload a valid PDF file."
|
| 118 |
+
return report_summary
|
| 119 |
|
| 120 |
# Gradio Interface with enhanced UI
|
| 121 |
def create_interface():
|
|
|
|
| 126 |
.gradio-button { background-color: #3B82F6; color: white; border-radius: 10px; padding: 15px 30px; font-size: 16px; transition: background-color 0.3s; }
|
| 127 |
.gradio-button:hover { background-color: #2563EB; }
|
| 128 |
.result-box { background-color: #ffffff; border-radius: 10px; padding: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); margin-top: 20px; max-width: 100%; }
|
| 129 |
+
.result-list { padding-left: 20px; margin: 10px 0; }
|
| 130 |
+
.result-summary { font-size: 18px; color: #2F4F4F; font-weight: 500; }
|
| 131 |
+
.feedback-box { background-color: #F0FFF4; padding: 10px; border-left: 4px solid #38A169; border-radius: 5px; margin-top: 10px; }
|
| 132 |
"""
|
| 133 |
|
| 134 |
gr.Markdown("<h1 class='title'>RadiologyScan AI</h1>")
|
|
|
|
| 137 |
with gr.Row():
|
| 138 |
with gr.Column(scale=1):
|
| 139 |
xray_input = gr.Image(label="Upload X-ray", type="pil", elem_id="xray-input")
|
| 140 |
+
with gr.Column(scale=1):
|
| 141 |
+
report_input = gr.File(label="Upload Patient Report (PDF)", file_count="single", elem_id="report-input")
|
| 142 |
|
| 143 |
with gr.Row():
|
| 144 |
predict_button = gr.Button("Analyze X-ray", elem_classes="gradio-button")
|
| 145 |
+
report_button = gr.Button("Analyze Report", elem_classes="gradio-button")
|
| 146 |
|
| 147 |
with gr.Column():
|
| 148 |
+
xray_output = gr.HTML(label="X-ray Diagnosis Summary", elem_classes="result-box")
|
| 149 |
+
xray_result = gr.HTML(label="Detailed X-ray Results", elem_classes="result-box")
|
| 150 |
+
additional_feedback = gr.HTML(label="Additional Feedback", elem_classes="result-box")
|
| 151 |
+
report_output = gr.Textbox(label="Report Summary", interactive=False, elem_classes="result-box")
|
| 152 |
|
| 153 |
predict_button.click(
|
| 154 |
fn=predict_xray,
|
| 155 |
inputs=xray_input,
|
| 156 |
+
outputs=[xray_output, xray_result, additional_feedback]
|
| 157 |
)
|
| 158 |
+
report_button.click(
|
| 159 |
+
fn=analyze_report,
|
| 160 |
+
inputs=report_input,
|
| 161 |
+
outputs=report_output)
|
| 162 |
|
| 163 |
return demo
|
| 164 |
|