Spaces:
Runtime error
Runtime error
fixes
Browse files- app.py +7 -2
- gradio_cached_examples/23/3D Model GIF/pointcloudcb15136570dba10312c5ed2976c55c6e5c7903f9opvwj32a.mp4 +0 -0
- gradio_cached_examples/23/3D Model GIF/pointcloudeed5baa5cdb39407318886f10f2fb96294f7394cp5ikcutv.mp4 +0 -0
- gradio_cached_examples/23/component 0/mesh-7259c79c-b649-4624-b8f8-bbf3b14f83cd953e9b1e5f740a28854cfc36438f0aff107b6445hxmr3f9j.ply +0 -0
- gradio_cached_examples/23/component 0/mesh-df8501bb-16fa-4466-9c0d-18409527fdd2ad7655a800cfbeee95686246fb97c498a43a20d1k_ba3j63.ply +0 -0
- gradio_cached_examples/23/log.csv +3 -0
- pc.py +174 -0
app.py
CHANGED
@@ -119,7 +119,10 @@ def generate_3D(input, model_name='base1B', guidance_scale=3.0, grid_size=128):
|
|
119 |
set_state('Converting to mesh...')
|
120 |
|
121 |
uniqid = uuid.uuid4()
|
122 |
-
file_path = f
|
|
|
|
|
|
|
123 |
save_ply(pc, file_path)
|
124 |
|
125 |
set_state('')
|
@@ -152,8 +155,10 @@ def ply_to_glb(ply_file, glb_file):
|
|
152 |
|
153 |
def save_ply(pc, file_name):
|
154 |
# Produce a mesh (with vertex colors)
|
|
|
155 |
with open(file_name, 'wb') as f:
|
156 |
-
|
|
|
157 |
|
158 |
|
159 |
def create_gif(pc):
|
|
|
119 |
set_state('Converting to mesh...')
|
120 |
|
121 |
uniqid = uuid.uuid4()
|
122 |
+
file_path = f"/tmp/mesh-{uniqid}.npy"
|
123 |
+
|
124 |
+
print('file_path', file_path)
|
125 |
+
|
126 |
save_ply(pc, file_path)
|
127 |
|
128 |
set_state('')
|
|
|
155 |
|
156 |
def save_ply(pc, file_name):
|
157 |
# Produce a mesh (with vertex colors)
|
158 |
+
print('file_name', file_name)
|
159 |
with open(file_name, 'wb') as f:
|
160 |
+
print('file_name', f)
|
161 |
+
pc.save(f)
|
162 |
|
163 |
|
164 |
def create_gif(pc):
|
gradio_cached_examples/23/3D Model GIF/pointcloudcb15136570dba10312c5ed2976c55c6e5c7903f9opvwj32a.mp4
ADDED
Binary file (36.5 kB). View file
|
|
gradio_cached_examples/23/3D Model GIF/pointcloudeed5baa5cdb39407318886f10f2fb96294f7394cp5ikcutv.mp4
ADDED
Binary file (69.1 kB). View file
|
|
gradio_cached_examples/23/component 0/mesh-7259c79c-b649-4624-b8f8-bbf3b14f83cd953e9b1e5f740a28854cfc36438f0aff107b6445hxmr3f9j.ply
ADDED
Binary file (61.6 kB). View file
|
|
gradio_cached_examples/23/component 0/mesh-df8501bb-16fa-4466-9c0d-18409527fdd2ad7655a800cfbeee95686246fb97c498a43a20d1k_ba3j63.ply
ADDED
Binary file (61.6 kB). View file
|
|
gradio_cached_examples/23/log.csv
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
component 0,3D Model GIF,Files,flag,username,timestamp
|
2 |
+
/home/ubuntu/projects/point-e/gradio_cached_examples/23/component 0/mesh-7259c79c-b649-4624-b8f8-bbf3b14f83cd953e9b1e5f740a28854cfc36438f0aff107b6445hxmr3f9j.ply,/home/ubuntu/projects/point-e/gradio_cached_examples/23/3D Model GIF/pointcloudcb15136570dba10312c5ed2976c55c6e5c7903f9opvwj32a.mp4,"{'visible': True, 'value': [{'orig_name': 'mesh-7259c79c-b649-4624-b8f8-bbf3b14f83cd.ply', 'name': '/tmp/mesh-7259c79c-b649-4624-b8f8-bbf3b14f83cd953e9b1e5f740a28854cfc36438f0aff107b6445.ply', 'size': 61618, 'data': None, 'is_file': True}], '__type__': 'update'}",,,2023-01-15 14:43:34.639847
|
3 |
+
/home/ubuntu/projects/point-e/gradio_cached_examples/23/component 0/mesh-df8501bb-16fa-4466-9c0d-18409527fdd2ad7655a800cfbeee95686246fb97c498a43a20d1k_ba3j63.ply,/home/ubuntu/projects/point-e/gradio_cached_examples/23/3D Model GIF/pointcloudeed5baa5cdb39407318886f10f2fb96294f7394cp5ikcutv.mp4,"{'visible': True, 'value': [{'orig_name': 'mesh-df8501bb-16fa-4466-9c0d-18409527fdd2.ply', 'name': '/tmp/mesh-df8501bb-16fa-4466-9c0d-18409527fdd2ad7655a800cfbeee95686246fb97c498a43a20d1.ply', 'size': 61618, 'data': None, 'is_file': True}], '__type__': 'update'}",,,2023-01-15 14:45:23.412352
|
pc.py
ADDED
@@ -0,0 +1,174 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import random
|
2 |
+
from dataclasses import dataclass
|
3 |
+
from typing import BinaryIO, Dict, List, Optional, Union
|
4 |
+
|
5 |
+
import numpy as np
|
6 |
+
|
7 |
+
from .ply_util import write_ply
|
8 |
+
|
9 |
+
COLORS = frozenset(["R", "G", "B", "A"])
|
10 |
+
|
11 |
+
|
12 |
+
def preprocess(data, channel):
|
13 |
+
if channel in COLORS:
|
14 |
+
return np.round(data * 255.0)
|
15 |
+
return data
|
16 |
+
|
17 |
+
|
18 |
+
@dataclass
|
19 |
+
class PointCloud:
|
20 |
+
"""
|
21 |
+
An array of points sampled on a surface. Each point may have zero or more
|
22 |
+
channel attributes.
|
23 |
+
|
24 |
+
:param coords: an [N x 3] array of point coordinates.
|
25 |
+
:param channels: a dict mapping names to [N] arrays of channel values.
|
26 |
+
"""
|
27 |
+
|
28 |
+
coords: np.ndarray
|
29 |
+
channels: Dict[str, np.ndarray]
|
30 |
+
|
31 |
+
@classmethod
|
32 |
+
def load(cls, f: Union[str, BinaryIO]) -> "PointCloud":
|
33 |
+
"""
|
34 |
+
Load the point cloud from a .npz file.
|
35 |
+
"""
|
36 |
+
if isinstance(f, str):
|
37 |
+
with open(f, "rb") as reader:
|
38 |
+
return cls.load(reader)
|
39 |
+
else:
|
40 |
+
obj = np.load(f)
|
41 |
+
keys = list(obj.keys())
|
42 |
+
return PointCloud(
|
43 |
+
coords=obj["coords"],
|
44 |
+
channels={k: obj[k] for k in keys if k != "coords"},
|
45 |
+
)
|
46 |
+
|
47 |
+
def save(self, f: Union[str, BinaryIO]):
|
48 |
+
"""
|
49 |
+
Save the point cloud to a .npz file.
|
50 |
+
"""
|
51 |
+
if isinstance(f, str):
|
52 |
+
with open(f, "wb") as writer:
|
53 |
+
self.save(writer)
|
54 |
+
else:
|
55 |
+
np.save(f, self.coords)
|
56 |
+
|
57 |
+
def write_ply(self, raw_f: BinaryIO):
|
58 |
+
write_ply(
|
59 |
+
raw_f,
|
60 |
+
coords=self.coords,
|
61 |
+
rgb=(
|
62 |
+
np.stack([self.channels[x] for x in "RGB"], axis=1)
|
63 |
+
if all(x in self.channels for x in "RGB")
|
64 |
+
else None
|
65 |
+
),
|
66 |
+
)
|
67 |
+
|
68 |
+
def random_sample(self, num_points: int, **subsample_kwargs) -> "PointCloud":
|
69 |
+
"""
|
70 |
+
Sample a random subset of this PointCloud.
|
71 |
+
|
72 |
+
:param num_points: maximum number of points to sample.
|
73 |
+
:param subsample_kwargs: arguments to self.subsample().
|
74 |
+
:return: a reduced PointCloud, or self if num_points is not less than
|
75 |
+
the current number of points.
|
76 |
+
"""
|
77 |
+
if len(self.coords) <= num_points:
|
78 |
+
return self
|
79 |
+
indices = np.random.choice(len(self.coords), size=(num_points,), replace=False)
|
80 |
+
return self.subsample(indices, **subsample_kwargs)
|
81 |
+
|
82 |
+
def farthest_point_sample(
|
83 |
+
self, num_points: int, init_idx: Optional[int] = None, **subsample_kwargs
|
84 |
+
) -> "PointCloud":
|
85 |
+
"""
|
86 |
+
Sample a subset of the point cloud that is evenly distributed in space.
|
87 |
+
|
88 |
+
First, a random point is selected. Then each successive point is chosen
|
89 |
+
such that it is furthest from the currently selected points.
|
90 |
+
|
91 |
+
The time complexity of this operation is O(NM), where N is the original
|
92 |
+
number of points and M is the reduced number. Therefore, performance
|
93 |
+
can be improved by randomly subsampling points with random_sample()
|
94 |
+
before running farthest_point_sample().
|
95 |
+
|
96 |
+
:param num_points: maximum number of points to sample.
|
97 |
+
:param init_idx: if specified, the first point to sample.
|
98 |
+
:param subsample_kwargs: arguments to self.subsample().
|
99 |
+
:return: a reduced PointCloud, or self if num_points is not less than
|
100 |
+
the current number of points.
|
101 |
+
"""
|
102 |
+
if len(self.coords) <= num_points:
|
103 |
+
return self
|
104 |
+
init_idx = random.randrange(len(self.coords)) if init_idx is None else init_idx
|
105 |
+
indices = np.zeros([num_points], dtype=np.int64)
|
106 |
+
indices[0] = init_idx
|
107 |
+
sq_norms = np.sum(self.coords**2, axis=-1)
|
108 |
+
|
109 |
+
def compute_dists(idx: int):
|
110 |
+
# Utilize equality: ||A-B||^2 = ||A||^2 + ||B||^2 - 2*(A @ B).
|
111 |
+
return sq_norms + sq_norms[idx] - 2 * (self.coords @ self.coords[idx])
|
112 |
+
|
113 |
+
cur_dists = compute_dists(init_idx)
|
114 |
+
for i in range(1, num_points):
|
115 |
+
idx = np.argmax(cur_dists)
|
116 |
+
indices[i] = idx
|
117 |
+
cur_dists = np.minimum(cur_dists, compute_dists(idx))
|
118 |
+
return self.subsample(indices, **subsample_kwargs)
|
119 |
+
|
120 |
+
def subsample(self, indices: np.ndarray, average_neighbors: bool = False) -> "PointCloud":
|
121 |
+
if not average_neighbors:
|
122 |
+
return PointCloud(
|
123 |
+
coords=self.coords[indices],
|
124 |
+
channels={k: v[indices] for k, v in self.channels.items()},
|
125 |
+
)
|
126 |
+
|
127 |
+
new_coords = self.coords[indices]
|
128 |
+
neighbor_indices = PointCloud(coords=new_coords, channels={}).nearest_points(self.coords)
|
129 |
+
|
130 |
+
# Make sure every point points to itself, which might not
|
131 |
+
# be the case if points are duplicated or there is rounding
|
132 |
+
# error.
|
133 |
+
neighbor_indices[indices] = np.arange(len(indices))
|
134 |
+
|
135 |
+
new_channels = {}
|
136 |
+
for k, v in self.channels.items():
|
137 |
+
v_sum = np.zeros_like(v[: len(indices)])
|
138 |
+
v_count = np.zeros_like(v[: len(indices)])
|
139 |
+
np.add.at(v_sum, neighbor_indices, v)
|
140 |
+
np.add.at(v_count, neighbor_indices, 1)
|
141 |
+
new_channels[k] = v_sum / v_count
|
142 |
+
return PointCloud(coords=new_coords, channels=new_channels)
|
143 |
+
|
144 |
+
def select_channels(self, channel_names: List[str]) -> np.ndarray:
|
145 |
+
data = np.stack([preprocess(self.channels[name], name) for name in channel_names], axis=-1)
|
146 |
+
return data
|
147 |
+
|
148 |
+
def nearest_points(self, points: np.ndarray, batch_size: int = 16384) -> np.ndarray:
|
149 |
+
"""
|
150 |
+
For each point in another set of points, compute the point in this
|
151 |
+
pointcloud which is closest.
|
152 |
+
|
153 |
+
:param points: an [N x 3] array of points.
|
154 |
+
:param batch_size: the number of neighbor distances to compute at once.
|
155 |
+
Smaller values save memory, while larger values may
|
156 |
+
make the computation faster.
|
157 |
+
:return: an [N] array of indices into self.coords.
|
158 |
+
"""
|
159 |
+
norms = np.sum(self.coords**2, axis=-1)
|
160 |
+
all_indices = []
|
161 |
+
for i in range(0, len(points), batch_size):
|
162 |
+
batch = points[i : i + batch_size]
|
163 |
+
dists = norms + np.sum(batch**2, axis=-1)[:, None] - 2 * (batch @ self.coords.T)
|
164 |
+
all_indices.append(np.argmin(dists, axis=-1))
|
165 |
+
return np.concatenate(all_indices, axis=0)
|
166 |
+
|
167 |
+
def combine(self, other: "PointCloud") -> "PointCloud":
|
168 |
+
assert self.channels.keys() == other.channels.keys()
|
169 |
+
return PointCloud(
|
170 |
+
coords=np.concatenate([self.coords, other.coords], axis=0),
|
171 |
+
channels={
|
172 |
+
k: np.concatenate([v, other.channels[k]], axis=0) for k, v in self.channels.items()
|
173 |
+
},
|
174 |
+
)
|