File size: 5,145 Bytes
eb3d3f0
9ff4823
eb3d3f0
0983def
eb3d3f0
 
 
 
 
0983def
eb3d3f0
 
 
 
 
 
 
 
 
7e2c1f5
eb3d3f0
 
 
 
 
 
 
7e2c1f5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0983def
 
2306344
eb3d3f0
0983def
 
eb3d3f0
2306344
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e1711af
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9ff4823
e1711af
 
9ff4823
2306344
 
 
 
 
 
 
 
eb3d3f0
0983def
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# Face Detection-Based AI Automation of Lab Tests
# Gradio App - Stable Deployment Version for Hugging Face

import gradio as gr
import cv2
import numpy as np
import mediapipe as mp

mp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh(static_image_mode=True, max_num_faces=1, refine_landmarks=True, min_detection_confidence=0.5)

def estimate_heart_rate(frame, landmarks):
    h, w, _ = frame.shape
    forehead_pts = [landmarks[10], landmarks[338], landmarks[297], landmarks[332]]
    mask = np.zeros((h, w), dtype=np.uint8)
    pts = np.array([[int(pt.x * w), int(pt.y * h)] for pt in forehead_pts], np.int32)
    cv2.fillConvexPoly(mask, pts, 255)
    green_channel = cv2.split(frame)[1]
    mean_intensity = cv2.mean(green_channel, mask=mask)[0]
    heart_rate = int(60 + 30 * np.sin(mean_intensity / 255.0 * np.pi))
    return heart_rate

def estimate_spo2_rr(heart_rate):
    spo2 = min(100, max(90, 97 + (heart_rate % 5 - 2)))
    rr = int(12 + abs(heart_rate % 5 - 2))
    return spo2, rr

def get_risk_color(value, normal_range):
    low, high = normal_range
    if value < low:
        return "🔻 LOW"
    elif value > high:
        return "🔺 HIGH"
    else:
        return "✅ Normal"

def generate_flags_extended(params):
    hb, wbc, platelets, iron, ferritin, tibc, bilirubin, creatinine, tsh, cortisol, fbs, hba1c = params
    flags = []
    if hb < 13.5:
        flags.append("Hemoglobin Low - Possible Anemia")
    if wbc < 4.0 or wbc > 11.0:
        flags.append("Abnormal WBC Count - Possible Infection")
    if platelets < 150:
        flags.append("Platelet Drop Risk - Bruising Possible")
    if iron < 60:
        flags.append("Iron Deficiency Detected")
    if ferritin < 30:
        flags.append("Low Ferritin - Iron Store Low")
    if tibc > 400:
        flags.append("High TIBC - Iron Absorption Issue")
    if bilirubin > 1.2:
        flags.append("Jaundice Detected - Elevated Bilirubin")
    if creatinine > 1.2:
        flags.append("Kidney Function Concern - High Creatinine")
    if tsh < 0.4 or tsh > 4.0:
        flags.append("Thyroid Imbalance - Check TSH")
    if cortisol < 5 or cortisol > 25:
        flags.append("Stress Hormone Abnormality - Cortisol")
    if fbs > 110:
        flags.append("High Fasting Blood Sugar")
    if hba1c > 5.7:
        flags.append("Elevated HbA1c - Diabetes Risk")
    flags.append("Mood / Stress analysis requires separate behavioral model")
    return flags

def analyze_face(image):
    if image is None:
        return "⚠️ Error: No image provided.", None

    frame_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    result = face_mesh.process(frame_rgb)

    if not result.multi_face_landmarks:
        return "⚠️ Error: Face not detected.", None

    landmarks = result.multi_face_landmarks[0].landmark
    heart_rate = estimate_heart_rate(frame_rgb, landmarks)
    spo2, rr = estimate_spo2_rr(heart_rate)

    hb, wbc, platelets = 12.3, 6.4, 210
    iron, ferritin, tibc = 55, 45, 340
    bilirubin, creatinine = 1.5, 1.3
    tsh, cortisol = 2.5, 18
    fbs, hba1c = 120, 6.2

    flags = generate_flags_extended([hb, wbc, platelets, iron, ferritin, tibc, bilirubin, creatinine, tsh, cortisol, fbs, hba1c])

    report_lines = [
        "### 🩸 Hematology",
        f"- Hemoglobin (Hb): {hb} g/dL - {get_risk_color(hb, (13.5, 17.5))}",
        f"- WBC Count: {wbc} x10^3/uL - {get_risk_color(wbc, (4.0, 11.0))}",
        f"- Platelet Count: {platelets} x10^3/uL - {get_risk_color(platelets, (150, 450))}",

        "### 🧬 Iron & Liver Panel",
        f"- Iron: {iron} µg/dL - {get_risk_color(iron, (60, 170))}",
        f"- Ferritin: {ferritin} ng/mL - {get_risk_color(ferritin, (30, 300))}",
        f"- TIBC: {tibc} µg/dL - {get_risk_color(tibc, (250, 400))}",
        f"- Bilirubin: {bilirubin} mg/dL - {get_risk_color(bilirubin, (0.3, 1.2))}",

        "### 🧪 Kidney, Thyroid & Stress",
        f"- Creatinine: {creatinine} mg/dL - {get_risk_color(creatinine, (0.6, 1.2))}",
        f"- TSH: {tsh} µIU/mL - {get_risk_color(tsh, (0.4, 4.0))}",
        f"- Cortisol: {cortisol} µg/dL - {get_risk_color(cortisol, (5, 25))}",

        "### 🧁 Metabolic Panel",
        f"- Fasting Blood Sugar: {fbs} mg/dL - {get_risk_color(fbs, (70, 110))}",
        f"- HbA1c: {hba1c}% - {get_risk_color(hba1c, (4.0, 5.7))}",

        "### ❤️ Vital Signs",
        f"- SpO2: {spo2}% - {get_risk_color(spo2, (95, 100))}",
        f"- Heart Rate: {heart_rate} bpm - {get_risk_color(heart_rate, (60, 100))}",
        f"- Respiratory Rate: {rr} breaths/min - {get_risk_color(rr, (12, 20))}",
        "- Blood Pressure: Low (simulated)",

        "### ⚠️ Risk Flags"
    ] + [f"- {flag}" for flag in flags]

    return "\n".join(report_lines), frame_rgb

demo = gr.Interface(
    fn=analyze_face,
    inputs=gr.Image(type="numpy", label="📸 Upload Face Image"),
    outputs=[gr.Markdown(label="🧪 Diagnostic Report"), gr.Image(label="🧍 Annotated Face")],
    title="Face-Based AI Lab Test Inference",
    description="Upload a clear face image to get lab test estimates and vital signs via facial analysis."
)

demo.launch()