Julien Blanchon commited on
Commit
195ceb2
·
1 Parent(s): e732b53
Files changed (4) hide show
  1. gradio_app.py +258 -307
  2. pyproject.docker.toml +1 -0
  3. pyproject.toml +1 -0
  4. uv.lock +34 -0
gradio_app.py CHANGED
@@ -8,20 +8,9 @@ import shutil
8
  from typing import Generator, Optional, Tuple
9
  import logging
10
 
11
- try:
12
- import gradio as gr
13
- except ImportError:
14
- print("❌ Gradio not found. Please install it with: pip install gradio>=4.0.0")
15
- sys.exit(1)
16
-
17
- try:
18
- from huggingface_hub import hf_hub_download, snapshot_download
19
- except ImportError:
20
- print(
21
- "❌ huggingface_hub not found. Please install it with: pip install huggingface_hub"
22
- )
23
- sys.exit(1)
24
-
25
  import torch
26
  from PIL import Image
27
 
@@ -57,9 +46,6 @@ training_state = TrainingState()
57
 
58
  def ensure_models_available():
59
  """Download models from HuggingFace if they're not available locally"""
60
- models_dir = "models"
61
-
62
- # Check if models directory exists and has the required files
63
  required_files = [
64
  "models/emlnet/res_decoder.pth",
65
  "models/emlnet/res_imagenet.pth",
@@ -115,6 +101,11 @@ def ensure_models_available():
115
  print("✅ Model files are already available locally.")
116
 
117
 
 
 
 
 
 
118
  def create_args_from_config(
119
  image_path: str,
120
  exp_name: str,
@@ -177,8 +168,9 @@ def create_args_from_config(
177
  return args
178
 
179
 
 
180
  def train_model(args: argparse.Namespace) -> None:
181
- """Training function that runs in a separate thread"""
182
  try:
183
  # Create and train model with streaming results
184
  training_state.model = GradioGaussianSplatting2D(args, training_state.results)
@@ -351,21 +343,6 @@ def start_training_and_stream(
351
  f"Loss: {metrics['loss']:.4f}"
352
  )
353
  logs_text += status_line
354
-
355
- # Add image status info for debugging
356
- if training_state.results.current_render is not None:
357
- logs_text += f"\n📸 Current render: {training_state.results.current_render.size}"
358
- else:
359
- logs_text += "\n📸 Current render: None"
360
-
361
- if training_state.results.current_gaussian_id is not None:
362
- logs_text += f"\n🆔 Gaussian ID: {training_state.results.current_gaussian_id.size}"
363
- else:
364
- logs_text += "\n🆔 Gaussian ID: None"
365
-
366
- logs_text += (
367
- f"\n💾 Stored steps: {len(training_state.results.step_renders)}"
368
- )
369
  else:
370
  logs_text = "Waiting for training to start..."
371
 
@@ -509,307 +486,281 @@ def update_step_slider_after_training() -> gr.Slider:
509
  )
510
 
511
 
512
- def create_interface():
513
- """Create the Gradio interface"""
514
-
515
- with gr.Blocks(
516
- title="Image-GS: 2D Gaussian Splatting", theme=gr.themes.Soft()
517
- ) as demo:
518
- gr.Markdown("""
519
- # Image-GS: Content-Adaptive Image Representation via 2D Gaussians
520
-
521
- Upload an image and configure parameters to train a 2D Gaussian Splatting representation.
522
- """)
523
-
524
- with gr.Row():
525
- with gr.Column(scale=1):
526
- gr.Markdown("## Configuration")
 
 
 
 
 
527
 
528
- # Image upload
529
- image_input = gr.Image(
530
- label="Input Image",
531
- type="pil",
532
- height=300,
533
- sources=["upload"],
534
- show_label=True,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
535
  )
536
 
537
- # Basic parameters
538
- with gr.Group():
539
- gr.Markdown("### Basic Parameters")
540
- exp_name = gr.Textbox(
541
- label="Experiment Name",
542
- value="gradio_experiment",
543
- info="Name for this training run",
544
- )
545
- num_gaussians = gr.Slider(
546
- minimum=100,
547
- maximum=50000,
548
- value=10000,
549
- step=1000,
550
- label="Number of Gaussians",
551
- info="Number of Gaussians (for compression rate control). More = higher quality but slower training",
552
- )
553
- max_steps = gr.Slider(
554
- minimum=100,
555
- maximum=20000,
556
- value=10000,
557
- step=100,
558
- label="Maximum Training Steps",
559
- info="Maximum number of optimization steps. Default: 10000",
560
- )
561
-
562
- # Quantization parameters
563
- with gr.Group():
564
- gr.Markdown("### Quantization")
565
- quantize = gr.Checkbox(
566
- label="Enable Quantization",
567
- value=False,
568
- info="Enable bit precision control of Gaussian parameters. Reduces memory usage.",
569
- )
570
- with gr.Row():
571
- pos_bits = gr.Slider(
572
- 4,
573
- 32,
574
- 16,
575
- step=1,
576
- label="Position Bits",
577
- info="Bit precision of individual coordinate dimension",
578
- )
579
- scale_bits = gr.Slider(
580
- 4,
581
- 32,
582
- 16,
583
- step=1,
584
- label="Scale Bits",
585
- info="Bit precision of individual scale dimension",
586
- )
587
- with gr.Row():
588
- rot_bits = gr.Slider(
589
- 4,
590
- 32,
591
- 16,
592
- step=1,
593
- label="Rotation Bits",
594
- info="Bit precision of Gaussian orientation angle",
595
- )
596
- feat_bits = gr.Slider(
597
- 4,
598
- 32,
599
- 16,
600
- step=1,
601
- label="Feature Bits",
602
- info="Bit precision of individual feature dimension",
603
- )
604
-
605
- # Initialization parameters
606
- with gr.Group():
607
- gr.Markdown("### Initialization")
608
- init_mode = gr.Radio(
609
- choices=["gradient", "saliency", "random"],
610
- value="saliency",
611
- label="Initialization Mode",
612
- info="Gaussian position initialization mode. Gradient uses image gradients, saliency uses attention maps.",
613
  )
614
- init_random_ratio = gr.Slider(
615
- minimum=0.0,
616
- maximum=1.0,
617
- value=0.3,
618
- step=0.1,
619
- label="Random Ratio",
620
- info="Ratio of Gaussians with randomly initialized position (default: 0.3)",
621
  )
622
-
623
- # Advanced parameters (collapsible)
624
- with gr.Accordion("Advanced Parameters", open=False):
625
- # Loss parameters
626
- gr.Markdown("#### Loss Weights")
627
- with gr.Row():
628
- l1_loss_ratio = gr.Slider(
629
- 0.0, 2.0, 1.0, step=0.1, label="L1 Loss"
630
- )
631
- l2_loss_ratio = gr.Slider(
632
- 0.0, 2.0, 0.0, step=0.1, label="L2 Loss"
633
- )
634
- ssim_loss_ratio = gr.Slider(
635
- 0.0, 1.0, 0.1, step=0.01, label="SSIM Loss"
636
- )
637
-
638
- # Learning rates
639
- gr.Markdown("#### Learning Rates")
640
- with gr.Row():
641
- pos_lr = gr.Number(value=5e-4, label="Position LR", precision=6)
642
- scale_lr = gr.Number(value=2e-3, label="Scale LR", precision=6)
643
- with gr.Row():
644
- rot_lr = gr.Number(value=2e-3, label="Rotation LR", precision=6)
645
- feat_lr = gr.Number(value=5e-3, label="Feature LR", precision=6)
646
-
647
- # Optimization options
648
- gr.Markdown("#### Optimization")
649
- disable_lr_schedule = gr.Checkbox(
650
- label="Disable LR Schedule",
651
- value=False,
652
- info="Keep learning rate constant",
653
  )
654
- disable_prog_optim = gr.Checkbox(
655
- label="Disable Progressive Optimization",
656
- value=False,
657
- info="Don't add Gaussians during training",
 
 
 
658
  )
659
 
660
- # Visualization parameters
661
- with gr.Group():
662
- gr.Markdown("### Visualization")
663
- vis_gaussians = gr.Checkbox(
664
- label="Visualize Gaussians",
665
- value=True,
666
- info="Visualize Gaussians during optimization (default: True)",
667
- )
668
- save_image_steps = gr.Slider(
669
- minimum=200,
670
- maximum=10000,
671
- value=200,
672
- step=100,
673
- label="Save Image Every N Steps",
674
- info="Frequency of rendering intermediate results during optimization (default: 100)",
675
- )
 
676
 
677
- # Control buttons
 
 
 
678
  with gr.Row():
679
- start_btn = gr.Button(
680
- "Start Training", variant="primary", size="lg"
 
 
681
  )
682
- stop_btn = gr.Button("Stop Training", variant="stop", size="lg")
683
-
684
- status_text = gr.Textbox(label="Status", interactive=False, lines=2)
685
-
686
- with gr.Column(scale=2):
687
- gr.Markdown("## Training Progress")
688
 
689
- # Progress logs (streaming)
690
- progress_logs = gr.Textbox(
691
- label="Training Logs",
692
- lines=10,
693
- max_lines=15,
694
- interactive=False,
695
- autoscroll=True,
 
 
 
 
 
 
 
 
696
  )
697
-
698
- # Initial map (computed at start based on initialization mode)
699
- gr.Markdown("### Initialization Map")
700
- initialization_map = gr.Image(
701
- label="Initialization Map",
702
- type="pil",
703
- height=200,
704
  )
705
 
706
- # Training images (streaming)
707
- gr.Markdown("### Current Training Results")
708
- with gr.Row():
709
- current_render = gr.Image(
710
- label="Current Render",
711
- type="pil",
712
- height=300,
713
- show_label=True,
714
- show_download_button=True,
715
- )
716
- current_gaussian_id = gr.Image(
717
- label="Gaussian ID",
718
- type="pil",
719
- height=300,
720
- show_label=True,
721
- show_download_button=True,
722
- )
723
-
724
- # Step slider for interactive browsing (will be updated dynamically)
725
- step_slider = gr.Slider(
726
- minimum=0,
727
  maximum=10000,
728
- value=0,
729
  step=100,
730
- label="Browse Training Steps",
731
- info="Slide to view results from different training steps (disabled during training)",
732
- interactive=False,
733
  )
734
 
735
- gr.Markdown("## Final Results")
736
- with gr.Row():
737
- final_render = gr.Image(
738
- label="Final Render", type="pil", height=300
739
- )
740
- final_checkpoint = gr.File(label="Download Final Checkpoint (.pt)")
741
 
742
- # Results buttons
743
- with gr.Row():
744
- results_btn = gr.Button("Load Final Results", size="lg")
745
- enable_slider_btn = gr.Button(
746
- "Enable Step Browsing", size="lg", variant="secondary"
747
- )
748
 
749
- # Event handlers
750
- start_btn.click(
751
- fn=start_training_and_stream,
752
- inputs=[
753
- image_input,
754
- exp_name,
755
- num_gaussians,
756
- quantize,
757
- pos_bits,
758
- scale_bits,
759
- rot_bits,
760
- feat_bits,
761
- init_mode,
762
- init_random_ratio,
763
- max_steps,
764
- vis_gaussians,
765
- save_image_steps,
766
- l1_loss_ratio,
767
- l2_loss_ratio,
768
- ssim_loss_ratio,
769
- pos_lr,
770
- scale_lr,
771
- rot_lr,
772
- feat_lr,
773
- disable_lr_schedule,
774
- disable_prog_optim,
775
- ],
776
- outputs=[
777
- status_text,
778
- progress_logs,
779
- initialization_map,
780
- current_render,
781
- current_gaussian_id,
782
- start_btn,
783
- stop_btn,
784
- ],
785
- )
786
 
787
- stop_btn.click(fn=stop_training, outputs=status_text)
 
 
 
 
 
 
 
788
 
789
- results_btn.click(
790
- fn=get_final_results, outputs=[final_render, final_checkpoint]
791
- )
 
 
 
 
792
 
793
- enable_slider_btn.click(
794
- fn=update_step_slider_after_training, outputs=[step_slider]
795
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
796
 
797
- step_slider.change(
798
- fn=browse_step_results,
799
- inputs=[step_slider],
800
- outputs=[current_render, current_gaussian_id],
801
- )
 
 
 
 
 
802
 
803
- return demo
 
 
 
804
 
 
 
 
 
 
 
805
 
806
- if __name__ == "__main__":
807
- # Ensure model files are available (download from HF if needed)
808
- ensure_models_available()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
809
 
810
- # Set torch hub directory
811
- torch.hub.set_dir("models/torch")
812
 
813
- # Create and launch the interface
814
- demo = create_interface()
815
- demo.launch(server_name="0.0.0.0", server_port=7860, share=False, debug=True)
 
 
 
 
 
 
 
8
  from typing import Generator, Optional, Tuple
9
  import logging
10
 
11
+ import gradio as gr
12
+ import spaces
13
+ from huggingface_hub import hf_hub_download
 
 
 
 
 
 
 
 
 
 
 
14
  import torch
15
  from PIL import Image
16
 
 
46
 
47
  def ensure_models_available():
48
  """Download models from HuggingFace if they're not available locally"""
 
 
 
49
  required_files = [
50
  "models/emlnet/res_decoder.pth",
51
  "models/emlnet/res_imagenet.pth",
 
101
  print("✅ Model files are already available locally.")
102
 
103
 
104
+ # Initialize models and setup at module level for ZeroGPU packing
105
+ ensure_models_available()
106
+ torch.hub.set_dir("models/torch")
107
+
108
+
109
  def create_args_from_config(
110
  image_path: str,
111
  exp_name: str,
 
168
  return args
169
 
170
 
171
+ @spaces.GPU(duration=300) # Request GPU for up to 300 seconds (5 minutes)
172
  def train_model(args: argparse.Namespace) -> None:
173
+ """Training function that runs with ZeroGPU allocation"""
174
  try:
175
  # Create and train model with streaming results
176
  training_state.model = GradioGaussianSplatting2D(args, training_state.results)
 
343
  f"Loss: {metrics['loss']:.4f}"
344
  )
345
  logs_text += status_line
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
346
  else:
347
  logs_text = "Waiting for training to start..."
348
 
 
486
  )
487
 
488
 
489
+ # Create Gradio interface at top level (best practice for Spaces)
490
+ with gr.Blocks(title="Image-GS: 2D Gaussian Splatting", theme=gr.themes.Soft()) as demo:
491
+ gr.Markdown("""
492
+ # Image-GS: Content-Adaptive Image Representation via 2D Gaussians
493
+
494
+ Upload an image and configure parameters to train a 2D Gaussian Splatting representation.
495
+ """)
496
+
497
+ with gr.Row():
498
+ with gr.Column(scale=1):
499
+ gr.Markdown("## Configuration")
500
+
501
+ # Image upload
502
+ image_input = gr.Image(
503
+ label="Input Image",
504
+ type="pil",
505
+ height=300,
506
+ sources=["upload"],
507
+ show_label=True,
508
+ )
509
 
510
+ # Basic parameters
511
+ with gr.Group():
512
+ gr.Markdown("### Basic Parameters")
513
+ exp_name = gr.Textbox(
514
+ label="Experiment Name",
515
+ value="gradio_experiment",
516
+ info="Name for this training run",
517
+ )
518
+ num_gaussians = gr.Slider(
519
+ minimum=100,
520
+ maximum=50000,
521
+ value=10000,
522
+ step=1000,
523
+ label="Number of Gaussians",
524
+ info="Number of Gaussians (for compression rate control). More = higher quality but slower training",
525
+ )
526
+ max_steps = gr.Slider(
527
+ minimum=100,
528
+ maximum=20000,
529
+ value=10000,
530
+ step=100,
531
+ label="Maximum Training Steps",
532
+ info="Maximum number of optimization steps. Default: 10000",
533
  )
534
 
535
+ # Quantization parameters
536
+ with gr.Group():
537
+ gr.Markdown("### Quantization")
538
+ quantize = gr.Checkbox(
539
+ label="Enable Quantization",
540
+ value=False,
541
+ info="Enable bit precision control of Gaussian parameters. Reduces memory usage.",
542
+ )
543
+ with gr.Row():
544
+ pos_bits = gr.Slider(
545
+ 4,
546
+ 32,
547
+ 16,
548
+ step=1,
549
+ label="Position Bits",
550
+ info="Bit precision of individual coordinate dimension",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
551
  )
552
+ scale_bits = gr.Slider(
553
+ 4,
554
+ 32,
555
+ 16,
556
+ step=1,
557
+ label="Scale Bits",
558
+ info="Bit precision of individual scale dimension",
559
  )
560
+ with gr.Row():
561
+ rot_bits = gr.Slider(
562
+ 4,
563
+ 32,
564
+ 16,
565
+ step=1,
566
+ label="Rotation Bits",
567
+ info="Bit precision of Gaussian orientation angle",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
568
  )
569
+ feat_bits = gr.Slider(
570
+ 4,
571
+ 32,
572
+ 16,
573
+ step=1,
574
+ label="Feature Bits",
575
+ info="Bit precision of individual feature dimension",
576
  )
577
 
578
+ # Initialization parameters
579
+ with gr.Group():
580
+ gr.Markdown("### Initialization")
581
+ init_mode = gr.Radio(
582
+ choices=["gradient", "saliency", "random"],
583
+ value="saliency",
584
+ label="Initialization Mode",
585
+ info="Gaussian position initialization mode. Gradient uses image gradients, saliency uses attention maps.",
586
+ )
587
+ init_random_ratio = gr.Slider(
588
+ minimum=0.0,
589
+ maximum=1.0,
590
+ value=0.3,
591
+ step=0.1,
592
+ label="Random Ratio",
593
+ info="Ratio of Gaussians with randomly initialized position (default: 0.3)",
594
+ )
595
 
596
+ # Advanced parameters (collapsible)
597
+ with gr.Accordion("Advanced Parameters", open=False):
598
+ # Loss parameters
599
+ gr.Markdown("#### Loss Weights")
600
  with gr.Row():
601
+ l1_loss_ratio = gr.Slider(0.0, 2.0, 1.0, step=0.1, label="L1 Loss")
602
+ l2_loss_ratio = gr.Slider(0.0, 2.0, 0.0, step=0.1, label="L2 Loss")
603
+ ssim_loss_ratio = gr.Slider(
604
+ 0.0, 1.0, 0.1, step=0.01, label="SSIM Loss"
605
  )
 
 
 
 
 
 
606
 
607
+ # Learning rates
608
+ gr.Markdown("#### Learning Rates")
609
+ with gr.Row():
610
+ pos_lr = gr.Number(value=5e-4, label="Position LR", precision=6)
611
+ scale_lr = gr.Number(value=2e-3, label="Scale LR", precision=6)
612
+ with gr.Row():
613
+ rot_lr = gr.Number(value=2e-3, label="Rotation LR", precision=6)
614
+ feat_lr = gr.Number(value=5e-3, label="Feature LR", precision=6)
615
+
616
+ # Optimization options
617
+ gr.Markdown("#### Optimization")
618
+ disable_lr_schedule = gr.Checkbox(
619
+ label="Disable LR Schedule",
620
+ value=False,
621
+ info="Keep learning rate constant",
622
  )
623
+ disable_prog_optim = gr.Checkbox(
624
+ label="Disable Progressive Optimization",
625
+ value=False,
626
+ info="Don't add Gaussians during training",
 
 
 
627
  )
628
 
629
+ # Visualization parameters
630
+ with gr.Group():
631
+ gr.Markdown("### Visualization")
632
+ vis_gaussians = gr.Checkbox(
633
+ label="Visualize Gaussians",
634
+ value=True,
635
+ info="Visualize Gaussians during optimization (default: True)",
636
+ )
637
+ save_image_steps = gr.Slider(
638
+ minimum=200,
 
 
 
 
 
 
 
 
 
 
 
639
  maximum=10000,
640
+ value=200,
641
  step=100,
642
+ label="Save Image Every N Steps",
643
+ info="Frequency of rendering intermediate results during optimization (default: 100)",
 
644
  )
645
 
646
+ # Control buttons
647
+ with gr.Row():
648
+ start_btn = gr.Button("Start Training", variant="primary", size="lg")
649
+ stop_btn = gr.Button("Stop Training", variant="stop", size="lg")
 
 
650
 
651
+ status_text = gr.Textbox(label="Status", interactive=False, lines=2)
 
 
 
 
 
652
 
653
+ with gr.Column(scale=2):
654
+ gr.Markdown("## Training Progress")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
655
 
656
+ # Progress logs (streaming)
657
+ progress_logs = gr.Textbox(
658
+ label="Training Logs",
659
+ lines=10,
660
+ max_lines=15,
661
+ interactive=False,
662
+ autoscroll=True,
663
+ )
664
 
665
+ # Initial map (computed at start based on initialization mode)
666
+ gr.Markdown("### Initialization Map")
667
+ initialization_map = gr.Image(
668
+ label="Initialization Map",
669
+ type="pil",
670
+ height=200,
671
+ )
672
 
673
+ # Training images (streaming)
674
+ gr.Markdown("### Current Training Results")
675
+ with gr.Row():
676
+ current_render = gr.Image(
677
+ label="Current Render",
678
+ type="pil",
679
+ height=300,
680
+ show_label=True,
681
+ show_download_button=True,
682
+ )
683
+ current_gaussian_id = gr.Image(
684
+ label="Gaussian ID",
685
+ type="pil",
686
+ height=300,
687
+ show_label=True,
688
+ show_download_button=True,
689
+ )
690
 
691
+ # Step slider for interactive browsing (will be updated dynamically)
692
+ step_slider = gr.Slider(
693
+ minimum=0,
694
+ maximum=10000,
695
+ value=0,
696
+ step=100,
697
+ label="Browse Training Steps",
698
+ info="Slide to view results from different training steps (disabled during training)",
699
+ interactive=False,
700
+ )
701
 
702
+ gr.Markdown("## Final Results")
703
+ with gr.Row():
704
+ final_render = gr.Image(label="Final Render", type="pil", height=300)
705
+ final_checkpoint = gr.File(label="Download Final Checkpoint (.pt)")
706
 
707
+ # Results buttons
708
+ with gr.Row():
709
+ results_btn = gr.Button("Load Final Results", size="lg")
710
+ enable_slider_btn = gr.Button(
711
+ "Enable Step Browsing", size="lg", variant="secondary"
712
+ )
713
 
714
+ # Event handlers
715
+ start_btn.click(
716
+ fn=start_training_and_stream,
717
+ inputs=[
718
+ image_input,
719
+ exp_name,
720
+ num_gaussians,
721
+ quantize,
722
+ pos_bits,
723
+ scale_bits,
724
+ rot_bits,
725
+ feat_bits,
726
+ init_mode,
727
+ init_random_ratio,
728
+ max_steps,
729
+ vis_gaussians,
730
+ save_image_steps,
731
+ l1_loss_ratio,
732
+ l2_loss_ratio,
733
+ ssim_loss_ratio,
734
+ pos_lr,
735
+ scale_lr,
736
+ rot_lr,
737
+ feat_lr,
738
+ disable_lr_schedule,
739
+ disable_prog_optim,
740
+ ],
741
+ outputs=[
742
+ status_text,
743
+ progress_logs,
744
+ initialization_map,
745
+ current_render,
746
+ current_gaussian_id,
747
+ start_btn,
748
+ stop_btn,
749
+ ],
750
+ )
751
+
752
+ stop_btn.click(fn=stop_training, outputs=status_text)
753
+
754
+ results_btn.click(fn=get_final_results, outputs=[final_render, final_checkpoint])
755
 
756
+ enable_slider_btn.click(fn=update_step_slider_after_training, outputs=[step_slider])
 
757
 
758
+ step_slider.change(
759
+ fn=browse_step_results,
760
+ inputs=[step_slider],
761
+ outputs=[current_render, current_gaussian_id],
762
+ )
763
+
764
+
765
+ if __name__ == "__main__":
766
+ demo.queue(max_size=20).launch(server_name="0.0.0.0", server_port=7860, share=False)
pyproject.docker.toml CHANGED
@@ -19,6 +19,7 @@ dependencies = [
19
  "gsplat",
20
  "gradio>=4.0.0",
21
  "huggingface_hub>=0.24.0",
 
22
  ]
23
 
24
  # We use python 3.13 and cu124 with PyTorch 2.6.0
 
19
  "gsplat",
20
  "gradio>=4.0.0",
21
  "huggingface_hub>=0.24.0",
22
+ "spaces>=0.28.0",
23
  ]
24
 
25
  # We use python 3.13 and cu124 with PyTorch 2.6.0
pyproject.toml CHANGED
@@ -19,6 +19,7 @@ dependencies = [
19
  "gsplat",
20
  "gradio>=4.0.0",
21
  "huggingface_hub>=0.24.0",
 
22
  ]
23
 
24
  # We use python 3.10 and cu124
 
19
  "gsplat",
20
  "gradio>=4.0.0",
21
  "huggingface_hub>=0.24.0",
22
+ "spaces>=0.28.0",
23
  ]
24
 
25
  # We use python 3.10 and cu124
uv.lock CHANGED
@@ -759,6 +759,7 @@ dependencies = [
759
  { name = "scikit-image" },
760
  { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
761
  { name = "scipy", version = "1.16.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" },
 
762
  { name = "torch", version = "2.6.0+cu124", source = { registry = "https://download.pytorch.org/whl/cu124" }, marker = "sys_platform == 'linux'" },
763
  { name = "torch", version = "2.8.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform != 'linux'" },
764
  { name = "torchmetrics" },
@@ -784,6 +785,7 @@ requires-dist = [
784
  { name = "pyyaml", specifier = ">=6.0.2" },
785
  { name = "scikit-image", specifier = ">=0.25.2" },
786
  { name = "scipy", specifier = ">=1.15.3" },
 
787
  { name = "torch", marker = "sys_platform != 'linux'", specifier = ">=2.6.0" },
788
  { name = "torch", marker = "sys_platform == 'linux'", specifier = ">=2.6.0", index = "https://download.pytorch.org/whl/cu124" },
789
  { name = "torchmetrics", specifier = ">=1.8.2" },
@@ -1723,6 +1725,20 @@ wheels = [
1723
  { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" },
1724
  ]
1725
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1726
  [[package]]
1727
  name = "pydantic"
1728
  version = "2.11.9"
@@ -2232,6 +2248,24 @@ wheels = [
2232
  { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" },
2233
  ]
2234
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2235
  [[package]]
2236
  name = "starlette"
2237
  version = "0.47.3"
 
759
  { name = "scikit-image" },
760
  { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
761
  { name = "scipy", version = "1.16.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" },
762
+ { name = "spaces" },
763
  { name = "torch", version = "2.6.0+cu124", source = { registry = "https://download.pytorch.org/whl/cu124" }, marker = "sys_platform == 'linux'" },
764
  { name = "torch", version = "2.8.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform != 'linux'" },
765
  { name = "torchmetrics" },
 
785
  { name = "pyyaml", specifier = ">=6.0.2" },
786
  { name = "scikit-image", specifier = ">=0.25.2" },
787
  { name = "scipy", specifier = ">=1.15.3" },
788
+ { name = "spaces", specifier = ">=0.28.0" },
789
  { name = "torch", marker = "sys_platform != 'linux'", specifier = ">=2.6.0" },
790
  { name = "torch", marker = "sys_platform == 'linux'", specifier = ">=2.6.0", index = "https://download.pytorch.org/whl/cu124" },
791
  { name = "torchmetrics", specifier = ">=1.8.2" },
 
1725
  { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" },
1726
  ]
1727
 
1728
+ [[package]]
1729
+ name = "psutil"
1730
+ version = "5.9.8"
1731
+ source = { registry = "https://pypi.org/simple" }
1732
+ sdist = { url = "https://files.pythonhosted.org/packages/90/c7/6dc0a455d111f68ee43f27793971cf03fe29b6ef972042549db29eec39a2/psutil-5.9.8.tar.gz", hash = "sha256:6be126e3225486dff286a8fb9a06246a5253f4c7c53b475ea5f5ac934e64194c", size = 503247, upload-time = "2024-01-19T20:47:09.517Z" }
1733
+ wheels = [
1734
+ { url = "https://files.pythonhosted.org/packages/e7/e3/07ae864a636d70a8a6f58da27cb1179192f1140d5d1da10886ade9405797/psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81", size = 248702, upload-time = "2024-01-19T20:47:36.303Z" },
1735
+ { url = "https://files.pythonhosted.org/packages/b3/bd/28c5f553667116b2598b9cc55908ec435cb7f77a34f2bff3e3ca765b0f78/psutil-5.9.8-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cb6403ce6d8e047495a701dc7c5bd788add903f8986d523e3e20b98b733e421", size = 285242, upload-time = "2024-01-19T20:47:39.65Z" },
1736
+ { url = "https://files.pythonhosted.org/packages/c5/4f/0e22aaa246f96d6ac87fe5ebb9c5a693fbe8877f537a1022527c47ca43c5/psutil-5.9.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d06016f7f8625a1825ba3732081d77c94589dca78b7a3fc072194851e88461a4", size = 288191, upload-time = "2024-01-19T20:47:43.078Z" },
1737
+ { url = "https://files.pythonhosted.org/packages/6e/f5/2aa3a4acdc1e5940b59d421742356f133185667dd190b166dbcfcf5d7b43/psutil-5.9.8-cp37-abi3-win32.whl", hash = "sha256:bc56c2a1b0d15aa3eaa5a60c9f3f8e3e565303b465dbf57a1b730e7a2b9844e0", size = 251252, upload-time = "2024-01-19T20:47:52.88Z" },
1738
+ { url = "https://files.pythonhosted.org/packages/93/52/3e39d26feae7df0aa0fd510b14012c3678b36ed068f7d78b8d8784d61f0e/psutil-5.9.8-cp37-abi3-win_amd64.whl", hash = "sha256:8db4c1b57507eef143a15a6884ca10f7c73876cdf5d51e713151c1236a0e68cf", size = 255090, upload-time = "2024-01-19T20:47:56.019Z" },
1739
+ { url = "https://files.pythonhosted.org/packages/05/33/2d74d588408caedd065c2497bdb5ef83ce6082db01289a1e1147f6639802/psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8", size = 249898, upload-time = "2024-01-19T20:47:59.238Z" },
1740
+ ]
1741
+
1742
  [[package]]
1743
  name = "pydantic"
1744
  version = "2.11.9"
 
2248
  { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" },
2249
  ]
2250
 
2251
+ [[package]]
2252
+ name = "spaces"
2253
+ version = "0.42.1"
2254
+ source = { registry = "https://pypi.org/simple" }
2255
+ dependencies = [
2256
+ { name = "gradio" },
2257
+ { name = "httpx" },
2258
+ { name = "packaging" },
2259
+ { name = "psutil" },
2260
+ { name = "pydantic" },
2261
+ { name = "requests" },
2262
+ { name = "typing-extensions" },
2263
+ ]
2264
+ sdist = { url = "https://files.pythonhosted.org/packages/9a/aa/84a43df8ce2e006e742b3f568720dca6c5e7862bca5062d80b0b4b414449/spaces-0.42.1.tar.gz", hash = "sha256:cf706325dc0d22b07629463bdb0c7dec747c7f419de50f58ece1058b7b283750", size = 28260, upload-time = "2025-09-25T16:30:09.15Z" }
2265
+ wheels = [
2266
+ { url = "https://files.pythonhosted.org/packages/c3/16/8b16ce2bb5170b2ab332ecb6e6f010eda69cfae44cd8644f71df53adad89/spaces-0.42.1-py3-none-any.whl", hash = "sha256:cbd2b1df62a154c215ea912f88c1ad480937cf509af967c3f339116c455222d6", size = 36397, upload-time = "2025-09-25T16:30:08.052Z" },
2267
+ ]
2268
+
2269
  [[package]]
2270
  name = "starlette"
2271
  version = "0.47.3"