Spaces:
Paused
Paused
| import os | |
| import sys | |
| import shutil | |
| import argparse | |
| from omegaconf import OmegaConf | |
| import trimesh | |
| from PIL import Image | |
| import torch | |
| from torchvision import transforms | |
| import logging as log | |
| # Add project root to path | |
| project_root = os.path.dirname(os.path.abspath(__file__)) | |
| if project_root not in sys.path: | |
| sys.path.insert(0, project_root) | |
| from demos.pipeline_fn import GuideFlow3dPipeline | |
| from lib.util import common, generation, pointcloud | |
| from demos.custom_utils import render_all_views | |
| import third_party.TRELLIS.trellis.models as models | |
| # Setup logging | |
| log.getLogger().setLevel(log.INFO) | |
| log.basicConfig(level=log.INFO, format='%(asctime)s - %(levelname)s - %(message)s') | |
| # Examples (matching run_gradio_demo.py) | |
| STRUCT_EXAMPLES = { | |
| "bench_chair": "example_data/structure_mesh/bench_chair.glb", | |
| "cabinet": "example_data/structure_mesh/cabinet.glb", | |
| "chair": "example_data/structure_mesh/chair.glb", | |
| "giraffe": "example_data/structure_mesh/giraffe.glb", | |
| "motorcycle": "example_data/structure_mesh/motorcycle.glb", | |
| "plane": "example_data/structure_mesh/plane.glb", | |
| } | |
| APP_MESH_EXAMPLES = { | |
| "B01DA8LC0A": "example_data/appearance_mesh/B01DA8LC0A.glb", | |
| "B01DJH73Y6": "example_data/appearance_mesh/B01DJH73Y6.glb", | |
| "B0728KSP33": "example_data/appearance_mesh/B0728KSP33.glb", | |
| "B07B4YXNR8": "example_data/appearance_mesh/B07B4YXNR8.glb", | |
| "B07QC84LP1": "example_data/appearance_mesh/B07QC84LP1.glb", | |
| "B07QFRSC8M": "example_data/appearance_mesh/B07QFRSC8M_zup.glb", | |
| "B082QC7YKR": "example_data/appearance_mesh/B082QC7YKR_zup.glb", | |
| } | |
| def generate_structure_cache(pipe, name, path, output_base): | |
| log.info(f"Processing Structure Example: {name}") | |
| output_dir = os.path.join(output_base, name) | |
| os.makedirs(output_dir, exist_ok=True) | |
| # Run preprocess to generate struct_renders, voxels, partfield | |
| # preprocess(self, structure_mesh, convert_yup_to_zup, output_dir) | |
| pipe.preprocess( | |
| structure_mesh=path, | |
| convert_yup_to_zup=False, # Assuming defaults | |
| output_dir=output_dir | |
| ) | |
| log.info(f"Completed Structure Example: {name}") | |
| def generate_appearance_cache(pipe, name, path, output_base): | |
| log.info(f"Processing Appearance Example: {name}") | |
| output_dir = os.path.join(output_base, name) | |
| os.makedirs(output_dir, exist_ok=True) | |
| # Logic adapted from pipe.run_appearance but focused on Appearance Mesh only | |
| # 1. Load and Save Z-up mesh | |
| cached_app_input_path = os.path.join(output_dir, "app_mesh_input.glb") | |
| shutil.copy2(path, cached_app_input_path) | |
| app_mesh_path = os.path.join(output_dir, "app_mesh.glb") | |
| app_mesh_zup_path = os.path.join(output_dir, "app_mesh_zup.glb") | |
| app_mesh = trimesh.load(path, force="mesh") | |
| app_mesh.export(app_mesh_path) | |
| # convert_appearance_yup_to_zup=False (Default) | |
| app_mesh.export(app_mesh_zup_path) | |
| # 2. Render Views | |
| app_render_dir = os.path.join(output_dir, 'app_renders') | |
| common.ensure_dir(app_render_dir) | |
| # Only render if not empty | |
| if not os.listdir(app_render_dir): | |
| render_all_views( | |
| app_mesh_zup_path, | |
| app_render_dir, | |
| num_views=pipe.cfg.num_views, | |
| num_workers=None | |
| ) | |
| # 3. Voxelize | |
| app_voxel_dir = os.path.join(output_dir, "voxels") | |
| common.ensure_dir(app_voxel_dir) | |
| app_voxels_path = os.path.join(app_voxel_dir, "app_voxels.ply") | |
| app_mesh_ply_path = os.path.join(app_render_dir, "mesh.ply") # Generated by render_all_views | |
| if not os.path.exists(app_voxels_path) and os.path.exists(app_mesh_ply_path): | |
| pointcloud.voxelize_mesh( | |
| app_mesh_ply_path, | |
| save_path=app_voxels_path, | |
| ) | |
| # 4. DinoV2 Features | |
| features_dir = os.path.join(output_dir, "features", pipe.cfg.feature_name) | |
| common.ensure_dir(features_dir) | |
| if not os.listdir(features_dir): | |
| dinov2_model = torch.hub.load(pipe.cfg.dinov2_repo, pipe.cfg.feature_name) | |
| dinov2_model.eval().cuda() | |
| transform = transforms.Compose([transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])]) | |
| generation.extract_feature(output_dir, dinov2_model, transform) | |
| del dinov2_model | |
| torch.cuda.empty_cache() | |
| # 5. SLAT Latent | |
| latents_dir = os.path.join(output_dir, "latents", pipe.cfg.latent_name) | |
| common.ensure_dir(latents_dir) | |
| if not os.listdir(latents_dir): | |
| encoder = models.from_pretrained(pipe.cfg.enc_pretrained).eval().cuda() | |
| generation.get_latent(output_dir, pipe.cfg.feature_name, pipe.cfg.latent_name, encoder) | |
| del encoder | |
| torch.cuda.empty_cache() | |
| # 6. PartField (Appearance) | |
| app_partfield_dir = os.path.join(output_dir, "partfield") | |
| common.ensure_dir(app_partfield_dir) | |
| existing_pf = [f for f in os.listdir(app_partfield_dir) if f.startswith("part_feat_app_mesh_zup")] | |
| if not existing_pf: | |
| from demos.pipeline_fn import partfield_pipeline_predict | |
| partfield_pipeline_predict( | |
| app_mesh_zup_path, | |
| app_partfield_dir, | |
| "app_mesh_zup" | |
| ) | |
| log.info(f"Completed Appearance Example: {name}") | |
| def main(): | |
| cfg_path = os.path.join(project_root, 'config', 'default.yaml') | |
| cfg = OmegaConf.load(cfg_path) | |
| pipe = GuideFlow3dPipeline().from_pretrained(cfg) | |
| output_base = os.path.join(project_root, "all_outputs") | |
| for name, path in STRUCT_EXAMPLES.items(): | |
| abs_path = os.path.join(project_root, path) | |
| generate_structure_cache(pipe, name, abs_path, output_base) | |
| for name, path in APP_MESH_EXAMPLES.items(): | |
| abs_path = os.path.join(project_root, path) | |
| generate_appearance_cache(pipe, name, abs_path, output_base) | |
| if __name__ == "__main__": | |
| main() | |