euler-loading 2.25.0__tar.gz → 2.26.0__tar.gz

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.
Files changed (77) hide show
  1. {euler_loading-2.25.0 → euler_loading-2.26.0}/CHANGELOG.md +18 -0
  2. {euler_loading-2.25.0 → euler_loading-2.26.0}/PKG-INFO +1 -1
  3. {euler_loading-2.25.0 → euler_loading-2.26.0}/docs/loaders.md +53 -4
  4. euler_loading-2.26.0/euler_loading/loaders/cpu/synscapes.py +769 -0
  5. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/generate/loaders.json +26 -0
  6. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/gpu/synscapes.py +64 -6
  7. {euler_loading-2.25.0 → euler_loading-2.26.0}/pyproject.toml +1 -1
  8. euler_loading-2.26.0/tests/test_synscapes.py +949 -0
  9. euler_loading-2.25.0/euler_loading/loaders/cpu/synscapes.py +0 -205
  10. euler_loading-2.25.0/tests/test_synscapes.py +0 -319
  11. {euler_loading-2.25.0 → euler_loading-2.26.0}/.gitignore +0 -0
  12. {euler_loading-2.25.0 → euler_loading-2.26.0}/LICENSE +0 -0
  13. {euler_loading-2.25.0 → euler_loading-2.26.0}/README.md +0 -0
  14. {euler_loading-2.25.0 → euler_loading-2.26.0}/docs/README.md +0 -0
  15. {euler_loading-2.25.0 → euler_loading-2.26.0}/docs/dataset.md +0 -0
  16. {euler_loading-2.25.0 → euler_loading-2.26.0}/docs/materialization.md +0 -0
  17. {euler_loading-2.25.0 → euler_loading-2.26.0}/docs/preprocessing.md +0 -0
  18. {euler_loading-2.25.0 → euler_loading-2.26.0}/docs/transform-descriptors.md +0 -0
  19. {euler_loading-2.25.0 → euler_loading-2.26.0}/docs/writing.md +0 -0
  20. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/__init__.py +0 -0
  21. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/_dataset_contract.py +0 -0
  22. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/_ds_crawler_utils.py +0 -0
  23. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/_metadata.py +0 -0
  24. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/_resolution.py +0 -0
  25. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/_writing.py +0 -0
  26. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/dataset.py +0 -0
  27. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/geometry.py +0 -0
  28. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/indexing.py +0 -0
  29. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/__init__.py +0 -0
  30. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/_annotations.py +0 -0
  31. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/_princeton_dense.py +0 -0
  32. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/_writer_utils.py +0 -0
  33. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/contracts.py +0 -0
  34. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/cpu/__init__.py +0 -0
  35. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/cpu/generic.py +0 -0
  36. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/cpu/generic_dense_depth.py +0 -0
  37. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/cpu/muses.py +0 -0
  38. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/cpu/princeton_dense.py +0 -0
  39. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/cpu/real_drive_sim.py +0 -0
  40. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/cpu/vkitti2.py +0 -0
  41. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/generate/__init__.py +0 -0
  42. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/generate/__main__.py +0 -0
  43. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/generic.py +0 -0
  44. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/gpu/__init__.py +0 -0
  45. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/gpu/generic.py +0 -0
  46. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/gpu/generic_dense_depth.py +0 -0
  47. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/gpu/muses.py +0 -0
  48. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/gpu/princeton_dense.py +0 -0
  49. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/gpu/real_drive_sim.py +0 -0
  50. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/gpu/vkitti2.py +0 -0
  51. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/materialized.py +0 -0
  52. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/muses.py +0 -0
  53. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/princeton_dense.py +0 -0
  54. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/real_drive_sim.py +0 -0
  55. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/synscapes.py +0 -0
  56. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/loaders/vkitti2.py +0 -0
  57. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/materialization.py +0 -0
  58. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/output_encoding.py +0 -0
  59. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/preprocessing.py +0 -0
  60. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/receipts.py +0 -0
  61. {euler_loading-2.25.0 → euler_loading-2.26.0}/euler_loading/transform_descriptors.py +0 -0
  62. {euler_loading-2.25.0 → euler_loading-2.26.0}/examples/README.md +0 -0
  63. {euler_loading-2.25.0 → euler_loading-2.26.0}/examples/real_drive_sim_preview.py +0 -0
  64. {euler_loading-2.25.0 → euler_loading-2.26.0}/examples/vkitti2_sample.py +0 -0
  65. {euler_loading-2.25.0 → euler_loading-2.26.0}/tests/__init__.py +0 -0
  66. {euler_loading-2.25.0 → euler_loading-2.26.0}/tests/conftest.py +0 -0
  67. {euler_loading-2.25.0 → euler_loading-2.26.0}/tests/example_rds_calib.json +0 -0
  68. {euler_loading-2.25.0 → euler_loading-2.26.0}/tests/test_dataset.py +0 -0
  69. {euler_loading-2.25.0 → euler_loading-2.26.0}/tests/test_id_schema.py +0 -0
  70. {euler_loading-2.25.0 → euler_loading-2.26.0}/tests/test_indexing.py +0 -0
  71. {euler_loading-2.25.0 → euler_loading-2.26.0}/tests/test_loaders.py +0 -0
  72. {euler_loading-2.25.0 → euler_loading-2.26.0}/tests/test_materialization.py +0 -0
  73. {euler_loading-2.25.0 → euler_loading-2.26.0}/tests/test_preprocessing.py +0 -0
  74. {euler_loading-2.25.0 → euler_loading-2.26.0}/tests/test_python_compat.py +0 -0
  75. {euler_loading-2.25.0 → euler_loading-2.26.0}/tests/test_real_dataset.py +0 -0
  76. {euler_loading-2.25.0 → euler_loading-2.26.0}/tests/test_transform_descriptors.py +0 -0
  77. {euler_loading-2.25.0 → euler_loading-2.26.0}/tests/test_writing.py +0 -0
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ - Add `read_extrinsics` to the Synscapes loaders, building a 4x4 rigid
6
+ transform from the six `camera.extrinsic` scalars. `transform_direction`
7
+ and `camera_axes` select the pose, its inverse, and vehicle or optical
8
+ camera axes; the assumed `Rz(yaw) @ Ry(pitch) @ Rx(roll)` order is recorded
9
+ in the modality metadata because the dataset does not document it.
10
+ - Add Synscapes writers for every modality, making the loader a
11
+ `DenseDepthCodec`. Depth writes a float32 EXR `Z` channel and needs a
12
+ filesystem path; the intrinsics and extrinsics writers merge into a single
13
+ `meta/<id>.json`, replacing it in one step and keeping its permissions,
14
+ symlink and unmodelled fields rather than truncating it in place.
15
+ - `sky_mask` now honours `meta['sky_class_id']`, or the same key in per-file
16
+ attributes, instead of hardcoding Cityscapes ID 23, so a dataset that
17
+ relabels sky round-trips through `write_sky_mask`.
18
+ - Accept the plural `camera.intrinsics` / `camera.extrinsics` spellings and
19
+ report missing camera fields by name instead of raising `KeyError`.
20
+
3
21
  ## 2.24.0 (unreleased)
