Rammohan0504 commited on
Commit
bbfb63b
·
verified ·
1 Parent(s): 4a6af8c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +17 -154
app.py CHANGED
@@ -47,7 +47,6 @@ def train_model(output_range):
47
  model = LinearRegression().fit(X, y)
48
  return model
49
 
50
-
51
  # Load models
52
  try:
53
  hemoglobin_model = joblib.load("hemoglobin_model_from_anemia_dataset.pkl")
@@ -115,7 +114,7 @@ def build_table(title, rows):
115
  html += '</tbody></table></div>'
116
  return html
117
 
118
- # Function to save the health report to PDF
119
  def save_results_to_pdf(test_results, filename):
120
  try:
121
  # Create a PDF document
@@ -146,11 +145,11 @@ def save_results_to_pdf(test_results, filename):
146
 
147
  # Add title
148
  flowables.append(Paragraph("Health Report", title_style))
 
149
 
150
- # Add test results to the report
151
  for label, value in test_results.items():
152
- line = f"{label}: {value}"
153
- flowables.append(Paragraph(line, body_style))
154
  flowables.append(Spacer(1, 12))
155
 
156
  # Build the PDF
@@ -159,14 +158,15 @@ def save_results_to_pdf(test_results, filename):
159
  except Exception as e:
160
  return f"Error saving PDF: {str(e)}", None
161
 
162
- # Build health card layout
163
- def build_health_card(profile_image, test_results, summary, patient_name="", patient_age="", patient_gender="", patient_id=""):
 
164
  from datetime import datetime
165
  current_date = datetime.now().strftime("%B %d, %Y")
166
 
 
167
  html = f"""
168
  <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;">
169
-
170
  <div style="background-color: rgba(255, 255, 255, 0.9); border-radius: 12px; padding: 20px; margin-bottom: 25px; border: 1px solid #e0e0e0;">
171
  <div style="display: flex; align-items: center; margin-bottom: 15px;">
172
  <div style="background: linear-gradient(135deg, #64b5f6, #42a5f5); padding: 8px 16px; border-radius: 8px; margin-right: 20px;">
@@ -174,25 +174,18 @@ def build_health_card(profile_image, test_results, summary, patient_name="", pat
174
  </div>
175
  <div style="margin-left: auto; text-align: right; color: #666; font-size: 12px;">
176
  <div>Report Date: {current_date}</div>
177
- {f'<div>Patient ID: {patient_id}</div>' if patient_id else ''}
178
  </div>
179
  </div>
180
  <div style="display: flex; align-items: center;">
181
  <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);">
182
  <div>
183
- <h2 style="margin: 0; font-size: 28px; color: #2c3e50; font-weight: 700;">{patient_name if patient_name else "Lab Test Results"}</h2>
184
- <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>
185
- <p style="margin: 4px 0 0 0; color: #888; font-size: 12px;">Face-Based Health Analysis Report</p>
186
  </div>
187
  </div>
188
  </div>
189
 
190
  <div style="background-color: rgba(255, 255, 255, 0.95); border-radius: 12px; padding: 25px; margin-bottom: 25px; border: 1px solid #e0e0e0;">
191
- {test_results['Hematology']}
192
- {test_results['Iron Panel']}
193
- {test_results['Liver & Kidney']}
194
- {test_results['Electrolytes']}
195
- {test_results['Vitals']}
196
  </div>
197
 
198
  <div style="background-color: rgba(255, 255, 255, 0.95); padding: 20px; border-radius: 12px; border: 1px solid #e0e0e0; margin-bottom: 25px;">
@@ -206,144 +199,19 @@ def build_health_card(profile_image, test_results, summary, patient_name="", pat
206
  <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;">
207
  📥 Download Report
208
  </button>
209
- <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);">
210
- 📞 Find Labs Near Me
211
- </button>
212
  </div>
213
  </div>
214
  """
215
  return html
216
 
