Spaces:
Runtime error
Runtime error
| try: | |
| import spaces | |
| except ImportError: | |
| # Define a dummy decorator if spaces is not available | |
| def GPU(func): | |
| return func | |
| spaces = type('spaces', (), {'GPU': GPU}) | |
| import os | |
| import torch | |
| import argparse | |
| from typing import * | |
| from diffusers import StableDiffusionPipeline | |
| from collections import deque | |
| from triplaneturbo_executable.utils.mesh_exporter import export_obj | |
| from triplaneturbo_executable import TriplaneTurboTextTo3DPipeline, TriplaneTurboTextTo3DPipelineConfig | |
| # Initialize configuration and parameters | |
| prompt = "a beautiful girl" | |
| output_dir = "output" | |
| adapter_name_or_path = "pretrained/triplane_turbo_sd_v1.pth" | |
| num_results_per_prompt = 1 | |
| seed = 42 | |
| device = "cuda" | |
| max_obj_files = 100 | |
| # download pretrained models if not exist | |
| if not os.path.exists(adapter_name_or_path): | |
| print(f"Downloading pretrained models from huggingface") | |
| os.system( | |
| f"huggingface-cli download --resume-download ZhiyuanthePony/TriplaneTurbo \ | |
| --include \"triplane_turbo_sd_v1.pth\" \ | |
| --local-dir ./pretrained \ | |
| --local-dir-use-symlinks False" | |
| ) | |
| # Initialize the TriplaneTurbo pipeline | |
| triplane_turbo_pipeline = TriplaneTurboTextTo3DPipeline.from_pretrained(adapter_name_or_path) | |
| triplane_turbo_pipeline.to(device) | |
| def generate_3d_model(prompt, num_results_per_prompt=1, seed=42, device="cuda"): | |
| """ | |
| Generate 3D models using TriplaneTurbo pipeline. | |
| Args: | |
| prompt (str): Text prompt for the 3D model | |
| num_results_per_prompt (int): Number of results to generate | |
| seed (int): Random seed for generation | |
| device (str): Device to use for computation | |
| Returns: | |
| dict: Output from the pipeline | |
| """ | |
| output = triplane_turbo_pipeline( | |
| prompt=prompt, | |
| num_results_per_prompt=num_results_per_prompt, | |
| generator=torch.Generator(device=device).manual_seed(seed), | |
| device=device, | |
| ) | |
| # Initialize a deque with maximum length of 100 to store obj file paths | |
| obj_file_queue = deque(maxlen=max_obj_files) | |
| # Save mesh | |
| os.makedirs(output_dir, exist_ok=True) | |
| for i, mesh in enumerate(output["mesh"]): | |
| vertices = mesh.v_pos | |
| # 1. First rotate -90 degrees around X-axis to make the model face up | |
| vertices = torch.stack([ | |
| vertices[:, 0], # x remains unchanged | |
| vertices[:, 2], # y = z | |
| -vertices[:, 1] # z = -y | |
| ], dim=1) | |
| # 2. Then rotate 90 degrees around Y-axis to make the model face the observer | |
| vertices = torch.stack([ | |
| -vertices[:, 2], # x = -z | |
| vertices[:, 1], # y remains unchanged | |
| vertices[:, 0] # z = x | |
| ], dim=1) | |
| mesh.v_pos = vertices | |
| # If mesh has normals, they need to be rotated in the same way | |
| if mesh.v_nrm is not None: | |
| normals = mesh.v_nrm | |
| # 1. Rotate -90 degrees around X-axis | |
| normals = torch.stack([ | |
| normals[:, 0], | |
| normals[:, 2], | |
| -normals[:, 1] | |
| ], dim=1) | |
| # 2. Rotate 90 degrees around Y-axis | |
| normals = torch.stack([ | |
| -normals[:, 2], | |
| normals[:, 1], | |
| normals[:, 0] | |
| ], dim=1) | |
| mesh._v_nrm = normals | |
| # Save obj file and add its path to the queue | |
| name = f"{prompt.replace(' ', '_')}_{seed}_{i}" | |
| save_paths = export_obj(mesh, f"{output_dir}/{name}.obj") | |
| obj_file_queue.append(save_paths[0]) | |
| # If an old file needs to be removed (queue is at max length) | |
| # and the file exists, delete it | |
| if len(obj_file_queue) == max_obj_files and os.path.exists(obj_file_queue[0]): | |
| old_file = obj_file_queue[0] | |
| try: | |
| os.remove(old_file) | |
| except OSError as e: | |
| print(f"Error deleting file {old_file}: {e}") | |
| # Run the pipeline | |
| output = generate_3d_model( | |
| prompt=prompt, | |
| num_results_per_prompt=num_results_per_prompt, | |
| seed=seed, | |
| device=device | |
| ) | |