BladeSzaSza commited on
Commit
9094d85
Β·
1 Parent(s): e8293cd

fixed hunyan

Browse files
models/model_3d_generator.py CHANGED
@@ -67,79 +67,139 @@ class Hunyuan3DGenerator:
67
  logger.info("πŸš€ Starting 3D model loading process...")
68
 
69
  try:
70
- # Import Hunyuan3D components
71
- logger.info("πŸ“¦ Importing transformers components...")
72
- from transformers import AutoModel, AutoProcessor
73
-
74
- model_id = self.lite_model_id if self.use_lite else self.model_id
75
- logger.info(f"πŸ“¦ Loading model: {model_id}")
76
-
77
- # Load preprocessor
78
- logger.info("πŸ“¦ Loading preprocessor...")
79
- self.preprocessor = AutoProcessor.from_pretrained(model_id)
80
- logger.info("βœ… Preprocessor loaded successfully")
81
-
82
- # Load model with optimizations
83
- torch_dtype = torch.float16 if self.device == "cuda" else torch.float32
84
- logger.info(f"πŸ“¦ Using torch dtype: {torch_dtype}")
85
-
86
- # Disable torch.compile to avoid dynamo issues
87
- logger.info("πŸ“¦ Disabling torch compile to avoid dynamo issues...")
88
- torch._dynamo.config.suppress_errors = True
89
-
90
- logger.info("πŸ“¦ Loading 3D model with safe device handling...")
91
- self.model = AutoModel.from_pretrained(
92
- model_id,
93
- torch_dtype=torch_dtype,
94
- low_cpu_mem_usage=True,
95
- device_map=None, # Avoid auto device mapping to prevent meta tensor issues
96
- trust_remote_code=True
97
- )
98
- logger.info("βœ… 3D model loaded from pretrained")
99
-
100
- # Safe device movement
101
- logger.info(f"πŸ“¦ Moving model to device: {self.device}")
102
  try:
103
- # Check if model is a meta tensor
104
- if hasattr(self.model, 'to_empty'):
105
- # Use to_empty for meta tensors
106
- logger.info("πŸ“¦ Using to_empty() for safe device movement...")
107
- self.model = self.model.to_empty(device=self.device, dtype=torch_dtype)
108
- else:
109
- # Standard device movement
110
- logger.info("πŸ“¦ Using standard to() for device movement...")
111
- self.model = self.model.to(self.device, dtype=torch_dtype)
112
- logger.info("βœ… Model successfully moved to device")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
 
114
- except RuntimeError as device_error:
115
- logger.error(f"❌ Device movement failed: {device_error}")
116
- if "meta tensor" in str(device_error):
117
- logger.info("πŸ”„ Attempting CPU fallback for meta tensor issue...")
118
- self.device = "cpu"
119
  try:
