2
2
import itertools
3
3
import math
4
4
import typing as T
5
+ import logging
5
6
6
7
from . import constants , geo , types
7
8
from .exceptions import MapillaryDuplicationError , MapillaryBadParameterError
8
9
10
+ LOG = logging .getLogger (__name__ )
11
+
9
12
10
13
Point = T .TypeVar ("Point" , bound = geo .Point )
11
14
PointSequence = T .List [Point ]
@@ -95,26 +98,63 @@ def cut_sequence(
95
98
sequence : T .List [types .ImageMetadata ],
96
99
max_images : int ,
97
100
max_sequence_filesize : int ,
101
+ max_sequence_pixels : int ,
98
102
) -> T .List [T .List [types .ImageMetadata ]]:
99
103
"""
100
104
Cut a sequence into multiple sequences by max_images or max filesize
101
105
"""
102
106
sequences : T .List [T .List [types .ImageMetadata ]] = []
103
107
last_sequence_file_size = 0
108
+ last_sequence_pixels = 0
109
+
104
110
for image in sequence :
111
+ # decent default values if width/height not available
112
+ width = 1024 if image .width is None else image .width
113
+ height = 1024 if image .height is None else image .height
114
+
105
115
filesize = os .path .getsize (image .filename )
106
- if len (sequences ) == 0 or (
107
- sequences [- 1 ]
108
- and (
109
- max_images < len (sequences [- 1 ])
110
- or max_sequence_filesize < last_sequence_file_size + filesize
111
- )
112
- ):
116
+
117
+ if len (sequences ) == 0 :
118
+ start_new_sequence = True
119
+ else :
120
+ if sequences [- 1 ]:
121
+ if max_images < len (sequences [- 1 ]):
122
+ LOG .debug (
123
+ "Cut the sequence because the current sequence (%s) reaches the max number of images (%s)" ,
124
+ len (sequences [- 1 ]),
125
+ max_images ,
126
+ )
127
+ start_new_sequence = True
128
+ elif max_sequence_filesize < last_sequence_file_size + filesize :
129
+ LOG .debug (
130
+ "Cut the sequence because the current sequence (%s) reaches the max filesize (%s)" ,
131
+ last_sequence_file_size + filesize ,
132
+ max_sequence_filesize ,
133
+ )
134
+ start_new_sequence = True
135
+ elif max_sequence_pixels < last_sequence_pixels + width * height :
136
+ LOG .debug (
137
+ "Cut the sequence because the current sequence (%s) reaches the max pixels (%s)" ,
138
+ last_sequence_pixels + width * height ,
139
+ max_sequence_pixels ,
140
+ )
141
+ start_new_sequence = True
142
+ else :
143
+ start_new_sequence = False
144
+ else :
145
+ start_new_sequence = False
146
+
147
+ if start_new_sequence :
113
148
sequences .append ([])
114
149
last_sequence_file_size = 0
150
+ last_sequence_pixels = 0
151
+
115
152
sequences [- 1 ].append (image )
116
153
last_sequence_file_size += filesize
154
+ last_sequence_pixels += width * height
155
+
117
156
assert sum (len (s ) for s in sequences ) == len (sequence )
157
+
118
158
return sequences
119
159
120
160
@@ -192,8 +232,21 @@ def _parse_filesize_in_bytes(filesize_str: str) -> int:
192
232
return int (filesize_str )
193
233
194
234
235
+ def _parse_pixels (pixels_str : str ) -> int :
236
+ pixels_str = pixels_str .strip ().upper ()
237
+
238
+ if pixels_str .endswith ("K" ):
239
+ return int (pixels_str [:- 1 ]) * 1000
240
+ elif pixels_str .endswith ("M" ):
241
+ return int (pixels_str [:- 1 ]) * 1000 * 1000
242
+ elif pixels_str .endswith ("G" ):
243
+ return int (pixels_str [:- 1 ]) * 1000 * 1000 * 1000
244
+ else :
245
+ return int (pixels_str )
246
+
247
+
195
248
def process_sequence_properties (
196
- metadatas : T .List [types .MetadataOrError ],
249
+ metadatas : T .Sequence [types .MetadataOrError ],
197
250
cutoff_distance = constants .CUTOFF_DISTANCE ,
198
251
cutoff_time = constants .CUTOFF_TIME ,
199
252
interpolate_directions = False ,
@@ -209,6 +262,13 @@ def process_sequence_properties(
209
262
f"Expect the envvar { constants ._ENV_PREFIX } MAX_SEQUENCE_FILESIZE to be a valid filesize that ends with B, K, M, or G, but got { constants .MAX_SEQUENCE_FILESIZE } "
210
263
)
211
264
265
+ try :
266
+ max_sequence_pixels = _parse_pixels (constants .MAX_SEQUENCE_PIXELS )
267
+ except ValueError :
268
+ raise MapillaryBadParameterError (
269
+ f"Expect the envvar { constants ._ENV_PREFIX } MAX_SEQUENCE_PIXELS to be a valid number of pixels that ends with K, M, or G, but got { constants .MAX_SEQUENCE_PIXELS } "
270
+ )
271
+
212
272
error_metadatas : T .List [types .ErrorMetadata ] = []
213
273
image_metadatas : T .List [types .ImageMetadata ] = []
214
274
video_metadatas : T .List [types .VideoMetadata ] = []
@@ -262,6 +322,7 @@ def process_sequence_properties(
262
322
dedups ,
263
323
constants .MAX_SEQUENCE_LENGTH ,
264
324
max_sequence_filesize_in_bytes ,
325
+ max_sequence_pixels ,
265
326
)
266
327
267
328
for c in cut :
0 commit comments