217
- # Initialize global variable for patient details
218
- current_patient_details = {'name': '', 'age': '', 'gender': '', 'id': ''}
219
-
220
- # Modified analyze_face function
221
- def analyze_face(input_data):
222
- if isinstance(input_data, str): # Video input (file path in Replit)
223
- cap = cv2.VideoCapture(input_data)
224
- if not cap.isOpened():
225
- return "<div style='color:red;'>⚠️ Error: Could not open video.</div>", None
226
- ret, frame = cap.read()
227
- cap.release()
228
- if not ret:
229
- return "<div style='color:red;'>⚠️ Error: Could not read video frame.</div>", None
230
- else: # Image input
231
- frame = input_data
232
- if frame is None:
233
- return "<div style='color:red;'>⚠️ Error: No image provided.</div>", None
234
-
235
- # Resize image to reduce processing time
236
- frame = cv2.resize(frame, (640, 480)) # Adjust resolution for Replit
237
- frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
238
- result = face_mesh.process(frame_rgb)
239
- if not result.multi_face_landmarks:
240
- return "<div style='color:red;'>⚠️ Error: Face not detected.</div>", None
241
- landmarks = result.multi_face_landmarks[0].landmark # Fixed: Use integer index
242
- features = extract_features(frame_rgb, landmarks)
243
- test_values = {}
244
- r2_scores = {}
245
-
246
- for label in models:
247
- if label == "Hemoglobin":
248
- prediction = models[label].predict([features])[0]
249
- test_values[label] = prediction
250
- r2_scores[label] = 0.385
251
- else:
252
- value = models[label].predict([[random.uniform(0.2, 0.5) for _ in range(7)]])[0]
253
- test_values[label] = value
254
- r2_scores[label] = 0.0
255
-
256
- gray = cv2.cvtColor(frame_rgb, cv2.COLOR_RGB2GRAY)
257
- green_std = np.std(frame_rgb[:, :, 1]) / 255
258
- brightness_std = np.std(gray) / 255
259
- tone_index = np.mean(frame_rgb[100:150, 100:150]) / 255 if frame_rgb[
260
- 100:150, 100:150].size else 0.5
261
- hr_features = [brightness_std, green_std, tone_index]
262
- heart_rate = float(np.clip(hr_model.predict([hr_features])[0], 60, 100))
263
- skin_patch = frame_rgb[100:150, 100:150]
264
- skin_tone_index = np.mean(skin_patch) / 255 if skin_patch.size else 0.5
265
- brightness_variation = np.std(cv2.cvtColor(frame_rgb,
266
- cv2.COLOR_RGB2GRAY)) / 255
267
- spo2_features = [heart_rate, brightness_variation, skin_tone_index]
268
- spo2 = spo2_model.predict([spo2_features])[0]
269
- rr = int(12 + abs(heart_rate % 5 - 2))
270
-
271
- test_results = {
272
- "Hematology":
273
- build_table("🩸 Hematology",
274
- [("Hemoglobin", test_values["Hemoglobin"], (13.5, 17.5)),
275
- ("WBC Count", test_values["WBC Count"], (4.0, 11.0)),
276
- ("Platelet Count", test_values["Platelet Count"],
277
- (150, 450))]),
278
- "Iron Panel":
279
- build_table("🧬 Iron Panel",
280
- [("Iron", test_values["Iron"], (60, 170)),
281
- ("Ferritin", test_values["Ferritin"], (30, 300)),
282
- ("TIBC", test_values["TIBC"], (250, 400))]),
283
- "Liver & Kidney":
284
- build_table("🧬 Liver & Kidney",
285
- [("Bilirubin", test_values["Bilirubin"], (0.3, 1.2)),
286
- ("Creatinine", test_values["Creatinine"], (0.6, 1.2)),
287
- ("Urea", test_values["Urea"], (7, 20))]),
288
- "Electrolytes":
289
- build_table("🧪 Electrolytes",
290
- [("Sodium", test_values["Sodium"], (135, 145)),
291
- ("Potassium", test_values["Potassium"], (3.5, 5.1))]),
292
- "Vitals":
293
- build_table("❤️ Vitals",
294
- [("SpO2", spo2, (95, 100)),
295
- ("Heart Rate", heart_rate, (60, 100)),
296
- ("Respiratory Rate", rr, (12, 20)),
297
- ("Temperature", test_values["Temperature"], (97, 99)),
298
- ("BP Systolic", test_values["BP Systolic"], (90, 120)),
299
- ("BP Diastolic", test_values["BP Diastolic"], (60, 80))])
300
- }
301
-
302
- summary = "<ul><li>Your hemoglobin is a bit low — this could mean mild anemia.</li><li>Low iron storage detected — consider an iron profile test.</li><li>Elevated bilirubin — possible jaundice. Recommend LFT.</li><li>High HbA1c — prediabetes indication. Recommend glucose check.</li><li>Low SpO₂ — suggest retesting with a pulse oximeter.</li></ul>"
303
-
304
- _, buffer = cv2.imencode('.png', frame_rgb)
305
- profile_image_base64 = base64.b64encode(buffer).decode('utf-8')
306
-
307
- # Use global patient details
308
- global current_patient_details
309
- health_card_html = build_health_card(
310
- profile_image_base64,
311
- test_results,
312
- summary,
313
- current_patient_details['name'],
314
- current_patient_details['age'],
315
- current_patient_details['gender'],
316
- current_patient_details['id']
317
- )
318
-
319
- # Generate PDF and return for download
320
- pdf_filename = f"Health_Report_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.pdf"
321
- pdf_result, pdf_filepath = save_results_to_pdf(test_results, pdf_filename)
322
-
323
- if pdf_filepath:
324
- # Copy the PDF to a temporary directory for Gradio to serve it
325
- temp_pdf_path = "/tmp/" + os.path.basename(pdf_filepath)
326
- shutil.copy(pdf_filepath, temp_pdf_path)
327
-
328
- return health_card_html, temp_pdf_path
329
-
330
-
331
- # Modified route_inputs function
332
  def route_inputs(mode, image, video, patient_name, patient_age, patient_gender, patient_id):
