OTVision 0.6.1__py3-none-any.whl → 0.6.3__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.
- OTVision/__init__.py +0 -10
- OTVision/application/detect/current_object_detector.py +1 -2
- OTVision/application/detect/detected_frame_factory.py +4 -3
- OTVision/application/detect/detected_frame_producer.py +1 -2
- OTVision/detect/builder.py +1 -1
- OTVision/detect/detected_frame_buffer.py +1 -1
- OTVision/detect/otdet.py +3 -2
- OTVision/detect/yolo.py +2 -2
- OTVision/domain/detect_producer_consumer.py +1 -1
- OTVision/domain/detection.py +128 -7
- OTVision/domain/frame.py +146 -1
- OTVision/domain/object_detection.py +1 -2
- OTVision/helpers/files.py +10 -2
- OTVision/helpers/input_types.py +15 -0
- OTVision/track/exporter/__init__.py +0 -0
- OTVision/track/exporter/filebased_exporter.py +24 -0
- OTVision/track/model/__init__.py +0 -0
- OTVision/track/model/filebased/__init__.py +0 -0
- OTVision/track/model/filebased/frame_chunk.py +203 -0
- OTVision/track/model/filebased/frame_group.py +95 -0
- OTVision/track/model/track_exporter.py +119 -0
- OTVision/track/model/tracking_interfaces.py +303 -0
- OTVision/track/parser/__init__.py +0 -0
- OTVision/track/parser/chunk_parser_plugins.py +99 -0
- OTVision/track/parser/frame_group_parser_plugins.py +127 -0
- OTVision/track/track.py +54 -332
- OTVision/track/tracker/__init__.py +0 -0
- OTVision/track/tracker/filebased_tracking.py +192 -0
- OTVision/track/tracker/tracker_plugin_iou.py +224 -0
- OTVision/version.py +1 -1
- OTVision/view/view_track.py +1 -1
- {otvision-0.6.1.dist-info → otvision-0.6.3.dist-info}/METADATA +8 -6
- {otvision-0.6.1.dist-info → otvision-0.6.3.dist-info}/RECORD +35 -23
- OTVision/track/iou.py +0 -282
- OTVision/track/iou_util.py +0 -140
- OTVision/track/preprocess.py +0 -453
- {otvision-0.6.1.dist-info → otvision-0.6.3.dist-info}/WHEEL +0 -0
- {otvision-0.6.1.dist-info → otvision-0.6.3.dist-info}/licenses/LICENSE +0 -0
OTVision/__init__.py
CHANGED
|
@@ -18,13 +18,3 @@ OTVision init module
|
|
|
18
18
|
#
|
|
19
19
|
# You should have received a copy of the GNU General Public License
|
|
20
20
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
# TODO: Might need to change this
|
|
24
|
-
from .convert.convert import main as convert
|
|
25
|
-
from .track.track import main as track
|
|
26
|
-
from .transform.transform import main as transform
|
|
27
|
-
|
|
28
|
-
# from .view.view import main as view
|
|
29
|
-
|
|
30
|
-
__all__: list = ["track", "convert", "transform"]
|
|
@@ -2,8 +2,7 @@ from typing import Generator
|
|
|
2
2
|
|
|
3
3
|
from OTVision.abstraction.pipes_and_filter import Filter
|
|
4
4
|
from OTVision.application.get_current_config import GetCurrentConfig
|
|
5
|
-
from OTVision.domain.
|
|
6
|
-
from OTVision.domain.frame import Frame
|
|
5
|
+
from OTVision.domain.frame import DetectedFrame, Frame
|
|
7
6
|
from OTVision.domain.object_detection import ObjectDetector, ObjectDetectorFactory
|
|
8
7
|
|
|
9
8
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from OTVision.domain.detection import
|
|
2
|
-
from OTVision.domain.frame import Frame, FrameKeys
|
|
1
|
+
from OTVision.domain.detection import Detection
|
|
2
|
+
from OTVision.domain.frame import DetectedFrame, Frame, FrameKeys
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class DetectedFrameFactory:
|
|
@@ -20,7 +20,8 @@ class DetectedFrameFactory:
|
|
|
20
20
|
|
|
21
21
|
return DetectedFrame(
|
|
22
22
|
source=frame[FrameKeys.source],
|
|
23
|
-
|
|
23
|
+
no=frame[FrameKeys.frame],
|
|
24
24
|
occurrence=frame[FrameKeys.occurrence],
|
|
25
25
|
detections=detections,
|
|
26
|
+
image=frame[FrameKeys.data],
|
|
26
27
|
)
|
|
@@ -2,8 +2,7 @@ from typing import Generator
|
|
|
2
2
|
|
|
3
3
|
from OTVision.abstraction.pipes_and_filter import Filter
|
|
4
4
|
from OTVision.domain.detect_producer_consumer import DetectedFrameProducer
|
|
5
|
-
from OTVision.domain.
|
|
6
|
-
from OTVision.domain.frame import Frame
|
|
5
|
+
from OTVision.domain.frame import DetectedFrame, Frame
|
|
7
6
|
from OTVision.domain.input_source_detect import InputSourceDetect
|
|
8
7
|
|
|
9
8
|
|
OTVision/detect/builder.py
CHANGED
|
@@ -42,7 +42,7 @@ from OTVision.detect.yolo import YoloDetectionConverter, YoloFactory
|
|
|
42
42
|
from OTVision.domain.cli import DetectCliParser
|
|
43
43
|
from OTVision.domain.current_config import CurrentConfig
|
|
44
44
|
from OTVision.domain.detect_producer_consumer import DetectedFrameProducer
|
|
45
|
-
from OTVision.domain.
|
|
45
|
+
from OTVision.domain.frame import DetectedFrame
|
|
46
46
|
from OTVision.domain.input_source_detect import InputSourceDetect
|
|
47
47
|
from OTVision.domain.object_detection import ObjectDetectorFactory
|
|
48
48
|
|
OTVision/detect/otdet.py
CHANGED
|
@@ -4,7 +4,8 @@ from pathlib import Path
|
|
|
4
4
|
from typing import Self
|
|
5
5
|
|
|
6
6
|
from OTVision import dataformat, version
|
|
7
|
-
from OTVision.domain.detection import
|
|
7
|
+
from OTVision.domain.detection import Detection
|
|
8
|
+
from OTVision.domain.frame import DetectedFrame
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
@dataclass
|
|
@@ -74,7 +75,7 @@ class OtdetBuilder:
|
|
|
74
75
|
converted_detections = [
|
|
75
76
|
self.__convert_detection(detection) for detection in frame.detections
|
|
76
77
|
]
|
|
77
|
-
data[str(frame.
|
|
78
|
+
data[str(frame.no)] = {
|
|
78
79
|
dataformat.DETECTIONS: converted_detections,
|
|
79
80
|
dataformat.OCCURRENCE: frame.occurrence.timestamp(),
|
|
80
81
|
}
|
OTVision/detect/yolo.py
CHANGED
|
@@ -33,8 +33,8 @@ from OTVision.abstraction.pipes_and_filter import Filter
|
|
|
33
33
|
from OTVision.application.detect.detected_frame_factory import DetectedFrameFactory
|
|
34
34
|
from OTVision.application.get_current_config import GetCurrentConfig
|
|
35
35
|
from OTVision.config import DetectConfig
|
|
36
|
-
from OTVision.domain.detection import
|
|
37
|
-
from OTVision.domain.frame import Frame, FrameKeys
|
|
36
|
+
from OTVision.domain.detection import Detection
|
|
37
|
+
from OTVision.domain.frame import DetectedFrame, Frame, FrameKeys
|
|
38
38
|
from OTVision.domain.object_detection import ObjectDetector, ObjectDetectorFactory
|
|
39
39
|
from OTVision.helpers.log import LOGGER_NAME
|
|
40
40
|
|
OTVision/domain/detection.py
CHANGED
|
@@ -1,9 +1,34 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
from OTVision.dataformat import (
|
|
4
|
+
CLASS,
|
|
5
|
+
CONFIDENCE,
|
|
6
|
+
FINISHED,
|
|
7
|
+
FIRST,
|
|
8
|
+
INTERPOLATED_DETECTION,
|
|
9
|
+
TRACK_ID,
|
|
10
|
+
H,
|
|
11
|
+
W,
|
|
12
|
+
X,
|
|
13
|
+
Y,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
TrackId = int
|
|
3
17
|
|
|
4
18
|
|
|
5
19
|
@dataclass(frozen=True, repr=True)
|
|
6
20
|
class Detection:
|
|
21
|
+
"""Detection data without track context data.
|
|
22
|
+
|
|
23
|
+
Attributes:
|
|
24
|
+
label (str): Assigned label, e.g. vehicle class.
|
|
25
|
+
conf (float): Confidence of detected class.
|
|
26
|
+
x (float): X-coordinate of detection center.
|
|
27
|
+
y (float): Y-coordinate of detection center.
|
|
28
|
+
w (float): Width of detection.
|
|
29
|
+
h (float): Height of detection.
|
|
30
|
+
"""
|
|
31
|
+
|
|
7
32
|
label: str
|
|
8
33
|
conf: float
|
|
9
34
|
x: float
|
|
@@ -11,10 +36,106 @@ class Detection:
|
|
|
11
36
|
w: float
|
|
12
37
|
h: float
|
|
13
38
|
|
|
39
|
+
def of_track(self, id: TrackId, is_first: bool) -> "TrackedDetection":
|
|
40
|
+
"""Convert to TrackedDetection by adding track information.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
id (TrackId): id of assigned track.
|
|
44
|
+
is_first (bool): whether this detection is first of track.
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
TrackedDetection: This detection data with additional track information.
|
|
48
|
+
"""
|
|
49
|
+
return TrackedDetection(
|
|
50
|
+
self.label,
|
|
51
|
+
self.conf,
|
|
52
|
+
self.x,
|
|
53
|
+
self.y,
|
|
54
|
+
self.w,
|
|
55
|
+
self.h,
|
|
56
|
+
is_first,
|
|
57
|
+
id,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
def to_otdet(self) -> dict:
|
|
61
|
+
return {
|
|
62
|
+
CLASS: self.label,
|
|
63
|
+
CONFIDENCE: self.conf,
|
|
64
|
+
X: self.x,
|
|
65
|
+
Y: self.y,
|
|
66
|
+
W: self.w,
|
|
67
|
+
H: self.h,
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass(frozen=True, repr=True)
|
|
72
|
+
class TrackedDetection(Detection):
|
|
73
|
+
"""Detection with additional track data.
|
|
74
|
+
At the time a detection is tracked,
|
|
75
|
+
it might not be known whether it is the last of a track.
|
|
76
|
+
|
|
77
|
+
Attributes:
|
|
78
|
+
is_first (bool): whether this detection is the first in the track.
|
|
79
|
+
track_id (TrackId): id of the assigned track.
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
is_first: bool
|
|
83
|
+
track_id: TrackId
|
|
84
|
+
|
|
85
|
+
def finish(self, is_last: bool, is_discarded: bool) -> "FinishedDetection":
|
|
86
|
+
return FinishedDetection.from_tracked_detection(self, is_last, is_discarded)
|
|
87
|
+
|
|
88
|
+
def as_last_detection(self, is_discarded: bool) -> "FinishedDetection":
|
|
89
|
+
return FinishedDetection.from_tracked_detection(
|
|
90
|
+
self, is_last=True, is_discarded=is_discarded
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
def as_intermediate_detection(self, is_discarded: bool) -> "FinishedDetection":
|
|
94
|
+
return FinishedDetection.from_tracked_detection(
|
|
95
|
+
self, is_last=False, is_discarded=is_discarded
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@dataclass(frozen=True, repr=True)
|
|
100
|
+
class FinishedDetection(TrackedDetection):
|
|
101
|
+
"""Detection data with extended track information including is_finished.
|
|
102
|
+
|
|
103
|
+
Attributes:
|
|
104
|
+
is_last (bool): whether this detection is the last in the track.
|
|
105
|
+
is_discarded (bool): whether the detections's track was discarded.
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
is_last: bool
|
|
109
|
+
is_discarded: bool
|
|
110
|
+
|
|
111
|
+
@classmethod
|
|
112
|
+
def from_tracked_detection(
|
|
113
|
+
cls, tracked_detection: TrackedDetection, is_last: bool, is_discarded: bool
|
|
114
|
+
) -> "FinishedDetection":
|
|
115
|
+
td = tracked_detection
|
|
116
|
+
return cls(
|
|
117
|
+
label=td.label,
|
|
118
|
+
conf=td.conf,
|
|
119
|
+
x=td.x,
|
|
120
|
+
y=td.y,
|
|
121
|
+
w=td.w,
|
|
122
|
+
h=td.h,
|
|
123
|
+
is_first=td.is_first,
|
|
124
|
+
track_id=td.track_id,
|
|
125
|
+
is_last=is_last,
|
|
126
|
+
is_discarded=is_discarded,
|
|
127
|
+
)
|
|
14
128
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
129
|
+
def to_dict(self) -> dict:
|
|
130
|
+
return {
|
|
131
|
+
CLASS: self.label,
|
|
132
|
+
CONFIDENCE: self.conf,
|
|
133
|
+
X: self.x,
|
|
134
|
+
Y: self.y,
|
|
135
|
+
W: self.w,
|
|
136
|
+
H: self.h,
|
|
137
|
+
INTERPOLATED_DETECTION: False,
|
|
138
|
+
FIRST: self.is_first,
|
|
139
|
+
FINISHED: self.is_last,
|
|
140
|
+
TRACK_ID: self.track_id,
|
|
141
|
+
}
|
OTVision/domain/frame.py
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
1
2
|
from datetime import datetime
|
|
2
|
-
from typing import Literal, Optional, TypedDict
|
|
3
|
+
from typing import Callable, Literal, Optional, Sequence, TypedDict
|
|
3
4
|
|
|
4
5
|
from numpy import ndarray
|
|
5
6
|
|
|
7
|
+
from OTVision.dataformat import FRAME, OCCURRENCE, TRACK_ID
|
|
8
|
+
from OTVision.domain.detection import (
|
|
9
|
+
Detection,
|
|
10
|
+
FinishedDetection,
|
|
11
|
+
TrackedDetection,
|
|
12
|
+
TrackId,
|
|
13
|
+
)
|
|
14
|
+
|
|
6
15
|
|
|
7
16
|
class FrameKeys:
|
|
8
17
|
"""Keys to access Frame dictionary."""
|
|
@@ -27,3 +36,139 @@ class Frame(TypedDict):
|
|
|
27
36
|
frame: int
|
|
28
37
|
source: str
|
|
29
38
|
occurrence: datetime
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
FrameNo = int
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass(frozen=True, kw_only=True)
|
|
45
|
+
class DetectedFrame:
|
|
46
|
+
"""Frame metadata, optional image and respective detections.
|
|
47
|
+
|
|
48
|
+
Attributes:
|
|
49
|
+
no (FrameNo): Frame number.
|
|
50
|
+
occurrence (datetime): Time stamp, at which frame was recorded.
|
|
51
|
+
source (str): Source from where frame was obtained, e.g. video file path.
|
|
52
|
+
detections (Sequence[Detection]): A sequence of Detections occurring in frame.
|
|
53
|
+
image (Optional[ndarray]): Optional image data of frame.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
no: FrameNo
|
|
57
|
+
occurrence: datetime
|
|
58
|
+
source: str
|
|
59
|
+
detections: Sequence[Detection]
|
|
60
|
+
image: Optional[ndarray] = None
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
IsLastFrame = Callable[[FrameNo, TrackId], bool]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@dataclass(frozen=True, kw_only=True)
|
|
67
|
+
class TrackedFrame(DetectedFrame):
|
|
68
|
+
"""Frame metadata with tracked detections.
|
|
69
|
+
Also provides additional aggregated information about:
|
|
70
|
+
observed, finished and unfinished tracks.
|
|
71
|
+
|
|
72
|
+
Attributes:
|
|
73
|
+
detections (Sequence[TrackedDetection]): overrides Frame.detections with more
|
|
74
|
+
specific type of detection.
|
|
75
|
+
observed_tracks (set[TrackId]): set of tracks of which detection occur in this
|
|
76
|
+
frame.
|
|
77
|
+
finished_tracks (set[TrackId]): track ids of tracks observed in this or prior
|
|
78
|
+
to this frame that can now be considered finished. These track ids should
|
|
79
|
+
no longer be observed/assigned in future frames. (successfully completed)
|
|
80
|
+
discarded_tracks (set[TrackId]): track ids, that are now considered discarded.
|
|
81
|
+
The corresponding tracks are no longer pursued, previous TrackedDetections
|
|
82
|
+
of these tracks are also considered discarded. Discarded tracks may be
|
|
83
|
+
observed but not finished.(unsuccessful, incomplete)
|
|
84
|
+
unfinished_tracks (set[TrackId]): observed tracks that are not yet finished
|
|
85
|
+
and were not discarded.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
detections: Sequence[TrackedDetection]
|
|
89
|
+
finished_tracks: set[TrackId]
|
|
90
|
+
discarded_tracks: set[TrackId]
|
|
91
|
+
observed_tracks: set[TrackId] = field(init=False)
|
|
92
|
+
unfinished_tracks: set[TrackId] = field(init=False)
|
|
93
|
+
|
|
94
|
+
def __post_init__(self) -> None:
|
|
95
|
+
"""
|
|
96
|
+
Derive observed and unfinished tracks from tracked detections and finished
|
|
97
|
+
track information.
|
|
98
|
+
"""
|
|
99
|
+
observed = {d.track_id for d in self.detections}
|
|
100
|
+
object.__setattr__(self, "observed_tracks", observed)
|
|
101
|
+
|
|
102
|
+
unfinished = {
|
|
103
|
+
o
|
|
104
|
+
for o in self.observed_tracks
|
|
105
|
+
if o not in self.finished_tracks and o not in self.discarded_tracks
|
|
106
|
+
}
|
|
107
|
+
object.__setattr__(self, "unfinished_tracks", unfinished)
|
|
108
|
+
|
|
109
|
+
def finish(
|
|
110
|
+
self,
|
|
111
|
+
is_last: IsLastFrame,
|
|
112
|
+
discarded_tracks: set[TrackId],
|
|
113
|
+
keep_discarded: bool = False,
|
|
114
|
+
) -> "FinishedFrame":
|
|
115
|
+
"""Turn this TrackedFrame into a finished frame
|
|
116
|
+
by adding is_finished information to all its detections.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
is_last (IsLastFrame): function to determine whether
|
|
120
|
+
a track is finished in a certain frame.
|
|
121
|
+
discarded_tracks (set[TrackId]): list of tracks considered discarded.
|
|
122
|
+
Used to mark corresponding tracks.
|
|
123
|
+
keep_discarded (bool): whether FinishedDetections marked as discarded
|
|
124
|
+
should be kept in detections list. Defaults to False.
|
|
125
|
+
Returns:
|
|
126
|
+
FinishedFrame: frame with FinishedDetections
|
|
127
|
+
"""
|
|
128
|
+
if keep_discarded:
|
|
129
|
+
detections = [
|
|
130
|
+
det.finish(
|
|
131
|
+
is_last=is_last(self.no, det.track_id),
|
|
132
|
+
is_discarded=(det.track_id in discarded_tracks),
|
|
133
|
+
)
|
|
134
|
+
for det in self.detections
|
|
135
|
+
]
|
|
136
|
+
else:
|
|
137
|
+
detections = [
|
|
138
|
+
det.finish(is_last=is_last(self.no, det.track_id), is_discarded=False)
|
|
139
|
+
for det in self.detections
|
|
140
|
+
if (det.track_id not in discarded_tracks)
|
|
141
|
+
]
|
|
142
|
+
|
|
143
|
+
return FinishedFrame(
|
|
144
|
+
no=self.no,
|
|
145
|
+
occurrence=self.occurrence,
|
|
146
|
+
source=self.source,
|
|
147
|
+
finished_tracks=self.finished_tracks,
|
|
148
|
+
detections=detections,
|
|
149
|
+
image=self.image,
|
|
150
|
+
discarded_tracks=discarded_tracks,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
@dataclass(frozen=True, kw_only=True)
|
|
155
|
+
class FinishedFrame(TrackedFrame):
|
|
156
|
+
"""TrackedFrame with FinishedDetections.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
detections (Sequence[FinishedDetection]): overrides TrackedFrame.detections
|
|
160
|
+
with more specific detection type.
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
detections: Sequence[FinishedDetection]
|
|
164
|
+
|
|
165
|
+
def to_detection_dicts(self) -> list[dict]:
|
|
166
|
+
frame_metadata = {FRAME: self.no, OCCURRENCE: self.occurrence.timestamp()}
|
|
167
|
+
|
|
168
|
+
# add frame metadata to each detection dict
|
|
169
|
+
detection_dict_list = [
|
|
170
|
+
{**detection.to_dict(), **frame_metadata} for detection in self.detections
|
|
171
|
+
]
|
|
172
|
+
|
|
173
|
+
detection_dict_list.sort(key=lambda det: det[TRACK_ID])
|
|
174
|
+
return detection_dict_list
|
|
@@ -2,8 +2,7 @@ from abc import ABC, abstractmethod
|
|
|
2
2
|
from typing import Generator
|
|
3
3
|
|
|
4
4
|
from OTVision.config import DetectConfig
|
|
5
|
-
from OTVision.domain.
|
|
6
|
-
from OTVision.domain.frame import Frame
|
|
5
|
+
from OTVision.domain.frame import DetectedFrame, Frame
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
class ObjectDetectorMetadata(ABC):
|
OTVision/helpers/files.py
CHANGED
|
@@ -329,6 +329,7 @@ def get_metadata(otdict: dict) -> dict:
|
|
|
329
329
|
# TODO: Type hint nested dict during refactoring
|
|
330
330
|
def denormalize_bbox(
|
|
331
331
|
otdict: dict,
|
|
332
|
+
file_path: Path | None = None,
|
|
332
333
|
keys_width: Union[list[str], None] = None,
|
|
333
334
|
keys_height: Union[list[str], None] = None,
|
|
334
335
|
metadata: dict[str, dict] = {},
|
|
@@ -337,6 +338,8 @@ def denormalize_bbox(
|
|
|
337
338
|
|
|
338
339
|
Args:
|
|
339
340
|
otdict (dict): dict of detections or tracks
|
|
341
|
+
file_path (Path): file path source of the given otdict
|
|
342
|
+
if all detections stem from the same file.
|
|
340
343
|
keys_width (list[str], optional): list of keys describing horizontal position.
|
|
341
344
|
Defaults to ["x", "w"].
|
|
342
345
|
keys_height (list[str], optional): list of keys describing vertical position.
|
|
@@ -351,7 +354,9 @@ def denormalize_bbox(
|
|
|
351
354
|
if keys_height is None:
|
|
352
355
|
keys_height = [dataformat.Y, dataformat.H]
|
|
353
356
|
log.debug("Denormalize frame wise")
|
|
354
|
-
otdict = _denormalize_transformation(
|
|
357
|
+
otdict = _denormalize_transformation(
|
|
358
|
+
otdict, keys_width, keys_height, metadata, file_path
|
|
359
|
+
)
|
|
355
360
|
return otdict
|
|
356
361
|
|
|
357
362
|
|
|
@@ -361,6 +366,7 @@ def _denormalize_transformation(
|
|
|
361
366
|
keys_width: list[str],
|
|
362
367
|
keys_height: list[str],
|
|
363
368
|
metadata: dict[str, dict] = {},
|
|
369
|
+
file_path: Path | None = None,
|
|
364
370
|
) -> dict:
|
|
365
371
|
"""Helper to do the actual denormalization.
|
|
366
372
|
|
|
@@ -371,6 +377,8 @@ def _denormalize_transformation(
|
|
|
371
377
|
keys_height (list[str]): list of keys describing vertical position.
|
|
372
378
|
Defaults to ["y", "h"].
|
|
373
379
|
metadata (dict[str, dict]): dict of metadata per input file.
|
|
380
|
+
file_path (Path): file path source of otdict
|
|
381
|
+
if all detections stem from the same file.
|
|
374
382
|
|
|
375
383
|
Returns:
|
|
376
384
|
dict: denormalized dict
|
|
@@ -378,7 +386,7 @@ def _denormalize_transformation(
|
|
|
378
386
|
changed_files = set()
|
|
379
387
|
|
|
380
388
|
for frame in otdict[dataformat.DATA].values():
|
|
381
|
-
input_file = frame[INPUT_FILE_PATH]
|
|
389
|
+
input_file = file_path.as_posix() if file_path else frame[INPUT_FILE_PATH]
|
|
382
390
|
metadate = metadata[input_file]
|
|
383
391
|
width = metadate[dataformat.VIDEO][dataformat.WIDTH]
|
|
384
392
|
height = metadate[dataformat.VIDEO][dataformat.HEIGHT]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
def check_types(
|
|
2
|
+
sigma_l: float, sigma_h: float, sigma_iou: float, t_min: int, t_miss_max: int
|
|
3
|
+
) -> None:
|
|
4
|
+
"""Raise ValueErrors if wrong types"""
|
|
5
|
+
|
|
6
|
+
if not isinstance(sigma_l, (int, float)):
|
|
7
|
+
raise ValueError("sigma_l has to be int or float")
|
|
8
|
+
if not isinstance(sigma_h, (int, float)):
|
|
9
|
+
raise ValueError("sigma_h has to be int or float")
|
|
10
|
+
if not isinstance(sigma_iou, (int, float)):
|
|
11
|
+
raise ValueError("sigma_iou has to be int or float")
|
|
12
|
+
if not isinstance(t_min, int):
|
|
13
|
+
raise ValueError("t_min has to be int")
|
|
14
|
+
if not isinstance(t_miss_max, int):
|
|
15
|
+
raise ValueError("t_miss_max has to be int")
|
|
File without changes
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from OTVision.config import CONFIG, DEFAULT_FILETYPE, TRACK
|
|
4
|
+
from OTVision.track.model.filebased.frame_chunk import FinishedChunk
|
|
5
|
+
from OTVision.track.model.filebased.frame_group import get_output_file
|
|
6
|
+
from OTVision.track.model.track_exporter import FinishedTracksExporter
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class FinishedChunkTrackExporter(FinishedTracksExporter[FinishedChunk]):
|
|
10
|
+
|
|
11
|
+
def __init__(self, file_type: str = CONFIG[DEFAULT_FILETYPE][TRACK]) -> None:
|
|
12
|
+
super().__init__(file_type)
|
|
13
|
+
|
|
14
|
+
def get_detection_dicts(self, container: FinishedChunk) -> list[dict]:
|
|
15
|
+
return container.to_detection_dicts()
|
|
16
|
+
|
|
17
|
+
def get_result_path(self, container: FinishedChunk) -> Path:
|
|
18
|
+
return get_output_file(container.file, self.file_type)
|
|
19
|
+
|
|
20
|
+
def get_metadata(self, container: FinishedChunk) -> dict:
|
|
21
|
+
return container.metadata
|
|
22
|
+
|
|
23
|
+
def get_frame_group_id(self, container: FinishedChunk) -> int:
|
|
24
|
+
return container.frame_group_id
|
|
File without changes
|
|
File without changes
|