Newbyl commited on
Commit
50ba3db
·
1 Parent(s): 7b27a72
Files changed (1) hide show
  1. app.py +275 -0
app.py ADDED
@@ -0,0 +1,275 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+ import random
4
+ import json
5
+ import itertools
6
+ from pathlib import Path
7
+
8
+ # List of methods that already have results
9
+ EXISTING_METHODS = ["Liveportrait", "ControlTalk", "Lia", "Hallo2", "Echomimic", "Dimitra", "Sadtalker", "Wav2Lip"]
10
+
11
+ # List of new methods to compare
12
+ NEW_METHODS = ["First-Order-Motion", "X-Portrait", "MCNET", "EMOPortrait", "DaGAN", "LIA-X", "OmniAvatar", "Real3DPortrait"]
13
+
14
+ # Number of videos per new method to compare
15
+ VIDEOS_PER_NEW_METHOD = 23
16
+
17
+ # File to save results
18
+ RESULTS_FILE = "comparison_results.json"
19
+
20
+ def find_videos_by_method(base_dir):
21
+ """Find all videos in the method folders."""
22
+ videos_by_method = {}
23
+
24
+ # Check each method directory
25
+ for method in EXISTING_METHODS + NEW_METHODS:
26
+ method_dir = os.path.join(base_dir, method)
27
+ if not os.path.exists(method_dir):
28
+ continue
29
+
30
+ videos = []
31
+ # Walk through the directory structure to find all video files
32
+ for root, _, files in os.walk(method_dir):
33
+ for file in files:
34
+ if file.lower().endswith(('.mp4', '.avi', '.mov', '.mkv')):
35
+ videos.append(os.path.join(root, file))
36
+
37
+ if videos:
38
+ videos_by_method[method] = videos
39
+
40
+ return videos_by_method
41
+
42
+ def generate_comparison_pairs(videos_by_method):
43
+ """Generate pairs of videos between new methods and existing methods."""
44
+ pairs = []
45
+
46
+ for new_method in NEW_METHODS:
47
+ if new_method not in videos_by_method:
48
+ continue
49
+
50
+ for existing_method in EXISTING_METHODS:
51
+ if existing_method not in videos_by_method:
52
+ continue
53
+
54
+ # Get video basenames to match videos across methods
55
+ new_method_videos = {os.path.basename(v): v for v in videos_by_method[new_method]}
56
+ existing_method_videos = {os.path.basename(v): v for v in videos_by_method[existing_method]}
57
+
58
+ # Find common videos between the two methods
59
+ common_videos = set(new_method_videos.keys()) & set(existing_method_videos.keys())
60
+
61
+ for video_name in common_videos:
62
+ new_video = new_method_videos[video_name]
63
+ existing_video = existing_method_videos[video_name]
64
+
65
+ # Randomly order the videos (left/right)
66
+ if random.choice([True, False]):
67
+ pairs.append({
68
+ 'left_video': new_video,
69
+ 'right_video': existing_video,
70
+ 'left_method': new_method,
71
+ 'right_method': existing_method,
72
+ 'video_name': video_name
73
+ })
74
+ else:
75
+ pairs.append({
76
+ 'left_video': existing_video,
77
+ 'right_video': new_video,
78
+ 'left_method': existing_method,
79
+ 'right_method': new_method,
80
+ 'video_name': video_name
81
+ })
82
+
83
+ # Shuffle pairs for unbiased comparison
84
+ random.shuffle(pairs)
85
+ return pairs
86
+
87
+ def load_results():
88
+ """Load existing comparison results."""
89
+ if os.path.exists(RESULTS_FILE):
90
+ try:
91
+ with open(RESULTS_FILE, 'r') as f:
92
+ return json.load(f)
93
+ except json.JSONDecodeError:
94
+ pass
95
+ return {"comparisons": [], "count": 0}
96
+
97
+ def save_result(results, comparison_data):
98
+ """Save the comparison result."""
99
+ results["comparisons"].append(comparison_data)
100
+ results["count"] += 1
101
+
102
+ with open(RESULTS_FILE, 'w') as f:
103
+ json.dump(results, f, indent=4)
104
+
105
+ return results
106
+
107
+ def get_total_expected_comparisons():
108
+ """Calculate the total number of comparisons needed."""
109
+ return len(NEW_METHODS) * VIDEOS_PER_NEW_METHOD
110
+
111
+ def create_app(videos_dir):
112
+ """Create the Gradio app for video comparison."""
113
+ # Load existing results if any
114
+ results = load_results()
115
+
116
+ # Find videos in the directory structure
117
+ videos_by_method = find_videos_by_method(videos_dir)
118
+
119
+ # Generate pairs for comparison
120
+ all_pairs = generate_comparison_pairs(videos_by_method)
121
+
122
+ # Calculate the total expected comparisons
123
+ total_expected = get_total_expected_comparisons()
124
+
125
+ # Track the current state
126
+ state = {
127
+ "current_pair_index": 0,
128
+ "results": results,
129
+ "all_pairs": all_pairs,
130
+ "total_expected": total_expected
131
+ }
132
+
133
+ def update_ui_state(state):
134
+ """Update the UI based on current state."""
135
+ if state["results"]["count"] >= state["total_expected"]:
136
+ return {
137
+ "left_video": None,
138
+ "right_video": None,
139
+ "status": f"Completed all {state['total_expected']} comparisons!",
140
+ "left_button_visible": False,
141
+ "right_button_visible": False,
142
+ "done_visible": True,
143
+ "progress": 100
144
+ }
145
+
146
+ if state["current_pair_index"] >= len(state["all_pairs"]):
147
+ return {
148
+ "left_video": None,
149
+ "right_video": None,
150
+ "status": "No more pairs to compare, but target count not reached.",
151
+ "left_button_visible": False,
152
+ "right_button_visible": False,
153
+ "done_visible": True,
154
+ "progress": (state["results"]["count"] / state["total_expected"]) * 100
155
+ }
156
+
157
+ current_pair = state["all_pairs"][state["current_pair_index"]]
158
+ progress_percent = (state["results"]["count"] / state["total_expected"]) * 100
159
+
160
+ return {
161
+ "left_video": current_pair["left_video"],
162
+ "right_video": current_pair["right_video"],
163
+ "status": f"Compare videos: {state['results']['count']}/{state['total_expected']} completed ({progress_percent:.1f}%)",
164
+ "left_button_visible": True,
165
+ "right_button_visible": True,
166
+ "done_visible": False,
167
+ "progress": progress_percent
168
+ }
169
+
170
+ def handle_choice(choice, state):
171
+ """Handle user's choice between videos."""
172
+ if state["results"]["count"] >= state["total_expected"]:
173
+ return state, update_ui_state(state)
174
+
175
+ if state["current_pair_index"] < len(state["all_pairs"]):
176
+ current_pair = state["all_pairs"][state["current_pair_index"]]
177
+
178
+ # Record the comparison result
179
+ comparison_data = {
180
+ "video_name": current_pair["video_name"],
181
+ "choice": choice,
182
+ "left_method": current_pair["left_method"],
183
+ "right_method": current_pair["right_method"],
184
+ "timestamp": str(import_datetime().now())
185
+ }
186
+
187
+ # Update results
188
+ state["results"] = save_result(state["results"], comparison_data)
189
+ state["current_pair_index"] += 1
190
+
191
+ return state, update_ui_state(state)
192
+
193
+ def import_datetime():
194
+ """Import datetime module on demand."""
195
+ import datetime
196
+ return datetime
197
+
198
+ with gr.Blocks() as demo:
199
+ gr.Markdown("# Video Comparison App")
200
+ gr.Markdown("Compare the quality of videos generated by different methods")
201
+
202
+ # State components
203
+ state_data = gr.State(state)
204
+
205
+ # Display components
206
+ with gr.Row():
207
+ with gr.Column():
208
+ left_video = gr.Video(label="Video A")
209
+ left_button = gr.Button("Choose Video A", variant="primary")
210
+ with gr.Column():
211
+ right_video = gr.Video(label="Video B")
212
+ right_button = gr.Button("Choose Video B", variant="primary")
213
+
214
+ progress_bar = gr.Progress()
215
+ status_text = gr.Markdown("")
216
+ done_text = gr.Markdown("All comparisons completed! Thank you for your participation.", visible=False)
217
+
218
+ # Initialize UI with first pair
219
+ ui_state = update_ui_state(state)
220
+ left_video.value = ui_state["left_video"]
221
+ right_video.value = ui_state["right_video"]
222
+ status_text.value = ui_state["status"]
223
+ left_button.visible = ui_state["left_button_visible"]
224
+ right_button.visible = ui_state["right_button_visible"]
225
+ done_text.visible = ui_state["done_visible"]
226
+
227
+ # Button click handlers
228
+ def handle_left_click(state_data):
229
+ new_state, ui_state = handle_choice("left", state_data)
230
+ return [
231
+ new_state,
232
+ ui_state["left_video"],
233
+ ui_state["right_video"],
234
+ ui_state["status"],
235
+ ui_state["left_button_visible"],
236
+ ui_state["right_button_visible"],
237
+ ui_state["done_visible"],
238
+ ui_state["progress"]
239
+ ]
240
+
241
+ def handle_right_click(state_data):
242
+ new_state, ui_state = handle_choice("right", state_data)
243
+ return [
244
+ new_state,
245
+ ui_state["left_video"],
246
+ ui_state["right_video"],
247
+ ui_state["status"],
248
+ ui_state["left_button_visible"],
249
+ ui_state["right_button_visible"],
250
+ ui_state["done_visible"],
251
+ ui_state["progress"]
252
+ ]
253
+
254
+ left_button.click(
255
+ handle_left_click,
256
+ inputs=[state_data],
257
+ outputs=[state_data, left_video, right_video, status_text, left_button, right_button, done_text, progress_bar]
258
+ )
259
+
260
+ right_button.click(
261
+ handle_right_click,
262
+ inputs=[state_data],
263
+ outputs=[state_data, left_video, right_video, status_text, left_button, right_button, done_text, progress_bar]
264
+ )
265
+
266
+ return demo
267
+
268
+ if __name__ == "__main__":
269
+ # Set the directory containing the method folders
270
+ videos_directory = input("Enter the directory containing the method folders: ").strip()
271
+ if not videos_directory:
272
+ videos_directory = "." # Default to current directory
273
+
274
+ app = create_app(videos_directory)
275
+ app.launch()