Spaces:
Running on Zero
Running on Zero
Upload 41 files
Browse files- __pycache__/app.cpython-310.pyc +0 -0
- app.py +22 -14
__pycache__/app.cpython-310.pyc
CHANGED
|
Binary files a/__pycache__/app.cpython-310.pyc and b/__pycache__/app.cpython-310.pyc differ
|
|
|
app.py
CHANGED
|
@@ -129,17 +129,26 @@ def apply_csv(frame_json, x_col, y_col, duration_col, image, image_name):
|
|
| 129 |
return gr.update(), gr.update()
|
| 130 |
try:
|
| 131 |
frame = pd.read_json(frame_json, orient="split")
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
x, y = frame[x_col].astype(float).to_numpy(), frame[y_col].astype(float).to_numpy()
|
| 144 |
duration = (frame[duration_col].astype(float).to_numpy()
|
| 145 |
if duration_col and duration_col != NO_DURATION else np.ones(len(x)))
|
|
@@ -147,8 +156,7 @@ def apply_csv(frame_json, x_col, y_col, duration_col, image, image_name):
|
|
| 147 |
if len(x) and min(x) >= 0 and min(y) >= 0 and max(x) <= 1.05 and max(y) <= 1.05: x, y = x*w, y*h
|
| 148 |
duration = duration / max(float(duration.max()), 1e-8)
|
| 149 |
points = [(float(np.clip(a, 0, w-1)), float(np.clip(b, 0, h-1)), float(c)) for a,b,c in zip(x,y,duration)]
|
| 150 |
-
|
| 151 |
-
gr.Info(f"Loaded {len(points)} gaze points from CSV{scope}.")
|
| 152 |
return points, draw_points(image, points)
|
| 153 |
except Exception as exc:
|
| 154 |
gr.Warning(f"Could not apply CSV: {exc}")
|
|
@@ -232,7 +240,7 @@ with gr.Blocks(title="GazeCorrect") as demo:
|
|
| 232 |
weight = gr.Slider(.1, 1, value=1, step=.1, label="Next click weight")
|
| 233 |
clear_button = gr.Button("Clear gaze", variant="secondary")
|
| 234 |
with gr.Accordion("Import gaze CSV", open=False):
|
| 235 |
-
gr.Markdown("Upload a CSV, then choose the
|
| 236 |
csv_file = gr.File(label="Choose CSV", file_types=[".csv", ".tsv", ".txt"])
|
| 237 |
with gr.Row(visible=False) as csv_mapping:
|
| 238 |
x_column = gr.Dropdown(label="X column")
|
|
|
|
| 129 |
return gr.update(), gr.update()
|
| 130 |
try:
|
| 131 |
frame = pd.read_json(frame_json, orient="split")
|
| 132 |
+
# ``utf-8-sig`` CSV exports can leave a BOM in the first header, so
|
| 133 |
+
# normalize it before locating the required ID column. Never fall back
|
| 134 |
+
# to importing every row: this file can contain gaze for many images.
|
| 135 |
+
id_col = next(
|
| 136 |
+
(column for column in frame.columns
|
| 137 |
+
if str(column).lstrip("\ufeff").strip().casefold() == "id"),
|
| 138 |
+
None,
|
| 139 |
+
)
|
| 140 |
+
if id_col is None:
|
| 141 |
+
raise ValueError('CSV must contain an "id" column to import gaze for the selected image.')
|
| 142 |
+
if not image_name:
|
| 143 |
+
raise ValueError("The uploaded image name is unavailable for matching the CSV id column.")
|
| 144 |
+
image_path = Path(image_name)
|
| 145 |
+
accepted_ids = {image_path.name.casefold(), image_path.stem.casefold()}
|
| 146 |
+
gaze_ids = frame[id_col].astype(str).str.strip().str.casefold()
|
| 147 |
+
frame = frame[gaze_ids.isin(accepted_ids)]
|
| 148 |
+
if frame.empty:
|
| 149 |
+
raise ValueError(
|
| 150 |
+
f'No gaze rows matched image "{image_path.name}" in the "{id_col}" column.'
|
| 151 |
+
)
|
| 152 |
x, y = frame[x_col].astype(float).to_numpy(), frame[y_col].astype(float).to_numpy()
|
| 153 |
duration = (frame[duration_col].astype(float).to_numpy()
|
| 154 |
if duration_col and duration_col != NO_DURATION else np.ones(len(x)))
|
|
|
|
| 156 |
if len(x) and min(x) >= 0 and min(y) >= 0 and max(x) <= 1.05 and max(y) <= 1.05: x, y = x*w, y*h
|
| 157 |
duration = duration / max(float(duration.max()), 1e-8)
|
| 158 |
points = [(float(np.clip(a, 0, w-1)), float(np.clip(b, 0, h-1)), float(c)) for a,b,c in zip(x,y,duration)]
|
| 159 |
+
gr.Info(f'Loaded {len(points)} gaze points for "{Path(image_name).name}" from CSV.')
|
|
|
|
| 160 |
return points, draw_points(image, points)
|
| 161 |
except Exception as exc:
|
| 162 |
gr.Warning(f"Could not apply CSV: {exc}")
|
|
|
|
| 240 |
weight = gr.Slider(.1, 1, value=1, step=.1, label="Next click weight")
|
| 241 |
clear_button = gr.Button("Clear gaze", variant="secondary")
|
| 242 |
with gr.Accordion("Import gaze CSV", open=False):
|
| 243 |
+
gr.Markdown("Upload a CSV with an `id` column, then choose the fixation X, Y, and optional duration/weight columns. Only rows whose ID matches the uploaded image filename (or filename without its extension) are imported.")
|
| 244 |
csv_file = gr.File(label="Choose CSV", file_types=[".csv", ".tsv", ".txt"])
|
| 245 |
with gr.Row(visible=False) as csv_mapping:
|
| 246 |
x_column = gr.Dropdown(label="X column")
|