TakashiKAWAMOTO-TTS commited on
Commit
ac2392f
·
1 Parent(s): 2e34547

meshing using ball pivoting

Browse files
Files changed (1) hide show
  1. app.py +84 -4
app.py CHANGED
@@ -3,6 +3,7 @@ import open3d as o3d
3
  import numpy as np
4
  import matplotlib.pyplot as plt
5
  import tempfile
 
6
  import os
7
 
8
  from types import SimpleNamespace
@@ -48,17 +49,96 @@ iface = gr.Interface(
48
  description="Upload a .ply, .pcd, or .xyz file. The app will downsample and render it."
49
  )
50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  if __name__ == "__main__":
52
  if DEBUG:
53
- test_file_path = "./samples/bunny.ply"
54
  with open(test_file_path, "rb") as f:
55
  dummy = SimpleNamespace()
56
  dummy.name = os.path.basename(test_file_path)
 
57
  dummy.read = lambda: f.read()
58
- result_img = process_point_cloud(dummy)
59
- process_point_cloud(dummy)
60
  out_path = os.path.join("temporal", "debug_render.png")
61
  plt.imsave(out_path, result_img)
62
  print(f"[DEBUG] Rendered image saved at: {out_path}")
63
  else:
64
- iface.launch()
 
 
3
  import numpy as np
4
  import matplotlib.pyplot as plt
5
  import tempfile
6
+ import traceback
7
  import os
8
 
9
  from types import SimpleNamespace
 
49
  description="Upload a .ply, .pcd, or .xyz file. The app will downsample and render it."
50
  )
51
 
52
+ def check_delimiter(file_path):
53
+ with open(file_path, "r") as f:
54
+ line = f.readline()
55
+ if "," in line:
56
+ return ","
57
+ elif "\t" in line:
58
+ return "\t"
59
+ else:
60
+ return " "
61
+
62
+ def meshing(file_obj):
63
+ try:
64
+ if DEBUG:
65
+ temp_path = os.path.join(file_obj.dir, file_obj.name)
66
+ ext = os.path.splitext(temp_path)[1].lower()
67
+ else:
68
+ temp_path = file_obj.name
69
+ ext = os.path.splitext(temp_path)[1].lower()
70
+
71
+ # Load the input point cloud
72
+ if ext == ".txt":
73
+ delimiter = check_delimiter(temp_path)
74
+ points = np.loadtxt(temp_path, delimiter=delimiter)
75
+ if points.shape[1] != 3:
76
+ raise ValueError("Text file must contain 3 columns (X Y Z)")
77
+ pcd = o3d.geometry.PointCloud()
78
+ pcd.points = o3d.utility.Vector3dVector(points)
79
+ else:
80
+ pcd = o3d.io.read_point_cloud(temp_path)
81
+
82
+ dists = pcd.compute_nearest_neighbor_distance()
83
+ avg_spacing = np.mean(dists)
84
+ normal_radius = avg_spacing*5.0 #2.0 # start with 2–3x spacing
85
+ pcd.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=normal_radius, max_nn=100)) #30))
86
+ pcd.orient_normals_consistent_tangent_plane(k=100) #30)
87
+
88
+ # Mesh using Ball Pivoting
89
+ mesh_radii = [avg_spacing * x for x in [3, 4, 5, 6]] #[1.5, 2.5, 3.5]]
90
+ mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_ball_pivoting(pcd, o3d.utility.DoubleVector(mesh_radii))
91
+
92
+ # Mesh using Poisson
93
+ # mesh, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(pcd, depth=9)
94
+
95
+ # Export as OBJ
96
+ mesh_output_path = os.path.join(tempfile.gettempdir(), "mesh_output.obj")
97
+ o3d.io.write_triangle_mesh(mesh_output_path, mesh, write_ascii=True)
98
+
99
+ # Render image preview
100
+ verts = np.asarray(mesh.vertices)
101
+ tris = np.asarray(mesh.triangles)
102
+ fig = plt.figure(figsize=(6, 6))
103
+ ax = fig.add_subplot(111, projection='3d')
104
+ ax.plot_trisurf(verts[:, 0], verts[:, 1], verts[:, 2], triangles=tris, color='lightblue', edgecolor='gray', linewidth=0.1)
105
+ ax.axis('off')
106
+ plt.tight_layout()
107
+ image_path = os.path.join(tempfile.gettempdir(), "mesh_render.png")
108
+ plt.savefig(image_path, dpi=150)
109
+ plt.close()
110
+ img_np = plt.imread(image_path)
111
+
112
+ return img_np, mesh_output_path
113
+
114
+ except Exception as e:
115
+ traceback.print_exc()
116
+ return np.zeros((200, 400, 3), dtype=np.uint8), None
117
+
118
+ iface_mesh = gr.Interface(
119
+ fn=meshing,
120
+ inputs=gr.File(file_types=[".txt", ".ply", ".pcd"], label="Upload Point Cloud"),
121
+ outputs=[
122
+ gr.Image(type="numpy", label="Mesh Preview"),
123
+ gr.File(label="Download Mesh (STL)")
124
+ ],
125
+ title="Point Cloud Meshing to STL",
126
+ description="Upload a point cloud (.txt, .ply, .pcd). The app creates a triangle mesh and exports it as an STL file."
127
+ )
128
+
129
  if __name__ == "__main__":
130
  if DEBUG:
131
+ test_file_path = "./samples/Panel_pca_by20_space.txt"
132
  with open(test_file_path, "rb") as f:
133
  dummy = SimpleNamespace()
134
  dummy.name = os.path.basename(test_file_path)
135
+ dummy.dir = os.path.dirname(test_file_path)
136
  dummy.read = lambda: f.read()
137
+ # result_img = process_point_cloud(dummy)
138
+ result_img, result_mesh = meshing(dummy)
139
  out_path = os.path.join("temporal", "debug_render.png")
140
  plt.imsave(out_path, result_img)
141
  print(f"[DEBUG] Rendered image saved at: {out_path}")
142
  else:
143
+ # iface.launch()
144
+ iface_mesh.launch()