Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -479,21 +479,21 @@ def run(orig_image: Image.Image, points: list, preset_name: str):
|
|
| 479 |
|
| 480 |
if orig_image is None:
|
| 481 |
gr.Warning("Upload an image first.")
|
| 482 |
-
return None, "", None
|
| 483 |
if not points or len(points) < 2:
|
| 484 |
gr.Warning("Provide at least 2 fixations (click the image or load a fixation file).")
|
| 485 |
-
return None, "", None
|
| 486 |
|
| 487 |
preset_key = PRESETS[preset_name]
|
| 488 |
try:
|
| 489 |
predictor = get_predictor(preset_key)
|
| 490 |
except FileNotFoundError as e:
|
| 491 |
gr.Warning(str(e))
|
| 492 |
-
return None, f"**Checkpoint not found** for preset `{preset_key}`.", None
|
| 493 |
except Exception as e: # noqa: BLE001
|
| 494 |
traceback.print_exc()
|
| 495 |
gr.Warning(f"Could not load model: {e}")
|
| 496 |
-
return None, "", None
|
| 497 |
|
| 498 |
w, h = orig_image.size
|
| 499 |
# Build a MIMIC-style scanpath dataframe. The 3rd component (weight)
|
|
@@ -512,7 +512,7 @@ def run(orig_image: Image.Image, points: list, preset_name: str):
|
|
| 512 |
scanpath = get_scanpath(df, "webdemo", img_height=h, img_width=w)
|
| 513 |
if scanpath is None or scanpath.numel() == 0:
|
| 514 |
gr.Warning("Could not build a scanpath from the fixations.")
|
| 515 |
-
return None, "", None
|
| 516 |
scanpath = scanpath[:200].to(predictor.device)
|
| 517 |
|
| 518 |
img_tensor = predictor.transform(np.array(orig_image)).unsqueeze(0).to(predictor.device)
|
|
@@ -529,7 +529,7 @@ def run(orig_image: Image.Image, points: list, preset_name: str):
|
|
| 529 |
except Exception as e: # noqa: BLE001
|
| 530 |
traceback.print_exc()
|
| 531 |
gr.Warning(f"Prediction failed: {e}")
|
| 532 |
-
return None, "", None
|
| 533 |
|
| 534 |
class_probs = {c: float(p) for c, p in zip(predictor.classes, probs)}
|
| 535 |
predicted_class = max(class_probs, key=class_probs.get)
|
|
@@ -540,14 +540,13 @@ def run(orig_image: Image.Image, points: list, preset_name: str):
|
|
| 540 |
display_img = np.array(orig_image.resize((img_size, img_size)))
|
| 541 |
gaze_hm = gaze_duration_heatmap(points, img_size, img_size, w, h)
|
| 542 |
overlay = make_overlay(display_img, gaze_hm)
|
| 543 |
-
heatmap_img = heatmap_to_image(gaze_hm)
|
| 544 |
|
| 545 |
prob_lines = "\n".join(
|
| 546 |
f"- **{c}**: {p:.3f}" for c, p in sorted(class_probs.items(), key=lambda kv: -kv[1])
|
| 547 |
)
|
| 548 |
summary = f"### Predicted: **{predicted_class}**\n\n{prob_lines}"
|
| 549 |
|
| 550 |
-
return class_probs, summary, overlay
|
| 551 |
|
| 552 |
|
| 553 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -607,24 +606,25 @@ with gr.Blocks(title="GazeAlign", css=_CSS) as demo:
|
|
| 607 |
clear_btn = gr.Button("Clear fixations")
|
| 608 |
delete_btn = gr.Button("Delete image", visible=False)
|
| 609 |
|
| 610 |
-
|
| 611 |
-
|
| 612 |
-
|
| 613 |
-
|
| 614 |
-
|
| 615 |
-
|
| 616 |
-
|
| 617 |
-
|
| 618 |
-
|
| 619 |
-
|
|
|
|
|
|
|
|
|
|
| 620 |
|
| 621 |
# ββ Right: results βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 622 |
with gr.Column(scale=1):
|
| 623 |
-
run_btn = gr.Button("Run GazeAlign", variant="primary", elem_id="run-btn")
|
| 624 |
label_output = gr.Label(label="Predicted class (probabilities)", num_top_classes=5)
|
| 625 |
summary_output = gr.Markdown()
|
| 626 |
overlay_output = gr.Image(label="Gaze-fixation heatmap (dwell-weighted) β overlay")
|
| 627 |
-
mask_output = gr.Image(label="Gaze-fixation heatmap (weighted by duration)")
|
| 628 |
|
| 629 |
gr.Markdown(
|
| 630 |
"<div class='footer-note'>Fixation tables use raw pixel or normalised "
|
|
@@ -665,7 +665,7 @@ with gr.Blocks(title="GazeAlign", css=_CSS) as demo:
|
|
| 665 |
run_btn.click(
|
| 666 |
run,
|
| 667 |
[orig_image_state, points_state, preset_dd],
|
| 668 |
-
[label_output, summary_output, overlay_output
|
| 669 |
)
|
| 670 |
|
| 671 |
|
|
|
|
| 479 |
|
| 480 |
if orig_image is None:
|
| 481 |
gr.Warning("Upload an image first.")
|
| 482 |
+
return None, "", None
|
| 483 |
if not points or len(points) < 2:
|
| 484 |
gr.Warning("Provide at least 2 fixations (click the image or load a fixation file).")
|
| 485 |
+
return None, "", None
|
| 486 |
|
| 487 |
preset_key = PRESETS[preset_name]
|
| 488 |
try:
|
| 489 |
predictor = get_predictor(preset_key)
|
| 490 |
except FileNotFoundError as e:
|
| 491 |
gr.Warning(str(e))
|
| 492 |
+
return None, f"**Checkpoint not found** for preset `{preset_key}`.", None
|
| 493 |
except Exception as e: # noqa: BLE001
|
| 494 |
traceback.print_exc()
|
| 495 |
gr.Warning(f"Could not load model: {e}")
|
| 496 |
+
return None, "", None
|
| 497 |
|
| 498 |
w, h = orig_image.size
|
| 499 |
# Build a MIMIC-style scanpath dataframe. The 3rd component (weight)
|
|
|
|
| 512 |
scanpath = get_scanpath(df, "webdemo", img_height=h, img_width=w)
|
| 513 |
if scanpath is None or scanpath.numel() == 0:
|
| 514 |
gr.Warning("Could not build a scanpath from the fixations.")
|
| 515 |
+
return None, "", None
|
| 516 |
scanpath = scanpath[:200].to(predictor.device)
|
| 517 |
|
| 518 |
img_tensor = predictor.transform(np.array(orig_image)).unsqueeze(0).to(predictor.device)
|
|
|
|
| 529 |
except Exception as e: # noqa: BLE001
|
| 530 |
traceback.print_exc()
|
| 531 |
gr.Warning(f"Prediction failed: {e}")
|
| 532 |
+
return None, "", None
|
| 533 |
|
| 534 |
class_probs = {c: float(p) for c, p in zip(predictor.classes, probs)}
|
| 535 |
predicted_class = max(class_probs, key=class_probs.get)
|
|
|
|
| 540 |
display_img = np.array(orig_image.resize((img_size, img_size)))
|
| 541 |
gaze_hm = gaze_duration_heatmap(points, img_size, img_size, w, h)
|
| 542 |
overlay = make_overlay(display_img, gaze_hm)
|
|
|
|
| 543 |
|
| 544 |
prob_lines = "\n".join(
|
| 545 |
f"- **{c}**: {p:.3f}" for c, p in sorted(class_probs.items(), key=lambda kv: -kv[1])
|
| 546 |
)
|
| 547 |
summary = f"### Predicted: **{predicted_class}**\n\n{prob_lines}"
|
| 548 |
|
| 549 |
+
return class_probs, summary, overlay
|
| 550 |
|
| 551 |
|
| 552 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
|
|
| 606 |
clear_btn = gr.Button("Clear fixations")
|
| 607 |
delete_btn = gr.Button("Delete image", visible=False)
|
| 608 |
|
| 609 |
+
# Collapsed by default β click the header (menu-style) to reveal.
|
| 610 |
+
with gr.Accordion("π Load fixations from a file (.csv / .xlsx / .xls)", open=False):
|
| 611 |
+
fixfile = gr.File(
|
| 612 |
+
label=_FIXFILE_LABEL, file_types=[".csv", ".xlsx", ".xls"], type="filepath"
|
| 613 |
+
)
|
| 614 |
+
with gr.Row(visible=False) as mapping_row:
|
| 615 |
+
id_col_dd = gr.Dropdown(label="ID column", choices=[])
|
| 616 |
+
x_col_dd = gr.Dropdown(label="X column", choices=[])
|
| 617 |
+
y_col_dd = gr.Dropdown(label="Y column", choices=[])
|
| 618 |
+
time_col_dd = gr.Dropdown(label="Time column (optional)", choices=[])
|
| 619 |
+
apply_fix_btn = gr.Button("Apply fixation file", visible=False)
|
| 620 |
+
|
| 621 |
+
run_btn = gr.Button("Run GazeAlign", variant="primary", elem_id="run-btn")
|
| 622 |
|
| 623 |
# ββ Right: results βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 624 |
with gr.Column(scale=1):
|
|
|
|
| 625 |
label_output = gr.Label(label="Predicted class (probabilities)", num_top_classes=5)
|
| 626 |
summary_output = gr.Markdown()
|
| 627 |
overlay_output = gr.Image(label="Gaze-fixation heatmap (dwell-weighted) β overlay")
|
|
|
|
| 628 |
|
| 629 |
gr.Markdown(
|
| 630 |
"<div class='footer-note'>Fixation tables use raw pixel or normalised "
|
|
|
|
| 665 |
run_btn.click(
|
| 666 |
run,
|
| 667 |
[orig_image_state, points_state, preset_dd],
|
| 668 |
+
[label_output, summary_output, overlay_output],
|
| 669 |
)
|
| 670 |
|
| 671 |
|