srivatsavdamaraju commited on
Commit
41802ba
verified
1 Parent(s): 904d13a

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +125 -0
app.py ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import cv2
3
+ import os
4
+ import uuid
5
+ import mediapipe as mp
6
+ import pandas as pd
7
+ import threading
8
+ import time
9
+
10
+ # Setup
11
+ OUTPUT_DIR = "captured_frames"
12
+ os.makedirs(OUTPUT_DIR, exist_ok=True)
13
+ df = pd.DataFrame(columns=["filename", "caption", "pose_coords"])
14
+
15
+ pose = mp.solutions.pose.Pose()
16
+ state = {
17
+ "video_path": None,
18
+ "cap": None,
19
+ "frame": None,
20
+ "play": False,
21
+ "thread": None
22
+ }
23
+
24
+ def load_video(video_file):
25
+ if state["cap"]:
26
+ state["cap"].release()
27
+ state["video_path"] = video_file.name
28
+ state["cap"] = cv2.VideoCapture(state["video_path"])
29
+ state["play"] = False
30
+ return "Video loaded. Use play/pause to navigate."
31
+
32
+ def play_video():
33
+ def play():
34
+ while state["cap"].isOpened() and state["play"]:
35
+ ret, frame = state["cap"].read()
36
+ if not ret:
37
+ break
38
+ state["frame"] = frame
39
+ time.sleep(0.1) # ~10 FPS
40
+
41
+ state["play"] = True
42
+ state["thread"] = threading.Thread(target=play)
43
+ state["thread"].start()
44
+ return "Playing video..."
45
+
46
+ def pause_video():
47
+ state["play"] = False
48
+ return "Video paused."
49
+
50
+ def show_frame():
51
+ if state["frame"] is not None:
52
+ return state["frame"][:, :, ::-1] # BGR to RGB
53
+ return None
54
+
55
+ def capture_frame(caption):
56
+ if state["frame"] is None:
57
+ return "No frame to capture.", None
58
+
59
+ frame = state["frame"]
60
+ filename = f"{uuid.uuid4().hex[:8]}.jpg"
61
+ path = os.path.join(OUTPUT_DIR, filename)
62
+ cv2.imwrite(path, frame)
63
+
64
+ frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
65
+ results = pose.process(frame_rgb)
66
+
67
+ coords = []
68
+ if results.pose_landmarks:
69
+ for lm in results.pose_landmarks.landmark:
70
+ coords.append((round(lm.x, 5), round(lm.y, 5), round(lm.z, 5)))
71
+
72
+ global df
73
+ df = pd.concat([df, pd.DataFrame([{
74
+ "filename": filename,
75
+ "caption": caption,
76
+ "pose_coords": coords
77
+ }])], ignore_index=True)
78
+
79
+ return f"Frame captured: {filename}", frame[:, :, ::-1]
80
+
81
+ def download_csv():
82
+ csv_path = os.path.join(OUTPUT_DIR, "pose_dataset.csv")
83
+ df.to_csv(csv_path, index=False)
84
+ return csv_path
85
+
86
+ def reset_all():
87
+ df.drop(df.index, inplace=True)
88
+ for f in os.listdir(OUTPUT_DIR):
89
+ os.remove(os.path.join(OUTPUT_DIR, f))
90
+ if state["cap"]:
91
+ state["cap"].release()
92
+ state.update({"video_path": None, "cap": None, "frame": None, "play": False})
93
+ return "App reset.", None
94
+
95
+ with gr.Blocks() as app:
96
+ gr.Markdown("## 馃徆 Archery Dataset Tool (Play, Pause, Pose + Annotation)")
97
+
98
+ video_input = gr.Video(label="Upload Video")
99
+ load_btn = gr.Button("Load Video")
100
+
101
+ with gr.Row():
102
+ play_btn = gr.Button("鈻讹笍 Play")
103
+ pause_btn = gr.Button("鈴革笍 Pause")
104
+ show_btn = gr.Button("馃攣 Show Current Frame")
105
+
106
+ image_box = gr.Image(label="Current Frame")
107
+ caption_input = gr.Textbox(label="Caption")
108
+ capture_btn = gr.Button("馃摳 Capture & Annotate Frame")
109
+
110
+ download_btn = gr.Button("馃摜 Download CSV")
111
+ csv_file = gr.File(label="Pose Dataset CSV")
112
+
113
+ reset_btn = gr.Button("馃攧 Reset")
114
+ status = gr.Textbox(label="Status")
115
+
116
+ # Event handlers
117
+ load_btn.click(load_video, inputs=video_input, outputs=status)
118
+ play_btn.click(play_video, outputs=status)
119
+ pause_btn.click(pause_video, outputs=status)
120
+ show_btn.click(show_frame, outputs=image_box)
121
+ capture_btn.click(capture_frame, inputs=caption_input, outputs=[status, image_box])
122
+ download_btn.click(download_csv, outputs=csv_file)
123
+ reset_btn.click(reset_all, outputs=[status, image_box])
124
+
125
+ app.launch()