Spaces:
Running
Running
Upload app.py with huggingface_hub
Browse files
app.py
CHANGED
|
@@ -36,6 +36,7 @@ except ImportError:
|
|
| 36 |
from models import EmotionLabel, EMOTION_LABELS, CulturalRegion, EMOTION_EMOJI
|
| 37 |
from face_detector import FaceEmotionDetector
|
| 38 |
from text_detector import TextEmotionDetector
|
|
|
|
| 39 |
from auth import (
|
| 40 |
validate_email,
|
| 41 |
is_email_used,
|
|
@@ -268,6 +269,12 @@ def load_text_detector():
|
|
| 268 |
det.load()
|
| 269 |
return det
|
| 270 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 271 |
|
| 272 |
# =====================================================================
|
| 273 |
# Helper: Render Functions
|
|
@@ -564,13 +571,14 @@ def show_demo():
|
|
| 564 |
)
|
| 565 |
|
| 566 |
st.markdown("# EMOSPHERE")
|
| 567 |
-
st.markdown("*Real-time multimodal emotion detection -- face &
|
| 568 |
|
| 569 |
face_det = load_face_detector()
|
| 570 |
text_det = load_text_detector()
|
|
|
|
| 571 |
|
| 572 |
-
tab_camera, tab_text, tab_history = st.tabs([
|
| 573 |
-
"Camera / Image", "Text Analysis", "History",
|
| 574 |
])
|
| 575 |
|
| 576 |
# -- Camera / Image Tab --
|
|
@@ -721,6 +729,91 @@ def show_demo():
|
|
| 721 |
"text": text_input[:100],
|
| 722 |
})
|
| 723 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 724 |
# -- History Tab --
|
| 725 |
with tab_history:
|
| 726 |
st.markdown("### Emotion History")
|
|
@@ -754,7 +847,7 @@ def show_demo():
|
|
| 754 |
for h in reversed(history[-10:]):
|
| 755 |
emo = EMOTION_EMOJI.get(EmotionLabel(h["dominant"]), "")
|
| 756 |
color = EMOTION_COLORS.get(EmotionLabel(h["dominant"]), "#94A3B8")
|
| 757 |
-
modality_icon = {"face": "📷", "text": "💬"}.get(
|
| 758 |
h["modality"], "🔮"
|
| 759 |
)
|
| 760 |
snippet = ""
|
|
|
|
| 36 |
from models import EmotionLabel, EMOTION_LABELS, CulturalRegion, EMOTION_EMOJI
|
| 37 |
from face_detector import FaceEmotionDetector
|
| 38 |
from text_detector import TextEmotionDetector
|
| 39 |
+
from posture_detector import PostureEmotionDetector
|
| 40 |
from auth import (
|
| 41 |
validate_email,
|
| 42 |
is_email_used,
|
|
|
|
| 269 |
det.load()
|
| 270 |
return det
|
| 271 |
|
| 272 |
+
@st.cache_resource
|
| 273 |
+
def load_posture_detector():
|
| 274 |
+
det = PostureEmotionDetector()
|
| 275 |
+
det.load()
|
| 276 |
+
return det
|
| 277 |
+
|
| 278 |
|
| 279 |
# =====================================================================
|
| 280 |
# Helper: Render Functions
|
|
|
|
| 571 |
)
|
| 572 |
|
| 573 |
st.markdown("# EMOSPHERE")
|
| 574 |
+
st.markdown("*Real-time multimodal emotion detection -- face, text, posture & gesture*")
|
| 575 |
|
| 576 |
face_det = load_face_detector()
|
| 577 |
text_det = load_text_detector()
|
| 578 |
+
posture_det = load_posture_detector()
|
| 579 |
|
| 580 |
+
tab_camera, tab_text, tab_posture, tab_history = st.tabs([
|
| 581 |
+
"Camera / Image", "Text Analysis", "Posture & Gesture", "History",
|
| 582 |
])
|
| 583 |
|
| 584 |
# -- Camera / Image Tab --
|
|
|
|
| 729 |
"text": text_input[:100],
|
| 730 |
})
|
| 731 |
|
| 732 |
+
# -- Posture & Gesture Tab --
|
| 733 |
+
with tab_posture:
|
| 734 |
+
st.markdown("### Posture & Gesture Emotion Detection")
|
| 735 |
+
st.markdown(
|
| 736 |
+
'<p style="color: #6B7B9D; font-size: 13px;">'
|
| 737 |
+
'Upload a full-body or upper-body image to analyze emotional cues from posture, '
|
| 738 |
+
'gestures, arm position, shoulder tension, and body language.</p>',
|
| 739 |
+
unsafe_allow_html=True,
|
| 740 |
+
)
|
| 741 |
+
|
| 742 |
+
col_posture_in, col_posture_out = st.columns([1, 1])
|
| 743 |
+
|
| 744 |
+
with col_posture_in:
|
| 745 |
+
posture_method = st.radio(
|
| 746 |
+
"Input method",
|
| 747 |
+
["Upload Image", "Webcam Snapshot"],
|
| 748 |
+
horizontal=True,
|
| 749 |
+
key="posture_method",
|
| 750 |
+
)
|
| 751 |
+
|
| 752 |
+
posture_data = None
|
| 753 |
+
|
| 754 |
+
if posture_method == "Upload Image":
|
| 755 |
+
posture_uploaded = st.file_uploader(
|
| 756 |
+
"Upload a body image",
|
| 757 |
+
type=["jpg", "jpeg", "png", "webp"],
|
| 758 |
+
key="posture_upload",
|
| 759 |
+
)
|
| 760 |
+
if posture_uploaded:
|
| 761 |
+
posture_data = posture_uploaded.read()
|
| 762 |
+
st.image(posture_data, caption="Uploaded image", use_container_width=True)
|
| 763 |
+
else:
|
| 764 |
+
posture_photo = st.camera_input("Take a photo", key="posture_cam")
|
| 765 |
+
if posture_photo:
|
| 766 |
+
posture_data = posture_photo.read()
|
| 767 |
+
|
| 768 |
+
with col_posture_out:
|
| 769 |
+
if posture_data:
|
| 770 |
+
if is_trial_expired(start):
|
| 771 |
+
st.session_state.auth_stage = "ended"
|
| 772 |
+
st.rerun()
|
| 773 |
+
return
|
| 774 |
+
|
| 775 |
+
with st.spinner("Analyzing posture & gestures..."):
|
| 776 |
+
posture_result = posture_det.detect(
|
| 777 |
+
posture_data,
|
| 778 |
+
CulturalRegion(cultural_region),
|
| 779 |
+
)
|
| 780 |
+
|
| 781 |
+
render_emotion_bubble(posture_result.dominant, posture_result.dominant_score)
|
| 782 |
+
st.markdown(
|
| 783 |
+
'<div class="glass-card">'
|
| 784 |
+
'<div style="color: #6B7B9D; font-size: 12px;">'
|
| 785 |
+
'Processed in {:.0f}ms'
|
| 786 |
+
' • Confidence: {:.1f}%'
|
| 787 |
+
' • Cultural: {}'
|
| 788 |
+
'</div></div>'.format(
|
| 789 |
+
posture_result.processing_time_ms,
|
| 790 |
+
posture_result.confidence * 100,
|
| 791 |
+
CULTURAL_OPTIONS.get(cultural_region, "Universal"),
|
| 792 |
+
),
|
| 793 |
+
unsafe_allow_html=True,
|
| 794 |
+
)
|
| 795 |
+
|
| 796 |
+
p_scores = {s.label: s.score for s in posture_result.scores}
|
| 797 |
+
render_emotion_bars(p_scores)
|
| 798 |
+
|
| 799 |
+
st.session_state.history.append({
|
| 800 |
+
"time": datetime.now(),
|
| 801 |
+
"modality": "posture",
|
| 802 |
+
"dominant": posture_result.dominant.value,
|
| 803 |
+
"score": posture_result.dominant_score,
|
| 804 |
+
"scores": p_scores,
|
| 805 |
+
})
|
| 806 |
+
else:
|
| 807 |
+
st.markdown(
|
| 808 |
+
'<div class="glass-card" style="text-align: center; padding: 40px;">'
|
| 809 |
+
'<span style="font-size: 48px;">🧙</span>'
|
| 810 |
+
'<p style="color: #6B7B9D; margin-top: 12px;">'
|
| 811 |
+
'Upload a body image or take a webcam snapshot<br/>'
|
| 812 |
+
'to detect emotions from posture & gestures'
|
| 813 |
+
'</p></div>',
|
| 814 |
+
unsafe_allow_html=True,
|
| 815 |
+
)
|
| 816 |
+
|
| 817 |
# -- History Tab --
|
| 818 |
with tab_history:
|
| 819 |
st.markdown("### Emotion History")
|
|
|
|
| 847 |
for h in reversed(history[-10:]):
|
| 848 |
emo = EMOTION_EMOJI.get(EmotionLabel(h["dominant"]), "")
|
| 849 |
color = EMOTION_COLORS.get(EmotionLabel(h["dominant"]), "#94A3B8")
|
| 850 |
+
modality_icon = {"face": "📷", "text": "💬", "posture": "🧙"}.get(
|
| 851 |
h["modality"], "🔮"
|
| 852 |
)
|
| 853 |
snippet = ""
|