Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,4 +331,4 @@ EmbodiedGen builds upon the following amazing projects and models:

## ⚖️ License

This project is licensed under the [Apache License 2.0](LICENSE). See the `LICENSE` file for details.
This project is licensed under the [Apache License 2.0](docs/LICENSE). See the `LICENSE` file for details.
2 changes: 1 addition & 1 deletion apps/app_style.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
lighting_css = """
<style>
#lighter_mesh canvas {
filter: brightness(1.9) !important;
filter: brightness(2.0) !important;
}
</style>
"""
Expand Down
67 changes: 62 additions & 5 deletions apps/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@
from easydict import EasyDict as edict
from PIL import Image
from embodied_gen.data.backproject_v2 import entrypoint as backproject_api
from embodied_gen.data.backproject_v3 import entrypoint as backproject_api_v3
from embodied_gen.data.differentiable_render import entrypoint as render_api
from embodied_gen.data.utils import trellis_preprocess, zip_files
from embodied_gen.data.utils import resize_pil, trellis_preprocess, zip_files
from embodied_gen.models.delight_model import DelightingModel
from embodied_gen.models.gs_model import GaussianOperator
from embodied_gen.models.segment_model import (
Expand Down Expand Up @@ -131,8 +132,8 @@ def build_covariance_from_scaling_rotation(
Gaussian.setup_functions = patched_setup_functions


DELIGHT = DelightingModel()
IMAGESR_MODEL = ImageRealESRGAN(outscale=4)
# DELIGHT = DelightingModel()
# IMAGESR_MODEL = ImageRealESRGAN(outscale=4)
# IMAGESR_MODEL = ImageStableSR()
if os.getenv("GRADIO_APP") == "imageto3d":
RBG_REMOVER = RembgRemover()
Expand Down Expand Up @@ -169,6 +170,8 @@ def build_covariance_from_scaling_rotation(
)
os.makedirs(TMP_DIR, exist_ok=True)
elif os.getenv("GRADIO_APP") == "texture_edit":
DELIGHT = DelightingModel()
IMAGESR_MODEL = ImageRealESRGAN(outscale=4)
PIPELINE_IP = build_texture_gen_pipe(
base_ckpt_dir="./weights",
ip_adapt_scale=0.7,
Expand Down Expand Up @@ -205,7 +208,7 @@ def preprocess_image_fn(
elif isinstance(image, np.ndarray):
image = Image.fromarray(image)

image_cache = image.copy().resize((512, 512))
image_cache = resize_pil(image.copy(), 1024)

bg_remover = RBG_REMOVER if rmbg_tag == "rembg" else RBG14_REMOVER
image = bg_remover(image)
Expand All @@ -221,7 +224,7 @@ def preprocess_sam_image_fn(
image = Image.fromarray(image)

sam_image = SAM_PREDICTOR.preprocess_image(image)
image_cache = Image.fromarray(sam_image).resize((512, 512))
image_cache = sam_image.copy()
SAM_PREDICTOR.predictor.set_image(sam_image)

return sam_image, image_cache
Expand Down Expand Up @@ -512,6 +515,60 @@ def extract_3d_representations_v2(
return mesh_glb_path, gs_path, mesh_obj_path, aligned_gs_path


def extract_3d_representations_v3(
state: dict,
enable_delight: bool,
texture_size: int,
req: gr.Request,
):
output_root = TMP_DIR
user_dir = os.path.join(output_root, str(req.session_hash))
gs_model, mesh_model = unpack_state(state, device="cpu")

filename = "sample"
gs_path = os.path.join(user_dir, f"{filename}_gs.ply")
gs_model.save_ply(gs_path)

# Rotate mesh and GS by 90 degrees around Z-axis.
rot_matrix = [[0, 0, -1], [0, 1, 0], [1, 0, 0]]
gs_add_rot = [[1, 0, 0], [0, -1, 0], [0, 0, -1]]
mesh_add_rot = [[1, 0, 0], [0, 0, -1], [0, 1, 0]]

# Addtional rotation for GS to align mesh.
gs_rot = np.array(gs_add_rot) @ np.array(rot_matrix)
pose = GaussianOperator.trans_to_quatpose(gs_rot)
aligned_gs_path = gs_path.replace(".ply", "_aligned.ply")
GaussianOperator.resave_ply(
in_ply=gs_path,
out_ply=aligned_gs_path,
instance_pose=pose,
device="cpu",
)

mesh = trimesh.Trimesh(
vertices=mesh_model.vertices.cpu().numpy(),
faces=mesh_model.faces.cpu().numpy(),
)
mesh.vertices = mesh.vertices @ np.array(mesh_add_rot)
mesh.vertices = mesh.vertices @ np.array(rot_matrix)

mesh_obj_path = os.path.join(user_dir, f"{filename}.obj")
mesh.export(mesh_obj_path)

mesh = backproject_api_v3(
gs_path=aligned_gs_path,
mesh_path=mesh_obj_path,
output_path=mesh_obj_path,
skip_fix_mesh=False,
texture_size=texture_size,
)

mesh_glb_path = os.path.join(user_dir, f"{filename}.glb")
mesh.export(mesh_glb_path)

return mesh_glb_path, gs_path, mesh_obj_path, aligned_gs_path


def extract_urdf(
gs_path: str,
mesh_obj_path: str,
Expand Down
37 changes: 16 additions & 21 deletions apps/image_to_3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
VERSION,
active_btn_by_content,
end_session,
extract_3d_representations_v2,
extract_3d_representations_v3,
extract_urdf,
get_seed,
image_to_3d,
Expand Down Expand Up @@ -179,17 +179,17 @@
)

generate_btn = gr.Button(
"🚀 1. Generate(~0.5 mins)",
"🚀 1. Generate(~2 mins)",
variant="primary",
interactive=False,
)
model_output_obj = gr.Textbox(label="raw mesh .obj", visible=False)
with gr.Row():
extract_rep3d_btn = gr.Button(
"🔍 2. Extract 3D Representation(~2 mins)",
variant="primary",
interactive=False,
)
# with gr.Row():
# extract_rep3d_btn = gr.Button(
# "🔍 2. Extract 3D Representation(~2 mins)",
# variant="primary",
# interactive=False,
# )
with gr.Accordion(
label="Enter Asset Attributes(optional)", open=False
):
Expand All @@ -207,7 +207,7 @@
)
with gr.Row():
extract_urdf_btn = gr.Button(
"🧩 3. Extract URDF with physics(~1 mins)",
"🧩 2. Extract URDF with physics(~1 mins)",
variant="primary",
interactive=False,
)
Expand All @@ -230,7 +230,7 @@
)
with gr.Row():
download_urdf = gr.DownloadButton(
label="⬇️ 4. Download URDF",
label="⬇️ 3. Download URDF",
variant="primary",
interactive=False,
)
Expand Down Expand Up @@ -326,7 +326,7 @@
image_prompt.change(
lambda: tuple(
[
gr.Button(interactive=False),
# gr.Button(interactive=False),
gr.Button(interactive=False),
gr.Button(interactive=False),
None,
Expand All @@ -344,7 +344,7 @@
]
),
outputs=[
extract_rep3d_btn,
# extract_rep3d_btn,
extract_urdf_btn,
download_urdf,
model_output_gs,
Expand Down Expand Up @@ -375,7 +375,7 @@
image_prompt_sam.change(
lambda: tuple(
[
gr.Button(interactive=False),
# gr.Button(interactive=False),
gr.Button(interactive=False),
gr.Button(interactive=False),
None,
Expand All @@ -394,7 +394,7 @@
]
),
outputs=[
extract_rep3d_btn,
# extract_rep3d_btn,
extract_urdf_btn,
download_urdf,
model_output_gs,
Expand Down Expand Up @@ -447,12 +447,7 @@
],
outputs=[output_buf, video_output],
).success(
lambda: gr.Button(interactive=True),
outputs=[extract_rep3d_btn],
)

extract_rep3d_btn.click(
extract_3d_representations_v2,
extract_3d_representations_v3,
inputs=[
output_buf,
project_delight,
Expand Down Expand Up @@ -495,4 +490,4 @@


if __name__ == "__main__":
demo.launch()
demo.launch(server_port=8081)
33 changes: 14 additions & 19 deletions apps/text_to_3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
VERSION,
active_btn_by_text_content,
end_session,
extract_3d_representations_v2,
extract_3d_representations_v3,
extract_urdf,
get_cached_image,
get_seed,
Expand Down Expand Up @@ -178,17 +178,17 @@
)

generate_btn = gr.Button(
"🚀 2. Generate 3D(~0.5 mins)",
"🚀 2. Generate 3D(~2 mins)",
variant="primary",
interactive=False,
)
model_output_obj = gr.Textbox(label="raw mesh .obj", visible=False)
with gr.Row():
extract_rep3d_btn = gr.Button(
"🔍 3. Extract 3D Representation(~1 mins)",
variant="primary",
interactive=False,
)
# with gr.Row():
# extract_rep3d_btn = gr.Button(
# "🔍 3. Extract 3D Representation(~1 mins)",
# variant="primary",
# interactive=False,
# )
with gr.Accordion(
label="Enter Asset Attributes(optional)", open=False
):
Expand All @@ -206,13 +206,13 @@
)
with gr.Row():
extract_urdf_btn = gr.Button(
"🧩 4. Extract URDF with physics(~1 mins)",
"🧩 3. Extract URDF with physics(~1 mins)",
variant="primary",
interactive=False,
)
with gr.Row():
download_urdf = gr.DownloadButton(
label="⬇️ 5. Download URDF",
label="⬇️ 4. Download URDF",
variant="primary",
interactive=False,
)
Expand Down Expand Up @@ -336,7 +336,7 @@
generate_img_btn.click(
lambda: tuple(
[
gr.Button(interactive=False),
# gr.Button(interactive=False),
gr.Button(interactive=False),
gr.Button(interactive=False),
gr.Button(interactive=False),
Expand All @@ -358,7 +358,7 @@
]
),
outputs=[
extract_rep3d_btn,
# extract_rep3d_btn,
extract_urdf_btn,
download_urdf,
generate_btn,
Expand Down Expand Up @@ -428,12 +428,7 @@
],
outputs=[output_buf, video_output],
).success(
lambda: gr.Button(interactive=True),
outputs=[extract_rep3d_btn],
)

extract_rep3d_btn.click(
extract_3d_representations_v2,
extract_3d_representations_v3,
inputs=[
output_buf,
project_delight,
Expand Down Expand Up @@ -476,4 +471,4 @@


if __name__ == "__main__":
demo.launch()
demo.launch(server_port=8082)
2 changes: 1 addition & 1 deletion apps/texture_edit.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,4 +381,4 @@ def active_btn_by_content(mesh_content: gr.Model3D, text_content: gr.Textbox):


if __name__ == "__main__":
demo.launch()
demo.launch(server_port=8083)
1 change: 0 additions & 1 deletion apps/visualize_asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,6 @@ def update_assets(p, s, c):

if __name__ == "__main__":
demo.launch(
server_name="10.34.8.77",
server_port=8088,
allowed_paths=[
"/horizon-bucket/robot_lab/datasets/embodiedgen/assets"
Expand Down
File renamed without changes.
2 changes: 2 additions & 0 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ conda activate embodiedgen
bash install.sh basic
```

Please `huggingface-cli login` to ensure that the ckpts can be downloaded automatically afterwards.

## ✅ Starting from Docker

We provide a pre-built Docker image on [Docker Hub](https://hub.docker.com/repository/docker/wangxinjie/embodiedgen) with a configured environment for your convenience. For more details, please refer to [Docker documentation](https://github.com/HorizonRobotics/EmbodiedGen/tree/master/docker).
Expand Down
2 changes: 2 additions & 0 deletions embodied_gen/data/asset_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,8 @@ def convert(self, urdf_path: str, output_file: str):
stage = Usd.Stage.Open(usd_path)
layer = stage.GetRootLayer()
with Usd.EditContext(stage, layer):
base_prim = stage.GetPseudoRoot().GetChildren()[0]
base_prim.SetMetadata("kind", "component")
for prim in stage.Traverse():
# Change texture path to relative path.
if prim.GetName() == "material_0":
Expand Down
23 changes: 1 addition & 22 deletions embodied_gen/data/backproject.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
CameraSetting,
get_images_from_grid,
init_kal_camera,
kaolin_to_opencv_view,
normalize_vertices_array,
post_process_texture,
save_mesh_with_mtl,
Expand Down Expand Up @@ -306,28 +307,6 @@ def bake_texture(
raise ValueError(f"Unknown mode: {mode}")


def kaolin_to_opencv_view(raw_matrix):
R_orig = raw_matrix[:, :3, :3]
t_orig = raw_matrix[:, :3, 3]

R_target = torch.zeros_like(R_orig)
R_target[:, :, 0] = R_orig[:, :, 2]
R_target[:, :, 1] = R_orig[:, :, 0]
R_target[:, :, 2] = R_orig[:, :, 1]

t_target = t_orig

target_matrix = (
torch.eye(4, device=raw_matrix.device)
.unsqueeze(0)
.repeat(raw_matrix.size(0), 1, 1)
)
target_matrix[:, :3, :3] = R_target
target_matrix[:, :3, 3] = t_target

return target_matrix


def parse_args():
parser = argparse.ArgumentParser(description="Render settings")

Expand Down
Loading