4
22
 
5
23
  Add source-backed capture, strict per-output writers, explicit NPY/PNG encoding, typed calibration views and replay. Consolidate pinhole geometry and correct legacy skew scaling.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: euler-loading
3
- Version: 2.25.0
3
+ Version: 2.26.0
4
4
  Summary: Multi-modal PyTorch dataloader using ds-crawler indices
5
5
  Project-URL: Homepage, https://github.com/d-rothen/euler-loading
6
6
  Project-URL: Repository, https://github.com/d-rothen/euler-loading
@@ -193,8 +193,26 @@ Writers exist for every modality above.
193
193
  | `depth` | 1HW / HW | float32 | `img/depth/<id>.exr`, `Z` channel, planar depth in metres |
194
194
  | `class_segmentation` | 1HW / HW | int64 | `img/class/<id>.png`, original Cityscapes label IDs |
195
195
  | `instance_segmentation` | 1HW / HW | int64 | `img/instance/<id>.png`, decoded as `R + 256 * G + 65536 * B` |
196
- | `sky_mask` | 1HW / HW | bool | Sky label ID `23` in `img/class/<id>.png` |
196
+ | `sky_mask` | 1HW / HW | bool | Sky label in `img/class/<id>.png`; ID `23` by default, or `meta['sky_class_id']` |
197
197
  | `read_intrinsics` | 3×3 | float32 | `camera.intrinsic` from `meta/<id>.json`: `fx`, `fy`, `u0`, `v0` |
