Spaces:
Running
on
Zero
Running
on
Zero
Commit
·
a176955
0
Parent(s):
Initial commit: EditP23 project with LFS tracking for binary files
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +48 -0
- .gitignore +30 -0
- .gitmodules +3 -0
- README.md +231 -0
- app.py +899 -0
- assets/stormtrooper.glb +3 -0
- examples/batman_backpack/edited.png +3 -0
- examples/batman_backpack/src.png +3 -0
- examples/batman_backpack/src_mv.png +3 -0
- examples/batman_jetpack/edited.png +3 -0
- examples/batman_jetpack/src.png +3 -0
- examples/batman_jetpack/src_mv.png +3 -0
- examples/bike_harley/edited.png +3 -0
- examples/bike_harley/src.png +3 -0
- examples/bike_harley/src_mv.png +3 -0
- examples/bike_modern/edited.png +3 -0
- examples/bike_modern/src.png +3 -0
- examples/bike_modern/src_mv.png +3 -0
- examples/bike_sport/edited.png +3 -0
- examples/bike_sport/src.png +3 -0
- examples/bike_sport/src_mv.png +3 -0
- examples/bike_vintage/edited.png +3 -0
- examples/bike_vintage/src.png +3 -0
- examples/bike_vintage/src_mv.png +3 -0
- examples/bmw_speedy/edited.png +3 -0
- examples/bmw_speedy/src.png +3 -0
- examples/bmw_speedy/src_mv.png +3 -0
- examples/cabin_alpine/edited.png +3 -0
- examples/cabin_alpine/src.png +3 -0
- examples/cabin_alpine/src_mv.png +3 -0
- examples/cabin_gothic/edited.png +3 -0
- examples/cabin_gothic/src.png +3 -0
- examples/cabin_gothic/src_mv.png +3 -0
- examples/cabin_haunted/edited.png +3 -0
- examples/cabin_haunted/src.png +3 -0
- examples/cabin_haunted/src_mv.png +3 -0
- examples/cake_oreo/edited.png +3 -0
- examples/cake_oreo/src.png +3 -0
- examples/cake_oreo/src_mv.png +3 -0
- examples/car_cartoon/edited.png +3 -0
- examples/car_cartoon/src.png +3 -0
- examples/car_cartoon/src_mv.png +3 -0
- examples/car_engine/edited.png +3 -0
- examples/car_engine/src.png +3 -0
- examples/car_engine/src_mv.png +3 -0
- examples/car_steampunk/edited.png +3 -0
- examples/car_steampunk/src.png +3 -0
- examples/car_steampunk/src_mv.png +3 -0
- examples/deer_pixar/edited.png +3 -0
- examples/deer_pixar/src.png +3 -0
.gitattributes
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
*.png filter=lfs diff=lfs merge=lfs -text
|
37 |
+
*.jpg filter=lfs diff=lfs merge=lfs -text
|
38 |
+
*.jpeg filter=lfs diff=lfs merge=lfs -text
|
39 |
+
*.glb filter=lfs diff=lfs merge=lfs -text
|
40 |
+
*.mp4 filter=lfs diff=lfs merge=lfs -text
|
41 |
+
*.fbx filter=lfs diff=lfs merge=lfs -text
|
42 |
+
*.stl filter=lfs diff=lfs merge=lfs -text
|
43 |
+
*.ply filter=lfs diff=lfs merge=lfs -text
|
44 |
+
*.gif filter=lfs diff=lfs merge=lfs -text
|
45 |
+
*.bmp filter=lfs diff=lfs merge=lfs -text
|
46 |
+
*.tiff filter=lfs diff=lfs merge=lfs -text
|
47 |
+
*.gltf filter=lfs diff=lfs merge=lfs -text
|
48 |
+
*.obj filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Byte-compiled / cache files
|
2 |
+
__pycache__/
|
3 |
+
*.py[cod]
|
4 |
+
|
5 |
+
# Gradio-specific temporary files
|
6 |
+
.gradio_cache/
|
7 |
+
.gradio/
|
8 |
+
|
9 |
+
# Temporal
|
10 |
+
tmp/
|
11 |
+
# SLURM logs or files
|
12 |
+
slurm/
|
13 |
+
*.slurm
|
14 |
+
|
15 |
+
# VSCode settings
|
16 |
+
.vscode/
|
17 |
+
|
18 |
+
# Environment files
|
19 |
+
.env
|
20 |
+
*.env
|
21 |
+
|
22 |
+
# Jupyter Notebook checkpoints
|
23 |
+
.ipynb_checkpoints/
|
24 |
+
|
25 |
+
# Mac and OS metadata
|
26 |
+
.DS_Store
|
27 |
+
|
28 |
+
# Python virtual environments
|
29 |
+
venv/
|
30 |
+
.env/
|
.gitmodules
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
[submodule "external/instant-mesh"]
|
2 |
+
path = external/instant-mesh
|
3 |
+
url = https://github.com/TencentARC/InstantMesh.git
|
README.md
ADDED
@@ -0,0 +1,231 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
title: EditP23
|
3 |
+
emoji: 🎨
|
4 |
+
colorFrom: blue
|
5 |
+
colorTo: purple
|
6 |
+
sdk: gradio
|
7 |
+
sdk_version: 5.38.2
|
8 |
+
app_file: app.py
|
9 |
+
pinned: false
|
10 |
+
---
|
11 |
+
|
12 |
+
# EditP23: 3D Editing via Propagation of Image Prompts to Multi-View
|
13 |
+
|
14 |
+
[](https://editp23.github.io/)
|
15 |
+
[](https://arxiv.org/abs/2506.20652)
|
16 |
+
|
17 |
+
This repository contains the official implementation for **EditP23**, a method for fast, mask-free 3D editing that propagates 2D image edits to multi-view representations in a 3D-consistent manner.
|
18 |
+
The edit is guided by an image pair, allowing users to leverage any preferred 2D editing tool, from manual painting to generative pipelines.
|
19 |
+
|
20 |
+
### Installation
|
21 |
+
<details>
|
22 |
+
<summary>Click to expand installation instructions</summary>
|
23 |
+
|
24 |
+
This project was tested on a Linux system with Python 3.11 and CUDA 12.6.
|
25 |
+
|
26 |
+
**1. Clone the Repository**
|
27 |
+
```bash
|
28 |
+
git clone --recurse-submodules https://github.com/editp23/EditP23.git
|
29 |
+
cd EditP23
|
30 |
+
```
|
31 |
+
|
32 |
+
**2. Install Dependencies**
|
33 |
+
```bash
|
34 |
+
conda create -n editp23 python=3.11 -y
|
35 |
+
conda activate editp23
|
36 |
+
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu126 # Ensure compatibility with your CUDA version. (tested with torch 2.6, cuda 12.6)
|
37 |
+
pip install diffusers==0.30.1 transformers accelerate pillow huggingface_hub numpy tqdm
|
38 |
+
```
|
39 |
+
|
40 |
+
</details>
|
41 |
+
|
42 |
+
### Quick Start
|
43 |
+
|
44 |
+
**1. Prepare Your Experiment Directory**
|
45 |
+
|
46 |
+
Create a directory for your experiment. Inside this directory, you must place three specific PNG files:
|
47 |
+
|
48 |
+
* `src.png`: The original, unedited view of your object.
|
49 |
+
* `edited.png`: The same view after you have applied your desired 2D edit.
|
50 |
+
* `src_mv.png`: The multi-view grid of the original object, which will be edited.
|
51 |
+
|
52 |
+
Your directory structure should look like this:
|
53 |
+
```text
|
54 |
+
examples/
|
55 |
+
└── robot_sunglasses/
|
56 |
+
├── src.png
|
57 |
+
├── edited.png
|
58 |
+
└── src_mv.png
|
59 |
+
```
|
60 |
+
|
61 |
+
**2. Run the Editing Script**
|
62 |
+
|
63 |
+
Execute the `main.py` script, pointing it to your experiment directory. You can adjust the guidance parameters based on the complexity of your edit.
|
64 |
+
|
65 |
+
#### Execution Examples
|
66 |
+
|
67 |
+
* **Mild Edit (Appearance Change):**
|
68 |
+
```bash
|
69 |
+
python src/main.py --exp_dir examples/robot_sunglasses --tar_guidance_scale 5.0 --n_max 31
|
70 |
+
```
|
71 |
+
* **Hard Edit (Large Geometry Change):**
|
72 |
+
```bash
|
73 |
+
python src/main.py --exp_dir examples/deer_wings --tar_guidance_scale 21.0 --n_max 39
|
74 |
+
```
|
75 |
+
|
76 |
+
The output will be saved in the `output/` subdirectory within your experiment folder.
|
77 |
+
|
78 |
+
### Command-Line Arguments
|
79 |
+
|
80 |
+
* `--exp_dir`: (Required) Path to the experiment directory.
|
81 |
+
* `--T_steps`: Total number of denoising steps. Default: `50`.
|
82 |
+
* `--n_max`: The number of denoising steps to apply edit-aware guidance. Higher values can help with more complex edits. Default: `31`. This value shouldn't exceed `T_steps`.
|
83 |
+
* `--src_guidance_scale`: CFG scale for the source condition. Can typically remain constant. Default: `3.5`.
|
84 |
+
* `--tar_guidance_scale`: CFG scale for the target (edited) condition. Higher values apply the edit more strongly. Default: `5.0`.
|
85 |
+
* `--seed`: Random seed for reproducibility. Default: `18`.
|
86 |
+
|
87 |
+
|
88 |
+
# Results in Multi-View
|
89 |
+
|
90 |
+
### Deer - Pixar style & Wings
|
91 |
+
|
92 |
+
| | Cond. View | View 1 | View 2 | View 3 |
|
93 |
+
| :--- |:-----------------------------------------------------------------:|:----------------------------------------------------:|:----------------------------------------------------:|:----------------------------------------------------:|
|
94 |
+
| **Original** |  |  |  |  |
|
95 |
+
| **Pixar style** |  |  |  |  |
|
96 |
+
| **Wings** |  |  |  |  |
|
97 |
+
|
98 |
+
<br>
|
99 |
+
|
100 |
+
### Person - Old & Zombie
|
101 |
+
|
102 |
+
| | Cond. View | View 1 | View 2 | View 3 |
|
103 |
+
|:-------------|:-----------------------------------------------------------------:|:----------------------------------------------------:|:----------------------------------------------------:|:----------------------------------------------------:|
|
104 |
+
| **Original** |  |  |  |  |
|
105 |
+
| **Old** |  |  |  |  |
|
106 |
+
| **Zombie** |  |  |  |  |
|
107 |
+
|
108 |
+
|
109 |
+
# Project Structure
|
110 |
+
The repository is organized as follows:
|
111 |
+
```text
|
112 |
+
EditP23/
|
113 |
+
├── examples/ # Example assets for quick testing
|
114 |
+
│ ├── deer_wings/
|
115 |
+
│ │ ├── src.png
|
116 |
+
│ │ ├── edited.png
|
117 |
+
│ │ └── src_mv.png
|
118 |
+
│ └── robot_sunglasses/
|
119 |
+
│ └── ...
|
120 |
+
├── assets/ # Raw asset files
|
121 |
+
│ └── stormtrooper.glb
|
122 |
+
├── scripts/ # Helper scripts for data preparation
|
123 |
+
│ ├── render_mesh.py
|
124 |
+
│ └── img2mv.py
|
125 |
+
├── src/ # Main source code
|
126 |
+
│ ├── init.py
|
127 |
+
│ ├── edit_mv.py
|
128 |
+
│ ├── main.py
|
129 |
+
│ ├── pipeline.py
|
130 |
+
│ └── utils.py
|
131 |
+
├── .gitignore
|
132 |
+
└── README.md
|
133 |
+
```
|
134 |
+
|
135 |
+
# Utilities
|
136 |
+
|
137 |
+
## Setup
|
138 |
+
|
139 |
+
This guide shows how to prepare inputs for **EditP23** and run an edit.
|
140 |
+
|
141 |
+
These helper scripts create the three PNG files every experiment needs:
|
142 |
+
|
143 |
+
| File | Purpose |
|
144 |
+
|---------------|-----------------------------------------------------------------|
|
145 |
+
| `src.png` | Original single view (the one you will edit). |
|
146 |
+
| `edited.png` | Your 2D edit of `src.png`. |
|
147 |
+
| `src_mv.png` | 6-view grid of the original object. |
|
148 |
+
|
149 |
+
### 1. Generate `src.png` and `src_mv.png`
|
150 |
+
**EditP23** needs a **source view** (`src.png`) and a **multi-view grid** (`src_mv.png`).
|
151 |
+
The grid contains six extra views at fixed azimuth/elevation pairs:
|
152 |
+
Angles (azimuth, elevation): `(30°, 20°) (90°, -10°) (150°, 20°) (210°, -10°) (270°, 20°) (330°, -10°)` and for the prompt view `(0°, 20°)`.
|
153 |
+
We provide two methods to generate these inputs. Both methods produce views on a clean, white background.
|
154 |
+
Both methods below produce the multi-view grid and the source view from the relevant angles on a white background.
|
155 |
+
|
156 |
+
#### Method A: From a Single Image
|
157 |
+
|
158 |
+
You can generate the multi-view grid from a single image of an object using our `img2mv.py` script. This script leverages the Zero123++ pipeline with a checkpoint from InstantMesh, which is fine-tuned to produce white backgrounds.
|
159 |
+
|
160 |
+
```bash
|
161 |
+
# This script takes a single input image and generates the corresponding multi-view grid.
|
162 |
+
python scripts/img2mv.py \
|
163 |
+
--input_image "examples/robot_sunglasses/src.png" \
|
164 |
+
--output_dir "examples/robot_sunglasses/"
|
165 |
+
```
|
166 |
+
**Note:** In this case, `src.png` serves as the source view for EditP23.
|
167 |
+
|
168 |
+
|
169 |
+
|
170 |
+
#### Method B: From a 3D Mesh
|
171 |
+
If you have a 3D model, you can use our Blender script to render both the source view and the multi-view grid.
|
172 |
+
**Prerequisite:** This script requires Blender (`pip install bpy`).
|
173 |
+
|
174 |
+
```bash
|
175 |
+
# This script renders a source view and a multi-view grid from a 3D mesh.
|
176 |
+
python scripts/render_mesh.py \
|
177 |
+
--mesh_path "assets/stormtrooper.glb" \
|
178 |
+
--output_dir "examples/stormtrooper/"
|
179 |
+
```
|
180 |
+
|
181 |
+
### 2. Generating `edited.png`
|
182 |
+
Once you have your **source view**, you can use any 2D image editor to make your desired changes. We use this user-provided edit to guide the 3D modification.
|
183 |
+
For quick edits, you can use readily available online tools, such as the following HuggingFace Spaces:
|
184 |
+
- [FlowEdit](https://huggingface.co/spaces/fallenshock/FlowEdit): Excellent for global, structural edits.
|
185 |
+
- [Flux-Inpainting](https://huggingface.co/spaces/black-forest-labs/FLUX.1-Fill-dev): Great for local modifications and inpainting.
|
186 |
+
|
187 |
+
|
188 |
+
## Reconstruction
|
189 |
+
After generating an edited multi-view image (`edited_mv.png`) with our main script, you can reconstruct it into a 3D model. We provide a helper script that uses the [InstantMesh](https://github.com/TencentARC/InstantMesh) framework to produce a textured `.obj` file and a turntable video.
|
190 |
+
|
191 |
+
|
192 |
+
### Additional Dependencies
|
193 |
+
First, you'll need to install several libraries required for the reconstruction process.
|
194 |
+
|
195 |
+
<details>
|
196 |
+
<summary>Click to expand installation instructions</summary>
|
197 |
+
|
198 |
+
```bash
|
199 |
+
# Install general dependencies
|
200 |
+
pip install opencv-python einops xatlas imageio[ffmpeg]
|
201 |
+
|
202 |
+
# Install NVIDIA's nvdiffrast library
|
203 |
+
pip install git+https://github.com/NVlabs/nvdiffrast/
|
204 |
+
|
205 |
+
# For video export, ensure ffmpeg is installed
|
206 |
+
# On conda, you can run:
|
207 |
+
conda install ffmpeg
|
208 |
+
```
|
209 |
+
</details>
|
210 |
+
|
211 |
+
### Running the Reconstruction
|
212 |
+
The reconstruction script takes the multi-view PNG as input and generates the 3D assets. The necessary model config file (instant-mesh-large.yaml) is included in the configs/ directory of the InstanMesh repository.
|
213 |
+
#### Example Command
|
214 |
+
````bash
|
215 |
+
python scripts/recon.py \
|
216 |
+
external/instant-mesh/configs/instant-mesh-large.yaml \
|
217 |
+
--input_file "examples/robot_sunglasses/output/edited_mv.png" \
|
218 |
+
--output_dir "examples/robot_sunglasses/output/recon/"
|
219 |
+
````
|
220 |
+
|
221 |
+
### Command-Line Arguments
|
222 |
+
Here are the arguments for the recon.py script:
|
223 |
+
|
224 |
+
| Argument | Description | Default |
|
225 |
+
| :------------ | :----------------------------------------------------------------- | :----------- |
|
226 |
+
| `config` | **(Required)** Path to the InstantMesh model config file. | |
|
227 |
+
| `--input_file`| **(Required)** Path to the multi-view PNG file you want to reconstruct. | |
|
228 |
+
| `--output_dir`| Directory where the output `.obj` and `.mp4` files will be saved. | `"outputs/"` |
|
229 |
+
| `--scale` | Scale of the input cameras. | `1.0` |
|
230 |
+
| `--distance` | Camera distance for rendering the output video. | `4.5` |
|
231 |
+
| `--no_video` | A flag to disable saving the `.mp4` video. | `False` |
|
app.py
ADDED
@@ -0,0 +1,899 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import gradio as gr
|
3 |
+
import numpy as np
|
4 |
+
from PIL import Image
|
5 |
+
import tempfile
|
6 |
+
import sys
|
7 |
+
import subprocess
|
8 |
+
from pathlib import Path
|
9 |
+
from typing import Optional
|
10 |
+
import re
|
11 |
+
import spaces
|
12 |
+
# NOTE: This script assumes it is located in the project root directory.
|
13 |
+
PYTHON_EXECUTABLE = sys.executable # Or specify a path like "/path/to/your/python"
|
14 |
+
# Construct paths relative to this app's location in the root.
|
15 |
+
APP_DIR = os.path.dirname(os.path.abspath(__file__))
|
16 |
+
MAIN_SCRIPT_PATH = os.path.join(APP_DIR, "src", "main.py")
|
17 |
+
EXAMPLES_PATH = os.path.join(APP_DIR, "examples")
|
18 |
+
|
19 |
+
# --- Gradio Interface ---
|
20 |
+
|
21 |
+
@spaces.GPU
|
22 |
+
def run_main_script(
|
23 |
+
src_cond_image_np: np.ndarray,
|
24 |
+
tgt_cond_image_np: np.ndarray,
|
25 |
+
original_mv_image_np: np.ndarray,
|
26 |
+
t_steps: int,
|
27 |
+
n_max: int,
|
28 |
+
src_gs: float,
|
29 |
+
tar_gs: float,
|
30 |
+
seed: int,
|
31 |
+
progress=gr.Progress(),
|
32 |
+
):
|
33 |
+
"""
|
34 |
+
Wrapper function for Gradio to prepare files and run the main.py script.
|
35 |
+
"""
|
36 |
+
# Ensure consistent types for filename generation and command-line args.
|
37 |
+
tar_gs = float(tar_gs)
|
38 |
+
n_max = int(n_max)
|
39 |
+
t_steps = int(t_steps)
|
40 |
+
src_gs = float(src_gs)
|
41 |
+
seed = int(seed)
|
42 |
+
|
43 |
+
if (
|
44 |
+
src_cond_image_np is None
|
45 |
+
or tgt_cond_image_np is None
|
46 |
+
or original_mv_image_np is None
|
47 |
+
):
|
48 |
+
raise gr.Error("Please provide all three input images.")
|
49 |
+
|
50 |
+
if not os.path.exists(MAIN_SCRIPT_PATH):
|
51 |
+
raise gr.Error(
|
52 |
+
f"Main script not found at '{MAIN_SCRIPT_PATH}'. Please update the MAIN_SCRIPT_PATH variable in the app."
|
53 |
+
)
|
54 |
+
|
55 |
+
progress(0, desc="Preparing experiment...")
|
56 |
+
with tempfile.TemporaryDirectory() as exp_dir:
|
57 |
+
# Save uploaded images to the required filenames
|
58 |
+
src_cond_img = Image.fromarray(src_cond_image_np).convert("RGB")
|
59 |
+
tgt_cond_img = Image.fromarray(tgt_cond_image_np).convert("RGB")
|
60 |
+
original_mv_img = Image.fromarray(original_mv_image_np).convert("RGB")
|
61 |
+
|
62 |
+
src_cond_img.save(os.path.join(exp_dir, "src.png"))
|
63 |
+
tgt_cond_img.save(os.path.join(exp_dir, "edited.png"))
|
64 |
+
original_mv_img.save(os.path.join(exp_dir, "src_mv.png"))
|
65 |
+
|
66 |
+
# Construct the command to run main.py
|
67 |
+
cmd = [
|
68 |
+
PYTHON_EXECUTABLE,
|
69 |
+
"-u", # Force unbuffered stdout
|
70 |
+
MAIN_SCRIPT_PATH,
|
71 |
+
"--exp_dir",
|
72 |
+
exp_dir,
|
73 |
+
"--T_steps",
|
74 |
+
str(t_steps),
|
75 |
+
"--n_max",
|
76 |
+
str(n_max),
|
77 |
+
"--src_guidance_scale",
|
78 |
+
str(src_gs),
|
79 |
+
"--tar_guidance_scale",
|
80 |
+
str(tar_gs),
|
81 |
+
"--seed",
|
82 |
+
str(seed),
|
83 |
+
]
|
84 |
+
|
85 |
+
print(f"🚀 Running command: {' '.join(cmd)}")
|
86 |
+
progress(0.05, desc="Executing main script...")
|
87 |
+
|
88 |
+
# Execute the script as a subprocess and stream the output.
|
89 |
+
process = subprocess.Popen(
|
90 |
+
cmd,
|
91 |
+
stdout=subprocess.PIPE,
|
92 |
+
stderr=subprocess.STDOUT, # Merge stderr with stdout
|
93 |
+
text=True,
|
94 |
+
bufsize=1,
|
95 |
+
universal_newlines=True,
|
96 |
+
)
|
97 |
+
|
98 |
+
# Regex to find the main tqdm progress in the format "current/total [time<remaining, speed]"
|
99 |
+
tqdm_regex = re.compile(r"(\d+)/(\d+)\s*\[.*<.*,.*s/it\]")
|
100 |
+
|
101 |
+
# Print stdout in real-time and update progress bar
|
102 |
+
if process.stdout:
|
103 |
+
for line in iter(process.stdout.readline, ""):
|
104 |
+
print(line, end="")
|
105 |
+
match = tqdm_regex.search(line)
|
106 |
+
if match:
|
107 |
+
current_step = int(match.group(1))
|
108 |
+
total_steps = int(match.group(2))
|
109 |
+
# This condition ensures we only track the main, multi-step progress bar
|
110 |
+
if total_steps > 1:
|
111 |
+
percent = current_step / total_steps
|
112 |
+
# Update progress bar with a clean description
|
113 |
+
progress(percent, desc=f"Denoising...")
|
114 |
+
|
115 |
+
# Wait for the process to finish and get the return code
|
116 |
+
process.wait()
|
117 |
+
|
118 |
+
# Check for errors after the process has completed
|
119 |
+
if process.returncode != 0:
|
120 |
+
print(f"❌ Script failed with exit code: {process.returncode}")
|
121 |
+
raise gr.Error(f"Script execution failed. Check console for details.")
|
122 |
+
|
123 |
+
print("\n✅ Script executed successfully.")
|
124 |
+
|
125 |
+
# Find the output file
|
126 |
+
output_dir = os.path.join(exp_dir, "output")
|
127 |
+
output_filename = f"result_tgs_{tar_gs}_nmax_{n_max}.png"
|
128 |
+
save_path = os.path.join(output_dir, output_filename)
|
129 |
+
|
130 |
+
progress(0.98, desc="Loading result...")
|
131 |
+
if not os.path.exists(save_path):
|
132 |
+
print(f"❌ Output file not found at expected path: {save_path}")
|
133 |
+
raise gr.Error(
|
134 |
+
"Output file was not created by the script. Check console logs for errors."
|
135 |
+
)
|
136 |
+
|
137 |
+
result_img = Image.open(save_path)
|
138 |
+
progress(1, desc="Done.")
|
139 |
+
return result_img
|
140 |
+
|
141 |
+
|
142 |
+
def clear_inputs():
|
143 |
+
"""Resets all input fields to their default state and makes them interactive."""
|
144 |
+
return {
|
145 |
+
original_mv_image: None,
|
146 |
+
src_cond_image: None,
|
147 |
+
tgt_cond_image: None,
|
148 |
+
t_steps: gr.Slider(value=50, interactive=True),
|
149 |
+
n_max: gr.Slider(value=31, interactive=True),
|
150 |
+
src_gs: gr.Slider(value=3.5, interactive=True),
|
151 |
+
tar_gs: gr.Slider(value=5.0, interactive=True),
|
152 |
+
seed: gr.Slider(value=18, interactive=True),
|
153 |
+
output_image: None,
|
154 |
+
}
|
155 |
+
|
156 |
+
|
157 |
+
# --- Markdown Content for UI ---
|
158 |
+
ABOUT_TEXT = """
|
159 |
+
<div style="text-align: center; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;">
|
160 |
+
<h1 style="font-weight: 800; font-size: 2.5em; margin-bottom: 0.2em;">EditP23: 3D Editing via Propagation of Image Prompts to Multi-View</h1>
|
161 |
+
<div style="margin-bottom: 1.5em; display: flex; justify-content: center; align-items: center; gap: 12px; flex-wrap: wrap;">
|
162 |
+
<a href="https://editp23.github.io/" target="_blank" class="link-button" style="background-color: #1d6aef;">▶️ Project Page</a>
|
163 |
+
<a href="https://arxiv.org/abs/2506.20652" target="_blank" class="link-button" style="background-color: #b31b1b;">📄 arXiv</a>
|
164 |
+
<a href="https://github.com/editp23/editp23" target="_blank" class="link-button" style="background-color: #24292e;">💻 GitHub</a>
|
165 |
+
</div>
|
166 |
+
<p style="font-size: 1.1em; max-width: 800px; margin: auto; line-height: 1.6;">
|
167 |
+
This is the official Gradio demo for <strong>EditP23</strong>, a method for fast, mask-free 3D editing that propagates 2D image edits to multi-view representations in a 3D-consistent manner. The edit is guided by an image pair, allowing users to leverage any preferred 2D editing tool, from manual painting to generative pipelines.
|
168 |
+
</p>
|
169 |
+
</div>
|
170 |
+
"""
|
171 |
+
|
172 |
+
HOW_TO_USE_TEXT = """
|
173 |
+
<div id="how-to-use-container">
|
174 |
+
<h2 id="understanding-inputs">Understanding the Inputs</h2>
|
175 |
+
<p><strong>EditP23</strong> requires three specific images to perform an edit. This demo automates the process, but understanding each component is key.</p>
|
176 |
+
<ol>
|
177 |
+
<li><strong>Original Multi-View Image (`src_mv.png`)</strong>: This is a 2x3 grid of six different views of the original, unedited object. The model uses this as the base to apply the edit consistently across all angles.</li>
|
178 |
+
<li><strong>Source Condition (`src.png`)</strong>: This is a single, frontal view of the original object. It acts as the "before" image for the edit.</li>
|
179 |
+
<li><strong>Target Condition (`edited.png`)</strong>: This is the "after" image. It's the same view as <code>src.png</code>, but with your desired 2D modification applied. The difference between this image and <code>src.png</code> is what guides the 3D edit.</li>
|
180 |
+
</ol>
|
181 |
+
<hr>
|
182 |
+
<h2 id="prepare-images">How to Prepare Your Own Images</h2>
|
183 |
+
<p>You can generate the required input images using the helper scripts provided in our <a href="https://github.com/editp23/editp23" target="_blank">GitHub repository</a>.</p>
|
184 |
+
<h4><strong>Step 1: Generate <code>src.png</code> and <code>src_mv.png</code></strong></h4>
|
185 |
+
<p>You have two options for creating the initial views of your object.</p>
|
186 |
+
<ul>
|
187 |
+
<li><strong>Method A: From a Single Image</strong><br>If you have a single image of an object, you can generate the multi-view grid using our <code>img2mv.py</code> script.
|
188 |
+
<pre><code>python scripts/img2mv.py --input_image "path/to/your_image.png" --output_dir "path/to/output/"</code></pre>
|
189 |
+
</li>
|
190 |
+
<li><strong>Method B: From a 3D Mesh (<code>.glb</code>, <code>.obj</code>)</strong><br>If you have a 3D model, you can render the required views using our Blender script.
|
191 |
+
<pre><code>python scripts/render_mesh.py --mesh_path "path/to/your_model.glb" --output_dir "path/to/output/"</code></pre>
|
192 |
+
</li>
|
193 |
+
</ul>
|
194 |
+
<h4><strong>Step 2: Create <code>edited.png</code></strong></h4>
|
195 |
+
<p>Use any 2D image editor to modify your <code>src.png</code>. This is where your creativity comes in! For quick edits, we recommend these online tools:</p>
|
196 |
+
<ul>
|
197 |
+
<li><a href="https://huggingface.co/spaces/fallenshock/FlowEdit" target="_blank">FlowEdit</a>: Excellent for global, structural edits.</li>
|
198 |
+
<li><a href="https://huggingface.co/spaces/black-forest-labs/FLUX.1-Fill-dev" target="_blank">Flux-Inpainting</a>: Great for local modifications and inpainting.</li>
|
199 |
+
</ul>
|
200 |
+
<hr>
|
201 |
+
<h2 id="understanding-params">Understanding the Parameters</h2>
|
202 |
+
<ul>
|
203 |
+
<li><strong><code>n_max</code></strong>: Controls how many denoising steps are influenced by your edit. Higher values are needed for more significant geometric changes.</li>
|
204 |
+
<li><strong><code>tar_guidance_scale</code></strong>: Determines the strength of your edit. Increase this for more dramatic changes, but be aware that very high values can sometimes introduce artifacts.</li>
|
205 |
+
<li><strong><code>src_guidance_scale</code></strong>: Controls how strongly the model adheres to the original object's identity. This can usually be left at its default value.</li>
|
206 |
+
</ul>
|
207 |
+
<hr>
|
208 |
+
<h2 id="reconstruct-model">Reconstructing a 3D Model</h2>
|
209 |
+
<p>After this demo generates an edited multi-view image, you can use the <code>scripts/recon.py</code> script from our repository to convert it back into a 3D model (<code>.obj</code> file).</p>
|
210 |
+
<pre><code>python scripts/recon.py path/to/instant-mesh-large.yaml --input_file "path/to/edited_mv.png" --output_dir "path/to/output/"</code></pre>
|
211 |
+
</div>
|
212 |
+
"""
|
213 |
+
|
214 |
+
# --- Gradio UI Layout ---
|
215 |
+
# Create a custom theme to match the website's color
|
216 |
+
theme = gr.themes.Base(
|
217 |
+
primary_hue=gr.themes.colors.blue,
|
218 |
+
secondary_hue=gr.themes.colors.blue,
|
219 |
+
font=[gr.themes.GoogleFont("Inter"), "ui-sans-serif", "system-ui", "sans-serif"],
|
220 |
+
).set(
|
221 |
+
button_primary_background_fill="*primary_500",
|
222 |
+
button_primary_background_fill_hover="*primary_600",
|
223 |
+
)
|
224 |
+
|
225 |
+
# Custom CSS for better layout and fixing UI quirks
|
226 |
+
CUSTOM_CSS = """
|
227 |
+
.gradio-container { max-width: 95% !important; }
|
228 |
+
.label-wrap { padding-top: 6px !import ant; } /* Fix label overlap */
|
229 |
+
.help-text { color: #9CA3AF; font-size: 0.9rem; margin-top: 4px; margin-bottom: 12px; }
|
230 |
+
.link-button { text-decoration: none; color: white; padding: 8px 16px; border-radius: 8px; font-weight: bold; transition: background-color 0.2s ease; }
|
231 |
+
.link-button:hover { background-color: #4a5568 !important; }
|
232 |
+
#action-buttons { margin-top: 1rem; }
|
233 |
+
|
234 |
+
/* --- CSS Rules for the Examples Table --- */
|
235 |
+
|
236 |
+
/* 1. CRITICAL FIX: Target the image's wrapper to prevent clipping. */
|
237 |
+
#example-table td > div {
|
238 |
+
overflow: visible !important; /* This is the key to stop cropping. */
|
239 |
+
display: flex;
|
240 |
+
justify-content: center;
|
241 |
+
align-items: center;
|
242 |
+
}
|
243 |
+
|
244 |
+
/* 2. General cell styling for alignment and spacing */
|
245 |
+
#example-table td {
|
246 |
+
vertical-align: middle !important;
|
247 |
+
padding: 8px !important;
|
248 |
+
}
|
249 |
+
|
250 |
+
/* 3. Force parameter columns (4-7) to have the same width */
|
251 |
+
#example-table th:nth-child(n+4):nth-child(-n+7),
|
252 |
+
#example-table td:nth-child(n+4):nth-child(-n+7) {
|
253 |
+
width: 85px !important;
|
254 |
+
max-width: 85px !important;
|
255 |
+
text-align: center;
|
256 |
+
word-break: break-word;
|
257 |
+
}
|
258 |
+
|
259 |
+
/* 4. Enlarge multi-view image (Col 1) with a 3:2 height:width ratio */
|
260 |
+
#example-table td:nth-child(1) img {
|
261 |
+
height: 180px !important;
|
262 |
+
width: 120px !important; /* 180px / 120px = 3:2 ratio */
|
263 |
+
object-fit: contain !important; /* Ensures the whole image is visible */
|
264 |
+
}
|
265 |
+
|
266 |
+
/* 5. Enlarge condition images (Col 2 & 3) */
|
267 |
+
#example-table td:nth-child(2) img,
|
268 |
+
#example-table td:nth-child(3) img {
|
269 |
+
height: 150px !important;
|
270 |
+
width: 150px !important;
|
271 |
+
object-fit: contain !important;
|
272 |
+
}
|
273 |
+
"""
|
274 |
+
|
275 |
+
|
276 |
+
with gr.Blocks(theme=theme, css=CUSTOM_CSS) as demo:
|
277 |
+
gr.Markdown(ABOUT_TEXT)
|
278 |
+
|
279 |
+
with gr.Tabs() as tabs:
|
280 |
+
with gr.TabItem("Interactive Demo", id=0):
|
281 |
+
with gr.Row(variant="panel", equal_height=False):
|
282 |
+
# Column 1: Inputs
|
283 |
+
with gr.Column(scale=1):
|
284 |
+
gr.Markdown("### 1. Input Images")
|
285 |
+
gr.Markdown(
|
286 |
+
'See the "How to Use" tab for details on generating the **Multi-View Image** and creating your own **Edited Condition**.',
|
287 |
+
elem_classes="help-text",
|
288 |
+
)
|
289 |
+
original_mv_image = gr.Image(
|
290 |
+
type="numpy",
|
291 |
+
label="Original Multi-View Image (src_mv.png)",
|
292 |
+
height=675,
|
293 |
+
width=450,
|
294 |
+
)
|
295 |
+
with gr.Row():
|
296 |
+
src_cond_image = gr.Image(
|
297 |
+
type="numpy",
|
298 |
+
label="Source Condition (src.png)",
|
299 |
+
height=350,
|
300 |
+
width=350,
|
301 |
+
)
|
302 |
+
tgt_cond_image = gr.Image(
|
303 |
+
type="numpy",
|
304 |
+
label="Target Condition (edited.png)",
|
305 |
+
height=350,
|
306 |
+
width=350,
|
307 |
+
)
|
308 |
+
|
309 |
+
# Column 2: Parameters & Action
|
310 |
+
with gr.Column(scale=1, min_width=300):
|
311 |
+
gr.Markdown("### 2. Parameters")
|
312 |
+
with gr.Accordion("Advanced Parameters", open=True):
|
313 |
+
t_steps = gr.Slider(
|
314 |
+
minimum=1,
|
315 |
+
maximum=100,
|
316 |
+
value=50,
|
317 |
+
step=1,
|
318 |
+
label="T_steps",
|
319 |
+
info="Total number of denoising steps.",
|
320 |
+
)
|
321 |
+
n_max = gr.Slider(
|
322 |
+
minimum=1,
|
323 |
+
maximum=50,
|
324 |
+
value=31,
|
325 |
+
step=1,
|
326 |
+
label="n_max",
|
327 |
+
info="Number of scheduler steps for edit-aware guidance. Increase for more significant edits.",
|
328 |
+
)
|
329 |
+
src_gs = gr.Slider(
|
330 |
+
minimum=1.0,
|
331 |
+
maximum=10.0,
|
332 |
+
value=3.5,
|
333 |
+
step=0.1,
|
334 |
+
label="Source CFG",
|
335 |
+
info="Guidance scale for the source condition. Can typically remain constant.",
|
336 |
+
)
|
337 |
+
tar_gs = gr.Slider(
|
338 |
+
minimum=1.0,
|
339 |
+
maximum=30.0,
|
340 |
+
value=5.0,
|
341 |
+
step=0.1,
|
342 |
+
label="Target CFG",
|
343 |
+
info="Guidance scale for the target condition. Increase for more significant edits.",
|
344 |
+
)
|
345 |
+
seed = gr.Slider(
|
346 |
+
minimum=0,
|
347 |
+
maximum=10000,
|
348 |
+
value=18,
|
349 |
+
step=1,
|
350 |
+
label="Seed",
|
351 |
+
info="Random seed for reproducibility.",
|
352 |
+
)
|
353 |
+
|
354 |
+
with gr.Row(elem_id="action-buttons"):
|
355 |
+
clear_button = gr.Button("Clear", variant="secondary", scale=1)
|
356 |
+
run_button = gr.Button("Generate", variant="primary", scale=2)
|
357 |
+
|
358 |
+
# Column 3: Output
|
359 |
+
with gr.Column(scale=2, min_width=350):
|
360 |
+
gr.Markdown("### 3. Output Image")
|
361 |
+
output_image = gr.Image(
|
362 |
+
type="pil",
|
363 |
+
label="Edited Result",
|
364 |
+
height=450,
|
365 |
+
width=450,
|
366 |
+
interactive=False,
|
367 |
+
)
|
368 |
+
gr.Markdown(
|
369 |
+
'After generating, you can use the `recon.py` script to create a 3D model. See the "How to Use" tab for the full command.',
|
370 |
+
elem_classes="help-text",
|
371 |
+
)
|
372 |
+
|
373 |
+
# --- Examples Section ---
|
374 |
+
if os.path.exists(EXAMPLES_PATH):
|
375 |
+
gr.Markdown("---")
|
376 |
+
gr.Markdown("### Click an Example to Load")
|
377 |
+
|
378 |
+
example_inputs = [
|
379 |
+
original_mv_image,
|
380 |
+
src_cond_image,
|
381 |
+
tgt_cond_image,
|
382 |
+
t_steps,
|
383 |
+
n_max,
|
384 |
+
src_gs,
|
385 |
+
tar_gs,
|
386 |
+
]
|
387 |
+
|
388 |
+
example_data = [
|
389 |
+
[
|
390 |
+
os.path.join(EXAMPLES_PATH, "bike_vintage", "src_mv.png"),
|
391 |
+
os.path.join(EXAMPLES_PATH, "bike_vintage", "src.png"),
|
392 |
+
os.path.join(EXAMPLES_PATH, "bike_vintage", "edited.png"),
|
393 |
+
50,
|
394 |
+
31,
|
395 |
+
3.5,
|
396 |
+
5.0,
|
397 |
+
18,
|
398 |
+
],
|
399 |
+
[
|
400 |
+
os.path.join(EXAMPLES_PATH, "robot_sunglasses", "src_mv.png"),
|
401 |
+
os.path.join(EXAMPLES_PATH, "robot_sunglasses", "src.png"),
|
402 |
+
os.path.join(EXAMPLES_PATH, "robot_sunglasses", "edited.png"),
|
403 |
+
50,
|
404 |
+
31,
|
405 |
+
3.5,
|
406 |
+
5.0,
|
407 |
+
18,
|
408 |
+
],
|
409 |
+
[
|
410 |
+
os.path.join(EXAMPLES_PATH, "stormtrooper_donut", "src_mv.png"),
|
411 |
+
os.path.join(EXAMPLES_PATH, "stormtrooper_donut", "src.png"),
|
412 |
+
os.path.join(EXAMPLES_PATH, "stormtrooper_donut", "edited.png"),
|
413 |
+
50,
|
414 |
+
42,
|
415 |
+
3.5,
|
416 |
+
12.0,
|
417 |
+
18,
|
418 |
+
],
|
419 |
+
[
|
420 |
+
os.path.join(EXAMPLES_PATH, "figure_zombie", "src_mv.png"),
|
421 |
+
os.path.join(EXAMPLES_PATH, "figure_zombie", "src.png"),
|
422 |
+
os.path.join(EXAMPLES_PATH, "figure_zombie", "edited.png"),
|
423 |
+
50,
|
424 |
+
31,
|
425 |
+
3.5,
|
426 |
+
5.0,
|
427 |
+
18,
|
428 |
+
],
|
429 |
+
[
|
430 |
+
os.path.join(EXAMPLES_PATH, "deer_pixar", "src_mv.png"),
|
431 |
+
os.path.join(EXAMPLES_PATH, "deer_pixar", "src.png"),
|
432 |
+
os.path.join(EXAMPLES_PATH, "deer_pixar", "edited.png"),
|
433 |
+
50,
|
434 |
+
31,
|
435 |
+
3.5,
|
436 |
+
5.0,
|
437 |
+
18,
|
438 |
+
],
|
439 |
+
[
|
440 |
+
os.path.join(EXAMPLES_PATH, "german-shep_plush", "src_mv.png"),
|
441 |
+
os.path.join(EXAMPLES_PATH, "german-shep_plush", "src.png"),
|
442 |
+
os.path.join(EXAMPLES_PATH, "german-shep_plush", "edited.png"),
|
443 |
+
50,
|
444 |
+
41,
|
445 |
+
3.5,
|
446 |
+
6.0,
|
447 |
+
18,
|
448 |
+
],
|
449 |
+
|
450 |
+
[
|
451 |
+
os.path.join(EXAMPLES_PATH, "deer_wings", "src_mv.png"),
|
452 |
+
os.path.join(EXAMPLES_PATH, "deer_wings", "src.png"),
|
453 |
+
os.path.join(EXAMPLES_PATH, "deer_wings", "edited.png"),
|
454 |
+
50,
|
455 |
+
39,
|
456 |
+
3.5,
|
457 |
+
21.0,
|
458 |
+
18,
|
459 |
+
],
|
460 |
+
[
|
461 |
+
os.path.join(EXAMPLES_PATH, "lego-car_spoiler", "src_mv.png"),
|
462 |
+
os.path.join(EXAMPLES_PATH, "lego-car_spoiler", "src.png"),
|
463 |
+
os.path.join(EXAMPLES_PATH, "lego-car_spoiler", "edited.png"),
|
464 |
+
50,
|
465 |
+
42,
|
466 |
+
3.5,
|
467 |
+
12.0,
|
468 |
+
18,
|
469 |
+
],
|
470 |
+
[
|
471 |
+
os.path.join(EXAMPLES_PATH, "batman_jetpack", "src_mv.png"),
|
472 |
+
os.path.join(EXAMPLES_PATH, "batman_jetpack", "src.png"),
|
473 |
+
os.path.join(EXAMPLES_PATH, "batman_jetpack", "edited.png"),
|
474 |
+
50,
|
475 |
+
31,
|
476 |
+
3.5,
|
477 |
+
5.0,
|
478 |
+
18,
|
479 |
+
],
|
480 |
+
[
|
481 |
+
os.path.join(EXAMPLES_PATH, "bike_sport", "src_mv.png"),
|
482 |
+
os.path.join(EXAMPLES_PATH, "bike_sport", "src.png"),
|
483 |
+
os.path.join(EXAMPLES_PATH, "bike_sport", "edited.png"),
|
484 |
+
50,
|
485 |
+
31,
|
486 |
+
3.5,
|
487 |
+
5.0,
|
488 |
+
18,
|
489 |
+
],
|
490 |
+
[
|
491 |
+
os.path.join(EXAMPLES_PATH, "red-dragon_tail", "src_mv.png"),
|
492 |
+
os.path.join(EXAMPLES_PATH, "red-dragon_tail", "src.png"),
|
493 |
+
os.path.join(EXAMPLES_PATH, "red-dragon_tail", "edited.png"),
|
494 |
+
50,
|
495 |
+
41,
|
496 |
+
3.5,
|
497 |
+
6.0,
|
498 |
+
18,
|
499 |
+
],
|
500 |
+
[
|
501 |
+
os.path.join(EXAMPLES_PATH, "cake_oreo", "src_mv.png"),
|
502 |
+
os.path.join(EXAMPLES_PATH, "cake_oreo", "src.png"),
|
503 |
+
os.path.join(EXAMPLES_PATH, "cake_oreo", "edited.png"),
|
504 |
+
50,
|
505 |
+
31,
|
506 |
+
3.5,
|
507 |
+
5.0,
|
508 |
+
18,
|
509 |
+
],
|
510 |
+
|
511 |
+
[
|
512 |
+
os.path.join(EXAMPLES_PATH, "bike_harley", "src_mv.png"),
|
513 |
+
os.path.join(EXAMPLES_PATH, "bike_harley", "src.png"),
|
514 |
+
os.path.join(EXAMPLES_PATH, "bike_harley", "edited.png"),
|
515 |
+
50,
|
516 |
+
31,
|
517 |
+
3.5,
|
518 |
+
5.0,
|
519 |
+
18,
|
520 |
+
],
|
521 |
+
[
|
522 |
+
os.path.join(EXAMPLES_PATH, "bike_modern", "src_mv.png"),
|
523 |
+
os.path.join(EXAMPLES_PATH, "bike_modern", "src.png"),
|
524 |
+
os.path.join(EXAMPLES_PATH, "bike_modern", "edited.png"),
|
525 |
+
50,
|
526 |
+
31,
|
527 |
+
3.5,
|
528 |
+
5.0,
|
529 |
+
18,
|
530 |
+
],
|
531 |
+
[
|
532 |
+
os.path.join(EXAMPLES_PATH, "bmw_speedy", "src_mv.png"),
|
533 |
+
os.path.join(EXAMPLES_PATH, "bmw_speedy", "src.png"),
|
534 |
+
os.path.join(EXAMPLES_PATH, "bmw_speedy", "edited.png"),
|
535 |
+
50,
|
536 |
+
31,
|
537 |
+
3.5,
|
538 |
+
5.0,
|
539 |
+
18,
|
540 |
+
],
|
541 |
+
[
|
542 |
+
os.path.join(EXAMPLES_PATH, "batman_backpack", "src_mv.png"),
|
543 |
+
os.path.join(EXAMPLES_PATH, "batman_backpack", "src.png"),
|
544 |
+
os.path.join(EXAMPLES_PATH, "batman_backpack", "edited.png"),
|
545 |
+
50,
|
546 |
+
31,
|
547 |
+
3.5,
|
548 |
+
5.0,
|
549 |
+
18,
|
550 |
+
],
|
551 |
+
|
552 |
+
[
|
553 |
+
os.path.join(EXAMPLES_PATH, "figure_backpack", "src_mv.png"),
|
554 |
+
os.path.join(EXAMPLES_PATH, "figure_backpack", "src.png"),
|
555 |
+
os.path.join(EXAMPLES_PATH, "figure_backpack", "edited.png"),
|
556 |
+
50,
|
557 |
+
31,
|
558 |
+
3.5,
|
559 |
+
5.0,
|
560 |
+
18,
|
561 |
+
],
|
562 |
+
[
|
563 |
+
os.path.join(EXAMPLES_PATH, "car_cartoon", "src_mv.png"),
|
564 |
+
os.path.join(EXAMPLES_PATH, "car_cartoon", "src.png"),
|
565 |
+
os.path.join(EXAMPLES_PATH, "car_cartoon", "edited.png"),
|
566 |
+
50,
|
567 |
+
31,
|
568 |
+
3.5,
|
569 |
+
5.0,
|
570 |
+
18,
|
571 |
+
],
|
572 |
+
[
|
573 |
+
os.path.join(EXAMPLES_PATH, "car_engine", "src_mv.png"),
|
574 |
+
os.path.join(EXAMPLES_PATH, "car_engine", "src.png"),
|
575 |
+
os.path.join(EXAMPLES_PATH, "car_engine", "edited.png"),
|
576 |
+
50,
|
577 |
+
31,
|
578 |
+
3.5,
|
579 |
+
5.0,
|
580 |
+
18,
|
581 |
+
],
|
582 |
+
[
|
583 |
+
os.path.join(EXAMPLES_PATH, "car_steampunk", "src_mv.png"),
|
584 |
+
os.path.join(EXAMPLES_PATH, "car_steampunk", "src.png"),
|
585 |
+
os.path.join(EXAMPLES_PATH, "car_steampunk", "edited.png"),
|
586 |
+
50,
|
587 |
+
41,
|
588 |
+
3.5,
|
589 |
+
6.0,
|
590 |
+
18,
|
591 |
+
],
|
592 |
+
[
|
593 |
+
os.path.join(EXAMPLES_PATH, "green-dragon_skirt", "src_mv.png"),
|
594 |
+
os.path.join(EXAMPLES_PATH, "green-dragon_skirt", "src.png"),
|
595 |
+
os.path.join(EXAMPLES_PATH, "green-dragon_skirt", "edited.png"),
|
596 |
+
50,
|
597 |
+
41,
|
598 |
+
3.5,
|
599 |
+
6.0,
|
600 |
+
18,
|
601 |
+
],
|
602 |
+
[
|
603 |
+
os.path.join(EXAMPLES_PATH, "gazebo_pagoda", "src_mv.png"),
|
604 |
+
os.path.join(EXAMPLES_PATH, "gazebo_pagoda", "src.png"),
|
605 |
+
os.path.join(EXAMPLES_PATH, "gazebo_pagoda", "edited.png"),
|
606 |
+
50,
|
607 |
+
41,
|
608 |
+
3.5,
|
609 |
+
6.0,
|
610 |
+
18,
|
611 |
+
],
|
612 |
+
[
|
613 |
+
os.path.join(EXAMPLES_PATH, "oasis_magical", "src_mv.png"),
|
614 |
+
os.path.join(EXAMPLES_PATH, "oasis_magical", "src.png"),
|
615 |
+
os.path.join(EXAMPLES_PATH, "oasis_magical", "edited.png"),
|
616 |
+
50,
|
617 |
+
39,
|
618 |
+
3.5,
|
619 |
+
5.0,
|
620 |
+
18,
|
621 |
+
],
|
622 |
+
[
|
623 |
+
os.path.join(EXAMPLES_PATH, "cabin_alpine", "src_mv.png"),
|
624 |
+
os.path.join(EXAMPLES_PATH, "cabin_alpine", "src.png"),
|
625 |
+
os.path.join(EXAMPLES_PATH, "cabin_alpine", "edited.png"),
|
626 |
+
50,
|
627 |
+
42,
|
628 |
+
3.5,
|
629 |
+
12.0,
|
630 |
+
18,
|
631 |
+
],
|
632 |
+
[
|
633 |
+
os.path.join(EXAMPLES_PATH, "cabin_gothic", "src_mv.png"),
|
634 |
+
os.path.join(EXAMPLES_PATH, "cabin_gothic", "src.png"),
|
635 |
+
os.path.join(EXAMPLES_PATH, "cabin_gothic", "edited.png"),
|
636 |
+
50,
|
637 |
+
42,
|
638 |
+
3.5,
|
639 |
+
12.0,
|
640 |
+
18,
|
641 |
+
],
|
642 |
+
[
|
643 |
+
os.path.join(EXAMPLES_PATH, "fox_tuxedo", "src_mv.png"),
|
644 |
+
os.path.join(EXAMPLES_PATH, "fox_tuxedo", "src.png"),
|
645 |
+
os.path.join(EXAMPLES_PATH, "fox_tuxedo", "edited.png"),
|
646 |
+
50,
|
647 |
+
31,
|
648 |
+
3.5,
|
649 |
+
5.0,
|
650 |
+
18,
|
651 |
+
],
|
652 |
+
|
653 |
+
[
|
654 |
+
os.path.join(EXAMPLES_PATH, "cabin_haunted", "src_mv.png"),
|
655 |
+
os.path.join(EXAMPLES_PATH, "cabin_haunted", "src.png"),
|
656 |
+
os.path.join(EXAMPLES_PATH, "cabin_haunted", "edited.png"),
|
657 |
+
50,
|
658 |
+
42,
|
659 |
+
3.5,
|
660 |
+
12.0,
|
661 |
+
18,
|
662 |
+
],
|
663 |
+
[
|
664 |
+
os.path.join(EXAMPLES_PATH, "fox_eyes", "src_mv.png"),
|
665 |
+
os.path.join(EXAMPLES_PATH, "fox_eyes", "src.png"),
|
666 |
+
os.path.join(EXAMPLES_PATH, "fox_eyes", "edited.png"),
|
667 |
+
50,
|
668 |
+
31,
|
669 |
+
3.5,
|
670 |
+
5.0,
|
671 |
+
18,
|
672 |
+
],
|
673 |
+
[
|
674 |
+
os.path.join(EXAMPLES_PATH, "gazebo_disney", "src_mv.png"),
|
675 |
+
os.path.join(EXAMPLES_PATH, "gazebo_disney", "src.png"),
|
676 |
+
os.path.join(EXAMPLES_PATH, "gazebo_disney", "edited.png"),
|
677 |
+
50,
|
678 |
+
31,
|
679 |
+
3.5,
|
680 |
+
5.0,
|
681 |
+
18,
|
682 |
+
],
|
683 |
+
[
|
684 |
+
os.path.join(EXAMPLES_PATH, "desk_wizard", "src_mv.png"),
|
685 |
+
os.path.join(EXAMPLES_PATH, "desk_wizard", "src.png"),
|
686 |
+
os.path.join(EXAMPLES_PATH, "desk_wizard", "edited.png"),
|
687 |
+
50,
|
688 |
+
42,
|
689 |
+
3.5,
|
690 |
+
12.0,
|
691 |
+
18,
|
692 |
+
],
|
693 |
+
|
694 |
+
[
|
695 |
+
os.path.join(EXAMPLES_PATH, "gazebo_light", "src_mv.png"),
|
696 |
+
os.path.join(EXAMPLES_PATH, "gazebo_light", "src.png"),
|
697 |
+
os.path.join(EXAMPLES_PATH, "gazebo_light", "edited.png"),
|
698 |
+
50,
|
699 |
+
31,
|
700 |
+
3.5,
|
701 |
+
5.0,
|
702 |
+
18,
|
703 |
+
],
|
704 |
+
[
|
705 |
+
os.path.join(EXAMPLES_PATH, "gazebo_roof", "src_mv.png"),
|
706 |
+
os.path.join(EXAMPLES_PATH, "gazebo_roof", "src.png"),
|
707 |
+
os.path.join(EXAMPLES_PATH, "gazebo_roof", "edited.png"),
|
708 |
+
50,
|
709 |
+
39,
|
710 |
+
3.5,
|
711 |
+
5.0,
|
712 |
+
18,
|
713 |
+
],
|
714 |
+
[
|
715 |
+
os.path.join(EXAMPLES_PATH, "grogu_earphones", "src_mv.png"),
|
716 |
+
os.path.join(EXAMPLES_PATH, "grogu_earphones", "src.png"),
|
717 |
+
os.path.join(EXAMPLES_PATH, "grogu_earphones", "edited.png"),
|
718 |
+
50,
|
719 |
+
41,
|
720 |
+
3.5,
|
721 |
+
6.0,
|
722 |
+
18,
|
723 |
+
],
|
724 |
+
|
725 |
+
[
|
726 |
+
os.path.join(EXAMPLES_PATH, "gazebo_rust", "src_mv.png"),
|
727 |
+
os.path.join(EXAMPLES_PATH, "gazebo_rust", "src.png"),
|
728 |
+
os.path.join(EXAMPLES_PATH, "gazebo_rust", "edited.png"),
|
729 |
+
50,
|
730 |
+
39,
|
731 |
+
3.5,
|
732 |
+
5.0,
|
733 |
+
18,
|
734 |
+
],
|
735 |
+
|
736 |
+
[
|
737 |
+
os.path.join(EXAMPLES_PATH, "german-shep_pixar", "src_mv.png"),
|
738 |
+
os.path.join(EXAMPLES_PATH, "german-shep_pixar", "src.png"),
|
739 |
+
os.path.join(EXAMPLES_PATH, "german-shep_pixar", "edited.png"),
|
740 |
+
50,
|
741 |
+
39,
|
742 |
+
3.5,
|
743 |
+
5.0,
|
744 |
+
18,
|
745 |
+
],
|
746 |
+
[
|
747 |
+
os.path.join(EXAMPLES_PATH, "grogu_kimono", "src_mv.png"),
|
748 |
+
os.path.join(EXAMPLES_PATH, "grogu_kimono", "src.png"),
|
749 |
+
os.path.join(EXAMPLES_PATH, "grogu_kimono", "edited.png"),
|
750 |
+
50,
|
751 |
+
39,
|
752 |
+
3.5,
|
753 |
+
21.0,
|
754 |
+
18,
|
755 |
+
],
|
756 |
+
[
|
757 |
+
os.path.join(EXAMPLES_PATH, "ship_fantasy", "src_mv.png"),
|
758 |
+
os.path.join(EXAMPLES_PATH, "ship_fantasy", "src.png"),
|
759 |
+
os.path.join(EXAMPLES_PATH, "ship_fantasy", "edited.png"),
|
760 |
+
50,
|
761 |
+
31,
|
762 |
+
3.5,
|
763 |
+
5.0,
|
764 |
+
18,
|
765 |
+
],
|
766 |
+
|
767 |
+
[
|
768 |
+
os.path.join(EXAMPLES_PATH, "grogu_lego-fig", "src_mv.png"),
|
769 |
+
os.path.join(EXAMPLES_PATH, "grogu_lego-fig", "src.png"),
|
770 |
+
os.path.join(EXAMPLES_PATH, "grogu_lego-fig", "edited.png"),
|
771 |
+
50,
|
772 |
+
39,
|
773 |
+
3.5,
|
774 |
+
21.0,
|
775 |
+
18,
|
776 |
+
],
|
777 |
+
[
|
778 |
+
os.path.join(EXAMPLES_PATH, "lego-car_spoiler", "src_mv.png"),
|
779 |
+
os.path.join(EXAMPLES_PATH, "lego-car_spoiler", "src.png"),
|
780 |
+
os.path.join(EXAMPLES_PATH, "lego-car_spoiler", "edited.png"),
|
781 |
+
50,
|
782 |
+
39,
|
783 |
+
3.5,
|
784 |
+
5.0,
|
785 |
+
18,
|
786 |
+
],
|
787 |
+
[
|
788 |
+
os.path.join(EXAMPLES_PATH, "nurse_sporty", "src_mv.png"),
|
789 |
+
os.path.join(EXAMPLES_PATH, "nurse_sporty", "src.png"),
|
790 |
+
os.path.join(EXAMPLES_PATH, "nurse_sporty", "edited.png"),
|
791 |
+
50,
|
792 |
+
31,
|
793 |
+
3.5,
|
794 |
+
5.0,
|
795 |
+
18,
|
796 |
+
],
|
797 |
+
[
|
798 |
+
os.path.join(EXAMPLES_PATH, "r2d2_golden", "src_mv.png"),
|
799 |
+
os.path.join(EXAMPLES_PATH, "r2d2_golden", "src.png"),
|
800 |
+
os.path.join(EXAMPLES_PATH, "r2d2_golden", "edited.png"),
|
801 |
+
50,
|
802 |
+
31,
|
803 |
+
3.5,
|
804 |
+
5.0,
|
805 |
+
18,
|
806 |
+
],
|
807 |
+
[
|
808 |
+
os.path.join(EXAMPLES_PATH, "grogu_the-force", "src_mv.png"),
|
809 |
+
os.path.join(EXAMPLES_PATH, "grogu_the-force", "src.png"),
|
810 |
+
os.path.join(EXAMPLES_PATH, "grogu_the-force", "edited.png"),
|
811 |
+
50,
|
812 |
+
39,
|
813 |
+
3.5,
|
814 |
+
21.0,
|
815 |
+
18,
|
816 |
+
],
|
817 |
+
|
818 |
+
[
|
819 |
+
os.path.join(EXAMPLES_PATH, "spiderbot_chrome", "src_mv.png"),
|
820 |
+
os.path.join(EXAMPLES_PATH, "spiderbot_chrome", "src.png"),
|
821 |
+
os.path.join(EXAMPLES_PATH, "spiderbot_chrome", "edited.png"),
|
822 |
+
50,
|
823 |
+
31,
|
824 |
+
3.5,
|
825 |
+
5.0,
|
826 |
+
18,
|
827 |
+
],
|
828 |
+
[
|
829 |
+
os.path.join(
|
830 |
+
EXAMPLES_PATH, "spiderbot_steampunk", "src_mv.png"
|
831 |
+
),
|
832 |
+
os.path.join(EXAMPLES_PATH, "spiderbot_steampunk", "src.png"),
|
833 |
+
os.path.join(
|
834 |
+
EXAMPLES_PATH, "spiderbot_steampunk", "edited.png"
|
835 |
+
),
|
836 |
+
50,
|
837 |
+
31,
|
838 |
+
3.5,
|
839 |
+
5.0,
|
840 |
+
18,
|
841 |
+
],
|
842 |
+
[
|
843 |
+
os.path.join(EXAMPLES_PATH, "superman_crossed", "src_mv.png"),
|
844 |
+
os.path.join(EXAMPLES_PATH, "superman_crossed", "src.png"),
|
845 |
+
os.path.join(EXAMPLES_PATH, "superman_crossed", "edited.png"),
|
846 |
+
50,
|
847 |
+
39,
|
848 |
+
3.5,
|
849 |
+
5.0,
|
850 |
+
18,
|
851 |
+
],
|
852 |
+
]
|
853 |
+
|
854 |
+
gr.Examples(
|
855 |
+
examples=example_data,
|
856 |
+
inputs=example_inputs,
|
857 |
+
label="Example Edits",
|
858 |
+
examples_per_page=10,
|
859 |
+
elem_id="example-table"
|
860 |
+
|
861 |
+
)
|
862 |
+
|
863 |
+
with gr.TabItem("How to Use", id=1):
|
864 |
+
gr.Markdown(HOW_TO_USE_TEXT)
|
865 |
+
|
866 |
+
# Define button actions
|
867 |
+
run_button.click(
|
868 |
+
fn=run_main_script,
|
869 |
+
inputs=[
|
870 |
+
src_cond_image,
|
871 |
+
tgt_cond_image,
|
872 |
+
original_mv_image,
|
873 |
+
t_steps,
|
874 |
+
n_max,
|
875 |
+
src_gs,
|
876 |
+
tar_gs,
|
877 |
+
seed,
|
878 |
+
],
|
879 |
+
outputs=output_image,
|
880 |
+
)
|
881 |
+
|
882 |
+
clear_button.click(
|
883 |
+
fn=clear_inputs,
|
884 |
+
inputs=[],
|
885 |
+
outputs=[
|
886 |
+
original_mv_image,
|
887 |
+
src_cond_image,
|
888 |
+
tgt_cond_image,
|
889 |
+
t_steps,
|
890 |
+
n_max,
|
891 |
+
src_gs,
|
892 |
+
tar_gs,
|
893 |
+
seed,
|
894 |
+
output_image,
|
895 |
+
],
|
896 |
+
)
|
897 |
+
|
898 |
+
if __name__ == "__main__":
|
899 |
+
demo.launch(share=True)
|
assets/stormtrooper.glb
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:921f8656fac3332d100969f40724455b7d34565625cf2a29d9e36f6c81b1d1c9
|
3 |
+
size 1659928
|
examples/batman_backpack/edited.png
ADDED
![]() |
Git LFS Details
|
examples/batman_backpack/src.png
ADDED
![]() |
Git LFS Details
|
examples/batman_backpack/src_mv.png
ADDED
![]() |
Git LFS Details
|
examples/batman_jetpack/edited.png
ADDED
![]() |
Git LFS Details
|
examples/batman_jetpack/src.png
ADDED
![]() |
Git LFS Details
|
examples/batman_jetpack/src_mv.png
ADDED
![]() |
Git LFS Details
|
examples/bike_harley/edited.png
ADDED
![]() |
Git LFS Details
|
examples/bike_harley/src.png
ADDED
![]() |
Git LFS Details
|
examples/bike_harley/src_mv.png
ADDED
![]() |
Git LFS Details
|
examples/bike_modern/edited.png
ADDED
![]() |
Git LFS Details
|
examples/bike_modern/src.png
ADDED
![]() |
Git LFS Details
|
examples/bike_modern/src_mv.png
ADDED
![]() |
Git LFS Details
|
examples/bike_sport/edited.png
ADDED
![]() |
Git LFS Details
|
examples/bike_sport/src.png
ADDED
![]() |
Git LFS Details
|
examples/bike_sport/src_mv.png
ADDED
![]() |
Git LFS Details
|
examples/bike_vintage/edited.png
ADDED
![]() |
Git LFS Details
|
examples/bike_vintage/src.png
ADDED
![]() |
Git LFS Details
|
examples/bike_vintage/src_mv.png
ADDED
![]() |
Git LFS Details
|
examples/bmw_speedy/edited.png
ADDED
![]() |
Git LFS Details
|
examples/bmw_speedy/src.png
ADDED
![]() |
Git LFS Details
|
examples/bmw_speedy/src_mv.png
ADDED
![]() |
Git LFS Details
|
examples/cabin_alpine/edited.png
ADDED
![]() |
Git LFS Details
|
examples/cabin_alpine/src.png
ADDED
![]() |
Git LFS Details
|
examples/cabin_alpine/src_mv.png
ADDED
![]() |
Git LFS Details
|
examples/cabin_gothic/edited.png
ADDED
![]() |
Git LFS Details
|
examples/cabin_gothic/src.png
ADDED
![]() |
Git LFS Details
|
examples/cabin_gothic/src_mv.png
ADDED
![]() |
Git LFS Details
|
examples/cabin_haunted/edited.png
ADDED
![]() |
Git LFS Details
|
examples/cabin_haunted/src.png
ADDED
![]() |
Git LFS Details
|
examples/cabin_haunted/src_mv.png
ADDED
![]() |
Git LFS Details
|
examples/cake_oreo/edited.png
ADDED
![]() |
Git LFS Details
|
examples/cake_oreo/src.png
ADDED
![]() |
Git LFS Details
|
examples/cake_oreo/src_mv.png
ADDED
![]() |
Git LFS Details
|
examples/car_cartoon/edited.png
ADDED
![]() |
Git LFS Details
|
examples/car_cartoon/src.png
ADDED
![]() |
Git LFS Details
|
examples/car_cartoon/src_mv.png
ADDED
![]() |
Git LFS Details
|
examples/car_engine/edited.png
ADDED
![]() |
Git LFS Details
|
examples/car_engine/src.png
ADDED
![]() |
Git LFS Details
|
examples/car_engine/src_mv.png
ADDED
![]() |
Git LFS Details
|
examples/car_steampunk/edited.png
ADDED
![]() |
Git LFS Details
|
examples/car_steampunk/src.png
ADDED
![]() |
Git LFS Details
|
examples/car_steampunk/src_mv.png
ADDED
![]() |
Git LFS Details
|
examples/deer_pixar/edited.png
ADDED
![]() |
Git LFS Details
|
examples/deer_pixar/src.png
ADDED
![]() |
Git LFS Details
|