Spaces:
Running
Running
| import numpy as np | |
| import gradio as gr | |
| from tensorflow.keras.models import load_model, Model | |
| from hpelm import ELM | |
| import joblib | |
| # ๐ Load scaler and ELM model | |
| scaler = joblib.load("elm_scaler1.pkl") | |
| elm = ELM(128, 1, classification='c') | |
| elm.load("elm_model1.txt") | |
| # โ๏ธ Load trained MobileNet1D and create feature extractor | |
| mobilenet = load_model("physio_model2.h5") | |
| feature_extractor = Model(inputs=mobilenet.input, outputs=mobilenet.get_layer("penultimate_dense").output) | |
| def preprocess_signal(ecg, eda, temp): | |
| """ | |
| Combines input arrays into 3-channel format expected by MobileNet1D. | |
| All signals must be of same length (e.g., 1280). | |
| """ | |
| ecg = np.array(ecg).reshape(-1, 1) | |
| eda = np.array(eda).reshape(-1, 1) | |
| temp = np.array(temp).reshape(-1, 1) | |
| return np.concatenate([ecg, eda, temp], axis=1) | |
| def predict_stress(ecg, eda, temp): | |
| try: | |
| # ๐ฆ Preprocessing | |
| signal = preprocess_signal(ecg, eda, temp) # Shape: (1280, 3) | |
| signal = signal.reshape(1, 1280, 3) | |
| # ๐ Feature Extraction | |
| features = feature_extractor.predict(signal) | |
| # ๐ Scaling for ELM | |
| features_scaled = scaler.transform(features) | |
| # ๐ฎ ELM Inference | |
| raw_pred = elm.predict(features_scaled) | |
| raw_pred = np.clip(raw_pred, -20, 20) | |
| prob = 1 / (1 + np.exp(-raw_pred)) | |
| label = "Stress" if prob > 0.5 else "No Stress" | |
| return f"{label} (Confidence: {prob[0][0]:.2f})" | |
| except Exception as e: | |
| return f"โ Error: {str(e)}" | |
| # ๐งช Gradio demo interface | |
| inputs = [ | |
| gr.Textbox(label="ECG Signal (comma-separated)", lines=2, placeholder="e.g. 0.1,0.12,...,0.13"), | |
| gr.Textbox(label="EDA Signal (comma-separated)", lines=2, placeholder="e.g. 0.2,0.18,...,0.15"), | |
| gr.Textbox(label="Temperature Signal (comma-separated)", lines=2, placeholder="e.g. 32.1,32.2,...,32.5") | |
| ] | |
| def parse_and_predict(ecg_str, eda_str, temp_str): | |
| try: | |
| ecg = list(map(float, ecg_str.strip().split(','))) | |
| eda = list(map(float, eda_str.strip().split(','))) | |
| temp = list(map(float, temp_str.strip().split(','))) | |
| if len(ecg) != 1280 or len(eda) != 1280 or len(temp) != 1280: | |
| return "โ Each signal must be exactly 1280 samples long." | |
| return predict_stress(ecg, eda, temp) | |
| except: | |
| return "โ Invalid input format. Use comma-separated values only." | |
| demo = gr.Interface(fn=parse_and_predict, inputs=inputs, outputs="text", title="Stress Detection via Physio Signals", | |
| description="Upload ECG, EDA, and Temperature signals (1280 samples each) to detect stress using MobileNet1D + ELM") | |
| # ๐ Run app | |
| if __name__ == "__main__": | |
| demo.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| share=True, | |
| show_api=True | |
| ) |