q3dviewer 1.1.0__py3-none-any.whl → 1.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- q3dviewer/base_glwidget.py +10 -1
- q3dviewer/basic_window.py +228 -0
- q3dviewer/cloud_viewer.py +74 -0
- q3dviewer/custom_items/camera_frame_item.py +173 -0
- q3dviewer/custom_items/cloud_item.py +1 -0
- q3dviewer/custom_items/trajectory_item.py +79 -0
- q3dviewer/gau_io.py +168 -0
- q3dviewer/tools/film_maker.py +2 -2
- q3dviewer/utils.py +71 -0
- {q3dviewer-1.1.0.dist-info → q3dviewer-1.1.1.dist-info}/METADATA +12 -9
- {q3dviewer-1.1.0.dist-info → q3dviewer-1.1.1.dist-info}/RECORD +15 -13
- {q3dviewer-1.1.0.dist-info → q3dviewer-1.1.1.dist-info}/entry_points.txt +1 -0
- q3dviewer/test/test_interpolation.py +0 -58
- q3dviewer/test/test_rendering.py +0 -72
- q3dviewer/tools/cinematographer.py +0 -367
- {q3dviewer-1.1.0.dist-info → q3dviewer-1.1.1.dist-info}/LICENSE +0 -0
- {q3dviewer-1.1.0.dist-info → q3dviewer-1.1.1.dist-info}/WHEEL +0 -0
- {q3dviewer-1.1.0.dist-info → q3dviewer-1.1.1.dist-info}/top_level.txt +0 -0
q3dviewer/gau_io.py
CHANGED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from plyfile import PlyData
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def gsdata_type(sh_dim):
|
|
6
|
+
return [('pw', '<f4', (3,)),
|
|
7
|
+
('rot', '<f4', (4,)),
|
|
8
|
+
('scale', '<f4', (3,)),
|
|
9
|
+
('alpha', '<f4'),
|
|
10
|
+
('sh', '<f4', (sh_dim))]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def matrix_to_quaternion(matrices):
|
|
14
|
+
m00, m01, m02 = matrices[:, 0, 0], matrices[:, 0, 1], matrices[:, 0, 2]
|
|
15
|
+
m10, m11, m12 = matrices[:, 1, 0], matrices[:, 1, 1], matrices[:, 1, 2]
|
|
16
|
+
m20, m21, m22 = matrices[:, 2, 0], matrices[:, 2, 1], matrices[:, 2, 2]
|
|
17
|
+
t = 1 + m00 + m11 + m22
|
|
18
|
+
s = np.ones_like(m00)
|
|
19
|
+
w = np.ones_like(m00)
|
|
20
|
+
x = np.ones_like(m00)
|
|
21
|
+
y = np.ones_like(m00)
|
|
22
|
+
z = np.ones_like(m00)
|
|
23
|
+
|
|
24
|
+
t_positive = t > 0.0000001
|
|
25
|
+
s[t_positive] = 0.5 / np.sqrt(t[t_positive])
|
|
26
|
+
w[t_positive] = 0.25 / s[t_positive]
|
|
27
|
+
x[t_positive] = (m21[t_positive] - m12[t_positive]) * s[t_positive]
|
|
28
|
+
y[t_positive] = (m02[t_positive] - m20[t_positive]) * s[t_positive]
|
|
29
|
+
z[t_positive] = (m10[t_positive] - m01[t_positive]) * s[t_positive]
|
|
30
|
+
|
|
31
|
+
c1 = np.logical_and(m00 > m11, m00 > m22)
|
|
32
|
+
cond1 = np.logical_and(np.logical_not(t_positive), np.logical_and(m00 > m11, m00 > m22))
|
|
33
|
+
|
|
34
|
+
s[cond1] = 2.0 * np.sqrt(1.0 + m00[cond1] - m11[cond1] - m22[cond1])
|
|
35
|
+
w[cond1] = (m21[cond1] - m12[cond1]) / s[cond1]
|
|
36
|
+
x[cond1] = 0.25 * s[cond1]
|
|
37
|
+
y[cond1] = (m01[cond1] + m10[cond1]) / s[cond1]
|
|
38
|
+
z[cond1] = (m02[cond1] + m20[cond1]) / s[cond1]
|
|
39
|
+
|
|
40
|
+
c2 = np.logical_and(np.logical_not(c1), m11 > m22)
|
|
41
|
+
cond2 = np.logical_and(np.logical_not(t_positive), c2)
|
|
42
|
+
s[cond2] = 2.0 * np.sqrt(1.0 + m11[cond2] - m00[cond2] - m22[cond2])
|
|
43
|
+
w[cond2] = (m02[cond2] - m20[cond2]) / s[cond2]
|
|
44
|
+
x[cond2] = (m01[cond2] + m10[cond2]) / s[cond2]
|
|
45
|
+
y[cond2] = 0.25 * s[cond2]
|
|
46
|
+
z[cond2] = (m12[cond2] + m21[cond2]) / s[cond2]
|
|
47
|
+
|
|
48
|
+
c3 = np.logical_and(np.logical_not(c1), np.logical_not(c2))
|
|
49
|
+
cond3 = np.logical_and(np.logical_not(t_positive), c3)
|
|
50
|
+
s[cond3] = 2.0 * np.sqrt(1.0 + m22[cond3] - m00[cond3] - m11[cond3])
|
|
51
|
+
w[cond3] = (m10[cond3] - m01[cond3]) / s[cond3]
|
|
52
|
+
x[cond3] = (m02[cond3] + m20[cond3]) / s[cond3]
|
|
53
|
+
y[cond3] = (m12[cond3] + m21[cond3]) / s[cond3]
|
|
54
|
+
z[cond3] = 0.25 * s[cond3]
|
|
55
|
+
return np.array([w, x, y, z]).T
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def load_ply(path, T=None):
|
|
59
|
+
plydata = PlyData.read(path)
|
|
60
|
+
pws = np.stack((np.asarray(plydata.elements[0]["x"]),
|
|
61
|
+
np.asarray(plydata.elements[0]["y"]),
|
|
62
|
+
np.asarray(plydata.elements[0]["z"])), axis=1)
|
|
63
|
+
|
|
64
|
+
alphas = np.asarray(plydata.elements[0]["opacity"])
|
|
65
|
+
alphas = 1/(1 + np.exp(-alphas))
|
|
66
|
+
|
|
67
|
+
scales = np.stack((np.asarray(plydata.elements[0]["scale_0"]),
|
|
68
|
+
np.asarray(plydata.elements[0]["scale_1"]),
|
|
69
|
+
np.asarray(plydata.elements[0]["scale_2"])), axis=1)
|
|
70
|
+
|
|
71
|
+
rots = np.stack((np.asarray(plydata.elements[0]["rot_0"]),
|
|
72
|
+
np.asarray(plydata.elements[0]["rot_1"]),
|
|
73
|
+
np.asarray(plydata.elements[0]["rot_2"]),
|
|
74
|
+
np.asarray(plydata.elements[0]["rot_3"])), axis=1)
|
|
75
|
+
|
|
76
|
+
rots /= np.linalg.norm(rots, axis=1)[:, np.newaxis]
|
|
77
|
+
|
|
78
|
+
sh_dim = len(plydata.elements[0][0])-14
|
|
79
|
+
shs = np.zeros([pws.shape[0], sh_dim])
|
|
80
|
+
shs[:, 0] = np.asarray(plydata.elements[0]["f_dc_0"])
|
|
81
|
+
shs[:, 1] = np.asarray(plydata.elements[0]["f_dc_1"])
|
|
82
|
+
shs[:, 2] = np.asarray(plydata.elements[0]["f_dc_2"])
|
|
83
|
+
|
|
84
|
+
sh_rest_dim = sh_dim - 3
|
|
85
|
+
for i in range(sh_rest_dim):
|
|
86
|
+
name = "f_rest_%d" % i
|
|
87
|
+
shs[:, 3 + i] = np.asarray(plydata.elements[0][name])
|
|
88
|
+
|
|
89
|
+
shs[:, 3:] = shs[:, 3:].reshape(-1, 3, sh_rest_dim//3).transpose([0, 2, 1]).reshape(-1, sh_rest_dim)
|
|
90
|
+
|
|
91
|
+
pws = pws.astype(np.float32)
|
|
92
|
+
rots = rots.astype(np.float32)
|
|
93
|
+
scales = np.exp(scales)
|
|
94
|
+
scales = scales.astype(np.float32)
|
|
95
|
+
alphas = alphas.astype(np.float32)
|
|
96
|
+
shs = shs.astype(np.float32)
|
|
97
|
+
|
|
98
|
+
dtypes = gsdata_type(sh_dim)
|
|
99
|
+
|
|
100
|
+
gs = np.rec.fromarrays(
|
|
101
|
+
[pws, rots, scales, alphas, shs], dtype=dtypes)
|
|
102
|
+
|
|
103
|
+
return gs
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def rotate_gaussian(T, gs):
|
|
107
|
+
# Transform to world
|
|
108
|
+
pws = (T @ gs['pw'].T).T
|
|
109
|
+
w = gs['rot'][:, 0]
|
|
110
|
+
x = gs['rot'][:, 1]
|
|
111
|
+
y = gs['rot'][:, 2]
|
|
112
|
+
z = gs['rot'][:, 3]
|
|
113
|
+
R = np.array([
|
|
114
|
+
[1.0 - 2*(y**2 + z**2), 2*(x*y - z*w), 2*(x * z + y * w)],
|
|
115
|
+
[2*(x*y + z*w), 1.0 - 2*(x**2 + z**2), 2*(y*z - x*w)],
|
|
116
|
+
[2*(x*z - y*w), 2*(y*z + x*w), 1.0 - 2*(x**2 + y**2)]
|
|
117
|
+
]).transpose(2, 0, 1)
|
|
118
|
+
R_new = T @ R
|
|
119
|
+
rots = matrix_to_quaternion(R_new)
|
|
120
|
+
gs['pw'] = pws
|
|
121
|
+
gs['rot'] = rots
|
|
122
|
+
return gs
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def load_gs(fn):
|
|
126
|
+
if fn.endswith('.ply'):
|
|
127
|
+
return load_ply(fn)
|
|
128
|
+
elif fn.endswith('.npy'):
|
|
129
|
+
return np.load(fn)
|
|
130
|
+
else:
|
|
131
|
+
print("%s is not a supported file." % fn)
|
|
132
|
+
exit(0)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def save_gs(fn, gs):
|
|
136
|
+
np.save(fn, gs)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def get_example_gs():
|
|
140
|
+
gs_data = np.array([[0., 0., 0., # xyz
|
|
141
|
+
1., 0., 0., 0., # rot
|
|
142
|
+
0.05, 0.05, 0.05, # size
|
|
143
|
+
1.,
|
|
144
|
+
1.772484, -1.772484, 1.772484],
|
|
145
|
+
[1., 0., 0.,
|
|
146
|
+
1., 0., 0., 0.,
|
|
147
|
+
0.2, 0.05, 0.05,
|
|
148
|
+
1.,
|
|
149
|
+
1.772484, -1.772484, -1.772484],
|
|
150
|
+
[0., 1., 0.,
|
|
151
|
+
1., 0., 0., 0.,
|
|
152
|
+
0.05, 0.2, 0.05,
|
|
153
|
+
1.,
|
|
154
|
+
-1.772484, 1.772484, -1.772484],
|
|
155
|
+
[0., 0., 1.,
|
|
156
|
+
1., 0., 0., 0.,
|
|
157
|
+
0.05, 0.05, 0.2,
|
|
158
|
+
1.,
|
|
159
|
+
-1.772484, -1.772484, 1.772484]
|
|
160
|
+
], dtype=np.float32)
|
|
161
|
+
dtypes = gsdata_type(3)
|
|
162
|
+
gs = np.frombuffer(gs_data.tobytes(), dtype=dtypes)
|
|
163
|
+
return gs
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
if __name__ == "__main__":
|
|
167
|
+
gs = load_gs("/home/liu/workspace/EasyGaussianSplatting/data/final.npy")
|
|
168
|
+
print(gs.shape)
|
q3dviewer/tools/film_maker.py
CHANGED
|
@@ -269,8 +269,8 @@ class CMMViewer(q3d.Viewer):
|
|
|
269
269
|
self.current_frame_index = 0
|
|
270
270
|
self.timer.start(self.update_interval) # Adjust the interval as needed
|
|
271
271
|
self.is_playing = True
|
|
272
|
-
self.play_button.setStyleSheet("")
|
|
273
|
-
self.play_button.setText("
|
|
272
|
+
self.play_button.setStyleSheet("background-color: red")
|
|
273
|
+
self.play_button.setText("Playing")
|
|
274
274
|
self.record_checkbox.setEnabled(False)
|
|
275
275
|
if self.is_recording is True:
|
|
276
276
|
self.start_recording()
|
q3dviewer/utils.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def matrix_to_quaternion(matrix):
|
|
6
|
+
trace = matrix[0, 0] + matrix[1, 1] + matrix[2, 2]
|
|
7
|
+
if trace > 0:
|
|
8
|
+
s = 0.5 / np.sqrt(trace + 1.0)
|
|
9
|
+
w = 0.25 / s
|
|
10
|
+
x = (matrix[2, 1] - matrix[1, 2]) * s
|
|
11
|
+
y = (matrix[0, 2] - matrix[2, 0]) * s
|
|
12
|
+
z = (matrix[1, 0] - matrix[0, 1]) * s
|
|
13
|
+
else:
|
|
14
|
+
if matrix[0, 0] > matrix[1, 1] and matrix[0, 0] > matrix[2, 2]:
|
|
15
|
+
s = 2.0 * np.sqrt(1.0 + matrix[0, 0] - matrix[1, 1] - matrix[2, 2])
|
|
16
|
+
w = (matrix[2, 1] - matrix[1, 2]) / s
|
|
17
|
+
x = 0.25 * s
|
|
18
|
+
y = (matrix[0, 1] + matrix[1, 0]) / s
|
|
19
|
+
z = (matrix[0, 2] + matrix[2, 0]) / s
|
|
20
|
+
elif matrix[1, 1] > matrix[2, 2]:
|
|
21
|
+
s = 2.0 * np.sqrt(1.0 + matrix[1, 1] - matrix[0, 0] - matrix[2, 2])
|
|
22
|
+
w = (matrix[0, 2] - matrix[2, 0]) / s
|
|
23
|
+
x = (matrix[0, 1] + matrix[1, 0]) / s
|
|
24
|
+
y = 0.25 * s
|
|
25
|
+
z = (matrix[1, 2] + matrix[2, 1]) / s
|
|
26
|
+
else:
|
|
27
|
+
s = 2.0 * np.sqrt(1.0 + matrix[2, 2] - matrix[0, 0] - matrix[1, 1])
|
|
28
|
+
w = (matrix[1, 0] - matrix[0, 1]) / s
|
|
29
|
+
x = (matrix[0, 2] + matrix[2, 0]) / s
|
|
30
|
+
y = (matrix[1, 2] + matrix[2, 1]) / s
|
|
31
|
+
z = 0.25 * s
|
|
32
|
+
return np.array([w, x, y, z])
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def quaternion_to_matrix(quaternion):
|
|
36
|
+
_EPS = np.finfo(float).eps * 4.0
|
|
37
|
+
q = np.array(quaternion[:4], dtype=np.float64, copy=True)
|
|
38
|
+
nq = np.dot(q, q)
|
|
39
|
+
if nq < _EPS:
|
|
40
|
+
return np.identity(4)
|
|
41
|
+
q *= np.sqrt(2.0 / nq)
|
|
42
|
+
q = np.outer(q, q)
|
|
43
|
+
return np.array((
|
|
44
|
+
(1.0-q[1, 1]-q[2, 2], q[0, 1]-q[2, 3], q[0, 2]+q[1, 3], 0.0),
|
|
45
|
+
(q[0, 1]+q[2, 3], 1.0-q[0, 0]-q[2, 2], q[1, 2]-q[0, 3], 0.0),
|
|
46
|
+
(q[0, 2]-q[1, 3], q[1, 2]+q[0, 3], 1.0-q[0, 0]-q[1, 1], 0.0),
|
|
47
|
+
(0.0, 0.0, 0.0, 1.0)
|
|
48
|
+
), dtype=np.float64)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def make_transform(pose, rotation):
|
|
52
|
+
transform = np.matrix(np.identity(4, dtype=np.float64))
|
|
53
|
+
transform = quaternion_to_matrix(rotation)
|
|
54
|
+
transform[0:3, 3] = np.transpose(pose)
|
|
55
|
+
return transform
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class FPSMonitor():
|
|
59
|
+
def __init__(self):
|
|
60
|
+
self.stamp_record = []
|
|
61
|
+
|
|
62
|
+
def count(self):
|
|
63
|
+
cur_stamp = time.time()
|
|
64
|
+
self.stamp_record.append(cur_stamp)
|
|
65
|
+
while len(self.stamp_record) > 0:
|
|
66
|
+
if(cur_stamp - self.stamp_record[0] > 1.):
|
|
67
|
+
self.stamp_record.pop(0)
|
|
68
|
+
else:
|
|
69
|
+
break
|
|
70
|
+
return len(self.stamp_record)
|
|
71
|
+
|
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: q3dviewer
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.1
|
|
4
4
|
Summary: A library designed for quickly deploying a 3D viewer.
|
|
5
5
|
Home-page: https://github.com/scomup/q3dviewer
|
|
6
6
|
Author: Liu Yang
|
|
7
|
+
License: UNKNOWN
|
|
8
|
+
Platform: UNKNOWN
|
|
7
9
|
Classifier: Programming Language :: Python :: 3
|
|
8
10
|
Classifier: License :: OSI Approved :: MIT License
|
|
9
11
|
Classifier: Operating System :: OS Independent
|
|
10
12
|
Description-Content-Type: text/markdown
|
|
11
|
-
License-File: LICENSE
|
|
12
|
-
Requires-Dist: numpy
|
|
13
|
-
Requires-Dist: pyside6
|
|
14
13
|
Requires-Dist: PyOpenGL
|
|
15
|
-
Requires-Dist:
|
|
14
|
+
Requires-Dist: imageio
|
|
15
|
+
Requires-Dist: imageio[ffmpeg]
|
|
16
|
+
Requires-Dist: laspy
|
|
16
17
|
Requires-Dist: meshio
|
|
17
|
-
Requires-Dist:
|
|
18
|
+
Requires-Dist: numpy
|
|
19
|
+
Requires-Dist: pillow
|
|
18
20
|
Requires-Dist: pye57
|
|
19
|
-
Requires-Dist:
|
|
20
|
-
Requires-Dist:
|
|
21
|
+
Requires-Dist: pypcd4
|
|
22
|
+
Requires-Dist: pyside6
|
|
21
23
|
|
|
22
24
|
## q3dviewer
|
|
23
25
|
|
|
@@ -150,7 +152,7 @@ def main():
|
|
|
150
152
|
|
|
151
153
|
# Create a viewer
|
|
152
154
|
viewer = q3d.Viewer(name='example')
|
|
153
|
-
|
|
155
|
+
|
|
154
156
|
# Add items to the viewer
|
|
155
157
|
viewer.add_items({
|
|
156
158
|
'grid': grid_item,
|
|
@@ -212,3 +214,4 @@ class YourItem(q3d.BaseItem):
|
|
|
212
214
|
```
|
|
213
215
|
|
|
214
216
|
Enjoy using `q3dviewer`!
|
|
217
|
+
|
|
@@ -1,32 +1,34 @@
|
|
|
1
1
|
q3dviewer/__init__.py,sha256=rP5XX_x8g7hxIMqNHlU89BN4dt5MSvoYYwip68fCmhc,173
|
|
2
|
-
q3dviewer/base_glwidget.py,sha256=
|
|
2
|
+
q3dviewer/base_glwidget.py,sha256=tk8icQsRZ3OrSLkHvywmrxElk6jpMooLDZdbZ3sRLnk,11313
|
|
3
3
|
q3dviewer/base_item.py,sha256=lzb04oRaS4rRJrAP6C1Bu4ugK237FgupMTB97zjNVFw,1768
|
|
4
|
-
q3dviewer/
|
|
4
|
+
q3dviewer/basic_window.py,sha256=CFErOPRMysFcCqq3vhDsQ-xZzLArO3m1yABCTIhq5do,7946
|
|
5
|
+
q3dviewer/cloud_viewer.py,sha256=IxxrB6Sl6aPCr9P9QzKHGkMcDP_DjsBWbkmIbsAoIM4,2358
|
|
6
|
+
q3dviewer/gau_io.py,sha256=S6NmqL5vSMgHVxKR-eu4CWCqgZeWBJKYRoOMAwr8Xbo,5890
|
|
5
7
|
q3dviewer/glwidget.py,sha256=im8hjVYEL0Zl7fOIHTQMJdWu7WNOHlvTdIDYjebz9WA,4940
|
|
8
|
+
q3dviewer/utils.py,sha256=evF0d-v17hbTmquC24fmMIp9CsXpUnSQZr4MVy2sfao,2426
|
|
6
9
|
q3dviewer/viewer.py,sha256=LH1INLFhi6pRjzazzQJ0AWT4hgyXI6GnmqoJFUwUZVE,2517
|
|
7
10
|
q3dviewer/custom_items/__init__.py,sha256=gOiAxdjDaAnFL8YbqSEWWWOwUrJfvzP9JLR34sCB9-4,434
|
|
8
11
|
q3dviewer/custom_items/axis_item.py,sha256=PTBSf5DmQI8ieSinYjY_aC7P8q1nzE-2Vc2GNd1O3Os,2568
|
|
12
|
+
q3dviewer/custom_items/camera_frame_item.py,sha256=VBsr3Avly_YWXViIh4DJkGc_HJt227GeOYLpGtbYTOw,5605
|
|
9
13
|
q3dviewer/custom_items/cloud_io_item.py,sha256=gjK3n9WKB7JwxC93ijkweEHA5EezpgNJ8KO-PBaDKCs,2835
|
|
10
|
-
q3dviewer/custom_items/cloud_item.py,sha256=
|
|
14
|
+
q3dviewer/custom_items/cloud_item.py,sha256=s46TxNDw7E6DW3V-ek_PF7egB3kRbnqpOBNUKdaC8IY,12620
|
|
11
15
|
q3dviewer/custom_items/frame_item.py,sha256=6BOM3MXi-Akv6KUXDC3QYEAXKxwk0Eo1KQn-F7jkqrQ,7559
|
|
12
16
|
q3dviewer/custom_items/gaussian_item.py,sha256=CZoXMmj2JPFfMqu7v4q4dLUI2cg_WfE1DHWGXjEYn6M,9869
|
|
13
17
|
q3dviewer/custom_items/grid_item.py,sha256=20n4TGm5YEaudhnEOCOk-HtsKwxVxaPr8YV36kO04yU,4802
|
|
14
18
|
q3dviewer/custom_items/image_item.py,sha256=ctNR81fVgxkdl2n3U_TPFL6yn086UhNI_A9fFHgkc-4,5491
|
|
15
19
|
q3dviewer/custom_items/line_item.py,sha256=u0oFN2iHzsRHtnbvyvC_iglEkCwEU2NnTuE536sKUAE,4348
|
|
16
20
|
q3dviewer/custom_items/text_item.py,sha256=nuHMVMQrwy50lNk9hxB94criFxbJJK-SYiK2fSXWUMQ,2158
|
|
21
|
+
q3dviewer/custom_items/trajectory_item.py,sha256=uoKQSrTs_m_m1M8iNAm3peiXnZ9uVPsYQLYas3Gksjg,2754
|
|
17
22
|
q3dviewer/shaders/cloud_frag.glsl,sha256=tbCsDUp9YlPe0hRWlFS724SH6TtMeLO-GVYROzEElZg,609
|
|
18
23
|
q3dviewer/shaders/cloud_vert.glsl,sha256=Vxgw-Zrr0knAK0z4qMXKML6IC4EbffKMwYN2TMXROoI,2117
|
|
19
24
|
q3dviewer/shaders/gau_frag.glsl,sha256=5_UY84tWDts59bxP8x4I-wgnzY8aGeGuo28wX--LW7E,975
|
|
20
25
|
q3dviewer/shaders/gau_prep.glsl,sha256=eCT9nm65uz32w8NaDjeGKhyAZh42Aea-QTwr3yQVr9U,7218
|
|
21
26
|
q3dviewer/shaders/gau_vert.glsl,sha256=NNbVhv_JyqZDK9iXAyBAcIHAtim7G9yWbC9IaUfTL1w,1666
|
|
22
27
|
q3dviewer/shaders/sort_by_key.glsl,sha256=CA2zOcbyDGYAJSJEUvgjUqNshg9NAehf8ipL3Jsv4qE,1097
|
|
23
|
-
q3dviewer/test/test_interpolation.py,sha256=rR_CXsYFLpn0zO0mHf_jL-naluDBMSky--FviOQga0Q,1657
|
|
24
|
-
q3dviewer/test/test_rendering.py,sha256=gbTcu7-cg20DgC5Zoi17C1s5lBGLfAE1rW9biqPjRsA,2164
|
|
25
28
|
q3dviewer/tools/__init__.py,sha256=01wG7BGM6VX0QyFBKsqPmyf2e-vrmV_N3-mo-VQ1VBg,20
|
|
26
|
-
q3dviewer/tools/cinematographer.py,sha256=o_24SSQ4mF062QQ7Gv3i90v7fA79PcHLB03UHXufuEA,13950
|
|
27
29
|
q3dviewer/tools/cloud_viewer.py,sha256=10f2LSWpmsXzxrGobXw188doVjJbgBfPoqZPUi35EtI,3867
|
|
28
30
|
q3dviewer/tools/example_viewer.py,sha256=yeVXT0k4-h1vTLKnGzWADZD3our6XUaYUTy0p5daTkE,959
|
|
29
|
-
q3dviewer/tools/film_maker.py,sha256=
|
|
31
|
+
q3dviewer/tools/film_maker.py,sha256=PkkMW6__ml7850U2UV2G1Pn4Ahk4EWa7edcvI_5-Z4Y,16028
|
|
30
32
|
q3dviewer/tools/gaussian_viewer.py,sha256=vIwWmiFhjNmknrEkBLzt2yiegeH7LP3OeNjnGM6GzaI,1633
|
|
31
33
|
q3dviewer/tools/lidar_calib.py,sha256=M01bGg2mT8LwVcYybolr4UW_UUaR-f-BFciEHtjeK-w,10488
|
|
32
34
|
q3dviewer/tools/lidar_cam_calib.py,sha256=SYNLDvi15MX7Q3aGn771fvu1cES9xeXgP0_WmDq33w4,11200
|
|
@@ -37,9 +39,9 @@ q3dviewer/utils/convert_ros_msg.py,sha256=sAoQfy3qLQKsIArBAVm8H--wlQXOcmkKK3-Ox9
|
|
|
37
39
|
q3dviewer/utils/gl_helper.py,sha256=dRY_kUqyPMr7NTcupUr6_VTvgnj53iE2C0Lk0-oFYsI,1435
|
|
38
40
|
q3dviewer/utils/maths.py,sha256=5TmjWUX1K3UjygXxrUsydjbo7tPzu0gD-yy7qtQUGBU,10588
|
|
39
41
|
q3dviewer/utils/range_slider.py,sha256=jZJQL-uQgnpgLvtYSWpKTrJlLkt3aqNpaRQAePEpNd0,3174
|
|
40
|
-
q3dviewer-1.1.
|
|
41
|
-
q3dviewer-1.1.
|
|
42
|
-
q3dviewer-1.1.
|
|
43
|
-
q3dviewer-1.1.
|
|
44
|
-
q3dviewer-1.1.
|
|
45
|
-
q3dviewer-1.1.
|
|
42
|
+
q3dviewer-1.1.1.dist-info/LICENSE,sha256=81cMOyNfw8KLb1JnPYngGHJ5W83gSbZEBU9MEP3tl-E,1124
|
|
43
|
+
q3dviewer-1.1.1.dist-info/METADATA,sha256=wSqlVSSanm719PxnxIE7VOStyogcvsVwK1QobHCOLQI,7032
|
|
44
|
+
q3dviewer-1.1.1.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92
|
|
45
|
+
q3dviewer-1.1.1.dist-info/entry_points.txt,sha256=EOjker7XYaBk70ffvNB_knPcfA33Bnlg21ZjEeM1EyI,362
|
|
46
|
+
q3dviewer-1.1.1.dist-info/top_level.txt,sha256=HFFDCbGu28txcGe2HPc46A7EPaguBa_b5oH7bufmxHM,10
|
|
47
|
+
q3dviewer-1.1.1.dist-info/RECORD,,
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
|
-
"""
|
|
4
|
-
Copyright 2024 Panasonic Advanced Technology Development Co.,Ltd. (Liu Yang)
|
|
5
|
-
Distributed under MIT license. See LICENSE for more information.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
"""
|
|
9
|
-
this script tests interpolation of 3D poses.
|
|
10
|
-
"""
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
import numpy as np
|
|
14
|
-
from q3dviewer.utils.maths import expSO3, logSO3, makeT, makeRt
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def interpolate_pose(T1, T2, v_max, omega_max, dt=0.1):
|
|
18
|
-
R1, t1 = makeRt(T1)
|
|
19
|
-
R2, t2 = makeRt(T2)
|
|
20
|
-
|
|
21
|
-
# Get transform time based on linear velocity
|
|
22
|
-
d = np.linalg.norm(t2 - t1)
|
|
23
|
-
t_lin = d / v_max
|
|
24
|
-
|
|
25
|
-
# Get transform time based on angular velocity
|
|
26
|
-
omega = logSO3(R2 @ R1.T)
|
|
27
|
-
theta = np.linalg.norm(omega)
|
|
28
|
-
t_ang = theta / omega_max
|
|
29
|
-
|
|
30
|
-
# Get total time based on the linear and angular time
|
|
31
|
-
t_total = max(t_lin, t_ang)
|
|
32
|
-
num_steps = int(np.ceil(t_total / dt))
|
|
33
|
-
|
|
34
|
-
# Generate interpolated transforms
|
|
35
|
-
interpolated_Ts = []
|
|
36
|
-
for i in range(num_steps + 1):
|
|
37
|
-
s = i / num_steps
|
|
38
|
-
t_interp = (1 - s) * t1 + s * t2
|
|
39
|
-
# Interpolate rotation using SO3
|
|
40
|
-
R_interp = expSO3(s * omega) @ R1
|
|
41
|
-
T_interp = makeT(R_interp, t_interp)
|
|
42
|
-
interpolated_Ts.append(T_interp)
|
|
43
|
-
|
|
44
|
-
return interpolated_Ts
|
|
45
|
-
|
|
46
|
-
if __name__ == "__main__":
|
|
47
|
-
T1 = np.eye(4) # Identity transformation
|
|
48
|
-
T2 = np.array([[0, -1, 0, 1], [1, 0, 0, 2], [0, 0, 1, 3], [0, 0, 0, 1]]) # Target transformation
|
|
49
|
-
|
|
50
|
-
v_max = 1.0 # Maximum linear velocity (m/s)
|
|
51
|
-
omega_max = np.pi / 4 # Maximum angular velocity (rad/s)
|
|
52
|
-
|
|
53
|
-
# Perform interpolation
|
|
54
|
-
interpolated_poses = interpolate_pose(T1, T2, v_max, omega_max)
|
|
55
|
-
for i, T in enumerate(interpolated_poses):
|
|
56
|
-
print(f"Step {i}:\n{T}\n")
|
|
57
|
-
|
|
58
|
-
|
q3dviewer/test/test_rendering.py
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
|
-
"""
|
|
4
|
-
Copyright 2024 Panasonic Advanced Technology Development Co.,Ltd. (Liu Yang)
|
|
5
|
-
Distributed under MIT license. See LICENSE for more information.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
"""
|
|
9
|
-
this script tests the rendering of a cloud in a camera frame based on the
|
|
10
|
-
camera pose and intrinsic matrix
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
import numpy as np
|
|
14
|
-
import q3dviewer as q3d
|
|
15
|
-
import cv2
|
|
16
|
-
|
|
17
|
-
cloud, _ = q3d.load_pcd('/home/liu/lab.pcd')
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
Tcw = np.array([[7.07106781e-01, 7.07106781e-01, 0.00000000e+00,
|
|
21
|
-
0.00000000e+00],
|
|
22
|
-
[-3.53553391e-01, 3.53553391e-01, 8.66025404e-01,
|
|
23
|
-
3.55271368e-15],
|
|
24
|
-
[6.12372436e-01, -6.12372436e-01, 5.00000000e-01,
|
|
25
|
-
-4.00000000e+01],
|
|
26
|
-
[0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
|
|
27
|
-
1.00000000e+00]])
|
|
28
|
-
# convert the opengl camera coordinate to the opencv camera coordinate
|
|
29
|
-
Tconv = np.array([[1, 0, 0, 0],
|
|
30
|
-
[0, -1, 0, 0],
|
|
31
|
-
[0, 0, -1, 0],
|
|
32
|
-
[0, 0, 0, 1]])
|
|
33
|
-
|
|
34
|
-
Tcw = Tconv @ Tcw
|
|
35
|
-
|
|
36
|
-
K = np.array([[1.64718029e+03, 0.00000000e+00, 9.51000000e+02],
|
|
37
|
-
[0.00000000e+00, 1.64718036e+03, 5.31000000e+02],
|
|
38
|
-
[0.00000000e+00, 0.00000000e+00, 1.00000000e+00]])
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def render_frame(cloud, Tcw, K, width, height):
|
|
42
|
-
image = np.zeros((height, width, 3), dtype=np.uint8)
|
|
43
|
-
Rcw, tcw = Tcw[:3, :3], Tcw[:3, 3]
|
|
44
|
-
pc = (Rcw @ cloud['xyz'].T).T + tcw
|
|
45
|
-
uv = (K @ pc.T).T
|
|
46
|
-
uv = uv[:, :2] / uv[:, 2][:, np.newaxis]
|
|
47
|
-
mask = (pc[:, 2] > 0) & (uv[:, 0] > 0) & (
|
|
48
|
-
uv[:, 0] < width) & (uv[:, 1] > 0) & (uv[:, 1] < height)
|
|
49
|
-
uv = uv[mask]
|
|
50
|
-
u = uv[:, 0].astype(int)
|
|
51
|
-
v = uv[:, 1].astype(int)
|
|
52
|
-
rgb = cloud['irgb'][mask]
|
|
53
|
-
r = rgb >> 16 & 0xff
|
|
54
|
-
g = rgb >> 8 & 0xff
|
|
55
|
-
b = rgb & 0xff
|
|
56
|
-
|
|
57
|
-
# Sort by depth to ensure front points are drawn first
|
|
58
|
-
depth = pc[mask, 2]
|
|
59
|
-
sorted_indices = np.argsort(depth)
|
|
60
|
-
u = u[sorted_indices]
|
|
61
|
-
v = v[sorted_indices]
|
|
62
|
-
r = r[sorted_indices]
|
|
63
|
-
g = g[sorted_indices]
|
|
64
|
-
b = b[sorted_indices]
|
|
65
|
-
|
|
66
|
-
image[v, u] = np.stack([b, g, r], axis=1)
|
|
67
|
-
return image
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
image = render_frame(cloud, Tcw, K, 1902, 1062)
|
|
71
|
-
cv2.imshow('image', image)
|
|
72
|
-
cv2.waitKey(0)
|