Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,18 +1,18 @@
|
|
1 |
-
import
|
2 |
-
import os
|
3 |
-
import shutil
|
4 |
-
import base64
|
5 |
import gradio as gr
|
6 |
import cv2
|
7 |
import numpy as np
|
8 |
import mediapipe as mp
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
from reportlab.lib.pagesizes import letter
|
10 |
-
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
|
11 |
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
|
12 |
from reportlab.lib import colors
|
13 |
-
from datetime import datetime
|
14 |
-
import joblib
|
15 |
-
from sklearn.linear_model import LinearRegression
|
16 |
|
17 |
# Initialize the face mesh model
|
18 |
mp_face_mesh = mp.solutions.face_mesh
|
@@ -55,7 +55,8 @@ try:
|
|
55 |
spo2_model = joblib.load("spo2_model_simulated.pkl")
|
56 |
hr_model = joblib.load("heart_rate_model.pkl")
|
57 |
except FileNotFoundError:
|
58 |
-
print(
|
|
|
59 |
exit(1)
|
60 |
|
61 |
models = {
|
@@ -119,10 +120,11 @@ def build_table(title, rows):
|
|
119 |
return html
|
120 |
|
121 |
|
122 |
-
# Function to save health report
|
123 |
-
def save_results_to_pdf(
|
124 |
try:
|
125 |
-
|
|
|
126 |
styles = getSampleStyleSheet()
|
127 |
|
128 |
# Define custom styles
|
@@ -146,23 +148,19 @@ def save_results_to_pdf(patient_details, test_results, pdf_filename):
|
|
146 |
|
147 |
# Build the PDF content
|
148 |
flowables = []
|
149 |
-
|
150 |
-
#
|
151 |
-
flowables.append(Paragraph(
|
152 |
-
|
153 |
-
flowables.append(Spacer(1, 12))
|
154 |
-
|
155 |
# Add test results to the report
|
156 |
-
for
|
157 |
-
|
158 |
-
|
159 |
-
flowables.append(Paragraph(f"{test}: {result}", body_style))
|
160 |
-
flowables.append(Spacer(1, 6))
|
161 |
flowables.append(Spacer(1, 12))
|
162 |
-
|
163 |
# Build the PDF
|
164 |
doc.build(flowables)
|
165 |
-
return f"PDF saved successfully as {
|
166 |
except Exception as e:
|
167 |
return f"Error saving PDF: {str(e)}", None
|
168 |
|
@@ -174,30 +172,55 @@ def build_health_card(profile_image, test_results, summary, patient_name="", pat
|
|
174 |
|
175 |
html = f"""
|
176 |
<div id="health-card" style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; max-width: 700px; margin: 20px auto; border-radius: 16px; background: linear-gradient(135deg, #e3f2fd 0%, #f3e5f5 100%); border: 2px solid #ddd; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15); padding: 30px; color: #1a1a1a;">
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
<
|
181 |
-
|
|
|
|
|
|
|
|
|
|
|
182 |
</div>
|
183 |
-
<div>
|
184 |
-
<img src="data:image/png;base64,{profile_image}" style="width:
|
|
|
|
|
|
|
|
|
|
|
185 |
</div>
|
186 |
</div>
|
187 |
|
188 |
-
<div style="margin-
|
189 |
-
{test_results}
|
|
|
|
|
|
|
|
|
190 |
</div>
|
191 |
|
192 |
-
<div style="margin-
|
193 |
-
<h4>📝 Summary & Recommendations</h4>
|
194 |
-
<div>
|
|
|
|
|
195 |
</div>
|
196 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
</div>
|
198 |
"""
|
199 |
return html
|
200 |
|
|
|
201 |
# Initialize global variable for patient details
|
202 |
current_patient_details = {'name': '', 'age': '', 'gender': '', 'id': ''}
|
203 |
|
@@ -206,22 +229,22 @@ def analyze_face(input_data):
|
|
206 |
if isinstance(input_data, str): # Video input (file path in Replit)
|
207 |
cap = cv2.VideoCapture(input_data)
|
208 |
if not cap.isOpened():
|
209 |
-
return
|
210 |
ret, frame = cap.read()
|
211 |
cap.release()
|
212 |
if not ret:
|
213 |
-
return
|
214 |
else: # Image input
|
215 |
frame = input_data
|
216 |
if frame is None:
|
217 |
-
return
|
218 |
|
219 |
# Resize image to reduce processing time
|
220 |
frame = cv2.resize(frame, (640, 480)) # Adjust resolution for Replit
|
221 |
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
222 |
result = face_mesh.process(frame_rgb)
|
223 |
if not result.multi_face_landmarks:
|
224 |
-
return
|
225 |
landmarks = result.multi_face_landmarks[
|
226 |
0].landmark # Fixed: Use integer index
|
227 |
features = extract_features(frame_rgb, landmarks)
|
@@ -302,11 +325,9 @@ def analyze_face(input_data):
|
|
302 |
current_patient_details['id']
|
303 |
)
|
304 |
|
305 |
-
# Generate PDF
|
306 |
pdf_filename = f"Health_Report_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.pdf"
|
307 |
-
|
308 |
-
# Pass the pdf_filename along with test_results to save_results_to_pdf
|
309 |
-
pdf_result, pdf_filepath = save_results_to_pdf(current_patient_details, test_results, pdf_filename)
|
310 |
|
311 |
if pdf_filepath:
|
312 |
# Copy the PDF to a temporary directory for Gradio to serve it
|
|
|
1 |
+
import os # Import the os module
|
|
|
|
|
|
|
2 |
import gradio as gr
|
3 |
import cv2
|
4 |
import numpy as np
|
5 |
import mediapipe as mp
|
6 |
+
from sklearn.linear_model import LinearRegression
|
7 |
+
import random
|
8 |
+
import base64
|
9 |
+
import joblib
|
10 |
+
from datetime import datetime
|
11 |
+
import shutil
|
12 |
from reportlab.lib.pagesizes import letter
|
13 |
+
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
|
14 |
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
|
15 |
from reportlab.lib import colors
|
|
|
|
|
|
|
16 |
|
17 |
# Initialize the face mesh model
|
18 |
mp_face_mesh = mp.solutions.face_mesh
|
|
|
55 |
spo2_model = joblib.load("spo2_model_simulated.pkl")
|
56 |
hr_model = joblib.load("heart_rate_model.pkl")
|
57 |
except FileNotFoundError:
|
58 |
+
print(
|
59 |
+
"Error: One or more .pkl model files are missing. Please upload them.")
|
60 |
exit(1)
|
61 |
|
62 |
models = {
|
|
|
120 |
return html
|
121 |
|
122 |
|
123 |
+
# Function to save the health report to PDF
|
124 |
+
def save_results_to_pdf(test_results, filename):
|
125 |
try:
|
126 |
+
# Create a PDF document
|
127 |
+
doc = SimpleDocTemplate(filename, pagesize=letter)
|
128 |
styles = getSampleStyleSheet()
|
129 |
|
130 |
# Define custom styles
|
|
|
148 |
|
149 |
# Build the PDF content
|
150 |
flowables = []
|
151 |
+
|
152 |
+
# Add title
|
153 |
+
flowables.append(Paragraph("Health Report", title_style))
|
154 |
+
|
|
|
|
|
155 |
# Add test results to the report
|
156 |
+
for label, value in test_results.items():
|
157 |
+
line = f"{label}: {value}"
|
158 |
+
flowables.append(Paragraph(line, body_style))
|
|
|
|
|
159 |
flowables.append(Spacer(1, 12))
|
160 |
+
|
161 |
# Build the PDF
|
162 |
doc.build(flowables)
|
163 |
+
return f"PDF saved successfully as {filename}", filename
|
164 |
except Exception as e:
|
165 |
return f"Error saving PDF: {str(e)}", None
|
166 |
|
|
|
172 |
|
173 |
html = f"""
|
174 |
<div id="health-card" style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; max-width: 700px; margin: 20px auto; border-radius: 16px; background: linear-gradient(135deg, #e3f2fd 0%, #f3e5f5 100%); border: 2px solid #ddd; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15); padding: 30px; color: #1a1a1a;">
|
175 |
+
|
176 |
+
<div style="background-color: rgba(255, 255, 255, 0.9); border-radius: 12px; padding: 20px; margin-bottom: 25px; border: 1px solid #e0e0e0;">
|
177 |
+
<div style="display: flex; align-items: center; margin-bottom: 15px;">
|
178 |
+
<div style="background: linear-gradient(135deg, #64b5f6, #42a5f5); padding: 8px 16px; border-radius: 8px; margin-right: 20px;">
|
179 |
+
<h3 style="margin: 0; font-size: 16px; color: white; font-weight: 600;">HEALTH CARD</h3>
|
180 |
+
</div>
|
181 |
+
<div style="margin-left: auto; text-align: right; color: #666; font-size: 12px;">
|
182 |
+
<div>Report Date: {current_date}</div>
|
183 |
+
{f'<div>Patient ID: {patient_id}</div>' if patient_id else ''}
|
184 |
+
</div>
|
185 |
</div>
|
186 |
+
<div style="display: flex; align-items: center;">
|
187 |
+
<img src="data:image/png;base64,{profile_image}" alt="Profile" style="width: 90px; height: 90px; border-radius: 50%; margin-right: 20px; border: 3px solid #fff; box-shadow: 0 4px 12px rgba(0,0,0,0.1);">
|
188 |
+
<div>
|
189 |
+
<h2 style="margin: 0; font-size: 28px; color: #2c3e50; font-weight: 700;">{patient_name if patient_name else "Lab Test Results"}</h2>
|
190 |
+
<p style="margin: 4px 0 0 0; color: #666; font-size: 14px;">{f"Age: {patient_age} | Gender: {patient_gender}" if patient_age and patient_gender else "AI-Generated Health Analysis"}</p>
|
191 |
+
<p style="margin: 4px 0 0 0; color: #888; font-size: 12px;">Face-Based Health Analysis Report</p>
|
192 |
+
</div>
|
193 |
</div>
|
194 |
</div>
|
195 |
|
196 |
+
<div style="background-color: rgba(255, 255, 255, 0.95); border-radius: 12px; padding: 25px; margin-bottom: 25px; border: 1px solid #e0e0e0;">
|
197 |
+
{test_results['Hematology']}
|
198 |
+
{test_results['Iron Panel']}
|
199 |
+
{test_results['Liver & Kidney']}
|
200 |
+
{test_results['Electrolytes']}
|
201 |
+
{test_results['Vitals']}
|
202 |
</div>
|
203 |
|
204 |
+
<div style="background-color: rgba(255, 255, 255, 0.95); padding: 20px; border-radius: 12px; border: 1px solid #e0e0e0; margin-bottom: 25px;">
|
205 |
+
<h4 style="margin: 0 0 15px 0; color: #2c3e50; font-size: 18px; font-weight: 600;">📝 Summary & Recommendations</h4>
|
206 |
+
<div style="color: #444; line-height: 1.6;">
|
207 |
+
{summary}
|
208 |
+
</div>
|
209 |
</div>
|
210 |
|
211 |
+
<div style="display: flex; gap: 15px; justify-content: center; flex-wrap: wrap;">
|
212 |
+
<button onclick="window.print()" style="padding: 12px 24px; background: linear-gradient(135deg, #4caf50, #45a049); color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: 600; font-size: 14px; box-shadow: 0 4px 12px rgba(76, 175, 80, 0.3); transition: all 0.3s;">
|
213 |
+
📥 Download Report
|
214 |
+
</button>
|
215 |
+
<button style="padding: 12px 24px; background: linear-gradient(135deg, #2196f3, #1976d2); color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: 600; font-size: 14px; box-shadow: 0 4px 12px rgba(33, 150, 243, 0.3);">
|
216 |
+
📞 Find Labs Near Me
|
217 |
+
</button>
|
218 |
+
</div>
|
219 |
</div>
|
220 |
"""
|
221 |
return html
|
222 |
|
223 |
+
|
224 |
# Initialize global variable for patient details
|
225 |
current_patient_details = {'name': '', 'age': '', 'gender': '', 'id': ''}
|
226 |
|
|
|
229 |
if isinstance(input_data, str): # Video input (file path in Replit)
|
230 |
cap = cv2.VideoCapture(input_data)
|
231 |
if not cap.isOpened():
|
232 |
+
return "<div style='color:red;'>⚠️ Error: Could not open video.</div>", None
|
233 |
ret, frame = cap.read()
|
234 |
cap.release()
|
235 |
if not ret:
|
236 |
+
return "<div style='color:red;'>⚠️ Error: Could not read video frame.</div>", None
|
237 |
else: # Image input
|
238 |
frame = input_data
|
239 |
if frame is None:
|
240 |
+
return "<div style='color:red;'>⚠️ Error: No image provided.</div>", None
|
241 |
|
242 |
# Resize image to reduce processing time
|
243 |
frame = cv2.resize(frame, (640, 480)) # Adjust resolution for Replit
|
244 |
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
245 |
result = face_mesh.process(frame_rgb)
|
246 |
if not result.multi_face_landmarks:
|
247 |
+
return "<div style='color:red;'>⚠️ Error: Face not detected.</div>", None
|
248 |
landmarks = result.multi_face_landmarks[
|
249 |
0].landmark # Fixed: Use integer index
|
250 |
features = extract_features(frame_rgb, landmarks)
|
|
|
325 |
current_patient_details['id']
|
326 |
)
|
327 |
|
328 |
+
# Generate PDF and return for download
|
329 |
pdf_filename = f"Health_Report_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.pdf"
|
330 |
+
pdf_result, pdf_filepath = save_results_to_pdf(test_results, pdf_filename)
|
|
|
|
|
331 |
|
332 |
if pdf_filepath:
|
333 |
# Copy the PDF to a temporary directory for Gradio to serve it
|