Spaces:
Running on A100
Running on A100
dont use lower settings
Browse files
app.py
CHANGED
|
@@ -11,7 +11,6 @@ import matplotlib.pyplot as plt
|
|
| 11 |
import matplotlib.colors as mcolors
|
| 12 |
from matplotlib.colorbar import ColorbarBase
|
| 13 |
import numpy as np
|
| 14 |
-
import plotly.graph_objects as go
|
| 15 |
import spaces
|
| 16 |
import torch
|
| 17 |
from huggingface_hub import snapshot_download
|
|
@@ -129,13 +128,19 @@ def _create_colorbar(
|
|
| 129 |
return output_path
|
| 130 |
|
| 131 |
|
| 132 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 133 |
coords: np.ndarray,
|
| 134 |
values: np.ndarray,
|
| 135 |
-
|
| 136 |
colormap: str = "viridis",
|
| 137 |
-
|
| 138 |
-
|
|
|
|
|
|
|
| 139 |
coords = np.asarray(coords, dtype=np.float32)
|
| 140 |
values = np.asarray(values, dtype=np.float32).reshape(-1)
|
| 141 |
if coords.ndim != 2 or coords.shape[1] != 3:
|
|
@@ -145,38 +150,37 @@ def _create_pointcloud_plot(
|
|
| 145 |
f"values must be (N,), got {values.shape} for coords {coords.shape}"
|
| 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 |
-
paper_bgcolor="rgb(20,20,20)",
|
| 176 |
-
plot_bgcolor="rgb(20,20,20)",
|
| 177 |
-
showlegend=False,
|
| 178 |
)
|
| 179 |
-
|
|
|
|
|
|
|
|
|
|
| 180 |
|
| 181 |
|
| 182 |
def _create_material_visualizations(
|
|
@@ -225,11 +229,12 @@ def _create_material_visualizations(
|
|
| 225 |
|
| 226 |
for prop_name, prop_data in properties.items():
|
| 227 |
if prop_data is not None:
|
| 228 |
-
|
|
|
|
| 229 |
colorbar_path = os.path.join(output_dir, f"{prop_name}_colorbar.png")
|
| 230 |
_create_colorbar(prop_data, prop_name, colorbar_path)
|
| 231 |
-
result[prop_name] = (
|
| 232 |
-
print(f"Created point cloud
|
| 233 |
|
| 234 |
return result
|
| 235 |
|
|
@@ -258,9 +263,8 @@ def process_3d_model(input_file):
|
|
| 258 |
print(f"Processing as Gaussian splat: {input_file}")
|
| 259 |
results = model.get_splat_materials(
|
| 260 |
input_file,
|
| 261 |
-
voxel_method="kaolin",
|
| 262 |
-
query_points="voxel_centers",
|
| 263 |
output_dir=output_dir,
|
|
|
|
| 264 |
)
|
| 265 |
else:
|
| 266 |
print(f"Processing as mesh: {input_file}")
|
|
@@ -385,7 +389,7 @@ Upload a Gaussian Splat (.ply) to predict volumetric mechanical properties (Youn
|
|
| 385 |
"""
|
| 386 |
|
| 387 |
|
| 388 |
-
with gr.Blocks(
|
| 389 |
gr.HTML(title_md)
|
| 390 |
gr.Markdown(description_md)
|
| 391 |
|
|
@@ -408,17 +412,29 @@ with gr.Blocks(css=css, title="VoMP") as demo:
|
|
| 408 |
# Row 1: Young's Modulus and Poisson's Ratio
|
| 409 |
with gr.Row():
|
| 410 |
with gr.Column(scale=1, min_width=200):
|
| 411 |
-
youngs_cloud = gr.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 412 |
youngs_colorbar = gr.Image(height=50, show_label=False)
|
| 413 |
|
| 414 |
with gr.Column(scale=1, min_width=200):
|
| 415 |
-
poissons_cloud = gr.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 416 |
poissons_colorbar = gr.Image(height=50, show_label=False)
|
| 417 |
|
| 418 |
# Row 2: Density and Download
|
| 419 |
with gr.Row():
|
| 420 |
with gr.Column(scale=1, min_width=200):
|
| 421 |
-
density_cloud = gr.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 422 |
density_colorbar = gr.Image(height=50, show_label=False)
|
| 423 |
|
| 424 |
with gr.Column(scale=1, min_width=200):
|
|
@@ -465,4 +481,4 @@ with gr.Blocks(css=css, title="VoMP") as demo:
|
|
| 465 |
)
|
| 466 |
|
| 467 |
if __name__ == "__main__":
|
| 468 |
-
demo.launch()
|
|
|
|
| 11 |
import matplotlib.colors as mcolors
|
| 12 |
from matplotlib.colorbar import ColorbarBase
|
| 13 |
import numpy as np
|
|
|
|
| 14 |
import spaces
|
| 15 |
import torch
|
| 16 |
from huggingface_hub import snapshot_download
|
|
|
|
| 128 |
return output_path
|
| 129 |
|
| 130 |
|
| 131 |
+
_SH_C0 = 0.28209479177387814
|
| 132 |
+
_SPLAT_POINT_SCALE = 0.0015
|
| 133 |
+
|
| 134 |
+
|
| 135 |
+
def _write_property_splat_ply(
|
| 136 |
coords: np.ndarray,
|
| 137 |
values: np.ndarray,
|
| 138 |
+
output_path: str,
|
| 139 |
colormap: str = "viridis",
|
| 140 |
+
point_scale: float = _SPLAT_POINT_SCALE,
|
| 141 |
+
) -> str:
|
| 142 |
+
"""Write a property-colored point cloud as a 3D Gaussian Splatting .ply.
|
| 143 |
+
"""
|
| 144 |
coords = np.asarray(coords, dtype=np.float32)
|
| 145 |
values = np.asarray(values, dtype=np.float32).reshape(-1)
|
| 146 |
if coords.ndim != 2 or coords.shape[1] != 3:
|
|
|
|
| 150 |
f"values must be (N,), got {values.shape} for coords {coords.shape}"
|
| 151 |
)
|
| 152 |
|
| 153 |
+
vmin, vmax = float(values.min()), float(values.max())
|
| 154 |
+
if vmax - vmin > 1e-12:
|
| 155 |
+
norm = (values - vmin) / (vmax - vmin)
|
| 156 |
+
else:
|
| 157 |
+
norm = np.zeros_like(values)
|
| 158 |
+
rgb = plt.cm.get_cmap(colormap)(norm)[:, :3].astype(np.float32) # 0..1
|
| 159 |
+
|
| 160 |
+
n = coords.shape[0]
|
| 161 |
+
fields = [
|
| 162 |
+
"x", "y", "z", "nx", "ny", "nz",
|
| 163 |
+
"f_dc_0", "f_dc_1", "f_dc_2",
|
| 164 |
+
"opacity", "scale_0", "scale_1", "scale_2",
|
| 165 |
+
"rot_0", "rot_1", "rot_2", "rot_3",
|
| 166 |
+
]
|
| 167 |
+
arr = np.zeros((n, len(fields)), dtype=np.float32)
|
| 168 |
+
arr[:, 0:3] = coords
|
| 169 |
+
arr[:, 6:9] = (rgb - 0.5) / _SH_C0
|
| 170 |
+
arr[:, 9] = 6.0
|
| 171 |
+
arr[:, 10:13] = np.log(point_scale)
|
| 172 |
+
arr[:, 13] = 1.0
|
| 173 |
+
|
| 174 |
+
header = (
|
| 175 |
+
"ply\nformat binary_little_endian 1.0\n"
|
| 176 |
+
f"element vertex {n}\n"
|
| 177 |
+
+ "".join(f"property float {f}\n" for f in fields)
|
| 178 |
+
+ "end_header\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
)
|
| 180 |
+
with open(output_path, "wb") as fp:
|
| 181 |
+
fp.write(header.encode("ascii"))
|
| 182 |
+
fp.write(arr.tobytes())
|
| 183 |
+
return output_path
|
| 184 |
|
| 185 |
|
| 186 |
def _create_material_visualizations(
|
|
|
|
| 229 |
|
| 230 |
for prop_name, prop_data in properties.items():
|
| 231 |
if prop_data is not None:
|
| 232 |
+
ply_path = os.path.join(output_dir, f"{prop_name}_cloud.ply")
|
| 233 |
+
_write_property_splat_ply(coords_normalized, prop_data, ply_path)
|
| 234 |
colorbar_path = os.path.join(output_dir, f"{prop_name}_colorbar.png")
|
| 235 |
_create_colorbar(prop_data, prop_name, colorbar_path)
|
| 236 |
+
result[prop_name] = (ply_path, colorbar_path)
|
| 237 |
+
print(f"Created point cloud for {prop_name}")
|
| 238 |
|
| 239 |
return result
|
| 240 |
|
|
|
|
| 263 |
print(f"Processing as Gaussian splat: {input_file}")
|
| 264 |
results = model.get_splat_materials(
|
| 265 |
input_file,
|
|
|
|
|
|
|
| 266 |
output_dir=output_dir,
|
| 267 |
+
seed=42,
|
| 268 |
)
|
| 269 |
else:
|
| 270 |
print(f"Processing as mesh: {input_file}")
|
|
|
|
| 389 |
"""
|
| 390 |
|
| 391 |
|
| 392 |
+
with gr.Blocks(title="VoMP") as demo:
|
| 393 |
gr.HTML(title_md)
|
| 394 |
gr.Markdown(description_md)
|
| 395 |
|
|
|
|
| 412 |
# Row 1: Young's Modulus and Poisson's Ratio
|
| 413 |
with gr.Row():
|
| 414 |
with gr.Column(scale=1, min_width=200):
|
| 415 |
+
youngs_cloud = gr.Model3D(
|
| 416 |
+
label="Young's Modulus",
|
| 417 |
+
clear_color=[0.1, 0.1, 0.1, 1.0],
|
| 418 |
+
height=400,
|
| 419 |
+
)
|
| 420 |
youngs_colorbar = gr.Image(height=50, show_label=False)
|
| 421 |
|
| 422 |
with gr.Column(scale=1, min_width=200):
|
| 423 |
+
poissons_cloud = gr.Model3D(
|
| 424 |
+
label="Poisson's Ratio",
|
| 425 |
+
clear_color=[0.1, 0.1, 0.1, 1.0],
|
| 426 |
+
height=400,
|
| 427 |
+
)
|
| 428 |
poissons_colorbar = gr.Image(height=50, show_label=False)
|
| 429 |
|
| 430 |
# Row 2: Density and Download
|
| 431 |
with gr.Row():
|
| 432 |
with gr.Column(scale=1, min_width=200):
|
| 433 |
+
density_cloud = gr.Model3D(
|
| 434 |
+
label="Density",
|
| 435 |
+
clear_color=[0.1, 0.1, 0.1, 1.0],
|
| 436 |
+
height=400,
|
| 437 |
+
)
|
| 438 |
density_colorbar = gr.Image(height=50, show_label=False)
|
| 439 |
|
| 440 |
with gr.Column(scale=1, min_width=200):
|
|
|
|
| 481 |
)
|
| 482 |
|
| 483 |
if __name__ == "__main__":
|
| 484 |
+
demo.launch(css=css)
|