Spaces:
Running
on
Zero
Running
on
Zero
improved visual
Browse files- app.py +50 -24
- convert_mesh.ipynb +19 -2
- data/scene0025_00/scene0025_00.obj +2 -2
- data/scene0426_00/scene0426_00.obj +2 -2
- data/scene0643_00/scene0643_00.obj +2 -2
- requirements.txt +1 -0
app.py
CHANGED
@@ -11,8 +11,7 @@ from copy import deepcopy
|
|
11 |
import numpy as np
|
12 |
import re
|
13 |
from bs4 import BeautifulSoup
|
14 |
-
import
|
15 |
-
|
16 |
|
17 |
import logging
|
18 |
|
@@ -38,7 +37,6 @@ max_new_tokens = 5000
|
|
38 |
obj_context_feature_type = "text"
|
39 |
|
40 |
|
41 |
-
|
42 |
tokenizer, model, data_loader = load_model_and_dataloader(
|
43 |
model_path=model_path,
|
44 |
model_base=model_base,
|
@@ -46,11 +44,12 @@ tokenizer, model, data_loader = load_model_and_dataloader(
|
|
46 |
load_4bit=load_4bit,
|
47 |
load_bf16=load_bf16,
|
48 |
scene_to_obj_mapping=scene_to_obj_mapping,
|
49 |
-
device_map=
|
50 |
) # Huggingface Zero-GPU has to use .to(device) to set the device, otherwise it will fail
|
51 |
|
52 |
model.to("cuda") # Huggingface Zero-GPU requires explicit device placement
|
53 |
|
|
|
54 |
def get_chatbot_response(user_chat_input, scene_id):
|
55 |
# Get the response from the model
|
56 |
prompt, response = get_model_response(
|
@@ -61,10 +60,11 @@ def get_chatbot_response(user_chat_input, scene_id):
|
|
61 |
user_input=user_chat_input,
|
62 |
max_new_tokens=max_new_tokens,
|
63 |
temperature=0.2,
|
64 |
-
top_p=0.9
|
65 |
)
|
66 |
return scene_id, prompt, response
|
67 |
|
|
|
68 |
# def get_chatbot_response(user_chat_input):
|
69 |
# # Get the response from the chatbot
|
70 |
# scene_id = "scene0643_00"
|
@@ -76,6 +76,7 @@ def get_chatbot_response(user_chat_input, scene_id):
|
|
76 |
# """
|
77 |
# return scene_id, scene_graph, response
|
78 |
|
|
|
79 |
# Resetting to blank
|
80 |
def reset_textbox():
|
81 |
return gr.update(value="")
|
@@ -126,7 +127,7 @@ def cylinder_frame(p0, p1):
|
|
126 |
return transformation
|
127 |
|
128 |
|
129 |
-
def create_cylinder_mesh(p0, p1, color, radius=0.
|
130 |
"""Create a colored cylinder mesh between two points p0 and p1."""
|
131 |
cylinder = o3d.geometry.TriangleMesh.create_cylinder(
|
132 |
radius=radius, height=1, resolution=resolution, split=split
|
@@ -164,15 +165,24 @@ def create_bbox(center, extents, color=[1, 0, 0], radius=0.02):
|
|
164 |
center = center.replace("[", "").replace("]", "")
|
165 |
extents = [float(x.strip()) for x in extents.split(",")]
|
166 |
center = [float(x.strip()) for x in center.split(",")]
|
|
|
|
|
|
|
|
|
|
|
167 |
|
168 |
-
|
|
|
|
|
|
|
|
|
169 |
x_corners = [sx / 2, sx / 2, -sx / 2, -sx / 2, sx / 2, sx / 2, -sx / 2, -sx / 2]
|
170 |
y_corners = [sy / 2, -sy / 2, -sy / 2, sy / 2, sy / 2, -sy / 2, -sy / 2, sy / 2]
|
171 |
z_corners = [sz / 2, sz / 2, sz / 2, sz / 2, -sz / 2, -sz / 2, -sz / 2, -sz / 2]
|
172 |
corners_3d = np.vstack([x_corners, y_corners, z_corners])
|
173 |
-
corners_3d[0, :] = corners_3d[0, :] + float(
|
174 |
-
corners_3d[1, :] = corners_3d[1, :] + float(
|
175 |
-
corners_3d[2, :] = corners_3d[2, :] + float(
|
176 |
corners_3d = np.transpose(corners_3d)
|
177 |
|
178 |
lines = [
|
@@ -201,7 +211,7 @@ def highlight_clusters_in_mesh(
|
|
201 |
centroids_extends_refer,
|
202 |
mesh,
|
203 |
output_dir,
|
204 |
-
output_file_name="highlighted_mesh.
|
205 |
):
|
206 |
print("*" * 50)
|
207 |
# Visualize the highlighted points by drawing 3D bounding boxes overlay on a mesh
|
@@ -218,7 +228,9 @@ def highlight_clusters_in_mesh(
|
|
218 |
for center, extent in centroids_extents_detailed:
|
219 |
print("center: ", center)
|
220 |
print("extent: ", extent)
|
221 |
-
bbox = create_bbox(
|
|
|
|
|
222 |
for b in bbox:
|
223 |
combined_mesh += b
|
224 |
|
@@ -227,7 +239,6 @@ def highlight_clusters_in_mesh(
|
|
227 |
for b in bbox:
|
228 |
combined_mesh += b
|
229 |
|
230 |
-
combined_mesh = prettify_mesh_for_gradio(combined_mesh)
|
231 |
# Save the combined mesh
|
232 |
output_file_path = os.path.join(output_path, output_file_name)
|
233 |
o3d.io.write_triangle_mesh(
|
@@ -261,6 +272,7 @@ def get_centroids_extents(obj_list, scene_dict):
|
|
261 |
centroids_extents.append((centroid, extent))
|
262 |
return centroids_extents
|
263 |
|
|
|
264 |
@spaces.GPU
|
265 |
def language_model_forward(
|
266 |
session_state, user_chat_input, top_p, temperature, dropdown_scene
|
@@ -283,7 +295,9 @@ def language_model_forward(
|
|
283 |
mesh = o3d.io.read_triangle_mesh(original_model_path)
|
284 |
|
285 |
# get chatbot response
|
286 |
-
scene_id, scene_graph, response = get_chatbot_response(
|
|
|
|
|
287 |
|
288 |
assert scene_id == session_state.scene # Ensure the scene ID matches
|
289 |
|
@@ -323,11 +337,13 @@ def language_model_forward(
|
|
323 |
centroids_extents_refer,
|
324 |
mesh,
|
325 |
session_output_dir,
|
326 |
-
output_file_name="highlighted_model.
|
327 |
)
|
328 |
-
|
329 |
# Update the chat history with the response
|
330 |
-
last_turn = session_state.chat_history_for_display[
|
|
|
|
|
331 |
last_turn = (last_turn[0], response)
|
332 |
session_state.chat_history_for_display[-1] = last_turn
|
333 |
session_state.save() # save the session state
|
@@ -335,7 +351,7 @@ def language_model_forward(
|
|
335 |
yield session_state, highlighted_model_path, session_state.chat_history_for_display
|
336 |
|
337 |
|
338 |
-
title = """<h1 align="center"
|
339 |
<p><center>
|
340 |
<a href="https://3d-grand.github.io/" target="_blank">[Project Page]</a>
|
341 |
<a href="https://www.dropbox.com/scl/fo/5p9nb4kalnz407sbqgemg/AG1KcxeIS_SUoJ1hoLPzv84?rlkey=weunabtbiz17jitfv3f4jpmm1&dl=0" target="_blank">[3D-GRAND Data]</a>
|
@@ -350,7 +366,7 @@ title = """<h1 align="center">π€ 3D-GRAND: Towards Better Grounding and Less H
|
|
350 |
|
351 |
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
352 |
session_state = gr.State(Session.create)
|
353 |
-
|
354 |
gr.HTML(title)
|
355 |
|
356 |
with gr.Column():
|
@@ -394,8 +410,8 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
394 |
)
|
395 |
gr.HTML(
|
396 |
"""<center><strong>
|
397 |
-
<div style="display:inline-block; color:
|
398 |
-
<div style="display:inline-block; color:
|
399 |
</strong></center>
|
400 |
"""
|
401 |
)
|
@@ -422,7 +438,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
422 |
gr.Examples(
|
423 |
examples=[
|
424 |
["The TV on the drawer, opposing the bed."],
|
425 |
-
["the desk next to the window"]
|
426 |
],
|
427 |
inputs=user_chat_input,
|
428 |
)
|
@@ -455,12 +471,22 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
455 |
dropdown_scene.change(
|
456 |
fn=change_scene_or_system_prompt,
|
457 |
inputs=[dropdown_scene],
|
458 |
-
outputs=[
|
|
|
|
|
|
|
|
|
|
|
459 |
)
|
460 |
clear_button.click(
|
461 |
fn=change_scene_or_system_prompt,
|
462 |
inputs=[dropdown_scene],
|
463 |
-
outputs=[
|
|
|
|
|
|
|
|
|
|
|
464 |
)
|
465 |
user_chat_input.submit(
|
466 |
fn=language_model_forward,
|
|
|
11 |
import numpy as np
|
12 |
import re
|
13 |
from bs4 import BeautifulSoup
|
14 |
+
import trimesh.transformations as tf
|
|
|
15 |
|
16 |
import logging
|
17 |
|
|
|
37 |
obj_context_feature_type = "text"
|
38 |
|
39 |
|
|
|
40 |
tokenizer, model, data_loader = load_model_and_dataloader(
|
41 |
model_path=model_path,
|
42 |
model_base=model_base,
|
|
|
44 |
load_4bit=load_4bit,
|
45 |
load_bf16=load_bf16,
|
46 |
scene_to_obj_mapping=scene_to_obj_mapping,
|
47 |
+
device_map="cpu",
|
48 |
) # Huggingface Zero-GPU has to use .to(device) to set the device, otherwise it will fail
|
49 |
|
50 |
model.to("cuda") # Huggingface Zero-GPU requires explicit device placement
|
51 |
|
52 |
+
|
53 |
def get_chatbot_response(user_chat_input, scene_id):
|
54 |
# Get the response from the model
|
55 |
prompt, response = get_model_response(
|
|
|
60 |
user_input=user_chat_input,
|
61 |
max_new_tokens=max_new_tokens,
|
62 |
temperature=0.2,
|
63 |
+
top_p=0.9,
|
64 |
)
|
65 |
return scene_id, prompt, response
|
66 |
|
67 |
+
|
68 |
# def get_chatbot_response(user_chat_input):
|
69 |
# # Get the response from the chatbot
|
70 |
# scene_id = "scene0643_00"
|
|
|
76 |
# """
|
77 |
# return scene_id, scene_graph, response
|
78 |
|
79 |
+
|
80 |
# Resetting to blank
|
81 |
def reset_textbox():
|
82 |
return gr.update(value="")
|
|
|
127 |
return transformation
|
128 |
|
129 |
|
130 |
+
def create_cylinder_mesh(p0, p1, color, radius=0.04, resolution=20, split=1):
|
131 |
"""Create a colored cylinder mesh between two points p0 and p1."""
|
132 |
cylinder = o3d.geometry.TriangleMesh.create_cylinder(
|
133 |
radius=radius, height=1, resolution=resolution, split=split
|
|
|
165 |
center = center.replace("[", "").replace("]", "")
|
166 |
extents = [float(x.strip()) for x in extents.split(",")]
|
167 |
center = [float(x.strip()) for x in center.split(",")]
|
168 |
+
angle = -np.pi / 2 # 90 degrees
|
169 |
+
axis = [1, 0, 0] # Rotate around x-axis
|
170 |
+
R = tf.rotation_matrix(angle, axis)
|
171 |
+
center_homogeneous = np.append(center, 1)
|
172 |
+
extents_homogeneous = np.append(extents, 1)
|
173 |
|
174 |
+
# Apply the rotation to the center and extents
|
175 |
+
rotated_center = np.dot(R, center_homogeneous)[:3]
|
176 |
+
rotated_extents = np.dot(R, extents_homogeneous)[:3]
|
177 |
+
|
178 |
+
sx, sy, sz = rotated_extents
|
179 |
x_corners = [sx / 2, sx / 2, -sx / 2, -sx / 2, sx / 2, sx / 2, -sx / 2, -sx / 2]
|
180 |
y_corners = [sy / 2, -sy / 2, -sy / 2, sy / 2, sy / 2, -sy / 2, -sy / 2, sy / 2]
|
181 |
z_corners = [sz / 2, sz / 2, sz / 2, sz / 2, -sz / 2, -sz / 2, -sz / 2, -sz / 2]
|
182 |
corners_3d = np.vstack([x_corners, y_corners, z_corners])
|
183 |
+
corners_3d[0, :] = corners_3d[0, :] + float(rotated_center[0])
|
184 |
+
corners_3d[1, :] = corners_3d[1, :] + float(rotated_center[1])
|
185 |
+
corners_3d[2, :] = corners_3d[2, :] + float(rotated_center[2])
|
186 |
corners_3d = np.transpose(corners_3d)
|
187 |
|
188 |
lines = [
|
|
|
211 |
centroids_extends_refer,
|
212 |
mesh,
|
213 |
output_dir,
|
214 |
+
output_file_name="highlighted_mesh.obj",
|
215 |
):
|
216 |
print("*" * 50)
|
217 |
# Visualize the highlighted points by drawing 3D bounding boxes overlay on a mesh
|
|
|
228 |
for center, extent in centroids_extents_detailed:
|
229 |
print("center: ", center)
|
230 |
print("extent: ", extent)
|
231 |
+
bbox = create_bbox(
|
232 |
+
center, extent, color=[1, 1, 0]
|
233 |
+
) # yellow color for all boxes
|
234 |
for b in bbox:
|
235 |
combined_mesh += b
|
236 |
|
|
|
239 |
for b in bbox:
|
240 |
combined_mesh += b
|
241 |
|
|
|
242 |
# Save the combined mesh
|
243 |
output_file_path = os.path.join(output_path, output_file_name)
|
244 |
o3d.io.write_triangle_mesh(
|
|
|
272 |
centroids_extents.append((centroid, extent))
|
273 |
return centroids_extents
|
274 |
|
275 |
+
|
276 |
@spaces.GPU
|
277 |
def language_model_forward(
|
278 |
session_state, user_chat_input, top_p, temperature, dropdown_scene
|
|
|
295 |
mesh = o3d.io.read_triangle_mesh(original_model_path)
|
296 |
|
297 |
# get chatbot response
|
298 |
+
scene_id, scene_graph, response = get_chatbot_response(
|
299 |
+
user_chat_input, session_state.scene
|
300 |
+
)
|
301 |
|
302 |
assert scene_id == session_state.scene # Ensure the scene ID matches
|
303 |
|
|
|
337 |
centroids_extents_refer,
|
338 |
mesh,
|
339 |
session_output_dir,
|
340 |
+
output_file_name="highlighted_model.obj",
|
341 |
)
|
342 |
+
|
343 |
# Update the chat history with the response
|
344 |
+
last_turn = session_state.chat_history_for_display[
|
345 |
+
-1
|
346 |
+
] # first is user input, second is assistant response
|
347 |
last_turn = (last_turn[0], response)
|
348 |
session_state.chat_history_for_display[-1] = last_turn
|
349 |
session_state.save() # save the session state
|
|
|
351 |
yield session_state, highlighted_model_path, session_state.chat_history_for_display
|
352 |
|
353 |
|
354 |
+
title = """<h1 align="center">π π¬ 3D-GRAND: Towards Better Grounding and Less Hallucination for 3D-LLMs π</h1>
|
355 |
<p><center>
|
356 |
<a href="https://3d-grand.github.io/" target="_blank">[Project Page]</a>
|
357 |
<a href="https://www.dropbox.com/scl/fo/5p9nb4kalnz407sbqgemg/AG1KcxeIS_SUoJ1hoLPzv84?rlkey=weunabtbiz17jitfv3f4jpmm1&dl=0" target="_blank">[3D-GRAND Data]</a>
|
|
|
366 |
|
367 |
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
368 |
session_state = gr.State(Session.create)
|
369 |
+
|
370 |
gr.HTML(title)
|
371 |
|
372 |
with gr.Column():
|
|
|
410 |
)
|
411 |
gr.HTML(
|
412 |
"""<center><strong>
|
413 |
+
<div style="display:inline-block; color:green">■</div> = Chosen Target
|
414 |
+
<div style="display:inline-block; color:yellow">■</div> = Landmarks
|
415 |
</strong></center>
|
416 |
"""
|
417 |
)
|
|
|
438 |
gr.Examples(
|
439 |
examples=[
|
440 |
["The TV on the drawer, opposing the bed."],
|
441 |
+
["the desk next to the window"],
|
442 |
],
|
443 |
inputs=user_chat_input,
|
444 |
)
|
|
|
471 |
dropdown_scene.change(
|
472 |
fn=change_scene_or_system_prompt,
|
473 |
inputs=[dropdown_scene],
|
474 |
+
outputs=[
|
475 |
+
session_state,
|
476 |
+
model_3d,
|
477 |
+
model_3d_grounding_result,
|
478 |
+
chat_history_for_display,
|
479 |
+
],
|
480 |
)
|
481 |
clear_button.click(
|
482 |
fn=change_scene_or_system_prompt,
|
483 |
inputs=[dropdown_scene],
|
484 |
+
outputs=[
|
485 |
+
session_state,
|
486 |
+
model_3d,
|
487 |
+
model_3d_grounding_result,
|
488 |
+
chat_history_for_display,
|
489 |
+
],
|
490 |
)
|
491 |
user_chat_input.submit(
|
492 |
fn=language_model_forward,
|
convert_mesh.ipynb
CHANGED
@@ -7,11 +7,28 @@
|
|
7 |
"outputs": [],
|
8 |
"source": [
|
9 |
"import trimesh\n",
|
|
|
|
|
10 |
"\n",
|
11 |
-
"
|
|
|
12 |
" # Load the PLY file\n",
|
13 |
" mesh = trimesh.load(ply_file)\n",
|
14 |
"\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
" # Export the mesh to the specified format\n",
|
16 |
" mesh.export(output_file)\n",
|
17 |
" print(f\"Converted {ply_file} to {output_file}\")"
|
@@ -103,7 +120,7 @@
|
|
103 |
"name": "python",
|
104 |
"nbconvert_exporter": "python",
|
105 |
"pygments_lexer": "ipython3",
|
106 |
-
"version": "3.10.
|
107 |
}
|
108 |
},
|
109 |
"nbformat": 4,
|
|
|
7 |
"outputs": [],
|
8 |
"source": [
|
9 |
"import trimesh\n",
|
10 |
+
"import numpy as np\n",
|
11 |
+
"import trimesh.transformations as tf\n",
|
12 |
"\n",
|
13 |
+
"# adjust bright factor to increase or decrease the brightness of the colors\n",
|
14 |
+
"def convert_ply_to_format(ply_file, output_file, bright_factor=1.5):\n",
|
15 |
" # Load the PLY file\n",
|
16 |
" mesh = trimesh.load(ply_file)\n",
|
17 |
"\n",
|
18 |
+
" # Define the rotation matrix to swap y and z axes\n",
|
19 |
+
" angle = -np.pi / 2 # 90 degrees\n",
|
20 |
+
" axis = [1, 0, 0] # Rotate around x-axis\n",
|
21 |
+
" R = tf.rotation_matrix(angle, axis)\n",
|
22 |
+
"\n",
|
23 |
+
" # Apply the rotation to the mesh\n",
|
24 |
+
" mesh.apply_transform(R)\n",
|
25 |
+
" \n",
|
26 |
+
" # Adjust the brightness of vertex colors if they exist\n",
|
27 |
+
" if mesh.visual.kind == 'vertex' and mesh.visual.vertex_colors is not None:\n",
|
28 |
+
" vertex_colors = np.asarray(mesh.visual.vertex_colors)[:, :3] # Ignore alpha channel if present\n",
|
29 |
+
" brightened_colors = np.clip(vertex_colors * bright_factor, 0, 255).astype(np.uint8)\n",
|
30 |
+
" mesh.visual.vertex_colors = brightened_colors\n",
|
31 |
+
"\n",
|
32 |
" # Export the mesh to the specified format\n",
|
33 |
" mesh.export(output_file)\n",
|
34 |
" print(f\"Converted {ply_file} to {output_file}\")"
|
|
|
120 |
"name": "python",
|
121 |
"nbconvert_exporter": "python",
|
122 |
"pygments_lexer": "ipython3",
|
123 |
+
"version": "3.10.14"
|
124 |
}
|
125 |
},
|
126 |
"nbformat": 4,
|
data/scene0025_00/scene0025_00.obj
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
-
size
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:eb45f524155df059915b0f386f493a18b6e9564571a480121572734770ff6b78
|
3 |
+
size 18951552
|
data/scene0426_00/scene0426_00.obj
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
-
size
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:3c8562b2bb6c62350e234930ecc118d38a09ccc4502c2680c0ee76e0a49a8223
|
3 |
+
size 14661106
|
data/scene0643_00/scene0643_00.obj
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
-
size
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:ce4f34b6e98523533fa20c7b4aa018d7b71dde857b6ea8c3f03541e10eaa32fa
|
3 |
+
size 18165757
|
requirements.txt
CHANGED
@@ -16,4 +16,5 @@ open3d
|
|
16 |
bs4
|
17 |
attrs
|
18 |
cattrs
|
|
|
19 |
|
|
|
16 |
bs4
|
17 |
attrs
|
18 |
cattrs
|
19 |
+
trimesh
|
20 |
|