File size: 2,925 Bytes
8531834
 
 
 
 
 
 
9c49404
8531834
9c49404
8531834
 
 
9c49404
8531834
 
 
 
 
0d35d61
 
 
 
 
2a29151
 
 
0d35d61
2a29151
 
 
 
 
8531834
 
0d35d61
8531834
 
 
2a29151
0d35d61
2a29151
 
 
 
 
 
 
 
 
8531834
0d35d61
2a29151
 
 
 
 
 
 
 
 
 
 
 
 
 
8531834
0d35d61
2a29151
 
 
0d35d61
9c49404
8531834
 
0d35d61
8531834
 
0d35d61
8531834
 
 
 
 
 
2a29151
0d35d61
 
 
2a29151
8531834
 
9c49404
0d35d61
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
import joblib
import cv2
import numpy as np
import mediapipe as mp
import gradio as gr
import matplotlib.pyplot as plt
import io
from PIL import Image

# ๋ชจ๋ธ ๋กœ๋“œ
model = joblib.load("image_model.pkl")
action_labels = {0: "Weightlifting", 1: "Soccer", 2: "Handball"}

# MediaPipe ์„ค์ •
mp_pose = mp.solutions.pose
pose = mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.5)
mp_drawing = mp.solutions.drawing_utils

def process_frame(frame):
    # 1. None ์ฒดํฌ
    if frame is None:
        return None, "Error: No image received from camera", None

    # 2. PIL.Image โ†’ numpy ๋ณ€ํ™˜
    if isinstance(frame, Image.Image):
        frame = np.array(frame)

    # 3. RGB ๋ณ€ํ™˜ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ
    try:
        image_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    except Exception as e:
        return frame, f"Error converting image: {e}", None

    results = pose.process(image_rgb)

    # ๊ด€์ ˆ ์‹œ๊ฐํ™”
    if results.pose_landmarks:
        mp_drawing.draw_landmarks(frame, results.pose_landmarks, mp_pose.POSE_CONNECTIONS)

    try:
        # ๋ชจ๋ธ ์ž…๋ ฅ ์ „์ฒ˜๋ฆฌ
        resized = cv2.resize(image_rgb, (128, 128))
        input_data = resized.flatten().reshape(1, -1)
        prediction_proba = model.predict_proba(input_data)[0]
        predicted_class = np.argmax(prediction_proba)
        prediction = action_labels.get(predicted_class, "Unknown")
        confidence = prediction_proba[predicted_class] * 100
        label = f'{prediction} ({confidence:.2f}%)'
    except Exception as e:
        return frame, f"Prediction error: {e}", None

    # ์˜ˆ์ธก ๊ทธ๋ž˜ํ”„ ์ƒ์„ฑ
    try:
        fig, ax = plt.subplots()
        ax.bar(action_labels.values(), prediction_proba, color='skyblue')
        ax.set_ylim([0, 1])
        ax.set_ylabel("Confidence")
        ax.set_title("Prediction Probabilities")
        buf = io.BytesIO()
        plt.savefig(buf, format="png")
        buf.seek(0)
        graph_img = Image.open(buf).convert("RGB")
        plt.close()
    except Exception as e:
        graph_img = None
        label += f" (Graph error: {e})"

    # ์˜ˆ์ธก ํ…์ŠคํŠธ ์ด๋ฏธ์ง€์— ํ‘œ์‹œ
    try:
        cv2.putText(frame, label, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0), 2)
    except:
        pass

    return frame, label, graph_img

# Gradio ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌ์„ฑ
demo = gr.Interface(
    fn=process_frame,
    inputs=gr.Image(source="webcam", streaming=False),  # โœ… ์‚ฌ์ง„ ์ดฌ์˜ ๋ฒ„ํŠผ ํ™œ์„ฑํ™”!
    outputs=[
        gr.Image(label="Pose + Prediction"),
        gr.Textbox(label="Predicted Action"),
        gr.Image(label="Confidence Graph")
    ],
    title="Pose Action Classifier",
    description=(
        "๐Ÿ“ฑ On mobile, tap the button to take a photo. "
        "You can switch to the back camera by tapping the camera icon. "
        "Internet Explorer is not supported โ€” use Chrome or Safari."
    )
)

if __name__ == "__main__":
    demo.launch()