CTPv 0.1.0__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.
@@ -0,0 +1,474 @@
1
+ Metadata-Version: 2.4
2
+ Name: CTPv
3
+ Version: 0.1.0
4
+ Summary: A toolbox of camera, Plücker, and transformation utilities
5
+ Author: Rhys Evans & Seppe Sels
6
+ Author-email: Rhys Evans & Seppe Sels <rhys.evans@uantwerpen.be>
7
+ License: MIT
8
+ Requires-Python: >=3.10
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Requires-Dist: numpy
12
+ Requires-Dist: matplotlib
13
+ Requires-Dist: scipy
14
+ Requires-Dist: scikit-learn
15
+ Requires-Dist: open3d
16
+ Dynamic: author
17
+ Dynamic: license-file
18
+ Dynamic: requires-python
19
+
20
+ **core\_toolbox\_python**
21
+ A lightweight Python toolbox providing utilities for camera intrinsics, Plücker‐line representations, and 3D transformation matrices. This package is organized into three submodules:
22
+
23
+ * **Camera.Intrinsics**: Classes for intrinsic camera matrices (Matlab/OpenCV conventions), radial distortion, ray generation, and JSON serialization.
24
+ * **Plucker.Line**: A `Line` class to represent 3D lines (start/end points or Plücker coordinates), intersection computations, line fitting, and basic plotting utilities.
25
+ * **Transformation.TransformationMatrix**: A 4×4 rigid‐body transformation class with support for Euler angles (radians/degrees), quaternions, Bundler‐format I/O, JSON serialization, inversion, chaining, and plotting (matplotlib/Open3D).
26
+
27
+ ---
28
+
29
+ ## Table of Contents
30
+
31
+ 1. [Features](#features)
32
+ 2. [Requirements](#requirements)
33
+ 3. [Installation](#installation)
34
+ 4. [Module Overview](#module-overview)
35
+
36
+ * [Camera.Intrinsics](#cameraintrinsics)
37
+ * [Plucker.Line](#pluckerline)
38
+ * [Transformation.TransformationMatrix](#transformationtransformationmatrix)
39
+ 5. [Usage Examples](#usage-examples)
40
+ 6. [Development & Contributing](#development--contributing)
41
+ 7. [License](#license)
42
+
43
+ ---
44
+
45
+ ## Features
46
+
47
+ * **Intrinsics & Distortion**
48
+
49
+ * Create and manipulate camera intrinsic matrices in both Matlab and OpenCV formats.
50
+ * Store and serialize radial‐distortion coefficients.
51
+ * Compute focal length in millimeters (if pixel size is known).
52
+ * Compute perspective (field‐of‐view) angles.
53
+ * Generate per‐pixel rays as Plücker‐line objects.
54
+ * Save/load intrinsic parameters to/from JSON.
55
+
56
+ * **Plücker‐Line Representation**
57
+
58
+ * Represent a set of 3D rays or line segments via Plücker coordinates.
59
+ * Compute shortest‐distance intersections between two sets of lines.
60
+ * Fit a line to a cloud of 3D points (including placeholder methods for RANSAC, to be implemented).
61
+ * Compute angles between two lines.
62
+ * Basic 3D plotting of lines (matplotlib).
63
+
64
+ * **Transformation Matrices**
65
+
66
+ * Encapsulate a 4×4 rigid transformation (rotation + translation).
67
+ * Get/set translation (`.T`) and rotation (`.R`) as 3×3 matrix.
68
+ * Get/set Euler angles in radians (`.angles`) or degrees (`.angles_degree`) via SciPy.
69
+ * Get/set quaternion (`.quaternion`) for the rotation.
70
+ * Apply transformation to point clouds.
71
+ * Invert transformations, chain multiple transformations with `@`.
72
+ * Save/load transformations in JSON.
73
+ * Save/load Bundler v0.3 camera entries for MeshLab (single‐camera mode).
74
+ * Plot coordinate frames in 3D (matplotlib, or Open3D if available).
75
+
76
+ ---
77
+
78
+ ## Requirements
79
+
80
+ * Python ≥ 3.7
81
+ * NumPy
82
+ * Matplotlib
83
+ * SciPy (especially `scipy.spatial.transform.Rotation`)
84
+ * scikit‐learn (for any future line‐fitting routines)
85
+
86
+ *(All dependencies are declared in `pyproject.toml` or `setup.py` under `dependencies`.)*
87
+
88
+ ---
89
+
90
+ ## Installation
91
+
92
+ 1. **Clone the repository**
93
+
94
+ ```bash
95
+ git clone https://github.com/yourusername/core_toolbox_python.git
96
+ cd core_toolbox_python
97
+ ```
98
+
99
+ 2. **Build a wheel (PEP 517)**
100
+
101
+ ```bash
102
+ python -m pip install --upgrade pip
103
+ pip install build
104
+ python -m build --wheel
105
+ ```
106
+
107
+ A `.whl` file will appear under `dist/`.
108
+
109
+ 3. **Install from the local wheel**
110
+
111
+ ```bash
112
+ pip install dist/core_toolbox_python-0.1.0-py3-none-any.whl
113
+ ```
114
+
115
+ 4. **Or install in editable/development mode**
116
+
117
+ ```bash
118
+ pip install -e .
119
+ ```
120
+
121
+ This lets you modify source code and have changes reflected immediately.
122
+
123
+ ---
124
+
125
+ ## Module Overview
126
+
127
+ ### Camera.Intrinsics
128
+
129
+ **File**: `core_toolbox_python/Camera/Intrinsics.py`
130
+
131
+ * **Class `RadialDistortion`**
132
+
133
+ * Holds distortion coefficients `k1, k2, k3`.
134
+ * `set_from_list([k1, k2, k3])`: assign three‐element coefficient list.
135
+
136
+ * **Class `IntrinsicMatrix`**
137
+
138
+ * Attributes:
139
+
140
+ * `fx, fy, cx, cy, s` (standard pinhole‐camera parameters).
141
+ * `width, height` (image resolution).
142
+ * `pixel_size` (in millimeters, e.g. sensor pixel pitch).
143
+ * `RadialDistortion`: an instance of `RadialDistortion`.
144
+ * `.info`: optional metadata (e.g. camera/lens ID).
145
+
146
+ * **Properties**:
147
+
148
+ * `.MatlabIntrinsics` (getter/setter): 3×3 matrix in Matlab convention (⎡fx s 0; 0 fy 0; cx cy 1⎤).
149
+ * `.OpenCVIntrinsics` (getter/setter): 3×3 matrix in OpenCV convention (⎡fx 0 cx; 0 fy cy; 0 0 1⎤).
150
+ * `.focal_length_mm`: returns `(fx ⋅ pixel_size, fy ⋅ pixel_size)`.
151
+ * `.PerspectiveAngle` (getter/setter): horizontal or vertical field‐of‐view (degrees) based on `width/height` vs `fx,fy`.
152
+
153
+ * **Methods**:
154
+
155
+ * `.CameraParams2Intrinsics(CameraParams)`: load intrinsics from an external camera‐parameters object (e.g. if you have a `CameraParams.IntrinsicMatrix` & `CameraParams.ImageSize`).
156
+ * `.Intrinsics2CameraParams()`: return a dictionary `{IntrinsicMatrix: […], ImageSize: […], RadialDistortion: …}`.
157
+ * `.ScaleIntrinsics(s)`: multiply `fx, fy, cx, cy, width, height` by scale ` s`.
158
+ * `.generate_rays() → Line`: produce a `Line` object where each row corresponds to a 3D ray originating from pixel centers; uses radial‐undistortion (if defined).
159
+ * `.save_intrinsics_to_json(filename)`: write a JSON file containing OpenCV intrinsics, distortion, resolution, pixel size, and `info`.
160
+ * `.load_intrinsics_from_json(filename)`: read JSON file and populate intrinsics, distortion, `width, height, pixel_size, info`.
161
+
162
+ * **Example** (at bottom of file):
163
+
164
+ ```python
165
+ if __name__ == "__main__":
166
+ I = IntrinsicMatrix()
167
+ I.info = "testCamera"
168
+ I.fx = I.fy = 1770
169
+ I.width, I.height = 1440, 1080
170
+ I.cx, I.cy = 685, 492
171
+ I.RadialDistortion.set_from_list([-0.5, 0.18, 0])
172
+ I.save_intrinsics_to_json("test.json")
173
+ rays = I.generate_rays() # Plücker‐line set
174
+ I2 = IntrinsicMatrix().load_intrinsics_from_json("test.json")
175
+ # … compute intersections, etc.
176
+ ```
177
+
178
+ ---
179
+
180
+ ### Plucker.Line
181
+
182
+ **File**: `core_toolbox_python/Plucker/Line.py`
183
+
184
+ * **Function `intersection_between_2_lines(L1, L2)`**
185
+
186
+ * Computes closest‐point midpoints and shortest distances between each corresponding pair of rays in two `Line` objects.
187
+ * Inputs:
188
+
189
+ * `L1`, `L2`: each a `Line` instance with `Ps` (start points) and `V` (direction vectors).
190
+ * Returns:
191
+
192
+ * `Points`: an `(N, 3)` array of midpoints between ray *i* from `L1` and ray *i* from `L2`.
193
+ * `distances`: an `(N,)` array of shortest distances.
194
+
195
+ * **Class `Line`**
196
+
197
+ * **Attributes**:
198
+
199
+ * `Ps`: `(N, 3)` array of start (origin) points of each line/ray.
200
+ * `Pe`: `(N, 3)` array of end points (so direction = `Pe − Ps`).
201
+
202
+ * **Properties**:
203
+
204
+ * `.V` (getter): normalized direction vectors for each ray (`(Pe − Ps)` normalized row‐wise).
205
+ * `.V` (setter): sets `Pe = Ps + new_direction`.
206
+ * `.Plucker` (getter): concatenates direction `V` and moment `U=Ps×(Ps+V)` into a `(N,6)` array.
207
+ * `.Plucker` (setter): given a `(N,6)` array, recovers `Ps` and `V` via cross‐product inversion.
208
+ * `.Plucker2` (alternative Plücker ordering): stores `(moment = Ps×Pe ∥ direction=Pe−Ps)`.
209
+
210
+ * **Methods**:
211
+
212
+ * `.GetAngle()`: returns the angle (in degrees) between each ray and the world‐Z unit vector.
213
+ * `.TransformLines(H)`: applies a `TransformationMatrix` `H` to both `Ps` and `Pe`.
214
+ * `.plot(limits=None, colors=None, …)`: wide‐ranging helper that draws as many lines as you like in 3D (within bounds).
215
+ * `.PlotLine(colori='g', linewidth=2)`: simpler per‐line plotting (downsamples if >500 rays).
216
+ * `.FindXYZNearestLine(XYZ)`: given a single 3D point cloud `XYZ`, returns the index of the ray that is closest.
217
+ * `.FitLine(XYZ)`: placeholder for least‐squares fit to 3D points (calls `_fitline3d`).
218
+ * `.FitLineRansac(XYZ, t=10)`: placeholder for RANSAC line fit (calls `_ransac_fit_line`).
219
+ * `.NormaliseLine()`: project all line origins so that `z=0`.
220
+ * `.DistanceLinePoint(XYZ)`: shortest distance from each line to each query point in `XYZ`.
221
+ * `.Lenght()`: length of each line segment (`‖Pe−Ps‖`).
222
+ * `@staticmethod FromStartEnd(start, end)`: build a `Line` from start/end points.
223
+ * `@staticmethod FromPlucker(VU)`: build a `Line` given a `(N,6)` Plücker array.
224
+ * **Internal helpers**: `_normalize_vectors`, `_is_within_bounds`, `_downsample`, `_fitline3d`, `_ransac_fit_line`, `_homogeneous_transform`, etc. (some are stubs for future extension).
225
+ * `.AngleBetweenLines(L1, L2)`: returns angle (radians, degrees) between two `Line` objects (single‐ray version).
226
+ * `.GenerateRay(I, uv)`: generate rays passing through pixel coordinates `uv` using intrinsics `I`.
227
+
228
+ * **Example** (at bottom of file):
229
+
230
+ ```python
231
+ if __name__ == "__main__":
232
+ L = Line()
233
+ L.Ps = np.array([[1,1,0]])
234
+ L.Pe = np.array([[2,1,0]])
235
+ print(L.V) # direction vector
236
+ L.PlotLine()
237
+ L2 = Line()
238
+ L2.Ps, L2.Pe = np.array([[0,0,0]]), np.array([[20,20,0]])
239
+ _, hoek = L.AngleBetweenLines(L, L2)
240
+ print("Angle between lines:", hoek)
241
+ ```
242
+
243
+ ---
244
+
245
+ ### Transformation.TransformationMatrix
246
+
247
+ **File**: `core_toolbox_python/Transformation/TransformationMatrix.py`
248
+
249
+ * **Class `TransformationMatrix`**
250
+
251
+ * Internally stores a 4×4 homogeneous transform `self.H` (initialized to identity).
252
+
253
+ * **Attributes**:
254
+
255
+ * `.H`: 4×4 NumPy array.
256
+ * `.info`: a two‐element list of arbitrary metadata (e.g. camera ID, timestamp).
257
+ * `.units`: string indicating units (default `"mm"`).
258
+
259
+ * **Properties**:
260
+
261
+ * `.T` (getter/setter): get/set the translation vector (3×1).
262
+ * `.R` (getter/setter): get/set the 3×3 rotation submatrix.
263
+ * `.angles` (getter/setter): Euler angles in radians (XYZ convention) via `scipy.spatial.transform.Rotation`.
264
+ * `.angles_degree` (getter/setter): Euler angles in degrees.
265
+ * `.quaternion` (getter/setter): quaternion `[x, y, z, w]` representation of the rotation.
266
+
267
+ * **Methods**:
268
+
269
+ * `.transform(points)`: apply the 4×4 transform to an `(N,3)` or `(3,)` array of 3D points, returning transformed `(N,3)`.
270
+ * `.invert()`: invert the transformation in‐place, swap and invert `H`, and reverse the `info` list.
271
+ * `.save_bundler_file(output_file, intrinsics=None)`: write a Bundler v0.3‐style camera entry (single camera, zero points) to a text file—storing focal length, distortion (set to zero), rotation rows, and translation vector. If `intrinsics` is `None`, a default intrinsic matrix is used (example values).
272
+ * `.load_bundler_file(filename)`: read a Bundler file (ignore first three lines), load rotation (3×3) and translation (3×1) back into `H`.
273
+ * `.plot(scale=1.0)`: visualize this transformation as a 3D coordinate frame (matplotlib).
274
+ * `.plot_open3d(scale=1.0)`: visualize using Open3D’s `TriangleMesh.create_coordinate_frame`; requires `open3d` installed.
275
+ * `.copy()`: return a deep copy of this `TransformationMatrix`.
276
+ * `.load_from_json(filename)`: read `H`, `info`, `units` from a JSON file.
277
+ * `.save_to_json(filename)`: write `H`, `info`, `units` to JSON.
278
+ * `__matmul__(self, other)`: allow chaining two transformations `T_combined = T1 @ T2` (i.e. matrix multiply). The combined `info` is taken as `[self.info[0], other.info[-1]]` by default.
279
+ * `__repr__`: printable representation of the 4×4 matrix.
280
+
281
+ * **Example** (at bottom of file):
282
+
283
+ ```python
284
+ if __name__ == "__main__":
285
+ T1 = TransformationMatrix()
286
+ T1.T = [0, 10, 0]
287
+ T1.angles_degree = [0, 30, 0]
288
+ T1.save_bundler_file("test.out")
289
+ print("T1:\n", T1)
290
+ print("Quaternion:", T1.quaternion)
291
+ T1.plot()
292
+
293
+ T2 = T1.copy()
294
+ T2.invert()
295
+ T2.plot()
296
+ T_combined = T1 @ T2
297
+ print("Combined:\n", T_combined)
298
+ ```
299
+
300
+ ---
301
+
302
+ ## Usage Examples
303
+
304
+ Below are some minimal snippets illustrating how to import and use the package once installed.
305
+
306
+ ### 1. Reading/Writing Intrinsics
307
+
308
+ ```python
309
+ from core_toolbox_python.Camera.Intrinsics import IntrinsicMatrix, RadialDistortion
310
+
311
+ # Create an intrinsic matrix
312
+ I = IntrinsicMatrix()
313
+ I.fx = 1200
314
+ I.fy = 1200
315
+ I.cx = 640
316
+ I.cy = 360
317
+ I.width = 1280
318
+ I.height = 720
319
+ I.pixel_size = 0.0034 # e.g. 3.4 µm
320
+ I.RadialDistortion.set_from_list([0.01, -0.001, 0.0])
321
+
322
+ # Compute OpenCV format
323
+ K_opencv = I.OpenCVIntrinsics
324
+ print("OpenCV Intrinsics:\n", K_opencv)
325
+
326
+ # Save to JSON
327
+ I.save_intrinsics_to_json("camera_intrinsics.json")
328
+
329
+ # Load back
330
+ I2 = IntrinsicMatrix().load_intrinsics_from_json("camera_intrinsics.json")
331
+ print("Loaded fx, fy:", I2.fx, I2.fy)
332
+ ```
333
+
334
+ ### 2. Generating Rays & Line Intersections
335
+
336
+ ```python
337
+ from core_toolbox_python.Camera.Intrinsics import IntrinsicMatrix
338
+ from core_toolbox_python.Plucker.Line import intersection_between_2_lines
339
+
340
+ # Suppose we have two camera poses, project rays, and compute their closest‐point intersections
341
+
342
+ # Camera 1 intrinsics
343
+ I1 = IntrinsicMatrix()
344
+ I1.fx = I1.fy = 1000
345
+ I1.cx, I1.cy = 320, 240
346
+ I1.width, I1.height = 640, 480
347
+ I1.pixel_size = 0.0025
348
+ # … set radial distortion if needed …
349
+
350
+ # Camera 2 intrinsics (shifted horizontally by 1 unit)
351
+ I2 = IntrinsicMatrix()
352
+ I2.fx = I2.fy = 1000
353
+ I2.cx, I2.cy = 320, 240
354
+ I2.width, I2.height = 640, 480
355
+ I2.pixel_size = 0.0025
356
+
357
+ # Generate full‐image rays from each camera (Plücker‐line sets)
358
+ rays1 = I1.generate_rays()
359
+ rays2 = I2.generate_rays()
360
+
361
+ # Compute midpoint & distances between corresponding rays
362
+ points_mid, distances = intersection_between_2_lines(rays1, rays2)
363
+ print("Mean distance between ray pairs:", distances.mean())
364
+ ```
365
+
366
+ ### 3. Creating & Transforming 3D Geometry
367
+
368
+ ```python
369
+ from core_toolbox_python.Transformation.TransformationMatrix import TransformationMatrix
370
+ import numpy as np
371
+
372
+ # Define a transformation: translate by [1,2,3], rotate 45° about Z
373
+ T = TransformationMatrix()
374
+ T.T = [1, 2, 3]
375
+ T.angles_degree = [0, 0, 45]
376
+
377
+ # Transform a set of points
378
+ points = np.array([[0,0,0], [1,0,0], [0,1,0]])
379
+ points_transformed = T.transform(points)
380
+ print("Transformed points:\n", points_transformed)
381
+
382
+ # Inverse transform
383
+ T_inv = T.copy()
384
+ T_inv.invert()
385
+ restored = T_inv.transform(points_transformed)
386
+ print("Restored (should match original):\n", restored)
387
+
388
+ # Save to JSON
389
+ T.save_to_json("transform.json")
390
+ T2 = TransformationMatrix().load_from_json("transform.json")
391
+
392
+ # Chain transformations
393
+ T_comb = T @ T2 # (applies T first, then T2)
394
+ ```
395
+
396
+ ### 4. Visualization
397
+
398
+ ```python
399
+ import matplotlib.pyplot as plt
400
+ from core_toolbox_python.Plucker.Line import Line
401
+
402
+ # Plotting a single ray
403
+ L = Line()
404
+ L.Ps = np.array([[0, 0, 0]])
405
+ L.Pe = np.array([[1, 1, 1]])
406
+ L.PlotLine(colori='r')
407
+
408
+ # Plot a coordinate frame
409
+ from core_toolbox_python.Transformation.TransformationMatrix import TransformationMatrix
410
+ T = TransformationMatrix()
411
+ T.T = [0, 0, 0]
412
+ T.angles_degree = [30, 45, 60]
413
+ T.plot(scale=1.0)
414
+ plt.show()
415
+ ```
416
+
417
+ ---
418
+
419
+ ### Development & Contributing
420
+
421
+ 1. **Clone & install in “editable” mode**
422
+ ```bash
423
+ git clone https://github.com/yourusername/core_toolbox_python.git
424
+ cd core_toolbox_python
425
+ pip install -e .
426
+ ```
427
+
428
+ 2. **Make changes on a feature branch**
429
+
430
+ * Create a new branch off `main` (or `develop`).
431
+
432
+ ```bash
433
+ git checkout -b feature/my_update
434
+ ```
435
+ * Implement or update functionality as needed (e.g., fill in placeholder methods, add examples, fix bugs).
436
+
437
+ 3. **Run tests & verify locally**
438
+
439
+ * If you add new functionality, include or update any unit tests.
440
+ * Make sure existing examples and import statements continue to work.
441
+
442
+ 4. **Tag-based release workflow**
443
+
444
+ * CI is configured to build wheels **only when a Git tag is pushed**.
445
+ * Once your branch is reviewed and merged into `main`, create a new lightweight or annotated tag following semantic versioning:
446
+
447
+ ```bash
448
+ git checkout main
449
+ git pull origin main
450
+ git tag -a vX.Y.Z -m "Release vX.Y.Z"
451
+ git push origin vX.Y.Z
452
+ ```
453
+ * Pushing that tag will trigger the GitHub Actions workflow to build wheels for all platforms and upload them as artifacts.
454
+
455
+ 5. **Submit a Pull Request**
456
+
457
+ * Push your feature branch to the remote repository.
458
+
459
+ ```bash
460
+ git push origin feature/my_update
461
+ ```
462
+ * Open a Pull Request against `main`, describing your changes. Once approved and merged, follow the tag‐based release step above.
463
+
464
+ 6. **After a successful tag build**
465
+
466
+ * Download platform‐specific wheel artifacts from the “Artifacts” section in the GitHub Actions run.
467
+ * Optionally, publish wheels to PyPI (you can use `twine upload dist/*` after downloading and verifying).
468
+
469
+ Thank you for contributing! If you have questions or need assistance, please open an issue or reach out directly.\`\`\`
470
+ ---
471
+
472
+ ## License
473
+
474
+ This project is distributed under the MIT License. See [LICENSE](LICENSE) for details.
@@ -0,0 +1,12 @@
1
+ CTPv/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ CTPv/Camera/Intrinsics.py,sha256=jYjTYOJMP978KlDH-XTZg6Sy7t2ICE_74q4EM3q88eU,6369
3
+ CTPv/Camera/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ CTPv/Plucker/Line.py,sha256=nxDKdSgLinN_kxCpAPoR472IX3Ib9-P-eNR1kwPVMHI,16568
5
+ CTPv/Plucker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ CTPv/Transformation/TransformationMatrix.py,sha256=k_n2Joq7sqfAXdoaFTGw-WIOUALsOv0iJ1MWKRtlqkY,12687
7
+ CTPv/Transformation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ ctpv-0.1.0.dist-info/licenses/LICENSE,sha256=HBhyqBIYiZbUP-uyGVPbBdjguM7XuuEGCVnBnud3kpM,1078
9
+ ctpv-0.1.0.dist-info/METADATA,sha256=ozfEx564pTQCgZOSaHHATolDX861raOWqPqxuM2NyfI,17275
10
+ ctpv-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
11
+ ctpv-0.1.0.dist-info/top_level.txt,sha256=4XT7Ark0McReh1zScVddxURLS_h3KP9djFII02cqPsQ,5
12
+ ctpv-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,7 @@
1
+ Copyright 2025 UAntwerp InViLab research group
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1 @@
1
+ CTPv