Skip to content

Commit 5cf95dd

Browse files
authored
fix: EXIF extraction (#728)
* fix types * remoev the hack in direction interpolation * update the make/model extraction order * extract GPS timestamps from EXIFTOOL
1 parent 982e1fa commit 5cf95dd

2 files changed

Lines changed: 26 additions & 19 deletions

File tree

mapillary_tools/exif_read.py

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import abc
24
import datetime
35
import io
@@ -477,9 +479,9 @@ def extract_orientation(self) -> int:
477479

478480
def _extract_alternative_fields(
479481
self,
480-
fields: T.Sequence[str],
481-
field_type: T.Type[_FIELD_TYPE],
482-
) -> T.Optional[_FIELD_TYPE]:
482+
fields: T.Iterable[str],
483+
field_type: type[_FIELD_TYPE],
484+
) -> _FIELD_TYPE | None:
483485
"""
484486
Extract a value for a list of ordered fields.
485487
Return the value of the first existed field in the list
@@ -736,17 +738,7 @@ def extract_direction(self) -> T.Optional[float]:
736738
"GPS GPSImgDirection",
737739
"GPS GPSTrack",
738740
]
739-
direction = self._extract_alternative_fields(fields, float)
740-
if direction is not None:
741-
if direction > 360:
742-
# fix negative value wrongly parsed in exifread
743-
# -360 degree -> 4294966935 when converting from hex
744-
bearing1 = bin(int(direction))[2:]
745-
bearing2 = "".join([str(int(int(a) == 0)) for a in bearing1])
746-
direction = -float(int(bearing2, 2))
747-
direction %= 360
748-
749-
return direction
741+
return self._extract_alternative_fields(fields, float)
750742

751743
def extract_lon_lat(self) -> T.Optional[T.Tuple[float, float]]:
752744
lat_tag = self.tags.get("GPS GPSLatitude")
@@ -774,7 +766,9 @@ def extract_make(self) -> T.Optional[str]:
774766
"""
775767
Extract camera make
776768
"""
777-
make = self._extract_alternative_fields(["Image Make", "EXIF LensMake"], str)
769+
make = self._extract_alternative_fields(
770+
["Image Make", "EXIF Make", "EXIF LensMake"], str
771+
)
778772
if make is None:
779773
return None
780774
return make.strip()
@@ -783,7 +777,9 @@ def extract_model(self) -> T.Optional[str]:
783777
"""
784778
Extract camera model
785779
"""
786-
model = self._extract_alternative_fields(["Image Model", "EXIF LensModel"], str)
780+
model = self._extract_alternative_fields(
781+
["Image Model", "EXIF Model", "EXIF LensModel"], str
782+
)
787783
if model is None:
788784
return None
789785
return model.strip()
@@ -818,8 +814,8 @@ def extract_orientation(self) -> int:
818814
def _extract_alternative_fields(
819815
self,
820816
fields: T.Sequence[str],
821-
field_type: T.Type[_FIELD_TYPE],
822-
) -> T.Optional[_FIELD_TYPE]:
817+
field_type: type[_FIELD_TYPE],
818+
) -> _FIELD_TYPE | None:
823819
"""
824820
Extract a value for a list of ordered fields.
825821
Return the value of the first existed field in the list

mapillary_tools/exiftool_read_video.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ def _aggregate_gps_track(
8686
lon_tag: str,
8787
lat_tag: str,
8888
alt_tag: T.Optional[str] = None,
89+
gps_time_tag: T.Optional[str] = None,
8990
direction_tag: T.Optional[str] = None,
9091
ground_speed_tag: T.Optional[str] = None,
9192
) -> T.List[GPSPoint]:
@@ -161,6 +162,15 @@ def _aggregate_float_values_same_length(
161162
# aggregate speeds (optional)
162163
ground_speeds = _aggregate_float_values_same_length(ground_speed_tag)
163164

165+
# GPS timestamp (optional)
166+
epoch_time = None
167+
if gps_time_tag is not None:
168+
gps_time_text = _extract_alternative_fields(texts_by_tag, [gps_time_tag], str)
169+
if gps_time_text is not None:
170+
dt = exif_read.parse_gps_datetime(gps_time_text)
171+
if dt is not None:
172+
epoch_time = geo.as_unix_time(dt)
173+
164174
# build track
165175
track = []
166176
for timestamp, lon, lat, alt, direction, ground_speed in zip(
@@ -180,7 +190,7 @@ def _aggregate_float_values_same_length(
180190
lat=lat,
181191
alt=alt,
182192
angle=direction,
183-
epoch_time=None,
193+
epoch_time=epoch_time,
184194
fix=None,
185195
precision=None,
186196
ground_speed=ground_speed,
@@ -228,6 +238,7 @@ def _aggregate_gps_track_by_sample_time(
228238
lon_tag: str,
229239
lat_tag: str,
230240
alt_tag: T.Optional[str] = None,
241+
gps_time_tag: T.Optional[str] = None,
231242
direction_tag: T.Optional[str] = None,
232243
ground_speed_tag: T.Optional[str] = None,
233244
gps_fix_tag: T.Optional[str] = None,

0 commit comments

Comments
 (0)