198
+ | `read_extrinsics` | 4×4 | float32 | `camera.extrinsic` from `meta/<id>.json`: `x`, `y`, `z`, `pitch`, `roll`, `yaw` |
199
+
200
+ Writers exist for every modality above. `write_depth` needs a filesystem path
201
+ because OpenEXR cannot write to a stream; dataset writers hand it a temporary
202
+ file automatically, so zip outputs work unchanged. `write_sky_mask` emits a
203
+ class image labelling sky with `meta['sky_class_id']`, default 23, and
204
+ `write_intrinsics` and `write_extrinsics` merge into one `meta/<id>.json`
205
+ rather than overwriting each other or the file's `scene` and `instance`
206
+ blocks.
207
+
208
+ That merge reads the file back, so it applies to filesystem destinations and
209
+ replaces the file atomically. A zip destination is handed a fresh stream per
210
+ modality instead, so writing both camera modalities into the **same** archive
211
+ produces two entries with the same name, of which only the last is
212
+ retrievable — give each modality its own output writer. Because the merge
213
+ keeps fields it does not model, writing a rescaled matrix without passing
214
+ `meta['resx']`/`['resy']` leaves the previous resolution in place; supply them
215
+ whenever the matrix no longer matches the recorded resolution.
198
216
 
199
217
  Formats follow the [Synscapes dataset reference](https://synscapes.on.liu.se/features.html)
200
218
  and [FoggySynscapes EXR reader](https://github.com/MartinHahner/FoggySynscapes/blob/main/source/Depth_processing/exr_to_mat.py).
@@ -202,14 +220,14 @@ Depth values are already in metres, so they are returned unchanged, including
202
220
  non-finite values. Semantic labels retain the original IDs, including void
203
221
  labels, without remapping to training IDs.
204
222
 
205
- EXR loading needs the optional OpenEXR dependency:
223
+ EXR depth loading and writing need the optional OpenEXR dependency:
206
224
 
207
225
  ```bash
208
226
  pip install "euler-loading[gpu,synscapes]" # omit gpu for NumPy-only use
209
227
  ```
210
228
 
211
- RGB, segmentation and intrinsics work without OpenEXR. All six functions
212
- accept paths and binary streams. Intrinsics are stored in per-image files,
229
+ RGB, segmentation, intrinsics and extrinsics work without OpenEXR; only depth
230
+ loading and writing need it. All readers accept paths and binary streams. Intrinsics are stored in per-image files,
213
231
  so the native `meta` directory is a regular modality:
214
232
 
215
233
  ```python
@@ -224,6 +242,37 @@ dataset = MultiModalDataset(modalities={
224
242
  })
225
243
  ```
226
244
 
245
+ #### Extrinsics conventions
246
+
247
+ Synscapes records the camera mount as six scalars — `x`, `y`, `z` in metres and
248
+ `pitch`, `roll`, `yaw` in radians — in the ego-vehicle frame, which the dataset
249
+ defines as x forward, y left, z up. `read_extrinsics` composes them into a
250
+ rigid 4×4 matrix, by default the camera's pose on the vehicle
251
+ (`X_ego = T @ X_camera`). Two keys, taken from per-file `attributes` first and
252
+ then from `meta`, select the other useful conventions:
253
+
254
+ | Key | Values | Meaning |
255
+ |---|---|---|
256
+ | `transform_direction` | `camera_to_ego` (default), `ego_to_camera` | Direction of the returned transform |
257
+ | `camera_axes` | `vehicle` (default), `optical` | Camera axes: vehicle-aligned, or x right / y down / z forward |
258
+
259
+ Combine `ego_to_camera` with `optical` to project ego-frame points — such as
260
+ the 3D bounding boxes in the instance metadata — through `read_intrinsics`:
261
+
262
+ ```python
263
+ T = synscapes.read_extrinsics(
264
+ "/data/Synscapes/meta/1.json",
265
+ {"transform_direction": "ego_to_camera", "camera_axes": "optical"},
266
+ )
267
+ ```
268
+
269
+ The dataset documents the six fields and the ego frame but not the order in
270
+ which the angles compose, so the loaders apply the usual automotive
271
+ `Rz(yaw) @ Ry(pitch) @ Rx(roll)` and record that in `loaders.json` under the
272
+ modality's `rotation_order`. The values are constant across the released
273
+ dataset. `write_extrinsics` reads the same two keys, so a matrix loaded with
274
+ one set of options writes back unchanged with the same options.
275
+
227
276
  Automatic resolution uses `loader="synscapes"` in the dataset contract.
228
277
  Intrinsics describe the metadata's image resolution (native 1440×720).
229
278
  When using `img/rgb-2k` at 2048×1024, scale the camera matrix with