Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 10 additions & 26 deletions mapillary_tools/process_sequence_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,43 +337,28 @@ def _video_name(video_metadata: types.VideoMetadata) -> str:

def _check_sequences_by_limits(
input_sequences: T.Sequence[PointSequence],
max_sequence_filesize_in_bytes: int | None,
max_capture_speed_kmh: float,
) -> tuple[list[PointSequence], list[types.ErrorMetadata]]:
output_sequences: list[PointSequence] = []
output_errors: list[types.ErrorMetadata] = []

for sequence in input_sequences:
try:
if max_sequence_filesize_in_bytes is not None:
sequence_filesize = sum(
(
utils.get_file_size(image.filename)
if image.filesize is None
else image.filesize
)
for image in sequence
)
if sequence_filesize > max_sequence_filesize_in_bytes:
raise exceptions.MapillaryFileTooLargeError(
f"Sequence file size {humanize.naturalsize(sequence_filesize)} exceeds max allowed {humanize.naturalsize(max_sequence_filesize_in_bytes)}",
)
avg_speed_kmh = geo.avg_speed(sequence) * 3.6 # Convert m/s to km/h
too_fast = len(sequence) >= 2 and avg_speed_kmh > max_capture_speed_kmh

avg_speed_kmh = geo.avg_speed(sequence) * 3.6 # Convert m/s to km/h
too_fast = len(sequence) >= 2 and avg_speed_kmh > max_capture_speed_kmh
if too_fast:
raise exceptions.MapillaryCaptureSpeedTooFastError(
f"Capture speed {avg_speed_kmh:.3f} km/h exceeds max allowed {max_capture_speed_kmh:.3f} km/h",
)
except exceptions.MapillaryDescriptionError as ex:
LOG.error(f"{_sequence_name(sequence)}: {ex}")
if too_fast:
error = exceptions.MapillaryCaptureSpeedTooFastError(
f"Capture speed {avg_speed_kmh:.3f} km/h exceeds max allowed {max_capture_speed_kmh:.3f} km/h",
)
LOG.error(f"{_sequence_name(sequence)}: {error}")
for image in sequence:
output_errors.append(
types.describe_error_metadata(
exc=ex, filename=image.filename, filetype=types.FileType.IMAGE
exc=error,
filename=image.filename,
filetype=types.FileType.IMAGE,
)
)

else:
output_sequences.append(sequence)

Expand Down Expand Up @@ -864,7 +849,6 @@ def process_sequence_properties(
# Check limits for sequences
sequences, errors = _check_sequences_by_limits(
sequences,
max_sequence_filesize_in_bytes=max_sequence_filesize_in_bytes,
max_capture_speed_kmh=max_capture_speed_kmh,
)
error_metadatas.extend(errors)
Expand Down
25 changes: 25 additions & 0 deletions tests/unit/test_sequence_processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,31 @@ def test_zigzag_detection_uturn_not_triggered(tmpdir: py.path.local):
assert len(image_metadatas) > 0


def test_capture_speed_exceeds_limit(tmpdir: py.path.local):
"""Test that sequences with speed exceeding the limit are rejected."""
# Create a sequence that moves very fast (> 400 km/h)
# At the equator: 0.01 degrees ≈ 1.11 km
# Moving 0.01 degrees in 1 second = 1.11 km/s = 4000 km/h (well above 400 km/h limit)
sequence = [
_make_image_metadata(
Path(tmpdir) / Path("./fast1.jpg"), 1.0, 1.0, 0, filesize=1
),
_make_image_metadata(
Path(tmpdir) / Path("./fast2.jpg"), 1.0, 1.01, 1, filesize=1
),
]

metadatas = psp.process_sequence_properties(sequence)
error_metadatas = [d for d in metadatas if isinstance(d, types.ErrorMetadata)]

# All images should be rejected due to speed limit
assert len(error_metadatas) == 2
assert all(
isinstance(d.error, exceptions.MapillaryCaptureSpeedTooFastError)
for d in error_metadatas
)


def test_zigzag_backwards_walk_single_deviation(tmpdir: py.path.local):
"""Test backwards walk with a single deviation point.

Expand Down