roi commited on
Commit
a176955
·
0 Parent(s):

Initial commit: EditP23 project with LFS tracking for binary files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +48 -0
  2. .gitignore +30 -0
  3. .gitmodules +3 -0
  4. README.md +231 -0
  5. app.py +899 -0
  6. assets/stormtrooper.glb +3 -0
  7. examples/batman_backpack/edited.png +3 -0
  8. examples/batman_backpack/src.png +3 -0
  9. examples/batman_backpack/src_mv.png +3 -0
  10. examples/batman_jetpack/edited.png +3 -0
  11. examples/batman_jetpack/src.png +3 -0
  12. examples/batman_jetpack/src_mv.png +3 -0
  13. examples/bike_harley/edited.png +3 -0
  14. examples/bike_harley/src.png +3 -0
  15. examples/bike_harley/src_mv.png +3 -0
  16. examples/bike_modern/edited.png +3 -0
  17. examples/bike_modern/src.png +3 -0
  18. examples/bike_modern/src_mv.png +3 -0
  19. examples/bike_sport/edited.png +3 -0
  20. examples/bike_sport/src.png +3 -0
  21. examples/bike_sport/src_mv.png +3 -0
  22. examples/bike_vintage/edited.png +3 -0
  23. examples/bike_vintage/src.png +3 -0
  24. examples/bike_vintage/src_mv.png +3 -0
  25. examples/bmw_speedy/edited.png +3 -0
  26. examples/bmw_speedy/src.png +3 -0
  27. examples/bmw_speedy/src_mv.png +3 -0
  28. examples/cabin_alpine/edited.png +3 -0
  29. examples/cabin_alpine/src.png +3 -0
  30. examples/cabin_alpine/src_mv.png +3 -0
  31. examples/cabin_gothic/edited.png +3 -0
  32. examples/cabin_gothic/src.png +3 -0
  33. examples/cabin_gothic/src_mv.png +3 -0
  34. examples/cabin_haunted/edited.png +3 -0
  35. examples/cabin_haunted/src.png +3 -0
  36. examples/cabin_haunted/src_mv.png +3 -0
  37. examples/cake_oreo/edited.png +3 -0
  38. examples/cake_oreo/src.png +3 -0
  39. examples/cake_oreo/src_mv.png +3 -0
  40. examples/car_cartoon/edited.png +3 -0
  41. examples/car_cartoon/src.png +3 -0
  42. examples/car_cartoon/src_mv.png +3 -0
  43. examples/car_engine/edited.png +3 -0
  44. examples/car_engine/src.png +3 -0
  45. examples/car_engine/src_mv.png +3 -0
  46. examples/car_steampunk/edited.png +3 -0
  47. examples/car_steampunk/src.png +3 -0
  48. examples/car_steampunk/src_mv.png +3 -0
  49. examples/deer_pixar/edited.png +3 -0
  50. 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
