Tenbatsu24 commited on
Commit Β·
ee97359
1
Parent(s): 7eb7023
change: css for readability
Browse files
app.py
CHANGED
|
@@ -30,7 +30,7 @@ MODEL_IDS = {
|
|
| 30 |
"DiNO": "OK-AI/dino-vitb16-pretrain-in1k",
|
| 31 |
"iBOT": "OK-AI/ibot-vitb16-pretrain-in1k",
|
| 32 |
"LeJEPA": "OK-AI/lejepa-vitb16-pretrain-in1k",
|
| 33 |
-
}
|
| 34 |
}
|
| 35 |
|
| 36 |
MODEL_KEYS = ["DiNO", "iBOT", "LeJEPA"]
|
|
@@ -98,10 +98,11 @@ def create_coming_soon_image(
|
|
| 98 |
|
| 99 |
return image
|
| 100 |
|
|
|
|
| 101 |
def resize_image_for_patches(
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
) -> torch.Tensor:
|
| 106 |
"""Resize so height = image_size and width is patch-aligned,
|
| 107 |
preserving aspect ratio. Returns (1, 3, H, W) float tensor."""
|
|
@@ -137,7 +138,9 @@ def pad_to_square(img: Image.Image, canvas_size: int) -> Image.Image:
|
|
| 137 |
# ββ PCA visualisation βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 138 |
|
| 139 |
|
| 140 |
-
def pca_vis(
|
|
|
|
|
|
|
| 141 |
"""Run image through model, PCA patch features β square-padded RGB PIL image."""
|
| 142 |
model_input = preprocess(image_tensor).to(DEVICE)
|
| 143 |
|
|
@@ -207,27 +210,55 @@ CSS = """
|
|
| 207 |
text-align: center;
|
| 208 |
padding: 1.5rem 0 0.25rem;
|
| 209 |
}
|
|
|
|
| 210 |
.subtitle-row {
|
| 211 |
text-align: center;
|
| 212 |
-
color: #
|
| 213 |
font-size: 0.9rem;
|
| 214 |
padding-bottom: 1rem;
|
| 215 |
}
|
|
|
|
| 216 |
.arch-header {
|
| 217 |
font-size: 1.2rem;
|
| 218 |
font-weight: 700;
|
| 219 |
margin-top: 1rem;
|
| 220 |
padding-left: 0.5rem;
|
| 221 |
-
border-left: 4px solid #
|
| 222 |
-
color: #
|
| 223 |
}
|
|
|
|
| 224 |
.model-label {
|
| 225 |
text-align: center;
|
| 226 |
-
font-weight:
|
| 227 |
-
font-size: 0.
|
| 228 |
-
color: #
|
| 229 |
padding: 0.25rem 0;
|
| 230 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 231 |
.output-col {
|
| 232 |
display: flex !important;
|
| 233 |
flex-direction: column !important;
|
|
@@ -242,21 +273,24 @@ CSS = """
|
|
| 242 |
max-height: 350px !important;
|
| 243 |
width: 100% !important;
|
| 244 |
}
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
text-decoration-color: #d1d5db;
|
| 249 |
}
|
| 250 |
-
|
| 251 |
-
|
|
|
|
|
|
|
|
|
|
| 252 |
}
|
|
|
|
| 253 |
.custom-footer {
|
| 254 |
text-align: center;
|
| 255 |
margin-top: 2.5rem;
|
| 256 |
padding-top: 1rem;
|
| 257 |
-
border-top: 1px solid #
|
| 258 |
-
font-size: 0.
|
| 259 |
-
color: #
|
| 260 |
}
|
| 261 |
footer { display: none !important; }
|
| 262 |
"""
|
|
@@ -287,21 +321,21 @@ with gr.Blocks(css=CSS, title="SSL ViT PCA Visualiser") as demo:
|
|
| 287 |
choices=["ep100", "ep300"],
|
| 288 |
value="ep300",
|
| 289 |
label="Epochs",
|
| 290 |
-
interactive=True
|
| 291 |
)
|
| 292 |
opt_weight = gr.Dropdown(
|
| 293 |
choices=["student", "teacher"],
|
| 294 |
value="teacher",
|
| 295 |
label="Weight Type",
|
| 296 |
info="LeJEPA always uses student",
|
| 297 |
-
interactive=True
|
| 298 |
)
|
| 299 |
|
| 300 |
opt_size = gr.Dropdown(
|
| 301 |
choices=["224", "448", "672", "1280"],
|
| 302 |
value="672",
|
| 303 |
label="Image Target Resolution",
|
| 304 |
-
interactive=True
|
| 305 |
)
|
| 306 |
|
| 307 |
run_btn = gr.Button("Visualise", variant="primary")
|
|
@@ -326,15 +360,18 @@ with gr.Blocks(css=CSS, title="SSL ViT PCA Visualiser") as demo:
|
|
| 326 |
with gr.Row(equal_height=True):
|
| 327 |
with gr.Column(elem_classes="output-col"):
|
| 328 |
gr.HTML(
|
| 329 |
-
f'<div class="model-label"><a href="https://huggingface.co/{MODEL_IDS["ViT-S/16"]["DiNO"]}" target="_blank">DiNO (S/16)</a></div>'
|
|
|
|
| 330 |
out_dino_s = gr.Image(show_label=False, interactive=False)
|
| 331 |
with gr.Column(elem_classes="output-col"):
|
| 332 |
gr.HTML(
|
| 333 |
-
f'<div class="model-label"><a href="https://huggingface.co/{MODEL_IDS["ViT-S/16"]["iBOT"]}" target="_blank">iBOT (S/16)</a></div>'
|
|
|
|
| 334 |
out_ibot_s = gr.Image(show_label=False, interactive=False)
|
| 335 |
with gr.Column(elem_classes="output-col"):
|
| 336 |
gr.HTML(
|
| 337 |
-
f'<div class="model-label"><a href="https://huggingface.co/{MODEL_IDS["ViT-S/16"]["LeJEPA"]}" target="_blank">LeJEPA (S/16)</a></div>'
|
|
|
|
| 338 |
out_lejepa_s = gr.Image(show_label=False, interactive=False)
|
| 339 |
|
| 340 |
# ββ ViT-B/16 Row ββ
|
|
@@ -342,21 +379,28 @@ with gr.Blocks(css=CSS, title="SSL ViT PCA Visualiser") as demo:
|
|
| 342 |
with gr.Row(equal_height=True):
|
| 343 |
with gr.Column(elem_classes="output-col"):
|
| 344 |
gr.HTML(
|
| 345 |
-
f'<div class="model-label"><a href="https://huggingface.co/{MODEL_IDS["ViT-B/16"]["DiNO"]}" target="_blank">DiNO (B/16)</a></div>'
|
|
|
|
| 346 |
out_dino_b = gr.Image(show_label=False, interactive=False)
|
| 347 |
with gr.Column(elem_classes="output-col"):
|
| 348 |
gr.HTML(
|
| 349 |
-
f'<div class="model-label"><a href="https://huggingface.co/{MODEL_IDS["ViT-B/16"]["iBOT"]}" target="_blank">iBOT (B/16)</a></div>'
|
|
|
|
| 350 |
out_ibot_b = gr.Image(show_label=False, interactive=False)
|
| 351 |
with gr.Column(elem_classes="output-col"):
|
| 352 |
gr.HTML(
|
| 353 |
-
f'<div class="model-label"><a href="https://huggingface.co/{MODEL_IDS["ViT-B/16"]["LeJEPA"]}" target="_blank">LeJEPA (B/16)</a></div>'
|
|
|
|
| 354 |
out_lejepa_b = gr.Image(show_label=False, interactive=False)
|
| 355 |
|
| 356 |
# Wire outputs orderly following the exact resolution pattern tracking inside the `run` loop
|
| 357 |
output_targets = [
|
| 358 |
-
out_dino_s,
|
| 359 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 360 |
]
|
| 361 |
|
| 362 |
run_btn.click(
|
|
|
|
| 30 |
"DiNO": "OK-AI/dino-vitb16-pretrain-in1k",
|
| 31 |
"iBOT": "OK-AI/ibot-vitb16-pretrain-in1k",
|
| 32 |
"LeJEPA": "OK-AI/lejepa-vitb16-pretrain-in1k",
|
| 33 |
+
},
|
| 34 |
}
|
| 35 |
|
| 36 |
MODEL_KEYS = ["DiNO", "iBOT", "LeJEPA"]
|
|
|
|
| 98 |
|
| 99 |
return image
|
| 100 |
|
| 101 |
+
|
| 102 |
def resize_image_for_patches(
|
| 103 |
+
image: Image.Image,
|
| 104 |
+
image_size: int,
|
| 105 |
+
patch_size: int = PATCH_SIZE,
|
| 106 |
) -> torch.Tensor:
|
| 107 |
"""Resize so height = image_size and width is patch-aligned,
|
| 108 |
preserving aspect ratio. Returns (1, 3, H, W) float tensor."""
|
|
|
|
| 138 |
# ββ PCA visualisation βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 139 |
|
| 140 |
|
| 141 |
+
def pca_vis(
|
| 142 |
+
model: torch.nn.Module, image_tensor: torch.Tensor, canvas_size: int
|
| 143 |
+
) -> Image.Image:
|
| 144 |
"""Run image through model, PCA patch features β square-padded RGB PIL image."""
|
| 145 |
model_input = preprocess(image_tensor).to(DEVICE)
|
| 146 |
|
|
|
|
| 210 |
text-align: center;
|
| 211 |
padding: 1.5rem 0 0.25rem;
|
| 212 |
}
|
| 213 |
+
/* Higher contrast subtitle */
|
| 214 |
.subtitle-row {
|
| 215 |
text-align: center;
|
| 216 |
+
color: #d1d5db;
|
| 217 |
font-size: 0.9rem;
|
| 218 |
padding-bottom: 1rem;
|
| 219 |
}
|
| 220 |
+
/* Higher contrast section headers */
|
| 221 |
.arch-header {
|
| 222 |
font-size: 1.2rem;
|
| 223 |
font-weight: 700;
|
| 224 |
margin-top: 1rem;
|
| 225 |
padding-left: 0.5rem;
|
| 226 |
+
border-left: 4px solid #60a5fa;
|
| 227 |
+
color: #f3f4f6;
|
| 228 |
}
|
| 229 |
+
/* Brighter model labels */
|
| 230 |
.model-label {
|
| 231 |
text-align: center;
|
| 232 |
+
font-weight: 700;
|
| 233 |
+
font-size: 0.9rem;
|
| 234 |
+
color: #f3f4f6;
|
| 235 |
padding: 0.25rem 0;
|
| 236 |
}
|
| 237 |
+
/* Make links readable before AND after clicking */
|
| 238 |
+
.subtitle-row a,
|
| 239 |
+
.model-label a,
|
| 240 |
+
.custom-footer a,
|
| 241 |
+
.subtitle-row a:visited,
|
| 242 |
+
.model-label a:visited,
|
| 243 |
+
.custom-footer a:visited {
|
| 244 |
+
color: #93c5fd;
|
| 245 |
+
text-decoration: underline;
|
| 246 |
+
text-decoration-color: #93c5fd;
|
| 247 |
+
font-weight: 600;
|
| 248 |
+
}
|
| 249 |
+
/* Strong hover state */
|
| 250 |
+
.subtitle-row a:hover,
|
| 251 |
+
.model-label a:hover,
|
| 252 |
+
.custom-footer a:hover {
|
| 253 |
+
color: #dbeafe;
|
| 254 |
+
text-decoration-color: #dbeafe;
|
| 255 |
+
}
|
| 256 |
+
/* Prevent browsers from turning visited links purple/dark */
|
| 257 |
+
.subtitle-row a:active,
|
| 258 |
+
.model-label a:active,
|
| 259 |
+
.custom-footer a:active {
|
| 260 |
+
color: #bfdbfe;
|
| 261 |
+
}
|
| 262 |
.output-col {
|
| 263 |
display: flex !important;
|
| 264 |
flex-direction: column !important;
|
|
|
|
| 273 |
max-height: 350px !important;
|
| 274 |
width: 100% !important;
|
| 275 |
}
|
| 276 |
+
/* Improve contrast of markdown/help text */
|
| 277 |
+
.gradio-container p {
|
| 278 |
+
color: #d1d5db;
|
|
|
|
| 279 |
}
|
| 280 |
+
/* Improve dropdown labels and general form text */
|
| 281 |
+
.gradio-container label,
|
| 282 |
+
.gradio-container .form,
|
| 283 |
+
.gradio-container .prose {
|
| 284 |
+
color: #f3f4f6;
|
| 285 |
}
|
| 286 |
+
/* More legible footer */
|
| 287 |
.custom-footer {
|
| 288 |
text-align: center;
|
| 289 |
margin-top: 2.5rem;
|
| 290 |
padding-top: 1rem;
|
| 291 |
+
border-top: 1px solid #374151;
|
| 292 |
+
font-size: 0.85rem;
|
| 293 |
+
color: #d1d5db;
|
| 294 |
}
|
| 295 |
footer { display: none !important; }
|
| 296 |
"""
|
|
|
|
| 321 |
choices=["ep100", "ep300"],
|
| 322 |
value="ep300",
|
| 323 |
label="Epochs",
|
| 324 |
+
interactive=True,
|
| 325 |
)
|
| 326 |
opt_weight = gr.Dropdown(
|
| 327 |
choices=["student", "teacher"],
|
| 328 |
value="teacher",
|
| 329 |
label="Weight Type",
|
| 330 |
info="LeJEPA always uses student",
|
| 331 |
+
interactive=True,
|
| 332 |
)
|
| 333 |
|
| 334 |
opt_size = gr.Dropdown(
|
| 335 |
choices=["224", "448", "672", "1280"],
|
| 336 |
value="672",
|
| 337 |
label="Image Target Resolution",
|
| 338 |
+
interactive=True,
|
| 339 |
)
|
| 340 |
|
| 341 |
run_btn = gr.Button("Visualise", variant="primary")
|
|
|
|
| 360 |
with gr.Row(equal_height=True):
|
| 361 |
with gr.Column(elem_classes="output-col"):
|
| 362 |
gr.HTML(
|
| 363 |
+
f'<div class="model-label"><a href="https://huggingface.co/{MODEL_IDS["ViT-S/16"]["DiNO"]}" target="_blank">DiNO (S/16)</a></div>'
|
| 364 |
+
)
|
| 365 |
out_dino_s = gr.Image(show_label=False, interactive=False)
|
| 366 |
with gr.Column(elem_classes="output-col"):
|
| 367 |
gr.HTML(
|
| 368 |
+
f'<div class="model-label"><a href="https://huggingface.co/{MODEL_IDS["ViT-S/16"]["iBOT"]}" target="_blank">iBOT (S/16)</a></div>'
|
| 369 |
+
)
|
| 370 |
out_ibot_s = gr.Image(show_label=False, interactive=False)
|
| 371 |
with gr.Column(elem_classes="output-col"):
|
| 372 |
gr.HTML(
|
| 373 |
+
f'<div class="model-label"><a href="https://huggingface.co/{MODEL_IDS["ViT-S/16"]["LeJEPA"]}" target="_blank">LeJEPA (S/16)</a></div>'
|
| 374 |
+
)
|
| 375 |
out_lejepa_s = gr.Image(show_label=False, interactive=False)
|
| 376 |
|
| 377 |
# ββ ViT-B/16 Row ββ
|
|
|
|
| 379 |
with gr.Row(equal_height=True):
|
| 380 |
with gr.Column(elem_classes="output-col"):
|
| 381 |
gr.HTML(
|
| 382 |
+
f'<div class="model-label"><a href="https://huggingface.co/{MODEL_IDS["ViT-B/16"]["DiNO"]}" target="_blank">DiNO (B/16)</a></div>'
|
| 383 |
+
)
|
| 384 |
out_dino_b = gr.Image(show_label=False, interactive=False)
|
| 385 |
with gr.Column(elem_classes="output-col"):
|
| 386 |
gr.HTML(
|
| 387 |
+
f'<div class="model-label"><a href="https://huggingface.co/{MODEL_IDS["ViT-B/16"]["iBOT"]}" target="_blank">iBOT (B/16)</a></div>'
|
| 388 |
+
)
|
| 389 |
out_ibot_b = gr.Image(show_label=False, interactive=False)
|
| 390 |
with gr.Column(elem_classes="output-col"):
|
| 391 |
gr.HTML(
|
| 392 |
+
f'<div class="model-label"><a href="https://huggingface.co/{MODEL_IDS["ViT-B/16"]["LeJEPA"]}" target="_blank">LeJEPA (B/16)</a></div>'
|
| 393 |
+
)
|
| 394 |
out_lejepa_b = gr.Image(show_label=False, interactive=False)
|
| 395 |
|
| 396 |
# Wire outputs orderly following the exact resolution pattern tracking inside the `run` loop
|
| 397 |
output_targets = [
|
| 398 |
+
out_dino_s,
|
| 399 |
+
out_ibot_s,
|
| 400 |
+
out_lejepa_s,
|
| 401 |
+
out_dino_b,
|
| 402 |
+
out_ibot_b,
|
| 403 |
+
out_lejepa_b,
|
| 404 |
]
|
| 405 |
|
| 406 |
run_btn.click(
|