| <!--Copyright 2023 The HuggingFace Team. All rights reserved. | |
| Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with | |
| the License. You may obtain a copy of the License at | |
| http://www.apache.org/licenses/LICENSE-2.0 | |
| Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | |
| an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | |
| specific language governing permissions and limitations under the License. | |
| --> | |
| # Shap-E | |
| The Shap-E model was proposed in [Shap-E: Generating Conditional 3D Implicit Functions](https://huggingface.co/papers/2305.02463) by Alex Nichol and Heewon Jun from [OpenAI](https://github.com/openai). | |
| The abstract from the paper is: | |
| *We present Shap-E, a conditional generative model for 3D assets. Unlike recent work on 3D generative models which produce a single output representation, Shap-E directly generates the parameters of implicit functions that can be rendered as both textured meshes and neural radiance fields. We train Shap-E in two stages: first, we train an encoder that deterministically maps 3D assets into the parameters of an implicit function; second, we train a conditional diffusion model on outputs of the encoder. When trained on a large dataset of paired 3D and text data, our resulting models are capable of generating complex and diverse 3D assets in a matter of seconds. When compared to Point-E, an explicit generative model over point clouds, Shap-E converges faster and reaches comparable or better sample quality despite modeling a higher-dimensional, multi-representation output space.* | |
| The original codebase can be found at [openai/shap-e](https://github.com/openai/shap-e). | |
| <Tip> | |
| Make sure to check out the Schedulers [guide](/using-diffusers/schedulers) to learn how to explore the tradeoff between scheduler speed and quality, and see the [reuse components across pipelines](/using-diffusers/loading#reuse-components-across-pipelines) section to learn how to efficiently load the same components into multiple pipelines. | |
| </Tip> | |
| ## Usage Examples | |
| In the following, we will walk you through some examples of how to use Shap-E pipelines to create 3D objects in gif format. | |
| ### Text-to-3D image generation | |
| We can use [`ShapEPipeline`] to create 3D object based on a text prompt. In this example, we will make a birthday cupcake for :firecracker: diffusers library's 1 year birthday. The workflow to use the Shap-E text-to-image pipeline is same as how you would use other text-to-image pipelines in diffusers. | |
| ```python | |
| import torch | |
| from diffusers import DiffusionPipeline | |
| device = torch.device("cuda" if torch.cuda.is_available() else "cpu") | |
| repo = "openai/shap-e" | |
| pipe = DiffusionPipeline.from_pretrained(repo, torch_dtype=torch.float16) | |
| pipe = pipe.to(device) | |
| guidance_scale = 15.0 | |
| prompt = ["A firecracker", "A birthday cupcake"] | |
| images = pipe( | |
| prompt, | |
| guidance_scale=guidance_scale, | |
| num_inference_steps=64, | |
| frame_size=256, | |
| ).images | |
| ``` | |
| The output of [`ShapEPipeline`] is a list of lists of images frames. Each list of frames can be used to create a 3D object. Let's use the `export_to_gif` utility function in diffusers to make a 3D cupcake! | |
| ```python | |
| from diffusers.utils import export_to_gif | |
| export_to_gif(images[0], "firecracker_3d.gif") | |
| export_to_gif(images[1], "cake_3d.gif") | |
| ``` | |
|  | |
|  | |
| ### Image-to-Image generation | |
| You can use [`ShapEImg2ImgPipeline`] along with other text-to-image pipelines in diffusers and turn your 2D generation into 3D. | |
| In this example, We will first genrate a cheeseburger with a simple prompt "A cheeseburger, white background" | |
| ```python | |
| from diffusers import DiffusionPipeline | |
| import torch | |
| pipe_prior = DiffusionPipeline.from_pretrained("kandinsky-community/kandinsky-2-1-prior", torch_dtype=torch.float16) | |
| pipe_prior.to("cuda") | |
| t2i_pipe = DiffusionPipeline.from_pretrained("kandinsky-community/kandinsky-2-1", torch_dtype=torch.float16) | |
| t2i_pipe.to("cuda") | |
| prompt = "A cheeseburger, white background" | |
| image_embeds, negative_image_embeds = pipe_prior(prompt, guidance_scale=1.0).to_tuple() | |
| image = t2i_pipe( | |
| prompt, | |
| image_embeds=image_embeds, | |
| negative_image_embeds=negative_image_embeds, | |
| ).images[0] | |
| image.save("burger.png") | |
| ``` | |
|  | |
| we will then use the Shap-E image-to-image pipeline to turn it into a 3D cheeseburger :) | |
| ```python | |
| from PIL import Image | |
| from diffusers.utils import export_to_gif | |
| repo = "openai/shap-e-img2img" | |
| pipe = DiffusionPipeline.from_pretrained(repo, torch_dtype=torch.float16) | |
| pipe = pipe.to("cuda") | |
| guidance_scale = 3.0 | |
| image = Image.open("burger.png").resize((256, 256)) | |
| images = pipe( | |
| image, | |
| guidance_scale=guidance_scale, | |
| num_inference_steps=64, | |
| frame_size=256, | |
| ).images | |
| gif_path = export_to_gif(images[0], "burger_3d.gif") | |
| ``` | |
|  | |
| ### Generate mesh | |
| For both [`ShapEPipeline`] and [`ShapEImg2ImgPipeline`], you can generate mesh output by passing `output_type` as `mesh` to the pipeline, and then use the [`ShapEPipeline.export_to_ply`] utility function to save the output as a `ply` file. We also provide a [`ShapEPipeline.export_to_obj`] function that you can use to save mesh outputs as `obj` files. | |
| ```python | |
| import torch | |
| from diffusers import DiffusionPipeline | |
| from diffusers.utils import export_to_ply | |
| device = torch.device("cuda" if torch.cuda.is_available() else "cpu") | |
| repo = "openai/shap-e" | |
| pipe = DiffusionPipeline.from_pretrained(repo, torch_dtype=torch.float16, variant="fp16") | |
| pipe = pipe.to(device) | |
| guidance_scale = 15.0 | |
| prompt = "A birthday cupcake" | |
| images = pipe(prompt, guidance_scale=guidance_scale, num_inference_steps=64, frame_size=256, output_type="mesh").images | |
| ply_path = export_to_ply(images[0], "3d_cake.ply") | |
| print(f"saved to folder: {ply_path}") | |
| ``` | |
| Huggingface Datasets supports mesh visualization for mesh files in `glb` format. Below we will show you how to convert your mesh file into `glb` format so that you can use the Dataset viewer to render 3D objects. | |
| We need to install `trimesh` library. | |
| ``` | |
| pip install trimesh | |
| ``` | |
| To convert the mesh file into `glb` format, | |
| ```python | |
| import trimesh | |
| mesh = trimesh.load("3d_cake.ply") | |
| mesh.export("3d_cake.glb", file_type="glb") | |
| ``` | |
| By default, the mesh output of Shap-E is from the bottom viewpoint; you can change the default viewpoint by applying a rotation transformation | |
| ```python | |
| import trimesh | |
| import numpy as np | |
| mesh = trimesh.load("3d_cake.ply") | |
| rot = trimesh.transformations.rotation_matrix(-np.pi / 2, [1, 0, 0]) | |
| mesh = mesh.apply_transform(rot) | |
| mesh.export("3d_cake.glb", file_type="glb") | |
| ``` | |
| Now you can upload your mesh file to your dataset and visualize it! Here is the link to the 3D cake we just generated | |
| https://huggingface.co/datasets/hf-internal-testing/diffusers-images/blob/main/shap_e/3d_cake.glb | |
| ## ShapEPipeline | |
| [[autodoc]] ShapEPipeline | |
| - all | |
| - __call__ | |
| ## ShapEImg2ImgPipeline | |
| [[autodoc]] ShapEImg2ImgPipeline | |
| - all | |
| - __call__ | |
| ## ShapEPipelineOutput | |
| [[autodoc]] pipelines.shap_e.pipeline_shap_e.ShapEPipelineOutput |