Merge pull request #440 from MrForExample/dev

Small Update for Hunyuan3D-2, Merge 2 pull requests, and add Decimate Mesh node
This commit is contained in:
Mr. For Example
2025-01-24 12:39:40 -06:00
committed by GitHub
6 changed files with 161 additions and 16 deletions
@@ -9,14 +9,11 @@ language:
tags:
- image-to-3d
- text-to-3d
pipeline_tag: text-to-3d
pipeline_tag: image-to-3d
---
<p align="center">
<img src="./assets/images/teaser.jpg">
</p>
<div align="center">
@@ -40,6 +37,9 @@ pipeline_tag: text-to-3d
“ Living out everyone’s imagination on creating and manipulating 3D assets.”
</p>
This repository contains the models of the paper [Hunyuan3D 2.0: Scaling Diffusion Models for High Resolution Textured 3D Assets Generation](https://huggingface.co/papers/2501.12202).
For code and more details on how to use it, refer to the [Github repository](https://github.com/Tencent/Hunyuan3D-2).
## 🔥 News
- Jan 21, 2025: 💬 Release [Hunyuan3D 2.0](https://huggingface.co/spaces/tencent/Hunyuan3D-2). Please give it a try!
@@ -60,8 +60,6 @@ We systematically evaluate our models, showing that Hunyuan3D 2.0 outperforms pr
including the open-source models and closed-source models in geometry details, condition alignment, texture quality, and
e.t.c.
<p align="center">
<img src="assets/images/system.jpg">
</p>
@@ -104,6 +102,7 @@ Generation results of Hunyuan3D 2.0:
|----------------------|------------|--------------------------------------------------------|
| Hunyuan3D-DiT-v2-0 | 2025-01-21 | [Download](https://huggingface.co/tencent/Hunyuan3D-2) |
| Hunyuan3D-Paint-v2-0 | 2025-01-21 | [Download](https://huggingface.co/tencent/Hunyuan3D-2) |
| Hunyuan3D-Delight-v2-0 | 2025-01-21 | [Download](https://huggingface.co/tencent/Hunyuan3D-2/tree/main/hunyuan3d-delight-v2-0) |
## 🤗 Get Started with Hunyuan3D 2.0
@@ -118,8 +117,9 @@ pip install -r requirements.txt
# for texture
cd hy3dgen/texgen/custom_rasterizer
python3 setup.py install
cd ../../..
cd hy3dgen/texgen/differentiable_renderer
bash compile_mesh_painter.sh
bash compile_mesh_painter.sh OR python3 setup.py install (on Windows)
```
### API Usage
@@ -184,9 +184,29 @@ If you found this repository helpful, please cite our report:
title={Hunyuan3D 2.0: Scaling Diffusion Models for High Resolution Textured 3D Assets Generation},
author={Tencent Hunyuan3D Team},
year={2025},
eprint={2501.12202},
archivePrefix={arXiv},
primaryClass={cs.CV}
}
@misc{yang2024tencent,
title={Tencent Hunyuan3D-1.0: A Unified Framework for Text-to-3D and Image-to-3D Generation},
author={Tencent Hunyuan3D Team},
year={2024},
eprint={2411.02293},
archivePrefix={arXiv},
primaryClass={cs.CV}
}
```
## Community Resources
Thanks for the contributions of community members, here we have these great extensions of Hunyuan3D 2.0:
- [ComfyUI-Hunyuan3DWrapper](https://github.com/kijai/ComfyUI-Hunyuan3DWrapper)
- [Hunyuan3D-2-for-windows](https://github.com/sdbds/Hunyuan3D-2-for-windows)
- [📦 A bundle for running on Windows | 整合包](https://github.com/YanWenKun/Comfy3D-WinPortable/releases/tag/r8-hunyuan3d2)
## Acknowledgements
We would like to thank the contributors to
@@ -201,4 +221,4 @@ and [HuggingFace](https://huggingface.co) repositories, for their open research
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=Tencent/Hunyuan3D-2&type=Date" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=Tencent/Hunyuan3D-2&type=Date" />
</picture>
</a>
</a>
@@ -0,0 +1,47 @@
from setuptools import setup, Extension
import pybind11
import sys
import platform
# Common compile arguments
common_compile_args = []
if sys.platform == 'win32':
# Windows-specific compile arguments
extra_compile_args = [
'/O2', # Optimization level
'/std:c++14', # C++ standard (using C++14 for better compatibility)
'/EHsc', # Exception handling model
'/MP', # Multi-process compilation
'/DWIN32_LEAN_AND_MEAN', # Exclude rarely-used Windows headers
]
extra_link_args = []
else:
# Linux/Unix compile arguments
extra_compile_args = [
'-O3', # Optimization level
'-std=c++14', # C++ standard
'-fPIC', # Position independent code
]
extra_link_args = ['-fPIC']
ext_modules = [
Extension(
"mesh_processor",
["mesh_processor.cpp"],
include_dirs=[
pybind11.get_include(),
pybind11.get_include(user=True)
],
language='c++',
extra_compile_args=common_compile_args + extra_compile_args,
extra_link_args=extra_link_args,
),
]
setup(
name="mesh_processor",
ext_modules=ext_modules,
install_requires=['pybind11>=2.6.0'],
python_requires='>=3.6',
)
@@ -140,6 +140,40 @@ class Hunyuan3DPaintPipeline:
texture = torch.tensor(texture_np / 255).float().to(texture.device)
return texture
def recenter_image(self, image, border_ratio=0.2):
if image.mode == 'RGB':
return image
elif image.mode == 'L':
image = image.convert('RGB')
return image
alpha_channel = np.array(image)[:, :, 3]
non_zero_indices = np.argwhere(alpha_channel > 0)
if non_zero_indices.size == 0:
raise ValueError("Image is fully transparent")
min_row, min_col = non_zero_indices.min(axis=0)
max_row, max_col = non_zero_indices.max(axis=0)
cropped_image = image.crop((min_col, min_row, max_col + 1, max_row + 1))
width, height = cropped_image.size
border_width = int(width * border_ratio)
border_height = int(height * border_ratio)
new_width = width + 2 * border_width
new_height = height + 2 * border_height
square_size = max(new_width, new_height)
new_image = Image.new('RGBA', (square_size, square_size), (255, 255, 255, 0))
paste_x = (square_size - new_width) // 2 + border_width
paste_y = (square_size - new_height) // 2 + border_height
new_image.paste(cropped_image, (paste_x, paste_y))
return new_image
@torch.no_grad()
def __call__(self, mesh, image):
@@ -153,6 +187,7 @@ class Hunyuan3DPaintPipeline:
else:
image_prompt = image
image_prompt = self.recenter_image(image_prompt)
image_prompt = self.models['delight_model'](image_prompt)
step_num_i += 1
+20 -7
View File
@@ -211,9 +211,22 @@ def poisson_mesh_reconstruction(points, normals=None):
def decimate_mesh(
verts, faces, target, backend="pymeshlab", remesh=False, optimalplacement=True
verts, faces, target=5e4, backend="pymeshlab", remesh=False, optimalplacement=True, verbose=True
):
# optimalplacement: default is True, but for flat mesh must turn False to prevent spike artifect.
""" perform mesh decimation.
Args:
verts (np.ndarray): mesh vertices, float [N, 3]
faces (np.ndarray): mesh faces, int [M, 3]
target (int): targeted number of faces
backend (str, optional): algorithm backend, can be "pymeshlab" or "pyfqmr". Defaults to "pymeshlab".
remesh (bool, optional): whether to remesh after decimation. Defaults to False.
optimalplacement (bool, optional): For flat mesh, use False to prevent spikes. Defaults to True.
verbose (bool, optional): whether to print the decimation process. Defaults to True.
Returns:
Tuple[np.ndarray]: vertices and faces after decimation.
"""
_ori_vert_shape = verts.shape
_ori_face_shape = faces.shape
@@ -231,7 +244,7 @@ def decimate_mesh(
ms.add_mesh(m, "mesh") # will copy!
# filters
# ms.meshing_decimation_clustering(threshold=pml.Percentage(1))
# ms.meshing_decimation_clustering(threshold=pml.PercentageValue(1))
ms.meshing_decimation_quadric_edge_collapse(
targetfacenum=int(target), optimalplacement=optimalplacement
)
@@ -239,17 +252,17 @@ def decimate_mesh(
if remesh:
# ms.apply_coord_taubin_smoothing()
ms.meshing_isotropic_explicit_remeshing(
iterations=3, targetlen=pml.Percentage(1)
iterations=3, targetlen=pml.PercentageValue(1)
)
# extract mesh
m = ms.current_mesh()
m.compact()
verts = m.vertex_matrix()
faces = m.face_matrix()
print(
f"[INFO] mesh decimation: {_ori_vert_shape} --> {verts.shape}, {_ori_face_shape} --> {faces.shape}"
)
if verbose:
print(f"[INFO] mesh decimation: {_ori_vert_shape} --> {verts.shape}, {_ori_face_shape} --> {faces.shape}")
return verts, faces
+30
View File
@@ -46,6 +46,7 @@ from .mesh_processer.mesh_utils import (
marching_cubes_density_to_mesh,
color_func_to_albedo,
interpolate_texture_map_attr,
decimate_mesh,
)
from FlexiCubes.flexicubes_trainer import FlexiCubesTrainer
@@ -608,6 +609,35 @@ class Fast_Clean_Mesh:
mesh = Mesh(v=vertices, f=faces, device=DEVICE)
return (mesh,)
class Decimate_Mesh:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"mesh": ("MESH",),
"target": ("INT", {"default": 5e4, "min": 0, "max": 0xffffffffffffffff}),
"remesh": ("BOOLEAN", {"default": True},),
"optimalplacement": ("BOOLEAN", {"default": True},),
},
}
RETURN_TYPES = (
"MESH",
)
RETURN_NAMES = (
"mesh",
)
FUNCTION = "process_mesh"
CATEGORY = "Comfy3D/Preprocessor"
def process_mesh(self, mesh, target, remesh, optimalplacement):
vertices, faces = decimate_mesh(mesh.v, mesh.f, target, remesh, optimalplacement)
mesh.v = vertices
mesh.f = faces
return (mesh,)
class Switch_3DGS_Axis:
@classmethod
+1 -1
View File
@@ -1,7 +1,7 @@
[project]
name = "comfyui-3d-pack"
description = "Make ComfyUI generates 3D assets as good & convenient as it generates image/video!"
version = "0.1.3"
version = "0.1.4"
license = { file = "LICENSE" }
dynamic = ["dependencies"]
[tool.setuptools.dynamic]