Move image resizing to frontend
Browse files
app.py
CHANGED
|
@@ -66,20 +66,6 @@ def process_image(image):
|
|
| 66 |
|
| 67 |
return sorted_probs
|
| 68 |
|
| 69 |
-
def resize_image(image, max_size=512):
|
| 70 |
-
"""Resize image to have a maximum dimension of max_size while preserving aspect ratio"""
|
| 71 |
-
width, height = image.size
|
| 72 |
-
if width > height:
|
| 73 |
-
if width > max_size:
|
| 74 |
-
new_width = max_size
|
| 75 |
-
new_height = int(height * (max_size / width))
|
| 76 |
-
else:
|
| 77 |
-
if height > max_size:
|
| 78 |
-
new_height = max_size
|
| 79 |
-
new_width = int(width * (max_size / height))
|
| 80 |
-
else:
|
| 81 |
-
return image
|
| 82 |
-
return image.resize((new_width, new_height), Image.Resampling.LANCZOS)
|
| 83 |
|
| 84 |
class GameState:
|
| 85 |
def __init__(self):
|
|
@@ -91,10 +77,35 @@ class GameState:
|
|
| 91 |
self.is_game_active = False
|
| 92 |
self.last_results = None
|
| 93 |
self.waiting_for_input = True
|
| 94 |
-
self.original_image = None
|
| 95 |
|
| 96 |
def reset(self):
|
| 97 |
self.__init__()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
|
| 99 |
game_state = GameState()
|
| 100 |
|
|
@@ -146,29 +157,26 @@ def start_game():
|
|
| 146 |
game_state.game_images = load_images()
|
| 147 |
game_state.is_game_active = True
|
| 148 |
game_state.waiting_for_input = True
|
| 149 |
-
|
| 150 |
-
# Store original image and create resized version for display
|
| 151 |
-
game_state.original_image = Image.open(game_state.game_images[0])
|
| 152 |
-
display_image = resize_image(game_state.original_image)
|
| 153 |
|
| 154 |
return (
|
| 155 |
-
gr.update(value=
|
| 156 |
-
gr.update(visible=False),
|
| 157 |
-
gr.update(visible=True, interactive=True),
|
| 158 |
-
gr.update(visible=True, interactive=True),
|
| 159 |
create_score_html(),
|
| 160 |
-
gr.update(visible=False)
|
| 161 |
)
|
| 162 |
|
| 163 |
def submit_guess(user_guess):
|
| 164 |
if not game_state.is_game_active or not game_state.waiting_for_input:
|
| 165 |
return [gr.update()] * 6
|
| 166 |
-
|
| 167 |
-
model_prediction = process_image(game_state.original_image)
|
| 168 |
-
correct_answer = "Real" if "real_images" in game_state.game_images[game_state.current_round] else "Fake"
|
| 169 |
|
| 170 |
-
#
|
|
|
|
|
|
|
| 171 |
model_guess = "Real" if model_prediction['Authentic'] > PROB_THRESHOLD else "Fake"
|
|
|
|
| 172 |
|
| 173 |
# Update scores
|
| 174 |
if user_guess == correct_answer:
|
|
@@ -195,15 +203,13 @@ def submit_guess(user_guess):
|
|
| 195 |
gr.update(visible=False),
|
| 196 |
gr.update(visible=False),
|
| 197 |
create_score_html(),
|
| 198 |
-
gr.update(visible=True, value=
|
| 199 |
)
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
game_state.original_image = Image.open(game_state.game_images[game_state.current_round])
|
| 203 |
-
display_image = resize_image(game_state.original_image)
|
| 204 |
|
| 205 |
return (
|
| 206 |
-
gr.update(value=
|
| 207 |
gr.update(visible=False),
|
| 208 |
gr.update(visible=True, interactive=True),
|
| 209 |
gr.update(visible=True, interactive=True),
|
|
@@ -231,6 +237,11 @@ custom_css = """
|
|
| 231 |
.guess-button {
|
| 232 |
min-width: 120px;
|
| 233 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 234 |
"""
|
| 235 |
|
| 236 |
# Define Gradio interface
|
|
@@ -262,7 +273,8 @@ with gr.Blocks(css=custom_css) as iface:
|
|
| 262 |
type="pil",
|
| 263 |
label="Current Image",
|
| 264 |
interactive=False,
|
| 265 |
-
visible=False
|
|
|
|
| 266 |
)
|
| 267 |
with gr.Row(elem_id="guess-buttons"):
|
| 268 |
real_button = gr.Button(
|
|
|
|
| 66 |
|
| 67 |
return sorted_probs
|
| 68 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
|
| 70 |
class GameState:
|
| 71 |
def __init__(self):
|
|
|
|
| 77 |
self.is_game_active = False
|
| 78 |
self.last_results = None
|
| 79 |
self.waiting_for_input = True
|
|
|
|
| 80 |
|
| 81 |
def reset(self):
|
| 82 |
self.__init__()
|
| 83 |
+
|
| 84 |
+
def get_game_over_message(self):
|
| 85 |
+
if self.user_score > self.model_score:
|
| 86 |
+
return """
|
| 87 |
+
<div style='text-align: center; margin-top: 20px; font-size: 1.2em;'>
|
| 88 |
+
🎉 Congratulations! You won! 🎉<br>
|
| 89 |
+
You've outperformed SuSy in detecting AI-generated images.<br>
|
| 90 |
+
Click 'Start New Game' to play again.
|
| 91 |
+
</div>
|
| 92 |
+
"""
|
| 93 |
+
elif self.user_score < self.model_score:
|
| 94 |
+
return """
|
| 95 |
+
<div style='text-align: center; margin-top: 20px; font-size: 1.2em;'>
|
| 96 |
+
Better luck next time! SuSy won this round.<br>
|
| 97 |
+
Keep practicing to improve your detection skills.<br>
|
| 98 |
+
Click 'Start New Game' to try again.
|
| 99 |
+
</div>
|
| 100 |
+
"""
|
| 101 |
+
else:
|
| 102 |
+
return """
|
| 103 |
+
<div style='text-align: center; margin-top: 20px; font-size: 1.2em;'>
|
| 104 |
+
It's a tie! You matched SuSy's performance!<br>
|
| 105 |
+
You're getting good at this.<br>
|
| 106 |
+
Click 'Start New Game' to play again.
|
| 107 |
+
</div>
|
| 108 |
+
"""
|
| 109 |
|
| 110 |
game_state = GameState()
|
| 111 |
|
|
|
|
| 157 |
game_state.game_images = load_images()
|
| 158 |
game_state.is_game_active = True
|
| 159 |
game_state.waiting_for_input = True
|
| 160 |
+
current_image = Image.open(game_state.game_images[0])
|
|
|
|
|
|
|
|
|
|
| 161 |
|
| 162 |
return (
|
| 163 |
+
gr.update(value=current_image, visible=True),
|
| 164 |
+
gr.update(visible=False),
|
| 165 |
+
gr.update(visible=True, interactive=True),
|
| 166 |
+
gr.update(visible=True, interactive=True),
|
| 167 |
create_score_html(),
|
| 168 |
+
gr.update(visible=False)
|
| 169 |
)
|
| 170 |
|
| 171 |
def submit_guess(user_guess):
|
| 172 |
if not game_state.is_game_active or not game_state.waiting_for_input:
|
| 173 |
return [gr.update()] * 6
|
|
|
|
|
|
|
|
|
|
| 174 |
|
| 175 |
+
# Compute Model Guess
|
| 176 |
+
current_image = Image.open(game_state.game_images[game_state.current_round])
|
| 177 |
+
model_prediction = process_image(current_image)
|
| 178 |
model_guess = "Real" if model_prediction['Authentic'] > PROB_THRESHOLD else "Fake"
|
| 179 |
+
correct_answer = "Real" if "real_images" in game_state.game_images[game_state.current_round] else "Fake"
|
| 180 |
|
| 181 |
# Update scores
|
| 182 |
if user_guess == correct_answer:
|
|
|
|
| 203 |
gr.update(visible=False),
|
| 204 |
gr.update(visible=False),
|
| 205 |
create_score_html(),
|
| 206 |
+
gr.update(visible=True, value=game_state.get_game_over_message())
|
| 207 |
)
|
| 208 |
+
|
| 209 |
+
next_image = Image.open(game_state.game_images[game_state.current_round])
|
|
|
|
|
|
|
| 210 |
|
| 211 |
return (
|
| 212 |
+
gr.update(value=next_image, visible=True),
|
| 213 |
gr.update(visible=False),
|
| 214 |
gr.update(visible=True, interactive=True),
|
| 215 |
gr.update(visible=True, interactive=True),
|
|
|
|
| 237 |
.guess-button {
|
| 238 |
min-width: 120px;
|
| 239 |
}
|
| 240 |
+
.image-container img {
|
| 241 |
+
max-height: 768px !important;
|
| 242 |
+
width: auto !important;
|
| 243 |
+
object-fit: contain !important;
|
| 244 |
+
}
|
| 245 |
"""
|
| 246 |
|
| 247 |
# Define Gradio interface
|
|
|
|
| 273 |
type="pil",
|
| 274 |
label="Current Image",
|
| 275 |
interactive=False,
|
| 276 |
+
visible=False,
|
| 277 |
+
elem_classes=["image-container"]
|
| 278 |
)
|
| 279 |
with gr.Row(elem_id="guess-buttons"):
|
| 280 |
real_button = gr.Button(
|