Spaces:
Running
on
L4
Running
on
L4
Commit
·
d5a5fa0
1
Parent(s):
20241dd
Update image assets and refactor app.py for improved functionality. Added new images, removed outdated ones, and updated paths in IMAGE_PATHS. Renamed render_demo3 function to render_demonstrate for clarity. Adjusted UI styles and fixed image loading issues.
Browse files- .gitattributes +4 -0
- app.py +118 -184
- test_samples/{oxford.jpeg → arc_de_tromphe.jpeg} +2 -2
- test_samples/jesus.jpg +2 -2
- test_samples/{friends.jpg → living_room.jpg} +2 -2
- test_samples/living_room_2.jpeg +3 -0
- test_samples/open_door.jpg +2 -2
- test_samples/oxford.jpg +3 -0
.gitattributes
CHANGED
@@ -38,3 +38,7 @@ test_samples/oxford.jpeg filter=lfs diff=lfs merge=lfs -text
|
|
38 |
test_samples/changi.jpg filter=lfs diff=lfs merge=lfs -text
|
39 |
test_samples/friends.jpg filter=lfs diff=lfs merge=lfs -text
|
40 |
test_samples/jesus.jpg filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
38 |
test_samples/changi.jpg filter=lfs diff=lfs merge=lfs -text
|
39 |
test_samples/friends.jpg filter=lfs diff=lfs merge=lfs -text
|
40 |
test_samples/jesus.jpg filter=lfs diff=lfs merge=lfs -text
|
41 |
+
test_samples/living_room_2.jpeg filter=lfs diff=lfs merge=lfs -text
|
42 |
+
test_samples/living_room.jpg filter=lfs diff=lfs merge=lfs -text
|
43 |
+
test_samples/oxford.jpg filter=lfs diff=lfs merge=lfs -text
|
44 |
+
test_samples/arc_de_tromphe.jpeg filter=lfs diff=lfs merge=lfs -text
|
app.py
CHANGED
@@ -27,6 +27,7 @@ import glob
|
|
27 |
|
28 |
|
29 |
|
|
|
30 |
CONFIG_PATH = "configs/inference/inference.yaml"
|
31 |
CONFIG = OmegaConf.load(CONFIG_PATH)
|
32 |
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
@@ -39,12 +40,13 @@ WIDTH = 576
|
|
39 |
HEIGHT = 576
|
40 |
|
41 |
|
42 |
-
IMAGE_PATHS = ['test_samples/
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
|
|
48 |
|
49 |
# If no images found, create placeholders
|
50 |
if not IMAGE_PATHS:
|
@@ -52,7 +54,6 @@ if not IMAGE_PATHS:
|
|
52 |
"""Create placeholder images for the demo"""
|
53 |
images = []
|
54 |
for i in range(num_samples):
|
55 |
-
# Create a gradient image as placeholder
|
56 |
img = np.zeros((height, width, 3), dtype=np.uint8)
|
57 |
for h in range(height):
|
58 |
for w in range(width):
|
@@ -314,13 +315,13 @@ def undo_navigation(
|
|
314 |
|
315 |
|
316 |
|
317 |
-
def
|
318 |
s: Literal["Selection", "Generation"],
|
319 |
idx: int,
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
):
|
325 |
gr.Markdown(
|
326 |
"""
|
@@ -377,17 +378,20 @@ def render_demo3(
|
|
377 |
upload_btn.click(
|
378 |
fn=process_uploaded_image,
|
379 |
inputs=[upload_image],
|
380 |
-
outputs=[
|
381 |
)
|
382 |
|
383 |
gr.Markdown("### Or Choose From Our Examples")
|
384 |
# Define image captions
|
385 |
image_captions = {
|
386 |
-
|
387 |
-
'test_samples/oxford.
|
388 |
'test_samples/open_door.jpg': 'Bedroom Interior',
|
|
|
|
|
|
|
389 |
'test_samples/jesus.jpg': 'Jesus College',
|
390 |
-
'test_samples/
|
391 |
}
|
392 |
|
393 |
# Load all images for the gallery with captions
|
@@ -401,7 +405,7 @@ def render_demo3(
|
|
401 |
print(f"Error loading image {img_path}: {e}")
|
402 |
|
403 |
# Show image gallery for selection
|
404 |
-
|
405 |
value=gallery_images,
|
406 |
label="Select an Image to Start Navigation",
|
407 |
columns=len(gallery_images),
|
@@ -436,22 +440,22 @@ def render_demo3(
|
|
436 |
gr.Warning(f"Error starting navigation: {e}")
|
437 |
return "Selection", None, None, None
|
438 |
|
439 |
-
|
440 |
fn=start_navigation,
|
441 |
inputs=None,
|
442 |
-
outputs=[
|
443 |
)
|
444 |
|
445 |
case "Generation":
|
446 |
with gr.Row():
|
447 |
with gr.Column(scale=3):
|
448 |
with gr.Row():
|
449 |
-
|
450 |
label="Current View",
|
451 |
width=256,
|
452 |
height=256,
|
453 |
)
|
454 |
-
|
455 |
label="Generated Video",
|
456 |
width=256,
|
457 |
height=256,
|
@@ -461,7 +465,7 @@ def render_demo3(
|
|
461 |
show_download_button=True,
|
462 |
)
|
463 |
|
464 |
-
|
465 |
value=[],
|
466 |
label="Generated Frames",
|
467 |
columns=[6],
|
@@ -472,7 +476,7 @@ def render_demo3(
|
|
472 |
try:
|
473 |
selected_path = IMAGE_PATHS[idx]
|
474 |
result = load_image_for_navigation(selected_path)
|
475 |
-
|
476 |
except Exception as e:
|
477 |
print(f"Error initializing current view: {e}")
|
478 |
|
@@ -503,15 +507,15 @@ def render_demo3(
|
|
503 |
distance=0,
|
504 |
),
|
505 |
inputs=[
|
506 |
-
|
507 |
-
|
508 |
],
|
509 |
outputs=[
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
],
|
516 |
)
|
517 |
|
@@ -528,42 +532,18 @@ def render_demo3(
|
|
528 |
distance=0,
|
529 |
),
|
530 |
inputs=[
|
531 |
-
|
532 |
-
|
533 |
],
|
534 |
outputs=[
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
],
|
541 |
)
|
542 |
|
543 |
-
# gr.Button(
|
544 |
-
# "↑0°\nAhead",
|
545 |
-
# size="sm",
|
546 |
-
# min_width=0,
|
547 |
-
# variant="primary",
|
548 |
-
# ).click(
|
549 |
-
# fn=partial(
|
550 |
-
# navigate_video,
|
551 |
-
# x_angle=0,
|
552 |
-
# y_angle=0,
|
553 |
-
# distance=10,
|
554 |
-
# ),
|
555 |
-
# inputs=[
|
556 |
-
# demo3_current_video,
|
557 |
-
# demo3_current_poses,
|
558 |
-
# ],
|
559 |
-
# outputs=[
|
560 |
-
# demo3_current_video,
|
561 |
-
# demo3_current_poses,
|
562 |
-
# demo3_current_view,
|
563 |
-
# demo3_video,
|
564 |
-
# demo3_generated_gallery,
|
565 |
-
# ],
|
566 |
-
# )
|
567 |
gr.Button(
|
568 |
"↗10°\nTurn",
|
569 |
size="sm",
|
@@ -577,15 +557,15 @@ def render_demo3(
|
|
577 |
distance=0,
|
578 |
),
|
579 |
inputs=[
|
580 |
-
|
581 |
-
|
582 |
],
|
583 |
outputs=[
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
],
|
590 |
)
|
591 |
gr.Button(
|
@@ -601,15 +581,15 @@ def render_demo3(
|
|
601 |
distance=0,
|
602 |
),
|
603 |
inputs=[
|
604 |
-
|
605 |
-
|
606 |
],
|
607 |
outputs=[
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
],
|
614 |
)
|
615 |
|
@@ -628,15 +608,15 @@ def render_demo3(
|
|
628 |
distance=-10,
|
629 |
),
|
630 |
inputs=[
|
631 |
-
|
632 |
-
|
633 |
],
|
634 |
outputs=[
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
],
|
641 |
)
|
642 |
|
@@ -653,78 +633,30 @@ def render_demo3(
|
|
653 |
distance=10,
|
654 |
),
|
655 |
inputs=[
|
656 |
-
|
657 |
-
|
658 |
],
|
659 |
outputs=[
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
],
|
666 |
)
|
667 |
-
# with gr.Tab("Advanced", elem_id="advanced-controls-tab"):
|
668 |
-
# with gr.Group():
|
669 |
-
# gr.Markdown("_**Select angles and distance:**_")
|
670 |
-
|
671 |
-
# demo3_y_angle = gr.Slider(
|
672 |
-
# minimum=-90,
|
673 |
-
# maximum=90,
|
674 |
-
# value=0,
|
675 |
-
# step=10,
|
676 |
-
# label="Horizontal Angle",
|
677 |
-
# interactive=True,
|
678 |
-
# )
|
679 |
-
# demo3_x_angle = gr.Slider(
|
680 |
-
# minimum=-40,
|
681 |
-
# maximum=40,
|
682 |
-
# value=0,
|
683 |
-
# step=10,
|
684 |
-
# label="Vertical Angle",
|
685 |
-
# interactive=True,
|
686 |
-
# )
|
687 |
-
# demo3_distance = gr.Slider(
|
688 |
-
# minimum=-200,
|
689 |
-
# maximum=200,
|
690 |
-
# value=100,
|
691 |
-
# step=10,
|
692 |
-
# label="Distance (negative = backward)",
|
693 |
-
# interactive=True,
|
694 |
-
# )
|
695 |
-
|
696 |
-
# gr.Button(
|
697 |
-
# "Generate Next Move", variant="primary"
|
698 |
-
# ).click(
|
699 |
-
# fn=navigate_video,
|
700 |
-
# inputs=[
|
701 |
-
# demo3_current_video,
|
702 |
-
# demo3_current_poses,
|
703 |
-
# demo3_x_angle,
|
704 |
-
# demo3_y_angle,
|
705 |
-
# demo3_distance,
|
706 |
-
# ],
|
707 |
-
# outputs=[
|
708 |
-
# demo3_current_video,
|
709 |
-
# demo3_current_poses,
|
710 |
-
# demo3_current_view,
|
711 |
-
# demo3_video,
|
712 |
-
# demo3_generated_gallery,
|
713 |
-
# ],
|
714 |
-
# )
|
715 |
gr.Markdown("---")
|
716 |
with gr.Group():
|
717 |
gr.Markdown("_**Navigation controls:**_")
|
718 |
with gr.Row():
|
719 |
gr.Button("Undo Last Move", variant="huggingface").click(
|
720 |
fn=undo_navigation,
|
721 |
-
inputs=[
|
722 |
outputs=[
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
],
|
729 |
)
|
730 |
|
@@ -741,7 +673,7 @@ def render_demo3(
|
|
741 |
|
742 |
gr.Button("Save Camera", variant="huggingface").click(
|
743 |
fn=save_camera_poses,
|
744 |
-
inputs=[
|
745 |
outputs=[]
|
746 |
)
|
747 |
|
@@ -755,12 +687,12 @@ def render_demo3(
|
|
755 |
gr.Button("Choose New Image", variant="secondary").click(
|
756 |
fn=reset_navigation,
|
757 |
inputs=[],
|
758 |
-
outputs=[
|
759 |
)
|
760 |
|
761 |
|
762 |
# Create the Gradio Blocks
|
763 |
-
with gr.Blocks(theme=gr.themes.Base(primary_hue="
|
764 |
gr.HTML(
|
765 |
"""
|
766 |
<style>
|
@@ -769,10 +701,10 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue="teal")) as demo:
|
|
769 |
font-weight: bold;
|
770 |
}
|
771 |
#page-title h1 {
|
772 |
-
color: #
|
773 |
}
|
774 |
.task-title h2 {
|
775 |
-
color: #
|
776 |
}
|
777 |
.header-button-row {
|
778 |
gap: 4px !important;
|
@@ -785,7 +717,7 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue="teal")) as demo:
|
|
785 |
gap: 5px !important;
|
786 |
}
|
787 |
.header-button a {
|
788 |
-
border: 1px solid #
|
789 |
}
|
790 |
.header-button .button-icon {
|
791 |
margin-right: 8px;
|
@@ -808,7 +740,7 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue="teal")) as demo:
|
|
808 |
margin-top: 8px;
|
809 |
}
|
810 |
#selected-demo-button {
|
811 |
-
color: #
|
812 |
text-decoration: underline;
|
813 |
}
|
814 |
.demo-button {
|
@@ -828,17 +760,17 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue="teal")) as demo:
|
|
828 |
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
829 |
}
|
830 |
#navigation-gallery .gallery-item.selected {
|
831 |
-
border: 3px solid #
|
832 |
}
|
833 |
/* Upload image styling */
|
834 |
#upload-image {
|
835 |
border-radius: 8px;
|
836 |
-
border: 2px dashed #
|
837 |
padding: 10px;
|
838 |
transition: all 0.3s ease;
|
839 |
}
|
840 |
#upload-image:hover {
|
841 |
-
border-color: #
|
842 |
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
843 |
}
|
844 |
/* Box styling */
|
@@ -846,8 +778,28 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue="teal")) as demo:
|
|
846 |
border-radius: 10px;
|
847 |
margin-bottom: 20px;
|
848 |
padding: 15px;
|
849 |
-
background-color: #
|
850 |
-
border: 1px solid #
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
851 |
}
|
852 |
</style>
|
853 |
"""
|
@@ -856,9 +808,9 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue="teal")) as demo:
|
|
856 |
demo_idx = gr.State(value=3)
|
857 |
|
858 |
with gr.Sidebar():
|
859 |
-
gr.Markdown("# VMem: Consistent Scene Generation with Surfel Memory
|
860 |
gr.Markdown(
|
861 |
-
"### Official Interactive Demo for [_VMem_](https://arxiv.org/abs/2502.06764)"
|
862 |
)
|
863 |
gr.Markdown("---")
|
864 |
gr.Markdown("#### Links ↓")
|
@@ -898,40 +850,22 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue="teal")) as demo:
|
|
898 |
min_width=0,
|
899 |
)
|
900 |
gr.Markdown("---")
|
901 |
-
gr.Markdown("
|
902 |
-
|
903 |
-
@gr.render(inputs=[demo_idx])
|
904 |
-
def render_demo_tabs(idx):
|
905 |
-
demo_tab_button3 = gr.Button(
|
906 |
-
"Navigate Image",
|
907 |
-
size="md", elem_classes=["demo-button"], **{"elem_id": "selected-demo-button"} if idx == 3 else {}
|
908 |
-
).click(
|
909 |
-
fn=lambda: 3,
|
910 |
-
outputs=demo_idx
|
911 |
-
)
|
912 |
-
gr.Markdown("---")
|
913 |
-
gr.Markdown("#### Troubleshooting ↓")
|
914 |
-
with gr.Group():
|
915 |
-
with gr.Accordion("Error or Unexpected Results?", open=False):
|
916 |
-
gr.Markdown("Please try again after refreshing the page and ensure you do not click the same button multiple times.")
|
917 |
-
with gr.Accordion("Too Slow or No GPU Allocation?", open=False):
|
918 |
-
gr.Markdown(
|
919 |
-
"Consider running the demo locally (click the dots in the top-right corner). Alternatively, you can subscribe to Hugging Face Pro for an increased GPU quota."
|
920 |
-
)
|
921 |
|
922 |
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
|
928 |
-
@gr.render(inputs=[demo_idx,
|
929 |
def render_demo(
|
930 |
-
_demo_idx,
|
931 |
):
|
932 |
match _demo_idx:
|
933 |
case 3:
|
934 |
-
|
935 |
|
936 |
|
937 |
if __name__ == "__main__":
|
|
|
27 |
|
28 |
|
29 |
|
30 |
+
|
31 |
CONFIG_PATH = "configs/inference/inference.yaml"
|
32 |
CONFIG = OmegaConf.load(CONFIG_PATH)
|
33 |
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
|
|
40 |
HEIGHT = 576
|
41 |
|
42 |
|
43 |
+
IMAGE_PATHS = ['test_samples/oxford.jpg',
|
44 |
+
'test_samples/open_door.jpg',
|
45 |
+
'test_samples/living_room.jpg',
|
46 |
+
'test_samples/living_room_2.jpeg',
|
47 |
+
'test_samples/arc_de_tromphe.jpeg',
|
48 |
+
'test_samples/changi.jpg',
|
49 |
+
'test_samples/jesus.jpg',]
|
50 |
|
51 |
# If no images found, create placeholders
|
52 |
if not IMAGE_PATHS:
|
|
|
54 |
"""Create placeholder images for the demo"""
|
55 |
images = []
|
56 |
for i in range(num_samples):
|
|
|
57 |
img = np.zeros((height, width, 3), dtype=np.uint8)
|
58 |
for h in range(height):
|
59 |
for w in range(width):
|
|
|
315 |
|
316 |
|
317 |
|
318 |
+
def render_demonstrate(
|
319 |
s: Literal["Selection", "Generation"],
|
320 |
idx: int,
|
321 |
+
demonstrate_stage: gr.State,
|
322 |
+
demonstrate_selected_index: gr.State,
|
323 |
+
demonstrate_current_video: gr.State,
|
324 |
+
demonstrate_current_poses: gr.State
|
325 |
):
|
326 |
gr.Markdown(
|
327 |
"""
|
|
|
378 |
upload_btn.click(
|
379 |
fn=process_uploaded_image,
|
380 |
inputs=[upload_image],
|
381 |
+
outputs=[demonstrate_stage, demonstrate_selected_index, demonstrate_current_video, demonstrate_current_poses]
|
382 |
)
|
383 |
|
384 |
gr.Markdown("### Or Choose From Our Examples")
|
385 |
# Define image captions
|
386 |
image_captions = {
|
387 |
+
|
388 |
+
'test_samples/oxford.jpg': 'Oxford University',
|
389 |
'test_samples/open_door.jpg': 'Bedroom Interior',
|
390 |
+
'test_samples/living_room.jpg': 'Living Room',
|
391 |
+
'test_samples/living_room_2.jpeg': 'Living Room 2',
|
392 |
+
'test_samples/arc_de_tromphe.jpeg': 'Arc de Triomphe',
|
393 |
'test_samples/jesus.jpg': 'Jesus College',
|
394 |
+
'test_samples/changi.jpg': 'Changi Airport',
|
395 |
}
|
396 |
|
397 |
# Load all images for the gallery with captions
|
|
|
405 |
print(f"Error loading image {img_path}: {e}")
|
406 |
|
407 |
# Show image gallery for selection
|
408 |
+
demonstrate_image_gallery = gr.Gallery(
|
409 |
value=gallery_images,
|
410 |
label="Select an Image to Start Navigation",
|
411 |
columns=len(gallery_images),
|
|
|
440 |
gr.Warning(f"Error starting navigation: {e}")
|
441 |
return "Selection", None, None, None
|
442 |
|
443 |
+
demonstrate_image_gallery.select(
|
444 |
fn=start_navigation,
|
445 |
inputs=None,
|
446 |
+
outputs=[demonstrate_stage, demonstrate_selected_index, demonstrate_current_video, demonstrate_current_poses]
|
447 |
)
|
448 |
|
449 |
case "Generation":
|
450 |
with gr.Row():
|
451 |
with gr.Column(scale=3):
|
452 |
with gr.Row():
|
453 |
+
demonstrate_current_view = gr.Image(
|
454 |
label="Current View",
|
455 |
width=256,
|
456 |
height=256,
|
457 |
)
|
458 |
+
demonstrate_video = gr.Video(
|
459 |
label="Generated Video",
|
460 |
width=256,
|
461 |
height=256,
|
|
|
465 |
show_download_button=True,
|
466 |
)
|
467 |
|
468 |
+
demonstrate_generated_gallery = gr.Gallery(
|
469 |
value=[],
|
470 |
label="Generated Frames",
|
471 |
columns=[6],
|
|
|
476 |
try:
|
477 |
selected_path = IMAGE_PATHS[idx]
|
478 |
result = load_image_for_navigation(selected_path)
|
479 |
+
demonstrate_current_view.value = result["image"]
|
480 |
except Exception as e:
|
481 |
print(f"Error initializing current view: {e}")
|
482 |
|
|
|
507 |
distance=0,
|
508 |
),
|
509 |
inputs=[
|
510 |
+
demonstrate_current_video,
|
511 |
+
demonstrate_current_poses,
|
512 |
],
|
513 |
outputs=[
|
514 |
+
demonstrate_current_video,
|
515 |
+
demonstrate_current_poses,
|
516 |
+
demonstrate_current_view,
|
517 |
+
demonstrate_video,
|
518 |
+
demonstrate_generated_gallery,
|
519 |
],
|
520 |
)
|
521 |
|
|
|
532 |
distance=0,
|
533 |
),
|
534 |
inputs=[
|
535 |
+
demonstrate_current_video,
|
536 |
+
demonstrate_current_poses,
|
537 |
],
|
538 |
outputs=[
|
539 |
+
demonstrate_current_video,
|
540 |
+
demonstrate_current_poses,
|
541 |
+
demonstrate_current_view,
|
542 |
+
demonstrate_video,
|
543 |
+
demonstrate_generated_gallery,
|
544 |
],
|
545 |
)
|
546 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
547 |
gr.Button(
|
548 |
"↗10°\nTurn",
|
549 |
size="sm",
|
|
|
557 |
distance=0,
|
558 |
),
|
559 |
inputs=[
|
560 |
+
demonstrate_current_video,
|
561 |
+
demonstrate_current_poses,
|
562 |
],
|
563 |
outputs=[
|
564 |
+
demonstrate_current_video,
|
565 |
+
demonstrate_current_poses,
|
566 |
+
demonstrate_current_view,
|
567 |
+
demonstrate_video,
|
568 |
+
demonstrate_generated_gallery,
|
569 |
],
|
570 |
)
|
571 |
gr.Button(
|
|
|
581 |
distance=0,
|
582 |
),
|
583 |
inputs=[
|
584 |
+
demonstrate_current_video,
|
585 |
+
demonstrate_current_poses,
|
586 |
],
|
587 |
outputs=[
|
588 |
+
demonstrate_current_video,
|
589 |
+
demonstrate_current_poses,
|
590 |
+
demonstrate_current_view,
|
591 |
+
demonstrate_video,
|
592 |
+
demonstrate_generated_gallery,
|
593 |
],
|
594 |
)
|
595 |
|
|
|
608 |
distance=-10,
|
609 |
),
|
610 |
inputs=[
|
611 |
+
demonstrate_current_video,
|
612 |
+
demonstrate_current_poses,
|
613 |
],
|
614 |
outputs=[
|
615 |
+
demonstrate_current_video,
|
616 |
+
demonstrate_current_poses,
|
617 |
+
demonstrate_current_view,
|
618 |
+
demonstrate_video,
|
619 |
+
demonstrate_generated_gallery,
|
620 |
],
|
621 |
)
|
622 |
|
|
|
633 |
distance=10,
|
634 |
),
|
635 |
inputs=[
|
636 |
+
demonstrate_current_video,
|
637 |
+
demonstrate_current_poses,
|
638 |
],
|
639 |
outputs=[
|
640 |
+
demonstrate_current_video,
|
641 |
+
demonstrate_current_poses,
|
642 |
+
demonstrate_current_view,
|
643 |
+
demonstrate_video,
|
644 |
+
demonstrate_generated_gallery,
|
645 |
],
|
646 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
647 |
gr.Markdown("---")
|
648 |
with gr.Group():
|
649 |
gr.Markdown("_**Navigation controls:**_")
|
650 |
with gr.Row():
|
651 |
gr.Button("Undo Last Move", variant="huggingface").click(
|
652 |
fn=undo_navigation,
|
653 |
+
inputs=[demonstrate_current_video, demonstrate_current_poses],
|
654 |
outputs=[
|
655 |
+
demonstrate_current_video,
|
656 |
+
demonstrate_current_poses,
|
657 |
+
demonstrate_current_view,
|
658 |
+
demonstrate_video,
|
659 |
+
demonstrate_generated_gallery,
|
660 |
],
|
661 |
)
|
662 |
|
|
|
673 |
|
674 |
gr.Button("Save Camera", variant="huggingface").click(
|
675 |
fn=save_camera_poses,
|
676 |
+
inputs=[demonstrate_current_video, demonstrate_current_poses],
|
677 |
outputs=[]
|
678 |
)
|
679 |
|
|
|
687 |
gr.Button("Choose New Image", variant="secondary").click(
|
688 |
fn=reset_navigation,
|
689 |
inputs=[],
|
690 |
+
outputs=[demonstrate_stage, demonstrate_selected_index, demonstrate_current_video, demonstrate_current_poses]
|
691 |
)
|
692 |
|
693 |
|
694 |
# Create the Gradio Blocks
|
695 |
+
with gr.Blocks(theme=gr.themes.Base(primary_hue="purple")) as demo:
|
696 |
gr.HTML(
|
697 |
"""
|
698 |
<style>
|
|
|
701 |
font-weight: bold;
|
702 |
}
|
703 |
#page-title h1 {
|
704 |
+
color: #9B6B9E !important;
|
705 |
}
|
706 |
.task-title h2 {
|
707 |
+
color: #B19CD9 !important;
|
708 |
}
|
709 |
.header-button-row {
|
710 |
gap: 4px !important;
|
|
|
717 |
gap: 5px !important;
|
718 |
}
|
719 |
.header-button a {
|
720 |
+
border: 1px solid #9B6B9E;
|
721 |
}
|
722 |
.header-button .button-icon {
|
723 |
margin-right: 8px;
|
|
|
740 |
margin-top: 8px;
|
741 |
}
|
742 |
#selected-demo-button {
|
743 |
+
color: #B19CD9;
|
744 |
text-decoration: underline;
|
745 |
}
|
746 |
.demo-button {
|
|
|
760 |
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
761 |
}
|
762 |
#navigation-gallery .gallery-item.selected {
|
763 |
+
border: 3px solid #9B6B9E;
|
764 |
}
|
765 |
/* Upload image styling */
|
766 |
#upload-image {
|
767 |
border-radius: 8px;
|
768 |
+
border: 2px dashed #9B6B9E;
|
769 |
padding: 10px;
|
770 |
transition: all 0.3s ease;
|
771 |
}
|
772 |
#upload-image:hover {
|
773 |
+
border-color: #9B6B9E;
|
774 |
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
775 |
}
|
776 |
/* Box styling */
|
|
|
778 |
border-radius: 10px;
|
779 |
margin-bottom: 20px;
|
780 |
padding: 15px;
|
781 |
+
background-color: #9B6B9E;
|
782 |
+
border: 1px solid #9B6B9E;
|
783 |
+
}
|
784 |
+
/* Start Navigation button styling */
|
785 |
+
button[data-testid="Start Navigation"] {
|
786 |
+
background-color: #B19CD9 !important;
|
787 |
+
border-color: #B19CD9 !important;
|
788 |
+
color: white !important;
|
789 |
+
}
|
790 |
+
button[data-testid="Start Navigation"]:hover {
|
791 |
+
background-color: #9B6B9E !important;
|
792 |
+
border-color: #9B6B9E !important;
|
793 |
+
}
|
794 |
+
/* Override Gradio's primary button color */
|
795 |
+
.gradio-button.primary {
|
796 |
+
background-color: #B19CD9 !important;
|
797 |
+
border-color: #B19CD9 !important;
|
798 |
+
color: white !important;
|
799 |
+
}
|
800 |
+
.gradio-button.primary:hover {
|
801 |
+
background-color: #9B6B9E !important;
|
802 |
+
border-color: #9B6B9E !important;
|
803 |
}
|
804 |
</style>
|
805 |
"""
|
|
|
808 |
demo_idx = gr.State(value=3)
|
809 |
|
810 |
with gr.Sidebar():
|
811 |
+
gr.Markdown("# VMem: Consistent Video Scene Generation with Surfel-Indexed View Memory", elem_id="page-title")
|
812 |
gr.Markdown(
|
813 |
+
"### Official Interactive Demo for [_VMem_](https://arxiv.org/abs/2502.06764) that enables interactive consistent video scene generation."
|
814 |
)
|
815 |
gr.Markdown("---")
|
816 |
gr.Markdown("#### Links ↓")
|
|
|
850 |
min_width=0,
|
851 |
)
|
852 |
gr.Markdown("---")
|
853 |
+
gr.Markdown("This demo interface is adapted from the History-Guided Video Diffusion demo template. We thank the authors for their work.")
|
854 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
855 |
|
856 |
|
857 |
+
demonstrate_stage = gr.State(value="Selection")
|
858 |
+
demonstrate_selected_index = gr.State(value=None)
|
859 |
+
demonstrate_current_video = gr.State(value=None)
|
860 |
+
demonstrate_current_poses = gr.State(value=None)
|
861 |
|
862 |
+
@gr.render(inputs=[demo_idx, demonstrate_stage, demonstrate_selected_index])
|
863 |
def render_demo(
|
864 |
+
_demo_idx, _demonstrate_stage, _demonstrate_selected_index
|
865 |
):
|
866 |
match _demo_idx:
|
867 |
case 3:
|
868 |
+
render_demonstrate(_demonstrate_stage, _demonstrate_selected_index, demonstrate_stage, demonstrate_selected_index, demonstrate_current_video, demonstrate_current_poses)
|
869 |
|
870 |
|
871 |
if __name__ == "__main__":
|
test_samples/{oxford.jpeg → arc_de_tromphe.jpeg}
RENAMED
File without changes
|
test_samples/jesus.jpg
CHANGED
![]() |
Git LFS Details
|
![]() |
Git LFS Details
|
test_samples/{friends.jpg → living_room.jpg}
RENAMED
File without changes
|
test_samples/living_room_2.jpeg
ADDED
![]() |
Git LFS Details
|
test_samples/open_door.jpg
CHANGED
![]() |
Git LFS Details
|
![]() |
Git LFS Details
|
test_samples/oxford.jpg
ADDED
![]() |
Git LFS Details
|