+ [![Project Page](https://img.shields.io/badge/Project-Page-blue)](https://editp23.github.io/)
15
+ [![arXiv](https://img.shields.io/badge/arXiv-2506.20652-b31b1b.svg)](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** | ![Original Condition View](resources/mv-gallery/1/src/prompt.png) | ![Original View 1](resources/mv-gallery/1/src/0.png) | ![Original View 2](resources/mv-gallery/1/src/1.png) | ![Original View 3](resources/mv-gallery/1/src/2.png) |
95
+ | **Pixar style** | ![Pixar Condition View](resources/mv-gallery/1/edit/prompt.png) | ![Pixar View 1](resources/mv-gallery/1/edit/0.png) | ![Pixar View 2](resources/mv-gallery/1/edit/1.png) | ![Pixar View 3](resources/mv-gallery/1/edit/2.png) |
96
+ | **Wings** | ![Wings Condition View](resources/mv-gallery/1/edit2/prompt.png) | ![Wings View 2](resources/mv-gallery/1/edit2/0.png) | ![Wings View 2](resources/mv-gallery/1/edit2/1.png) | ![Wings View 3](resources/mv-gallery/1/edit2/2.png) |
97
+
98
+ <br>
99
+
100
+ ### Person - Old & Zombie
101
+
102
+ | | Cond. View | View 1 | View 2 | View 3 |
103
+ |:-------------|:-----------------------------------------------------------------:|:----------------------------------------------------:|:----------------------------------------------------:|:----------------------------------------------------:|
104
+ | **Original** | ![Original Condition View](resources/mv-gallery/2/src/prompt.png) | ![Original View 1](resources/mv-gallery/2/src/0.png) | ![Original View 2](resources/mv-gallery/2/src/1.png) | ![Original View 3](resources/mv-gallery/2/src/2.png) |
105
+ | **Old** | ![Old Condition View](resources/mv-gallery/2/edit/prompt.png) | ![Old View 1](resources/mv-gallery/2/edit/0.png) | ![Old View 2](resources/mv-gallery/2/edit/1.png) | ![Old View 3](resources/mv-gallery/2/edit/2.png) |
106
+ | **Zombie** | ![Zombie Condition View](resources/mv-gallery/2/edit2/prompt.png) | ![Zombie View 2](resources/mv-gallery/2/edit2/0.png) | ![Zombie View 2](resources/mv-gallery/2/edit2/1.png) | ![Zombie View 3](resources/mv-gallery/2/edit2/2.png) |
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

  • SHA256: b931e0b36421524569533d2076f7885050f376c8a89978ee5b6c5fb91364ebbf
  • Pointer size: 131 Bytes
  • Size of remote file: 212 kB
examples/batman_backpack/src.png ADDED

Git LFS Details

  • SHA256: 0829cda6608dbcc1de82f45c3887fdcfbdf4f5271976ca67b3d3d815ccebf018
  • Pointer size: 130 Bytes
  • Size of remote file: 94.7 kB
examples/batman_backpack/src_mv.png ADDED

Git LFS Details

  • SHA256: 6309e40375714b89f843d3623e00150c79add3d417a8b04317539fcaf3d997e0
  • Pointer size: 131 Bytes
  • Size of remote file: 171 kB
examples/batman_jetpack/edited.png ADDED

Git LFS Details

  • SHA256: b312bfaeb098b1fe45ed61824b6e0a9a956e6f8969d880347eb4ac17512a0ac6
  • Pointer size: 131 Bytes
  • Size of remote file: 224 kB
examples/batman_jetpack/src.png ADDED

Git LFS Details

  • SHA256: 0829cda6608dbcc1de82f45c3887fdcfbdf4f5271976ca67b3d3d815ccebf018
  • Pointer size: 130 Bytes
  • Size of remote file: 94.7 kB
examples/batman_jetpack/src_mv.png ADDED

Git LFS Details

  • SHA256: 6309e40375714b89f843d3623e00150c79add3d417a8b04317539fcaf3d997e0
  • Pointer size: 131 Bytes
  • Size of remote file: 171 kB
examples/bike_harley/edited.png ADDED

Git LFS Details

  • SHA256: b810cc2f73c107c698f03c2bd8ad4d5e13646ba5a327818670a98c1c7cb96da4
  • Pointer size: 131 Bytes
  • Size of remote file: 165 kB
examples/bike_harley/src.png ADDED

Git LFS Details

  • SHA256: d122fa2e465bf5cfe1856cf913e029fee66d2229ea7b8a5f77254f0acaa44622
  • Pointer size: 131 Bytes
  • Size of remote file: 181 kB
examples/bike_harley/src_mv.png ADDED

Git LFS Details

  • SHA256: 343367a134e514ac65e3d06181e61a944ddf86112b52054ba2719383129e1862
  • Pointer size: 131 Bytes
  • Size of remote file: 356 kB
examples/bike_modern/edited.png ADDED

Git LFS Details

  • SHA256: 39e655a517446a880a7d9063fe271469bca3e6f7f0a8795f4e2c6d4596b195b9
  • Pointer size: 131 Bytes
  • Size of remote file: 164 kB
examples/bike_modern/src.png ADDED

Git LFS Details

  • SHA256: d122fa2e465bf5cfe1856cf913e029fee66d2229ea7b8a5f77254f0acaa44622
  • Pointer size: 131 Bytes
  • Size of remote file: 181 kB
examples/bike_modern/src_mv.png ADDED

Git LFS Details

  • SHA256: 343367a134e514ac65e3d06181e61a944ddf86112b52054ba2719383129e1862
  • Pointer size: 131 Bytes
  • Size of remote file: 356 kB
examples/bike_sport/edited.png ADDED

Git LFS Details

  • SHA256: 337d0f6dbe4df38020aa3de73d6acce82801f7efdcaedd37f297d9ec223e6cc4
  • Pointer size: 131 Bytes
  • Size of remote file: 101 kB
examples/bike_sport/src.png ADDED

Git LFS Details

  • SHA256: a161a0125c23afc5f79dced0ff10055722fe6379c54e9324aeed894a09ca613c
  • Pointer size: 130 Bytes
  • Size of remote file: 91.7 kB
examples/bike_sport/src_mv.png ADDED

Git LFS Details

  • SHA256: 2f2c13a76e416db634e873ecd9b5c492c42e14e4c3310ee1583851c829582b32
  • Pointer size: 131 Bytes
  • Size of remote file: 291 kB
examples/bike_vintage/edited.png ADDED

Git LFS Details

  • SHA256: b8230a205104ffa813e9231068e805be17bbe6c5efb8e41a4dc4a489c5e9206c
  • Pointer size: 131 Bytes
  • Size of remote file: 171 kB
examples/bike_vintage/src.png ADDED

Git LFS Details

  • SHA256: d122fa2e465bf5cfe1856cf913e029fee66d2229ea7b8a5f77254f0acaa44622
  • Pointer size: 131 Bytes
  • Size of remote file: 181 kB
examples/bike_vintage/src_mv.png ADDED

Git LFS Details

  • SHA256: 343367a134e514ac65e3d06181e61a944ddf86112b52054ba2719383129e1862
  • Pointer size: 131 Bytes
  • Size of remote file: 356 kB
examples/bmw_speedy/edited.png ADDED

Git LFS Details

  • SHA256: d45865fba033e4e599ab4a35198aac39e00bc00404147531bf37bdf25f5cf598
  • Pointer size: 130 Bytes
  • Size of remote file: 91.1 kB
examples/bmw_speedy/src.png ADDED

Git LFS Details

  • SHA256: d0b7c8e768928d36db07363dd2a5cc7d0df6895118a4a57d1ad417f2dca9cccd
  • Pointer size: 131 Bytes
  • Size of remote file: 109 kB
examples/bmw_speedy/src_mv.png ADDED

Git LFS Details

  • SHA256: 9d914de8ed583b5cf016dc4b601dc72b62f6999885c289a745ee09d86903dbda
  • Pointer size: 131 Bytes
  • Size of remote file: 178 kB
examples/cabin_alpine/edited.png ADDED

Git LFS Details

  • SHA256: be31a56b0aeea55dc8d71c23919017f8ad0c9a1d1c0b67370f37f427df93271c
  • Pointer size: 131 Bytes
  • Size of remote file: 859 kB
examples/cabin_alpine/src.png ADDED

Git LFS Details

  • SHA256: 0655a2cca2e8b5e9590228252c239079963425d5f6d9f5ccc698fd78ed02687a
  • Pointer size: 131 Bytes
  • Size of remote file: 304 kB
examples/cabin_alpine/src_mv.png ADDED

Git LFS Details

  • SHA256: 6b211a612b264cb26d0b18f2a80f5273716f4d7d5b86a669f4c4ab8cf4167ff6
  • Pointer size: 131 Bytes
  • Size of remote file: 520 kB
examples/cabin_gothic/edited.png ADDED

Git LFS Details

  • SHA256: b7efc56a9f254cda00ec54ce93bec15335ecfe5f6bf10911a262fcd783f2bb8d
  • Pointer size: 131 Bytes
  • Size of remote file: 881 kB
examples/cabin_gothic/src.png ADDED

Git LFS Details

  • SHA256: 0655a2cca2e8b5e9590228252c239079963425d5f6d9f5ccc698fd78ed02687a
  • Pointer size: 131 Bytes
  • Size of remote file: 304 kB
examples/cabin_gothic/src_mv.png ADDED

Git LFS Details

  • SHA256: 6b211a612b264cb26d0b18f2a80f5273716f4d7d5b86a669f4c4ab8cf4167ff6
  • Pointer size: 131 Bytes
  • Size of remote file: 520 kB
examples/cabin_haunted/edited.png ADDED

Git LFS Details

  • SHA256: 5ce7a3b5abda615bd3f1e9694ba0d8925c912ef249b3f0127e7228f29a9ece44
  • Pointer size: 131 Bytes
  • Size of remote file: 270 kB
examples/cabin_haunted/src.png ADDED

Git LFS Details

  • SHA256: 0655a2cca2e8b5e9590228252c239079963425d5f6d9f5ccc698fd78ed02687a
  • Pointer size: 131 Bytes
  • Size of remote file: 304 kB
examples/cabin_haunted/src_mv.png ADDED

Git LFS Details

  • SHA256: 6b211a612b264cb26d0b18f2a80f5273716f4d7d5b86a669f4c4ab8cf4167ff6
  • Pointer size: 131 Bytes
  • Size of remote file: 520 kB
examples/cake_oreo/edited.png ADDED

Git LFS Details

  • SHA256: fe262f65660d656341c7780a5ce444eae965980abbba45d44754fde07e6d976f
  • Pointer size: 131 Bytes
  • Size of remote file: 476 kB
examples/cake_oreo/src.png ADDED

Git LFS Details

  • SHA256: bab8e40296d3df9d572c43b494a3cf7de0374c9209a69765a91e00f4c4c2cba3
  • Pointer size: 131 Bytes
  • Size of remote file: 251 kB
examples/cake_oreo/src_mv.png ADDED

Git LFS Details

  • SHA256: d8b8961a2dad370cf1dc548aed6d8e563c84f895027095d95872c565c3a7673a
  • Pointer size: 131 Bytes
  • Size of remote file: 428 kB
examples/car_cartoon/edited.png ADDED

Git LFS Details

  • SHA256: d2f31141552cb72b4a5e7b204926d3c6cd7e36651edc2924a3d5d8e10437694e
  • Pointer size: 130 Bytes
  • Size of remote file: 93.6 kB
examples/car_cartoon/src.png ADDED

Git LFS Details

  • SHA256: 10dbdbdfe282d8f232caf66c6d84f9116639bcc50b8e70b2cde2a0f352fdccfe
  • Pointer size: 131 Bytes
  • Size of remote file: 102 kB
examples/car_cartoon/src_mv.png ADDED

Git LFS Details

  • SHA256: a0bf471ec55d12cac52b73620503439b3910fc2e31c8f7569d28c80beb57b1bb
  • Pointer size: 131 Bytes
  • Size of remote file: 183 kB
examples/car_engine/edited.png ADDED

Git LFS Details

  • SHA256: d506435b214bb037f0c65312b8c29b356c79c31db7abc1c5e9776c38a1890fca
  • Pointer size: 131 Bytes
  • Size of remote file: 255 kB
examples/car_engine/src.png ADDED

Git LFS Details

  • SHA256: 10dbdbdfe282d8f232caf66c6d84f9116639bcc50b8e70b2cde2a0f352fdccfe
  • Pointer size: 131 Bytes
  • Size of remote file: 102 kB
examples/car_engine/src_mv.png ADDED

Git LFS Details

  • SHA256: a0bf471ec55d12cac52b73620503439b3910fc2e31c8f7569d28c80beb57b1bb
  • Pointer size: 131 Bytes
  • Size of remote file: 183 kB
examples/car_steampunk/edited.png ADDED

Git LFS Details

  • SHA256: 2f1f047c038f82081928c1c008b71529fe683bdbedf23814729f07156bb04405
  • Pointer size: 130 Bytes
  • Size of remote file: 94.1 kB
examples/car_steampunk/src.png ADDED

Git LFS Details

  • SHA256: 10dbdbdfe282d8f232caf66c6d84f9116639bcc50b8e70b2cde2a0f352fdccfe
  • Pointer size: 131 Bytes
  • Size of remote file: 102 kB
examples/car_steampunk/src_mv.png ADDED

Git LFS Details

  • SHA256: a0bf471ec55d12cac52b73620503439b3910fc2e31c8f7569d28c80beb57b1bb
  • Pointer size: 131 Bytes
  • Size of remote file: 183 kB
examples/deer_pixar/edited.png ADDED

Git LFS Details

  • SHA256: 3851883c3f4985b580179430dd59ecabb2ab307d2fb2fac9b1d098ab8335c3d9
  • Pointer size: 131 Bytes
  • Size of remote file: 125 kB
examples/deer_pixar/src.png ADDED

Git LFS Details

  • SHA256: 4283b7e23c6a7173982dd16f6943aaa3fc1367b0b20a4736c5b4b4ffeee0a1d5
  • Pointer size: 131 Bytes
  • Size of remote file: 107 kB