evaluators 2.0.0__tar.gz → 2.1.1__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.
- {evaluators-2.0.0 → evaluators-2.1.1}/PKG-INFO +4 -1
- {evaluators-2.0.0 → evaluators-2.1.1}/pyproject.toml +5 -1
- evaluators-2.0.0/sources/evaluators/integrations/pl.py → evaluators-2.1.1/sources/evaluators/integrations/lightning.py +19 -21
- evaluators-2.1.1/sources/evaluators/memory/utils/encoding.py +148 -0
- evaluators-2.0.0/sources/evaluators/memory/utils/encoding.py +0 -102
- {evaluators-2.0.0 → evaluators-2.1.1}/README.md +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/__init__.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/_engine.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/_streams.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/cli/__main__.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/cli/memory.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/constants.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/memory/__init__.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/memory/encoded_memmap/__init__.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/memory/encoded_memmap/_reader.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/memory/encoded_memmap/_writer.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/memory/interfaces.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/memory/lmdb/__init__.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/memory/lmdb/_reader.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/memory/lmdb/_writer.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/memory/memmap/__init__.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/memory/memmap/_buffers.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/memory/memmap/_reader.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/memory/memmap/_writer.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/memory/schema.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/metrics/__init__.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/metrics/adapters/coco.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/metrics/adapters/trackeval.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/metrics/domain/depth.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/metrics/domain/dvps.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/metrics/domain/segmentation/__init__.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/metrics/domain/segmentation/_utils.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/metrics/domain/segmentation/panoptic.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/metrics/domain/segmentation/semantic.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/metrics/domain/step.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/metrics/domain/tracking.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/metrics/stats.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/presets/__init__.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/presets/cityscapes.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/presets/kitti.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/presets/semkitti.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/scheduling/__init__.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/scheduling/_catalog.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/scheduling/_partitioner.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/types.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/utils/comms.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/utils/tensor_ops.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/visuals/__init__.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/visuals/metric.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/visuals/tools/__init__.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/visuals/tools/_visualizer.py +0 -0
- {evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/visuals/tools/transform.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: evaluators
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.1
|
|
4
4
|
Summary: Various scene understanding and perception evaluation metrics.
|
|
5
5
|
Author: Kurt Stolle
|
|
6
6
|
Author-email: Kurt Stolle <kurt@computer.org>
|
|
@@ -27,7 +27,10 @@ Requires-Dist: lmdb
|
|
|
27
27
|
Requires-Dist: tifffile
|
|
28
28
|
Requires-Dist: pydantic
|
|
29
29
|
Requires-Dist: opencv-python>=4.13.0.92
|
|
30
|
+
Requires-Dist: imagecodecs>=2026.3.6
|
|
31
|
+
Requires-Dist: lightning>=2.6.1 ; extra == 'lightning'
|
|
30
32
|
Requires-Python: >=3.13, <3.14
|
|
33
|
+
Provides-Extra: lightning
|
|
31
34
|
Description-Content-Type: text/markdown
|
|
32
35
|
|
|
33
36
|
# Scalable Distributed Evaluation for Computer Vision
|
|
@@ -4,7 +4,7 @@ build-backend = "uv_build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "evaluators"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.1.1"
|
|
8
8
|
description = "Various scene understanding and perception evaluation metrics."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.13, <3.14"
|
|
@@ -35,8 +35,12 @@ dependencies = [
|
|
|
35
35
|
"tifffile",
|
|
36
36
|
"pydantic",
|
|
37
37
|
"opencv-python>=4.13.0.92",
|
|
38
|
+
"imagecodecs>=2026.3.6",
|
|
38
39
|
]
|
|
39
40
|
|
|
41
|
+
[project.optional-dependencies]
|
|
42
|
+
lightning = ["lightning>=2.6.1"]
|
|
43
|
+
|
|
40
44
|
[dependency-groups]
|
|
41
45
|
dev = [
|
|
42
46
|
"hypothesis>=6.140.2",
|
|
@@ -13,12 +13,9 @@ Exports
|
|
|
13
13
|
import logging
|
|
14
14
|
import shutil
|
|
15
15
|
from pathlib import Path
|
|
16
|
-
from typing import Type
|
|
17
16
|
|
|
18
17
|
from evaluators import MetricStream, run_offline_evaluation
|
|
19
18
|
from evaluators.memory import (
|
|
20
|
-
EncodedMemmapTemporalWriter,
|
|
21
|
-
LMDBTemporalWriter,
|
|
22
19
|
MemmapTemporalWriter,
|
|
23
20
|
TemporalWriterProtocol,
|
|
24
21
|
)
|
|
@@ -39,34 +36,33 @@ class _DistributedWriterBase(Callback):
|
|
|
39
36
|
self,
|
|
40
37
|
output_dir: str | Path,
|
|
41
38
|
*,
|
|
42
|
-
|
|
43
|
-
backend: Type[TemporalWriterProtocol] = MemmapTemporalWriter,
|
|
39
|
+
backend: type[TemporalWriterProtocol] = MemmapTemporalWriter,
|
|
44
40
|
**backend_kwargs,
|
|
45
41
|
) -> None:
|
|
46
42
|
super().__init__()
|
|
47
43
|
self.output_dir = Path(output_dir)
|
|
48
|
-
self.chunk_size_frames = chunk_size_frames
|
|
49
44
|
self.backend = backend
|
|
50
45
|
self.backend_kwargs = backend_kwargs
|
|
51
|
-
# Map: stream_name -> (MetricStream,
|
|
52
|
-
self._active_streams: dict[
|
|
46
|
+
# Map: stream_name -> (MetricStream, Backend)
|
|
47
|
+
self._active_streams: dict[
|
|
48
|
+
str, tuple[MetricStream, TemporalWriterProtocol]
|
|
49
|
+
] = {}
|
|
53
50
|
|
|
54
51
|
def _setup_streams(self, pl_module: LightningModule) -> None:
|
|
55
52
|
"""Discovers MetricStreams and binds them to dedicated writers."""
|
|
56
53
|
self._active_streams = {}
|
|
57
54
|
|
|
58
|
-
discovered_streams: list[MetricStream] = []
|
|
59
|
-
|
|
60
55
|
# Robust Discovery: Walk the module tree using standard PyTorch traversal
|
|
61
|
-
|
|
62
|
-
if isinstance(module, MetricStream)
|
|
63
|
-
|
|
56
|
+
discovered_streams: list[MetricStream] = [
|
|
57
|
+
module for module in pl_module.modules() if isinstance(module, MetricStream)
|
|
58
|
+
]
|
|
64
59
|
|
|
65
60
|
if not discovered_streams:
|
|
66
61
|
if comms.get_rank() == 0:
|
|
67
62
|
logger.warning(
|
|
68
|
-
|
|
69
|
-
|
|
63
|
+
"No MetricStreams found in %s; %s will be idle.",
|
|
64
|
+
pl_module.__class__.__name__,
|
|
65
|
+
self.__class__.__name__,
|
|
70
66
|
)
|
|
71
67
|
return
|
|
72
68
|
|
|
@@ -75,22 +71,22 @@ class _DistributedWriterBase(Callback):
|
|
|
75
71
|
stream_dir = self.output_dir / stream.name
|
|
76
72
|
|
|
77
73
|
if stream.schema is None:
|
|
78
|
-
|
|
74
|
+
msg = (
|
|
79
75
|
f"MetricStream '{stream.name}' has no schema defined. "
|
|
80
76
|
"Explicit schemas are required for storage backends."
|
|
81
77
|
)
|
|
78
|
+
raise RuntimeError(msg)
|
|
82
79
|
|
|
83
80
|
writer = self.backend(
|
|
84
81
|
output_dir=str(stream_dir),
|
|
85
82
|
schema=stream.schema,
|
|
86
|
-
chunk_size_frames=self.chunk_size_frames,
|
|
87
83
|
**self.backend_kwargs,
|
|
88
84
|
)
|
|
89
85
|
stream.bind(writer)
|
|
90
86
|
self._active_streams[stream.name] = (stream, writer)
|
|
91
87
|
|
|
92
88
|
def _close_writers(self) -> None:
|
|
93
|
-
"""
|
|
89
|
+
"""Close all writers and clears the active streams list."""
|
|
94
90
|
for name, (_, writer) in self._active_streams.items():
|
|
95
91
|
writer.close()
|
|
96
92
|
logger.debug("Closed writer for stream: %s", name)
|
|
@@ -129,7 +125,7 @@ class DistributedEvaluationCallback(_DistributedWriterBase):
|
|
|
129
125
|
output_dir: str | Path,
|
|
130
126
|
*,
|
|
131
127
|
chunk_size_frames: int = 1_000,
|
|
132
|
-
backend:
|
|
128
|
+
backend: type[TemporalWriterProtocol] = MemmapTemporalWriter,
|
|
133
129
|
keep_artifacts: bool = True,
|
|
134
130
|
**backend_kwargs,
|
|
135
131
|
) -> None:
|
|
@@ -180,7 +176,7 @@ class DistributedEvaluationCallback(_DistributedWriterBase):
|
|
|
180
176
|
comms.barrier()
|
|
181
177
|
if not self.keep_artifacts and comms.get_rank() == 0:
|
|
182
178
|
shutil.rmtree(self.output_dir)
|
|
183
|
-
|
|
179
|
+
|
|
184
180
|
self._active_streams = {}
|
|
185
181
|
|
|
186
182
|
|
|
@@ -193,6 +189,8 @@ class DistributedInferenceWriter(_DistributedWriterBase):
|
|
|
193
189
|
def on_predict_start(self, trainer: Trainer, pl_module: LightningModule) -> None:
|
|
194
190
|
self._setup_streams(pl_module)
|
|
195
191
|
|
|
196
|
-
def on_predict_epoch_end(
|
|
192
|
+
def on_predict_epoch_end(
|
|
193
|
+
self, trainer: Trainer, pl_module: LightningModule
|
|
194
|
+
) -> None:
|
|
197
195
|
self._close_writers()
|
|
198
196
|
self._active_streams = {}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Serialization Layer for LMDB Backend.
|
|
3
|
+
=====================================
|
|
4
|
+
|
|
5
|
+
Provides functional registries to convert PyTorch tensors to bytes (and back)
|
|
6
|
+
using image-specific codecs (PNG, TIFF) and generic raw formats.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import functools
|
|
10
|
+
|
|
11
|
+
import io
|
|
12
|
+
from typing import Callable, Literal
|
|
13
|
+
|
|
14
|
+
import numpy as np
|
|
15
|
+
import tifffile
|
|
16
|
+
import torch
|
|
17
|
+
import torchvision.io
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"decode_png",
|
|
21
|
+
"decode_raw",
|
|
22
|
+
"decode_tiff",
|
|
23
|
+
"encode_png",
|
|
24
|
+
"encode_raw",
|
|
25
|
+
"encode_tiff",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def encode_png(tensor: torch.Tensor) -> bytes:
|
|
30
|
+
"""
|
|
31
|
+
Encode a tensor to PNG.
|
|
32
|
+
|
|
33
|
+
Expects (C, H, W) shape and uint8 dtype.
|
|
34
|
+
"""
|
|
35
|
+
if tensor.ndim != 3:
|
|
36
|
+
msg = (
|
|
37
|
+
f"Expected 3D tensor (C, H, W) for PNG encoding, got shape: {tensor.shape}"
|
|
38
|
+
)
|
|
39
|
+
raise ValueError(msg)
|
|
40
|
+
if tensor.dtype != torch.uint8:
|
|
41
|
+
msg = f"Expected uint8 dtype for PNG encoding, got: {tensor.dtype}"
|
|
42
|
+
raise ValueError(msg)
|
|
43
|
+
|
|
44
|
+
encoded = torchvision.io.encode_png(tensor.cpu())
|
|
45
|
+
# encode_png returns a 1D uint8 tensor. Get bytes.
|
|
46
|
+
return encoded.numpy().tobytes()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def decode_png(data: bytes, device: torch.device | None = None) -> torch.Tensor:
|
|
50
|
+
"""
|
|
51
|
+
Decode PNG bytes back to a tensor.
|
|
52
|
+
"""
|
|
53
|
+
# Try decode_image which auto-detects
|
|
54
|
+
t_1d = torch.frombuffer(bytearray(data), dtype=torch.uint8)
|
|
55
|
+
tensor = torchvision.io.decode_image(
|
|
56
|
+
t_1d, mode=torchvision.io.ImageReadMode.UNCHANGED
|
|
57
|
+
)
|
|
58
|
+
if device is not None:
|
|
59
|
+
tensor = tensor.to(device)
|
|
60
|
+
return tensor
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def encode_tiff(tensor: torch.Tensor, **kwargs) -> bytes:
|
|
64
|
+
"""
|
|
65
|
+
Encode a tensor to TIFF format using ``tifffile``.
|
|
66
|
+
|
|
67
|
+
Suitable for depth maps.
|
|
68
|
+
"""
|
|
69
|
+
if tensor.ndim != 3:
|
|
70
|
+
msg = (
|
|
71
|
+
f"Expected 3D tensor (C, H, W) for TIFF encoding, got shape: {tensor.shape}"
|
|
72
|
+
)
|
|
73
|
+
raise ValueError(msg)
|
|
74
|
+
|
|
75
|
+
# Determine `imwrite` parameters based on dtype
|
|
76
|
+
if len(kwargs) > 0:
|
|
77
|
+
write = functools.partial(tifffile.imwrite, **kwargs)
|
|
78
|
+
elif tensor.is_floating_point():
|
|
79
|
+
# Assume depth maps, use LERC compression with a small error threshold of 1mm
|
|
80
|
+
write = functools.partial(
|
|
81
|
+
tifffile.imwrite,
|
|
82
|
+
compression="lerc",
|
|
83
|
+
compressionargs={"level": 0.001},
|
|
84
|
+
)
|
|
85
|
+
else:
|
|
86
|
+
# Assume segmentation masks
|
|
87
|
+
write = functools.partial(
|
|
88
|
+
tifffile.imwrite, compression="zstd", compressionargs={"level": 3}
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# Permute to (H, W, C), remove channel if C=1, then move to CPU and convert to numpy
|
|
92
|
+
arr = tensor.permute(1, 2, 0).squeeze(-1).cpu().numpy()
|
|
93
|
+
|
|
94
|
+
# Ensure C-order
|
|
95
|
+
arr = np.ascontiguousarray(arr)
|
|
96
|
+
|
|
97
|
+
# Write to an in-memory buffer and get bytes
|
|
98
|
+
with io.BytesIO() as buf:
|
|
99
|
+
write(buf, arr, **kwargs)
|
|
100
|
+
return buf.getvalue()
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def decode_tiff(data: bytes, device: torch.device | None = None) -> torch.Tensor:
|
|
104
|
+
"""
|
|
105
|
+
Decode TIFF bytes back to a tensor.
|
|
106
|
+
|
|
107
|
+
Returns a tensor in (C, H, W) format.
|
|
108
|
+
"""
|
|
109
|
+
with io.BytesIO(data) as buf:
|
|
110
|
+
arr = tifffile.imread(buf)
|
|
111
|
+
|
|
112
|
+
# tifffile returns numpy array, convert to tensor
|
|
113
|
+
tensor = torch.from_numpy(arr)
|
|
114
|
+
|
|
115
|
+
# Convert (H, W) to (H, W, 1) if single-channel
|
|
116
|
+
if tensor.ndim == 2:
|
|
117
|
+
tensor.unsqueeze_(-1)
|
|
118
|
+
|
|
119
|
+
# Permute back to (C, H, W)
|
|
120
|
+
tensor = tensor.permute(2, 0, 1)
|
|
121
|
+
|
|
122
|
+
# Move to device if specified
|
|
123
|
+
if device is not None:
|
|
124
|
+
tensor = tensor.to(device)
|
|
125
|
+
|
|
126
|
+
# Ensure contiguous memory for better performance in downstream processing
|
|
127
|
+
return tensor.contiguous()
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def encode_raw(tensor: torch.Tensor) -> bytes:
|
|
131
|
+
"""
|
|
132
|
+
Generic raw serialization using PyTorch's native save (uses zip/pickle).
|
|
133
|
+
Good for small metadata like sequence_ids or unsupported large tensors.
|
|
134
|
+
"""
|
|
135
|
+
with io.BytesIO() as buf:
|
|
136
|
+
torch.save(tensor.cpu(), buf)
|
|
137
|
+
return buf.getvalue()
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def decode_raw(data: bytes, device: torch.device | None = None) -> torch.Tensor:
|
|
141
|
+
"""
|
|
142
|
+
Decode generic raw bytes.
|
|
143
|
+
"""
|
|
144
|
+
with io.BytesIO(data) as buf:
|
|
145
|
+
tensor = torch.load(buf, weights_only=True)
|
|
146
|
+
if device is not None:
|
|
147
|
+
tensor = tensor.to(device)
|
|
148
|
+
return tensor
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Serialization Layer for LMDB Backend.
|
|
3
|
-
=====================================
|
|
4
|
-
|
|
5
|
-
Provides functional registries to convert PyTorch tensors to bytes (and back)
|
|
6
|
-
using image-specific codecs (PNG, TIFF) and generic raw formats.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
import io
|
|
10
|
-
from typing import Callable, Literal
|
|
11
|
-
|
|
12
|
-
import numpy as np
|
|
13
|
-
import tifffile
|
|
14
|
-
import torch
|
|
15
|
-
import torchvision.io
|
|
16
|
-
|
|
17
|
-
__all__ = [
|
|
18
|
-
"encode_png",
|
|
19
|
-
"decode_png",
|
|
20
|
-
"encode_tiff",
|
|
21
|
-
"decode_tiff",
|
|
22
|
-
"encode_raw",
|
|
23
|
-
"decode_raw",
|
|
24
|
-
]
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def encode_png(tensor: torch.Tensor) -> bytes:
|
|
28
|
-
"""
|
|
29
|
-
Encodes a tensor to PNG.
|
|
30
|
-
Expects (C, H, W) or (H, W). If uint8 is not the dtype, it casts (assumes categorical mask).
|
|
31
|
-
"""
|
|
32
|
-
if tensor.ndim == 2:
|
|
33
|
-
tensor = tensor.unsqueeze(0)
|
|
34
|
-
if tensor.dtype != torch.uint8:
|
|
35
|
-
# Warning: For segmentation masks, values > 255 will be clipped if not handled carefully,
|
|
36
|
-
# but typically panoptic ids or labels are packed, or we only support uint8 for png.
|
|
37
|
-
# Actually, PNG can support 16-bit. torchvision's encode_png only supports uint8.
|
|
38
|
-
# If >255, we should probably fall back to raw or use a different encoder.
|
|
39
|
-
if tensor.max() > 255:
|
|
40
|
-
return encode_raw(tensor)
|
|
41
|
-
tensor = tensor.to(torch.uint8)
|
|
42
|
-
|
|
43
|
-
encoded = torchvision.io.encode_png(tensor.cpu())
|
|
44
|
-
# encode_png returns a 1D uint8 tensor. Get bytes.
|
|
45
|
-
return encoded.numpy().tobytes()
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def decode_png(data: bytes, device: torch.device | None = None) -> torch.Tensor:
|
|
49
|
-
"""
|
|
50
|
-
Decodes PNG bytes back to a tensor.
|
|
51
|
-
"""
|
|
52
|
-
# Try decode_image which auto-detects
|
|
53
|
-
t_1d = torch.frombuffer(bytearray(data), dtype=torch.uint8)
|
|
54
|
-
tensor = torchvision.io.decode_image(t_1d, mode=torchvision.io.ImageReadMode.UNCHANGED)
|
|
55
|
-
if device is not None:
|
|
56
|
-
tensor = tensor.to(device)
|
|
57
|
-
return tensor
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
def encode_tiff(tensor: torch.Tensor) -> bytes:
|
|
61
|
-
"""
|
|
62
|
-
Encodes a tensor to TIFF format using tifffile. Suitable for depth maps.
|
|
63
|
-
"""
|
|
64
|
-
arr = tensor.cpu().numpy()
|
|
65
|
-
with io.BytesIO() as buf:
|
|
66
|
-
tifffile.imwrite(buf, arr)
|
|
67
|
-
return buf.getvalue()
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def decode_tiff(data: bytes, device: torch.device | None = None) -> torch.Tensor:
|
|
71
|
-
"""
|
|
72
|
-
Decodes TIFF bytes back to a tensor.
|
|
73
|
-
"""
|
|
74
|
-
with io.BytesIO(data) as buf:
|
|
75
|
-
arr = tifffile.imread(buf)
|
|
76
|
-
|
|
77
|
-
# tifffile returns numpy array, convert to tensor
|
|
78
|
-
tensor = torch.from_numpy(arr)
|
|
79
|
-
if device is not None:
|
|
80
|
-
tensor = tensor.to(device)
|
|
81
|
-
return tensor
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
def encode_raw(tensor: torch.Tensor) -> bytes:
|
|
85
|
-
"""
|
|
86
|
-
Generic raw serialization using PyTorch's native save (uses zip/pickle).
|
|
87
|
-
Good for small metadata like sequence_ids or unsupported large tensors.
|
|
88
|
-
"""
|
|
89
|
-
with io.BytesIO() as buf:
|
|
90
|
-
torch.save(tensor.cpu(), buf)
|
|
91
|
-
return buf.getvalue()
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
def decode_raw(data: bytes, device: torch.device | None = None) -> torch.Tensor:
|
|
95
|
-
"""
|
|
96
|
-
Decodes generic raw bytes.
|
|
97
|
-
"""
|
|
98
|
-
with io.BytesIO(data) as buf:
|
|
99
|
-
tensor = torch.load(buf, weights_only=True)
|
|
100
|
-
if device is not None:
|
|
101
|
-
tensor = tensor.to(device)
|
|
102
|
-
return tensor
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/metrics/domain/segmentation/__init__.py
RENAMED
|
File without changes
|
{evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/metrics/domain/segmentation/_utils.py
RENAMED
|
File without changes
|
{evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/metrics/domain/segmentation/panoptic.py
RENAMED
|
File without changes
|
{evaluators-2.0.0 → evaluators-2.1.1}/sources/evaluators/metrics/domain/segmentation/semantic.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|