File size: 7,441 Bytes
d69126e
e486d98
d69126e
cf37aee
e486d98
b03ed51
e486d98
 
 
 
 
 
d69126e
e486d98
d69126e
e486d98
 
68a1a0c
e486d98
68a1a0c
e486d98
 
 
 
 
9d38c97
e486d98
 
1c3feda
e486d98
9d38c97
e486d98
 
 
 
 
9d38c97
e486d98
 
 
 
 
68a1a0c
e486d98
 
 
 
3bfc3b0
e486d98
3bfc3b0
e486d98
 
68a1a0c
e486d98
 
 
cf37aee
e486d98
 
 
9d38c97
e486d98
 
 
9d38c97
e486d98
9d38c97
e486d98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3c4ebea
e486d98
3c4ebea
e486d98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9d38c97
e486d98
f9b9c98
e486d98
d69126e
e486d98
d69126e
e486d98
 
d69126e
e486d98
 
 
b03ed51
e486d98
 
 
d69126e
e486d98
d69126e
3bfc3b0
e486d98
 
9d38c97
e486d98
 
3bfc3b0
e486d98
 
3bfc3b0
e486d98
 
3bfc3b0
e486d98
 
 
3c4ebea
e486d98
 
 
 
 
 
 
 
 
 
 
 
 
d69126e
3bfc3b0
e486d98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d69126e
e486d98
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
import torch
import gradio as gr
import numpy as np
from PIL import Image
import trimesh
import cv2
import open3d as o3d

# Critical Model Imports
from transformers import pipeline, AutoFeatureExtractor, AutoModelForImageToImage
from diffusers import StableDiffusionControlNetImg2ImgPipeline, ControlNetModel
from huggingface_hub import hf_hub_download

