dogincharge hysts HF staff commited on
Commit
e8d6995
0 Parent(s):

Duplicate from hysts/Shap-E

Browse files

Co-authored-by: hysts <hysts@users.noreply.huggingface.co>

Files changed (16) hide show
  1. .gitattributes +34 -0
  2. .gitignore +164 -0
  3. .pre-commit-config.yaml +36 -0
  4. .style.yapf +5 -0
  5. .vscode/settings.json +18 -0
  6. LICENSE +21 -0
  7. LICENSE.Shap-E +21 -0
  8. README.md +18 -0
  9. app.py +29 -0
  10. app_image_to_3d.py +74 -0
  11. app_text_to_3d.py +89 -0
  12. model.py +65 -0
  13. requirements.txt +6 -0
  14. settings.py +7 -0
  15. style.css +20 -0
  16. utils.py +9 -0
.gitattributes ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ *.tflite filter=lfs diff=lfs merge=lfs -text
29
+ *.tgz filter=lfs diff=lfs merge=lfs -text
30
+ *.wasm filter=lfs diff=lfs merge=lfs -text
31
+ *.xz filter=lfs diff=lfs merge=lfs -text
32
+ *.zip filter=lfs diff=lfs merge=lfs -text
33
+ *.zst filter=lfs diff=lfs merge=lfs -text
34
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ gradio_cached_examples/
2
+ shap_e_model_cache/
3
+ corgi.png
4
+
5
+ # Byte-compiled / optimized / DLL files
6
+ __pycache__/
7
+ *.py[cod]
8
+ *$py.class
9
+
10
+ # C extensions
11
+ *.so
12
+
13
+ # Distribution / packaging
14
+ .Python
15
+ build/
16
+ develop-eggs/
17
+ dist/
18
+ downloads/
19
+ eggs/
20
+ .eggs/
21
+ lib/
22
+ lib64/
23
+ parts/
24
+ sdist/
25
+ var/
26
+ wheels/
27
+ share/python-wheels/
28
+ *.egg-info/
29
+ .installed.cfg
30
+ *.egg
31
+ MANIFEST
32
+
33
+ # PyInstaller
34
+ # Usually these files are written by a python script from a template
35
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
36
+ *.manifest
37
+ *.spec
38
+
39
+ # Installer logs
40
+ pip-log.txt
41
+ pip-delete-this-directory.txt
42
+
43
+ # Unit test / coverage reports
44
+ htmlcov/
45
+ .tox/
46
+ .nox/
47
+ .coverage
48
+ .coverage.*
49
+ .cache
50
+ nosetests.xml
51
+ coverage.xml
52
+ *.cover
53
+ *.py,cover
54
+ .hypothesis/
55
+ .pytest_cache/
56
+ cover/
57
+
58
+ # Translations
59
+ *.mo
60
+ *.pot
61
+
62
+ # Django stuff:
63
+ *.log
64
+ local_settings.py
65
+ db.sqlite3
66
+ db.sqlite3-journal
67
+
68
+ # Flask stuff:
69
+ instance/
70
+ .webassets-cache
71
+
72
+ # Scrapy stuff:
73
+ .scrapy
74
+
75
+ # Sphinx documentation
76
+ docs/_build/
77
+
78
+ # PyBuilder
79
+ .pybuilder/
80
+ target/
81
+
82
+ # Jupyter Notebook
83
+ .ipynb_checkpoints
84
+
85
+ # IPython
86
+ profile_default/
87
+ ipython_config.py
88
+
89
+ # pyenv
90
+ # For a library or package, you might want to ignore these files since the code is
91
+ # intended to run in multiple environments; otherwise, check them in:
92
+ # .python-version
93
+
94
+ # pipenv
95
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
96
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
97
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
98
+ # install all needed dependencies.
99
+ #Pipfile.lock
100
+
101
+ # poetry
102
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
103
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
104
+ # commonly ignored for libraries.
105
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
106
+ #poetry.lock
107
+
108
+ # pdm
109
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
110
+ #pdm.lock
111
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
112
+ # in version control.
113
+ # https://pdm.fming.dev/#use-with-ide
114
+ .pdm.toml
115
+
116
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
117
+ __pypackages__/
118
+
119
+ # Celery stuff
120
+ celerybeat-schedule
121
+ celerybeat.pid
122
+
123
+ # SageMath parsed files
124
+ *.sage.py
125
+
126
+ # Environments
127
+ .env
128
+ .venv
129
+ env/
130
+ venv/
131
+ ENV/
132
+ env.bak/
133
+ venv.bak/
134
+
135
+ # Spyder project settings
136
+ .spyderproject
137
+ .spyproject
138
+
139
+ # Rope project settings
140
+ .ropeproject
141
+
142
+ # mkdocs documentation
143
+ /site
144
+
145
+ # mypy
146
+ .mypy_cache/
147
+ .dmypy.json
148
+ dmypy.json
149
+
150
+ # Pyre type checker
151
+ .pyre/
152
+
153
+ # pytype static type analyzer
154
+ .pytype/
155
+
156
+ # Cython debug symbols
157
+ cython_debug/
158
+
159
+ # PyCharm
160
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
161
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
162
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
163
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
164
+ #.idea/
.pre-commit-config.yaml ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v4.2.0
4
+ hooks:
5
+ - id: check-executables-have-shebangs
6
+ - id: check-json
7
+ - id: check-merge-conflict
8
+ - id: check-shebang-scripts-are-executable
9
+ - id: check-toml
10
+ - id: check-yaml
11
+ - id: double-quote-string-fixer
12
+ - id: end-of-file-fixer
13
+ - id: mixed-line-ending
14
+ args: ['--fix=lf']
15
+ - id: requirements-txt-fixer
16
+ - id: trailing-whitespace
17
+ - repo: https://github.com/myint/docformatter
18
+ rev: v1.4
19
+ hooks:
20
+ - id: docformatter
21
+ args: ['--in-place']
22
+ - repo: https://github.com/pycqa/isort
23
+ rev: 5.12.0
24
+ hooks:
25
+ - id: isort
26
+ - repo: https://github.com/pre-commit/mirrors-mypy
27
+ rev: v0.991
28
+ hooks:
29
+ - id: mypy
30
+ args: ['--ignore-missing-imports']
31
+ additional_dependencies: ['types-python-slugify']
32
+ - repo: https://github.com/google/yapf
33
+ rev: v0.32.0
34
+ hooks:
35
+ - id: yapf
36
+ args: ['--parallel', '--in-place']
.style.yapf ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ [style]
2
+ based_on_style = pep8
3
+ blank_line_before_nested_class_or_def = false
4
+ spaces_before_comment = 2
5
+ split_before_logical_operator = true
.vscode/settings.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "python.linting.enabled": true,
3
+ "python.linting.flake8Enabled": true,
4
+ "python.linting.pylintEnabled": false,
5
+ "python.linting.lintOnSave": true,
6
+ "python.formatting.provider": "yapf",
7
+ "python.formatting.yapfArgs": [
8
+ "--style={based_on_style: pep8, indent_width: 4, blank_line_before_nested_class_or_def: false, spaces_before_comment: 2, split_before_logical_operator: true}"
9
+ ],
10
+ "[python]": {
11
+ "editor.formatOnType": true,
12
+ "editor.codeActionsOnSave": {
13
+ "source.organizeImports": true
14
+ }
15
+ },
16
+ "editor.formatOnSave": true,
17
+ "files.insertFinalNewline": true
18
+ }
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2023 hysts
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
LICENSE.Shap-E ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2023 OpenAI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Shap-E
3
+ emoji: 🧢
4
+ colorFrom: yellow
5
+ colorTo: blue
6
+ sdk: gradio
7
+ sdk_version: 3.38.0
8
+ python_version: 3.10.11
9
+ app_file: app.py
10
+ pinned: false
11
+ license: mit
12
+ suggested_hardware: t4-small
13
+ duplicated_from: hysts/Shap-E
14
+ ---
15
+
16
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
17
+
18
+ https://arxiv.org/abs/2305.02463
app.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+
3
+ import os
4
+
5
+ import gradio as gr
6
+ import torch
7
+
8
+ from app_image_to_3d import create_demo as create_demo_image_to_3d
9
+ from app_text_to_3d import create_demo as create_demo_text_to_3d
10
+ from model import Model
11
+
12
+ DESCRIPTION = '# [Shap-E](https://github.com/openai/shap-e)'
13
+
14
+ if not torch.cuda.is_available():
15
+ DESCRIPTION += '\n<p>Running on CPU 🥶 This demo does not work on CPU.</p>'
16
+
17
+ model = Model()
18
+
19
+ with gr.Blocks(css='style.css') as demo:
20
+ gr.Markdown(DESCRIPTION)
21
+ gr.DuplicateButton(value='Duplicate Space for private use',
22
+ elem_id='duplicate-button',
23
+ visible=os.getenv('SHOW_DUPLICATE_BUTTON') == '1')
24
+ with gr.Tabs():
25
+ with gr.Tab(label='Text to 3D'):
26
+ create_demo_text_to_3d(model)
27
+ with gr.Tab(label='Image to 3D'):
28
+ create_demo_image_to_3d(model)
29
+ demo.queue(max_size=10).launch()
app_image_to_3d.py ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+
3
+ import pathlib
4
+ import shlex
5
+ import subprocess
6
+
7
+ import gradio as gr
8
+
9
+ from model import Model
10
+ from settings import CACHE_EXAMPLES, MAX_SEED
11
+ from utils import randomize_seed_fn
12
+
13
+
14
+ def create_demo(model: Model) -> gr.Blocks:
15
+ if not pathlib.Path('corgi.png').exists():
16
+ subprocess.run(
17
+ shlex.split(
18
+ 'wget https://raw.githubusercontent.com/openai/shap-e/d99cedaea18e0989e340163dbaeb4b109fa9e8ec/shap_e/examples/example_data/corgi.png -O corgi.png'
19
+ ))
20
+ examples = ['corgi.png']
21
+
22
+ def process_example_fn(image_path: str) -> str:
23
+ return model.run_image(image_path)
24
+
25
+ with gr.Blocks() as demo:
26
+ with gr.Box():
27
+ image = gr.Image(label='Input image', show_label=False, type='pil')
28
+ run_button = gr.Button('Run')
29
+ result = gr.Model3D(label='Result', show_label=False)
30
+ with gr.Accordion('Advanced options', open=False):
31
+ seed = gr.Slider(label='Seed',
32
+ minimum=0,
33
+ maximum=MAX_SEED,
34
+ step=1,
35
+ value=0)
36
+ randomize_seed = gr.Checkbox(label='Randomize seed',
37
+ value=True)
38
+ guidance_scale = gr.Slider(label='Guidance scale',
39
+ minimum=1,
40
+ maximum=20,
41
+ step=0.1,
42
+ value=3.0)
43
+ num_inference_steps = gr.Slider(
44
+ label='Number of inference steps',
45
+ minimum=1,
46
+ maximum=100,
47
+ step=1,
48
+ value=64)
49
+
50
+ gr.Examples(examples=examples,
51
+ inputs=image,
52
+ outputs=result,
53
+ fn=process_example_fn,
54
+ cache_examples=CACHE_EXAMPLES)
55
+
56
+ inputs = [
57
+ image,
58
+ seed,
59
+ guidance_scale,
60
+ num_inference_steps,
61
+ ]
62
+
63
+ run_button.click(
64
+ fn=randomize_seed_fn,
65
+ inputs=[seed, randomize_seed],
66
+ outputs=seed,
67
+ queue=False,
68
+ ).then(
69
+ fn=model.run_image,
70
+ inputs=inputs,
71
+ outputs=result,
72
+ api_name='image-to-3d',
73
+ )
74
+ return demo
app_text_to_3d.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+
3
+ import gradio as gr
4
+
5
+ from model import Model
6
+ from settings import CACHE_EXAMPLES, MAX_SEED
7
+ from utils import randomize_seed_fn
8
+
9
+
10
+ def create_demo(model: Model) -> gr.Blocks:
11
+ examples = [
12
+ 'A chair that looks like an avocado',
13
+ 'An airplane that looks like a banana',
14
+ 'A spaceship',
15
+ 'A birthday cupcake',
16
+ 'A chair that looks like a tree',
17
+ 'A green boot',
18
+ 'A penguin',
19
+ 'Ube ice cream cone',
20
+ 'A bowl of vegetables',
21
+ ]
22
+
23
+ def process_example_fn(prompt: str) -> str:
24
+ return model.run_text(prompt)
25
+
26
+ with gr.Blocks() as demo:
27
+ with gr.Box():
28
+ with gr.Row(elem_id='prompt-container'):
29
+ prompt = gr.Text(label='Prompt',
30
+ show_label=False,
31
+ max_lines=1,
32
+ placeholder='Enter your prompt',
33
+ container=False)
34
+ run_button = gr.Button('Run', scale=0)
35
+ result = gr.Model3D(label='Result', show_label=False)
36
+ with gr.Accordion('Advanced options', open=False):
37
+ seed = gr.Slider(label='Seed',
38
+ minimum=0,
39
+ maximum=MAX_SEED,
40
+ step=1,
41
+ value=0)
42
+ randomize_seed = gr.Checkbox(label='Randomize seed',
43
+ value=True)
44
+ guidance_scale = gr.Slider(label='Guidance scale',
45
+ minimum=1,
46
+ maximum=20,
47
+ step=0.1,
48
+ value=15.0)
49
+ num_inference_steps = gr.Slider(
50
+ label='Number of inference steps',
51
+ minimum=1,
52
+ maximum=100,
53
+ step=1,
54
+ value=64)
55
+
56
+ gr.Examples(examples=examples,
57
+ inputs=prompt,
58
+ outputs=result,
59
+ fn=process_example_fn,
60
+ cache_examples=CACHE_EXAMPLES)
61
+
62
+ inputs = [
63
+ prompt,
64
+ seed,
65
+ guidance_scale,
66
+ num_inference_steps,
67
+ ]
68
+ prompt.submit(
69
+ fn=randomize_seed_fn,
70
+ inputs=[seed, randomize_seed],
71
+ outputs=seed,
72
+ queue=False,
73
+ ).then(
74
+ fn=model.run_text,
75
+ inputs=inputs,
76
+ outputs=result,
77
+ )
78
+ run_button.click(
79
+ fn=randomize_seed_fn,
80
+ inputs=[seed, randomize_seed],
81
+ outputs=seed,
82
+ queue=False,
83
+ ).then(
84
+ fn=model.run_text,
85
+ inputs=inputs,
86
+ outputs=result,
87
+ api_name='text-to-3d',
88
+ )
89
+ return demo
model.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tempfile
2
+
3
+ import numpy as np
4
+ import PIL.Image
5
+ import torch
6
+ import trimesh
7
+ from diffusers import ShapEImg2ImgPipeline, ShapEPipeline
8
+ from diffusers.utils import export_to_ply
9
+
10
+
11
+ class Model:
12
+ def __init__(self):
13
+ self.device = torch.device(
14
+ 'cuda' if torch.cuda.is_available() else 'cpu')
15
+ self.pipe = ShapEPipeline.from_pretrained('openai/shap-e',
16
+ torch_dtype=torch.float16)
17
+ self.pipe.to(self.device)
18
+
19
+ self.pipe_img = ShapEImg2ImgPipeline.from_pretrained(
20
+ 'openai/shap-e-img2img', torch_dtype=torch.float16)
21
+ self.pipe_img.to(self.device)
22
+
23
+ def to_glb(self, ply_path: str) -> str:
24
+ mesh = trimesh.load(ply_path)
25
+ rot = trimesh.transformations.rotation_matrix(-np.pi / 2, [1, 0, 0])
26
+ mesh = mesh.apply_transform(rot)
27
+ rot = trimesh.transformations.rotation_matrix(np.pi, [0, 1, 0])
28
+ mesh = mesh.apply_transform(rot)
29
+ mesh_path = tempfile.NamedTemporaryFile(suffix='.glb', delete=False)
30
+ mesh.export(mesh_path.name, file_type='glb')
31
+ return mesh_path.name
32
+
33
+ def run_text(self,
34
+ prompt: str,
35
+ seed: int = 0,
36
+ guidance_scale: float = 15.0,
37
+ num_steps: int = 64) -> str:
38
+ generator = torch.Generator(device=self.device).manual_seed(seed)
39
+ images = self.pipe(prompt,
40
+ generator=generator,
41
+ guidance_scale=guidance_scale,
42
+ num_inference_steps=num_steps,
43
+ output_type='mesh').images
44
+ ply_path = tempfile.NamedTemporaryFile(suffix='.ply',
45
+ delete=False,
46
+ mode='w+b')
47
+ export_to_ply(images[0], ply_path.name)
48
+ return self.to_glb(ply_path.name)
49
+
50
+ def run_image(self,
51
+ image: PIL.Image.Image,
52
+ seed: int = 0,
53
+ guidance_scale: float = 3.0,
54
+ num_steps: int = 64) -> str:
55
+ generator = torch.Generator(device=self.device).manual_seed(seed)
56
+ images = self.pipe_img(image,
57
+ generator=generator,
58
+ guidance_scale=guidance_scale,
59
+ num_inference_steps=num_steps,
60
+ output_type='mesh').images
61
+ ply_path = tempfile.NamedTemporaryFile(suffix='.ply',
62
+ delete=False,
63
+ mode='w+b')
64
+ export_to_ply(images[0], ply_path.name)
65
+ return self.to_glb(ply_path.name)
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ git+https://github.com/huggingface/diffusers@09fab56
2
+ gradio==3.38.0
3
+ torch==2.0.1
4
+ torchvision==0.15.2
5
+ transformers==4.31.0
6
+ trimesh==3.22.3
settings.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ import numpy as np
4
+
5
+ CACHE_EXAMPLES = os.getenv('CACHE_EXAMPLES') == '1'
6
+
7
+ MAX_SEED = np.iinfo(np.int32).max
style.css ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ h1 {
2
+ text-align: center;
3
+ }
4
+
5
+ #component-0 {
6
+ max-width: 730px;
7
+ margin: auto;
8
+ padding-top: 1.5rem;
9
+ }
10
+
11
+ #prompt-container {
12
+ gap: 0;
13
+ }
14
+
15
+ #duplicate-button {
16
+ margin: auto;
17
+ color: #fff;
18
+ background: #1565c0;
19
+ border-radius: 100vh;
20
+ }
utils.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import random
2
+
3
+ from settings import MAX_SEED
4
+
5
+
6
+ def randomize_seed_fn(seed: int, randomize_seed: bool) -> int:
7
+ if randomize_seed:
8
+ seed = random.randint(0, MAX_SEED)
9
+ return seed