@@ -146,6 +146,55 @@ def duplication_check(
146146 return dedups , dups
147147
148148
149+ def _check_null_island (
150+ sequence : PointSequence ,
151+ ) -> tuple [PointSequence , list [types .ErrorMetadata ]]:
152+ """
153+ Filter out images with null island (0, 0) GPS coordinates.
154+
155+ Returns:
156+ Tuple of (valid images, error metadatas for null island images)
157+ """
158+ valid : PointSequence = []
159+ errors : list [types .ErrorMetadata ] = []
160+
161+ for image in sequence :
162+ if image .lat == 0 and image .lon == 0 :
163+ ex = exceptions .MapillaryNullIslandError (
164+ "GPS coordinates in Null Island (0, 0)"
165+ )
166+ errors .append (
167+ types .describe_error_metadata (
168+ exc = ex , filename = image .filename , filetype = types .FileType .IMAGE
169+ )
170+ )
171+ else :
172+ valid .append (image )
173+
174+ return valid , errors
175+
176+
177+ def _check_sequences_null_island (
178+ input_sequences : T .Sequence [PointSequence ],
179+ ) -> tuple [list [PointSequence ], list [types .ErrorMetadata ]]:
180+ """Apply null island check to all sequences."""
181+ output_sequences : list [PointSequence ] = []
182+ output_errors : list [types .ErrorMetadata ] = []
183+
184+ for sequence in input_sequences :
185+ output_sequence , errors = _check_null_island (sequence )
186+ if output_sequence :
187+ output_sequences .append (output_sequence )
188+ output_errors .extend (errors )
189+
190+ if output_errors :
191+ LOG .info (
192+ f"Null island check: { len (output_errors )} images removed with (0, 0) coordinates"
193+ )
194+
195+ return output_sequences , output_errors
196+
197+
149198def _group_images_by (
150199 image_metadatas : T .Iterable [types .ImageMetadata ],
151200 group_key_func : T .Callable [[types .ImageMetadata ], T .Hashable ],
@@ -310,14 +359,6 @@ def _check_sequences_by_limits(
310359 f"Sequence file size { humanize .naturalsize (sequence_filesize )} exceeds max allowed { humanize .naturalsize (max_sequence_filesize_in_bytes )} " ,
311360 )
312361
313- contains_null_island = any (
314- image .lat == 0 and image .lon == 0 for image in sequence
315- )
316- if contains_null_island :
317- raise exceptions .MapillaryNullIslandError (
318- "GPS coordinates in Null Island (0, 0)"
319- )
320-
321362 avg_speed_kmh = geo .avg_speed (sequence ) * 3.6 # Convert m/s to km/h
322363 too_fast = len (sequence ) >= 2 and avg_speed_kmh > max_capture_speed_kmh
323364 if too_fast :
@@ -765,6 +806,10 @@ def process_sequence_properties(
765806 cutoff_time = cutoff_time ,
766807 )
767808
809+ # Null island check
810+ sequences , errors = _check_sequences_null_island (sequences )
811+ error_metadatas .extend (errors )
812+
768813 # Duplication check
769814 sequences , errors = _check_sequences_duplication (
770815 sequences ,
@@ -789,7 +834,7 @@ def process_sequence_properties(
789834 error_metadatas .extend (errors )
790835
791836 # Check for zig-zag GPS patterns
792- # NOTE: This is done after _check_sequences_by_limits to filter missing or zero coordinates
837+ # NOTE: This is done after _check_sequences_null_island to filter zero coordinates
793838 if not skip_zigzag_check :
794839 sequences , errors = _check_sequences_zigzag (
795840 sequences ,
0 commit comments