333
  if mode == "Image" and image is None:
334
  return "<div style='color:red;'>⚠️ Error: No image provided.</div>", None
335
  if mode == "Video" and video is None:
336
  return "<div style='color:red;'>⚠️ Error: No video provided.</div>", None
337
-
338
- # Store patient details globally for use in analyze_face
339
- global current_patient_details
340
- current_patient_details = {
341
- 'name': patient_name,
342
- 'age': patient_age,
343
- 'gender': patient_gender,
344
- 'id': patient_id
345
- }
346
-
347
  health_card_html, pdf_file_path = analyze_face(image if mode == "Image" else video)
348
  return health_card_html, pdf_file_path
349
 
@@ -360,20 +228,15 @@ with gr.Blocks() as demo:
360
  patient_id = gr.Textbox(label="Patient ID", placeholder="Enter patient ID (optional)")
361
 
362
  gr.Markdown("### Image/Video Input")
363
- mode_selector = gr.Radio(label="Choose Input Mode",
364
- choices=["Image", "Video"],
365
- value="Image")
366
  image_input = gr.Image(type="numpy", label="📸 Upload Face Image")
367
- video_input = gr.Video(label="Upload Face Video",
368
- sources=["upload", "webcam"])
369
  submit_btn = gr.Button("🔍 Analyze")
370
  with gr.Column():
371
  result_html = gr.HTML(label="🧪 Health Report Table")
372
  result_pdf = gr.File(label="Download Health Report PDF", interactive=False)
373
 
374
- submit_btn.click(fn=route_inputs,
375
- inputs=[mode_selector, image_input, video_input, patient_name, patient_age, patient_gender, patient_id],
376
- outputs=[result_html, result_pdf])
377
 
378
- # Launch Gradio for Replit
379
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
47
  model = LinearRegression().fit(X, y)
48
  return model
49
 
 
50
  # Load models
51
  try:
52
  hemoglobin_model = joblib.load("hemoglobin_model_from_anemia_dataset.pkl")
 
114
  html += '</tbody></table></div>'
115
  return html
116
 
117
+ # Function to save the health report to PDF (showing only the Health Card section)
118
  def save_results_to_pdf(test_results, filename):
