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/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)
@@ -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("Stop")
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.0
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: pillow
14
+ Requires-Dist: imageio
15
+ Requires-Dist: imageio[ffmpeg]
16
+ Requires-Dist: laspy
16
17
  Requires-Dist: meshio
17
- Requires-Dist: pypcd4
18
+ Requires-Dist: numpy
19
+ Requires-Dist: pillow
18
20
  Requires-Dist: pye57
19
- Requires-Dist: laspy
20
- Requires-Dist: imageio
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=k4fVwV2A_0CS7zZgHargbKE7push-l2UN7rmr2Z9vFo,10916
2
+ q3dviewer/base_glwidget.py,sha256=tk8icQsRZ3OrSLkHvywmrxElk6jpMooLDZdbZ3sRLnk,11313
3
3
  q3dviewer/base_item.py,sha256=lzb04oRaS4rRJrAP6C1Bu4ugK237FgupMTB97zjNVFw,1768
4
- q3dviewer/gau_io.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
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=7r6s_j1qEUfLe70t-M68-oIrGRrPOUcZp18ML6jST0s,12542
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=CC4RuK0bE_-0kcdU6xyzqR47pB4TEcm0g4LlDrFs3qY,16004
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.0.dist-info/LICENSE,sha256=81cMOyNfw8KLb1JnPYngGHJ5W83gSbZEBU9MEP3tl-E,1124
41
- q3dviewer-1.1.0.dist-info/METADATA,sha256=hiWxWsKDWmCaXB-lJYhi-kutcydCeafxfzDSgeQv5Y8,6991
42
- q3dviewer-1.1.0.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92
43
- q3dviewer-1.1.0.dist-info/entry_points.txt,sha256=aeUdGH7UIgMZEMFUc-0xPZWspY95GoPdZcZuLceq85g,361
44
- q3dviewer-1.1.0.dist-info/top_level.txt,sha256=HFFDCbGu28txcGe2HPc46A7EPaguBa_b5oH7bufmxHM,10
45
- q3dviewer-1.1.0.dist-info/RECORD,,
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,,
@@ -6,3 +6,4 @@ lidar_calib = q3dviewer.tools.lidar_calib:main
6
6
  lidar_cam_calib = q3dviewer.tools.lidar_cam_calib:main
7
7
  mesh_viewer = q3dviewer.tools.mesh_viewer:main
8
8
  ros_viewer = q3dviewer.tools.ros_viewer:main
9
+
@@ -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
-
@@ -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)