120
- if hasattr(self.model, 'to_empty'):
121
- self.model = self.model.to_empty(device="cpu", dtype=torch_dtype)
122
- else:
123
- self.model = self.model.to("cpu", dtype=torch_dtype)
124
- logger.info("βœ… Fallback to CPU successful")
125
- except Exception as cpu_error:
126
- logger.error(f"❌ CPU fallback also failed: {cpu_error}")
127
- logger.info("πŸ”„ Using fallback mode...")
128
- self.model = "fallback"
129
- else:
130
- logger.error(f"❌ Non-meta tensor device error: {device_error}")
131
- logger.info("πŸ”„ Using fallback mode...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  self.model = "fallback"
133
-
134
- # Enable optimizations safely
135
- logger.info("πŸ“¦ Applying model optimizations...")
136
- if self.model != "fallback" and hasattr(self.model, 'enable_attention_slicing'):
137
- self.model.enable_attention_slicing()
138
- logger.info("βœ… Attention slicing enabled")
139
- else:
140
- logger.info("⚠️ Attention slicing not available")
141
-
142
- logger.info("πŸŽ‰ 3D model loading completed successfully!")
 
143
 
144
  except Exception as e:
145
  logger.error(f"❌ Failed to load Hunyuan3D model: {e}")
@@ -184,78 +244,117 @@ class Hunyuan3DGenerator:
184
  else:
185
  logger.info("πŸ–ΌοΈ Input is already PIL Image")
186
 
187
- # Ensure RGB
188
  logger.info(f"πŸ–ΌοΈ Image mode: {image.mode}")
189
- if image.mode != 'RGB':
190
- logger.info("πŸ–ΌοΈ Converting image to RGB mode")
191
- image = image.convert('RGB')
192
 
193
  logger.info(f"πŸ–ΌοΈ Final image size: {image.size}")
194
 
195
- # Resize for processing
196
- logger.info("πŸ–ΌοΈ Resizing image for processing (512x512)...")
197
- image = image.resize((512, 512), Image.Resampling.LANCZOS)
198
- logger.info("βœ… Image resized successfully")
199
-
200
  # Remove background if requested
201
- if remove_background:
202
  logger.info("🎭 Removing background from image...")
203
  try:
204
- image = self._remove_background(image)
205
- logger.info("βœ… Background removal completed")
 
 
 
 
 
 
206
  except Exception as bg_error:
207
  logger.error(f"❌ Background removal failed: {bg_error}")
208
  logger.info("πŸ”„ Continuing with original image...")
209
 
210
- # Process with model
211
- logger.info("🧠 Starting model inference...")
212
- with torch.no_grad():
 
 
213
  try:
214
- # Preprocess image
215
- logger.info("πŸ”„ Preprocessing image for model...")
216
- inputs = self.preprocessor(images=image, return_tensors="pt")
217
- logger.info(f"πŸ”„ Input tensor shape: {inputs['pixel_values'].shape if 'pixel_values' in inputs else 'unknown'}")
218
-
219
- # Move inputs to device safely
220
- logger.info(f"πŸ”„ Moving inputs to device: {self.device}")
221
- try:
222
- # Avoid device-related dynamo issues
223
- device_str = str(self.device) # Convert to string to avoid torch.device in dynamo
224
- inputs = {k: v.to(device_str) for k, v in inputs.items() if hasattr(v, 'to')}
225
- logger.info("βœ… Inputs moved to device successfully")
226
- except Exception as device_error:
227
- logger.error(f"❌ Failed to move inputs to device: {device_error}")
228
- raise device_error
229
 
230
- # Generate 3D
231
- logger.info("πŸš€ Starting 3D generation inference...")
232
- logger.info(f"πŸš€ Parameters: steps={self.num_inference_steps}, guidance={self.guidance_scale}")
233
-
234
- outputs = self.model.generate(
235
- **inputs,
236
- num_inference_steps=self.num_inference_steps,
237
- guidance_scale=self.guidance_scale,
238
- texture_resolution=texture_resolution
239
- )
240
- logger.info("βœ… 3D generation completed successfully")
241
-
242
- # Extract mesh
243
- logger.info("πŸ”§ Extracting mesh from model outputs...")
244
- mesh = self._extract_mesh(outputs)
245
- logger.info("βœ… Mesh extraction completed")
246
-
247
- except Exception as inference_error:
248
- logger.error(f"❌ Model inference failed: {inference_error}")
249
- logger.error(f"❌ Inference error type: {type(inference_error).__name__}")
250
- raise inference_error
251
-
252
- # Save mesh
253
- logger.info("πŸ’Ύ Saving generated mesh...")
254
- mesh_path = self._save_mesh(mesh)
255
- logger.info(f"βœ… Mesh saved to: {mesh_path}")
256
 
257
- logger.info("πŸŽ‰ 3D generation process completed successfully!")
258
- return mesh_path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
 
260
  except Exception as e:
261
  logger.error(f"❌ 3D generation error: {e}")
 
67
  logger.info("πŸš€ Starting 3D model loading process...")
68
 
69
  try:
70
+ # Try to import Hunyuan3D components
71
+ logger.info("πŸ“¦ Attempting to import Hunyuan3D components...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  try:
73
+ from hy3dshape.pipelines import Hunyuan3DDiTFlowMatchingPipeline
74
+ from hy3dshape.rembg import BackgroundRemover
75
+ logger.info("βœ… Hunyuan3D components imported successfully")
76
+
77
+ # Load the pipeline
78
+ model_id = self.lite_model_id if self.use_lite else self.model_id
79
+ logger.info(f"πŸ“¦ Loading Hunyuan3D pipeline: {model_id}")
80
+
81
+ self.model = Hunyuan3DDiTFlowMatchingPipeline.from_pretrained(model_id)
82
+ self.bg_remover = BackgroundRemover()
83
+
84
+ logger.info("βœ… Hunyuan3D pipeline loaded successfully")
85
+
86
+ except ImportError as import_error:
87
+ logger.error(f"❌ Failed to import Hunyuan3D components: {import_error}")
88
+ logger.info("πŸ”„ Hunyuan3D not installed, trying alternative approach...")
89
+
90
+ # Fallback: Try using transformers AutoModel
91
+ logger.info("πŸ“¦ Importing transformers components...")
92
+ from transformers import AutoModel, AutoProcessor
93
+
94
+ model_id = self.lite_model_id if self.use_lite else self.model_id
95
+ logger.info(f"πŸ“¦ Loading model: {model_id}")
96
+
97
+ # Check if model exists on HuggingFace
98
+ try:
99
+ from huggingface_hub import model_info
100
+ info = model_info(model_id)
101
+ logger.info(f"βœ… Model found on HuggingFace: {info.modelId}")
102
+ except Exception as hub_error:
103
+ logger.error(f"❌ Model not found on HuggingFace: {hub_error}")
104
+ logger.info("πŸ”„ Using fallback 3D generation")
105
+ self.model = "fallback"
106
+ return
107
+
108
+ # Load preprocessor
109
+ logger.info("πŸ“¦ Loading preprocessor...")
110
+ try:
111
+ self.preprocessor = AutoProcessor.from_pretrained(model_id)
112
+ logger.info("βœ… Preprocessor loaded successfully")
113
+ except Exception as proc_error:
114
+ logger.error(f"❌ Preprocessor loading failed: {proc_error}")
115
+ logger.info("πŸ”„ Using fallback mode")
116
+ self.model = "fallback"
117
+ return
118
+
119
+ # Load model with optimizations
120
+ torch_dtype = torch.float16 if self.device == "cuda" else torch.float32
121
+ logger.info(f"πŸ“¦ Using torch dtype: {torch_dtype}")
122
+
123
+ # Disable torch.compile to avoid dynamo issues
124
+ logger.info("πŸ“¦ Disabling torch compile to avoid dynamo issues...")
125
+ torch._dynamo.config.suppress_errors = True
126
+
127
+ logger.info("πŸ“¦ Loading 3D model with safe device handling...")
128
+
129
+ # Try loading with different strategies
130
+ loading_successful = False
131
+
132
+ # Strategy 1: Load directly to device
133
+ try:
134
+ logger.info("πŸ“¦ Strategy 1: Direct device loading...")
135
+ self.model = AutoModel.from_pretrained(
136
+ model_id,
137
+ torch_dtype=torch_dtype,
138
+ device_map={"": self.device},
139
+ low_cpu_mem_usage=True,
140
+ trust_remote_code=True
141
+ )
142
+ loading_successful = True
143
+ logger.info("βœ… Direct device loading successful")
144
+ except Exception as e1:
145
+ logger.error(f"❌ Strategy 1 failed: {e1}")
146
 
147
+ # Strategy 2: Load to CPU first
148
+ if not loading_successful:
 
 
 
149
  try:
150
+ logger.info("πŸ“¦ Strategy 2: CPU-first loading...")
151
+ # Load model to CPU first to avoid meta tensor issues
152
+ self.model = AutoModel.from_pretrained(
153
+ model_id,
154
+ torch_dtype=torch.float32, # Use float32 for CPU loading
155
+ low_cpu_mem_usage=True,
156
+ device_map=None, # No device mapping initially
157
+ trust_remote_code=True
158
+ )
159
+ logger.info("βœ… 3D model loaded to CPU")
160
+
161
+ # Now safely move to target device
162
+ logger.info(f"πŸ“¦ Moving model to target device: {self.device}")
163
+ try:
164
+ if self.device == "cuda":
165
+ # Convert to appropriate dtype for GPU
166
+ self.model = self.model.to(device=self.device, dtype=torch.float16)
167
+ logger.info("βœ… Model moved to CUDA with fp16")
168
+ else:
169
+ # Keep on CPU
170
+ self.model = self.model.to(device="cpu", dtype=torch.float32)
171
+ logger.info("βœ… Model kept on CPU with fp32")
172
+ loading_successful = True
173
+
174
+ except Exception as device_error:
175
+ logger.error(f"❌ Device movement failed: {device_error}")
176
+ logger.info("πŸ”„ Falling back to CPU...")
177
+ self.device = "cpu"
178
+ if self.model is not None:
179
+ self.model = self.model.to("cpu", dtype=torch.float32)
180
+ loading_successful = True
181
+ else:
182
+ logger.error("❌ Model is None, using fallback mode")
183
+ self.model = "fallback"
184
+ except Exception as e2:
185
+ logger.error(f"❌ Strategy 2 failed: {e2}")
186
+
187
+ # If all strategies failed, use fallback
188
+ if not loading_successful:
189
+ logger.error("❌ All loading strategies failed")
190
+ logger.info("πŸ”„ Using fallback 3D generation")
191
  self.model = "fallback"
192
+ return
193
+
194
+ # Enable optimizations safely
195
+ logger.info("πŸ“¦ Applying model optimizations...")
196
+ if self.model != "fallback" and hasattr(self.model, 'enable_attention_slicing'):
197
+ self.model.enable_attention_slicing()
198
+ logger.info("βœ… Attention slicing enabled")
199
+ else:
200
+ logger.info("⚠️ Attention slicing not available")
201
+
202
+ logger.info("πŸŽ‰ 3D model loading completed successfully!")
203
 
204
  except Exception as e:
205
  logger.error(f"❌ Failed to load Hunyuan3D model: {e}")
 
244
  else:
245
  logger.info("πŸ–ΌοΈ Input is already PIL Image")
246
 
247
+ # Ensure RGBA for Hunyuan3D
248
  logger.info(f"πŸ–ΌοΈ Image mode: {image.mode}")
249
+ if image.mode != 'RGBA':
250
+ logger.info("πŸ–ΌοΈ Converting image to RGBA mode")
251
+ image = image.convert('RGBA')
252
 
253
  logger.info(f"πŸ–ΌοΈ Final image size: {image.size}")
254
 
 
 
 
 
 
255
  # Remove background if requested
256
+ if remove_background and image.mode == 'RGB':
257
  logger.info("🎭 Removing background from image...")
258
  try:
259
+ if hasattr(self, 'bg_remover'):
260
+ # Use Hunyuan3D's background remover
261
+ image = self.bg_remover(image)
262
+ logger.info("βœ… Background removed using Hunyuan3D remover")
263
+ else:
264
+ # Use fallback background removal
265
+ image = self._remove_background(image)
266
+ logger.info("βœ… Background removed using fallback method")
267
  except Exception as bg_error:
268
  logger.error(f"❌ Background removal failed: {bg_error}")
269
  logger.info("πŸ”„ Continuing with original image...")
270
 
271
+ # Check if we have the Hunyuan3D pipeline
272
+ if hasattr(self.model, '__call__') and hasattr(self, 'bg_remover'):
273
+ # Using Hunyuan3D pipeline
274
+ logger.info("🧠 Using Hunyuan3D pipeline for 3D generation...")
275
+
276
  try:
277
+ # Generate 3D model using Hunyuan3D
278
+ logger.info("πŸš€ Starting Hunyuan3D generation...")
279
+ mesh_outputs = self.model(image=image)
 
 
 
 
 
 
 
 
 
 
 
 
280
 
281
+ if isinstance(mesh_outputs, list) and len(mesh_outputs) > 0:
282
+ mesh = mesh_outputs[0]
283
+ logger.info("βœ… 3D mesh generated successfully")
284
+
285
+ # Save mesh
286
+ logger.info("πŸ’Ύ Saving generated mesh...")
287
+ mesh_path = self._save_mesh(mesh)
288
+ logger.info(f"βœ… Mesh saved to: {mesh_path}")
289
+
290
+ return mesh_path
291
+ else:
292
+ logger.error("❌ No mesh output from Hunyuan3D")
293
+ raise Exception("Empty mesh output")
294
+
295
+ except Exception as hunyuan_error:
296
+ logger.error(f"❌ Hunyuan3D generation failed: {hunyuan_error}")
297
+ logger.info("πŸ”„ Falling back to alternative generation...")
298
+ return self._generate_fallback_3d(image)
 
 
 
 
 
 
 
 
299
 
300
+ else:
301
+ # Using transformers-based approach (original code)
302
+ logger.info("🧠 Using transformers-based 3D generation...")
303
+
304
+ # Resize for processing
305
+ logger.info("πŸ–ΌοΈ Resizing image for processing (512x512)...")
306
+ image = image.resize((512, 512), Image.Resampling.LANCZOS)
307
+ logger.info("βœ… Image resized successfully")
308
+
309
+ # Process with model
310
+ logger.info("🧠 Starting model inference...")
311
+ with torch.no_grad():
312
+ try:
313
+ # Preprocess image
314
+ logger.info("πŸ”„ Preprocessing image for model...")
315
+ inputs = self.preprocessor(images=image, return_tensors="pt")
316
+ logger.info(f"πŸ”„ Input tensor shape: {inputs['pixel_values'].shape if 'pixel_values' in inputs else 'unknown'}")
317
+
318
+ # Move inputs to device safely
319
+ logger.info(f"πŸ”„ Moving inputs to device: {self.device}")
320
+ try:
321
+ # Avoid device-related dynamo issues
322
+ device_str = str(self.device) # Convert to string to avoid torch.device in dynamo
323
+ inputs = {k: v.to(device_str) for k, v in inputs.items() if hasattr(v, 'to')}
324
+ logger.info("βœ… Inputs moved to device successfully")
325
+ except Exception as device_error:
326
+ logger.error(f"❌ Failed to move inputs to device: {device_error}")
327
+ raise device_error
328
+
329
+ # Generate 3D
330
+ logger.info("πŸš€ Starting 3D generation inference...")
331
+ logger.info(f"πŸš€ Parameters: steps={self.num_inference_steps}, guidance={self.guidance_scale}")
332
+
333
+ outputs = self.model.generate(
334
+ **inputs,
335
+ num_inference_steps=self.num_inference_steps,
336
+ guidance_scale=self.guidance_scale,
337
+ texture_resolution=texture_resolution
338
+ )
339
+ logger.info("βœ… 3D generation completed successfully")
340
+
341
+ # Extract mesh
342
+ logger.info("πŸ”§ Extracting mesh from model outputs...")
343
+ mesh = self._extract_mesh(outputs)
344
+ logger.info("βœ… Mesh extraction completed")
345
+
346
+ except Exception as inference_error:
347
+ logger.error(f"❌ Model inference failed: {inference_error}")
348
+ logger.error(f"❌ Inference error type: {type(inference_error).__name__}")
349
+ raise inference_error
350
+
351
+ # Save mesh
352
+ logger.info("πŸ’Ύ Saving generated mesh...")
353
+ mesh_path = self._save_mesh(mesh)
354
+ logger.info(f"βœ… Mesh saved to: {mesh_path}")
355
+
356
+ logger.info("πŸŽ‰ 3D generation process completed successfully!")
357
+ return mesh_path
358
 
359
  except Exception as e:
360
  logger.error(f"❌ 3D generation error: {e}")
requirements_hunyuan3d.txt ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Additional requirements for Hunyuan3D-2.1 support
2
+ # Install these in addition to the main requirements.txt
3
+
4
+ # Hunyuan3D specific dependencies
5
+ # Note: The hy3dshape and hy3dpaint modules need to be installed from the Hunyuan3D repository
6
+ # git clone https://huggingface.co/spaces/tencent/Hunyuan3D-2.1
7
+ # Then copy the hy3dshape and hy3dpaint folders to your project
8
+
9
+ # Core dependencies that Hunyuan3D uses
10
+ trimesh>=3.23.5
11
+ pygltflib>=1.16.1
12
+ scikit-image>=0.22.0
13
+ opencv-python>=4.8.0
14
+ Pillow>=10.0.0
15
+ numpy>=1.24.0
16
+ torch>=2.0.0
17
+ torchvision>=0.15.0
18
+ transformers>=4.35.0
19
+ diffusers>=0.25.0
20
+ accelerate>=0.25.0
21
+ safetensors>=0.4.0
22
+ huggingface-hub>=0.19.0
23
+ spaces>=0.19.0
24
+
25
+ # For background removal
26
+ rembg>=2.0.50
27
+
28
+ # For 3D visualization and processing
29
+ pymeshlab>=2022.2.post3
30
+ open3d>=0.17.0
31
+
32
+ # Optional: For mesh optimization
33
+ xatlas>=0.0.7
34
+ pyvista>=0.42.0
35
+
36
+ # Note: Some dependencies might require specific versions or CUDA compatibility
37
+ # Adjust versions based on your system configuration