119
  try:
120
  # Create a PDF document
 
145
 
146
  # Add title
147
  flowables.append(Paragraph("Health Report", title_style))
148
+ flowables.append(Spacer(1, 12))
149
 
150
+ # Only add the health card content here
151
  for label, value in test_results.items():
152
+ flowables.append(Paragraph(value, body_style))
 
153
  flowables.append(Spacer(1, 12))
154
 
155
  # Build the PDF
 
158
  except Exception as e:
159
  return f"Error saving PDF: {str(e)}", None
160
 
161
+
162
+ # Function for Health Card Output (removes patient details)
163
+ def build_health_card(profile_image, test_results, summary):
164
  from datetime import datetime
165
  current_date = datetime.now().strftime("%B %d, %Y")
166
 
167
+ # Build the Health Card HTML
168
  html = f"""
169
  <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;">
 
170
  <div style="background-color: rgba(255, 255, 255, 0.9); border-radius: 12px; padding: 20px; margin-bottom: 25px; border: 1px solid #e0e0e0;">
171
  <div style="display: flex; align-items: center; margin-bottom: 15px;">
172
  <div style="background: linear-gradient(135deg, #64b5f6, #42a5f5); padding: 8px 16px; border-radius: 8px; margin-right: 20px;">
 
174
  </div>
175
  <div style="margin-left: auto; text-align: right; color: #666; font-size: 12px;">
176
  <div>Report Date: {current_date}</div>
 
177
  </div>
178
  </div>
179
  <div style="display: flex; align-items: center;">
180
  <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);">
181
  <div>
182
+ <h2 style="margin: 0; font-size: 28px; color: #2c3e50; font-weight: 700;">Face-Based Health Analysis Report</h2>
 
 
183
  </div>
184
  </div>
185
  </div>
186
 
187
  <div style="background-color: rgba(255, 255, 255, 0.95); border-radius: 12px; padding: 25px; margin-bottom: 25px; border: 1px solid #e0e0e0;">
188
+ {test_results}
 
 
 
 
189
  </div>
190
 
191
  <div style="background-color: rgba(255, 255, 255, 0.95); padding: 20px; border-radius: 12px; border: 1px solid #e0e0e0; margin-bottom: 25px;">
 
199
  <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;">
200
  📥 Download Report
201
  </button>
 
 
 
202
  </div>
203
  </div>
204
  """
205
  return html
206
 
207
+ # Define the Gradio interface
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  def route_inputs(mode, image, video, patient_name, patient_age, patient_gender, patient_id):
209
  if mode == "Image" and image is None:
210
  return "<div style='color:red;'>⚠️ Error: No image provided.</div>", None
211
  if mode == "Video" and video is None:
212
  return "<div style='color:red;'>⚠️ Error: No video provided.</div>", None
213
+
214
+ # Process the inputs for analysis
 
 
 
 
 
 
 
 
215
  health_card_html, pdf_file_path = analyze_face(image if mode == "Image" else video)
216
  return health_card_html, pdf_file_path
217
 
 
228
  patient_id = gr.Textbox(label="Patient ID", placeholder="Enter patient ID (optional)")
229
 
230
  gr.Markdown("### Image/Video Input")
231
+ mode_selector = gr.Radio(label="Choose Input Mode", choices=["Image", "Video"], value="Image")
 
 
232
  image_input = gr.Image(type="numpy", label="📸 Upload Face Image")
233
+ video_input = gr.Video(label="Upload Face Video", sources=["upload", "webcam"])
 
234
  submit_btn = gr.Button("🔍 Analyze")
235
  with gr.Column():
236
  result_html = gr.HTML(label="🧪 Health Report Table")
237
  result_pdf = gr.File(label="Download Health Report PDF", interactive=False)
238
 
239
+ submit_btn.click(fn=route_inputs, inputs=[mode_selector, image_input, video_input, patient_name, patient_age, patient_gender, patient_id], outputs=[result_html, result_pdf])
 
 
240
 
241
+ # Launch Gradio interface
242
  demo.launch(server_name="0.0.0.0", server_port=7860)