class CompleteMeshGenerator:
    def __init__(self):
        # Critical Model Configuration
        self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
        
        # Depth Estimation Model
        try:
            self.depth_estimator = pipeline(
                "depth-estimation", 
                model="Intel/dpt-large",
                device=self.device
            )
        except Exception as e:
            print(f"Depth Estimation Model Load Error: {e}")
            self.depth_estimator = None
        
        # Multi-View Generation Setup
        try:
            # Load ControlNet for multi-view generation
            self.controlnet = ControlNetModel.from_pretrained(
                "lllyasviel/control_v11f1p_sd15_depth", 
                torch_dtype=torch.float32
            )
            
            self.multi_view_pipeline = StableDiffusionControlNetImg2ImgPipeline.from_pretrained(
                "runwayml/stable-diffusion-v1-5", 
                controlnet=self.controlnet,
                torch_dtype=torch.float32
            ).to(self.device)
        except Exception as e:
            print(f"Multi-View Generation Model Load Error: {e}")
            self.multi_view_pipeline = None

    def generate_depth_map(self, image):
        """
        Advanced Depth Map Generation
        """
        if self.depth_estimator is None:
            raise ValueError("Depth estimation model not loaded")
        
        # Ensure image is in correct format
        if isinstance(image, np.ndarray):
            image = Image.fromarray(image)
        
        # Estimate depth
        depth_result = self.depth_estimator(image)
        depth_map = np.array(depth_result['depth'])
        
        return depth_map

    def generate_multi_view_images(self, input_image, num_views=4):
        """
        Generate Multiple View Images
        """
        if self.multi_view_pipeline is None:
            raise ValueError("Multi-view generation pipeline not loaded")
        
        # Estimate initial depth map
        depth_map = self.generate_depth_map(input_image)
        
        # Convert depth map to PIL Image
        depth_image = Image.fromarray((depth_map * 255).astype(np.uint8))
        
        # View generation parameters
        view_angles = [
            (30, "Side view"),
            (150, "Opposite side"),
            (90, "Top view"),
            (270, "Bottom view")
        ]
        
        multi_view_images = []
        
        for angle, description in view_angles[:num_views]:
            try:
                generated_image = self.multi_view_pipeline(
                    prompt=f"3D object view from {description}",
                    image=input_image,
                    control_image=depth_image,
                    controlnet_conditioning_scale=1.0,
                    rotation=angle,
                    guidance_scale=7.5
                ).images[0]
                
                multi_view_images.append(generated_image)
            except Exception as e:
                print(f"View generation error for angle {angle}: {e}")
        
        return multi_view_images

    def advanced_point_cloud_reconstruction(self, depth_maps):
        """
        Advanced Point Cloud Reconstruction
        """
        point_clouds = []
        
        for depth_map in depth_maps:
            # Create point cloud from depth map
            height, width = depth_map.shape
            x = np.linspace(0, width-1, width)
            y = np.linspace(0, height-1, height)
            xx, yy = np.meshgrid(x, y)
            
            # Convert depth to 3D points
            points_3d = np.column_stack([
                xx.ravel(), 
                yy.ravel(), 
                depth_map.ravel()
            ])
            
            # Create Open3D point cloud
            pcd = o3d.geometry.PointCloud()
            pcd.points = o3d.utility.Vector3dVector(points_3d)
            
            point_clouds.append(pcd)
        
        # Merge point clouds
        merged_pcd = point_clouds[0]
        for pcd in point_clouds[1:]:
            merged_pcd += pcd
        
        return merged_pcd

    def mesh_reconstruction(self, point_cloud):
        """
        Advanced Mesh Reconstruction
        """
        # Poisson surface reconstruction
        mesh, _ = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(point_cloud, depth=9)
        
        # Clean and smooth mesh
        mesh.compute_vertex_normals()
        mesh = mesh.filter_smooth_laplacian(number_of_iterations=10)
        
        return mesh

    def create_3d_model(self, input_image):
        """
        Comprehensive 3D Model Generation Pipeline
        """
        try:
            # Generate multi-view images
            multi_view_images = self.generate_multi_view_images(input_image)
            
            # Extract depth maps
            depth_maps = [np.array(self.generate_depth_map(img)) for img in multi_view_images]
            
            # Advanced point cloud reconstruction
            point_cloud = self.advanced_point_cloud_reconstruction(depth_maps)
            
            # Mesh generation
            mesh = self.mesh_reconstruction(point_cloud)
            
            # Save mesh in multiple formats
            output_path = "reconstructed_3d_model"
            o3d.io.write_triangle_mesh(f"{output_path}.ply", mesh)
            
            # Convert to trimesh for additional formats
            trimesh_mesh = trimesh.Trimesh(
                vertices=np.asarray(mesh.vertices),
                faces=np.asarray(mesh.triangles)
            )
            trimesh_mesh.export(f"{output_path}.obj")
            trimesh_mesh.export(f"{output_path}.stl")
            
            return (
                "3D Model Generated Successfully!", 
                multi_view_images,
                [f"{output_path}.ply", f"{output_path}.obj", f"{output_path}.stl"]
            )
        
        except Exception as e:
            return f"3D Model Generation Error: {str(e)}", None, None

    def create_gradio_interface(self):
        interface = gr.Interface(
            fn=self.create_3d_model,
            inputs=gr.Image(type="pil", label="Upload Image for 3D Reconstruction"),
            outputs=[
                gr.Textbox(label="Generation Status"),
                gr.Gallery(label="Generated Multi-View Images"),
                gr.File(label="Reconstructed 3D Model Files")
            ],
            title="Advanced 3D Model Generator",
            description="""
            Generate comprehensive 3D models from single images using:
            - Multi-view image generation
            - Advanced depth estimation
            - Point cloud reconstruction
            - Mesh generation
            """,
            allow_flagging="never"
        )
        
        return interface

def main():
    mesh_generator = CompleteMeshGenerator()
    interface = mesh_generator.create_gradio_interface()
    interface.launch(debug=True)

if __name__ == "__main__":
    main()