Skip to content

Instantly share code, notes, and snippets.

@peterneubauer
Last active October 17, 2017 23:45
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peterneubauer/288633b8ae0358fa53ae to your computer and use it in GitHub Desktop.
Save peterneubauer/288633b8ae0358fa53ae to your computer and use it in GitHub Desktop.

Bulk-uploading images taken outside Mapillary apps

Prepare the data

Copy the images from your Action Cam into a folder structure where every folder contains the images that will form one sequence (taken in consequtive 2s intervals)

tree  ~/Downloads/colombia 
/Users/peterneubauer/Downloads/colombia
└── 01
    ├── 01_0016.jpg
    ├── 01_0017.jpg
    └── 01_0018.jpg

1 directory, 3 files

Install exiftool

brew install exiftool

Clone the Mapillary Tools git repo

git clone git@github.com:mapillary/mapillary_tools.git
cd mapillary_tools/python

Inspect the original image

For a GoPro image:

exiftool ~/Downloads/colombia/01/01_0116.jpg 
ExifTool Version Number         : 9.76
File Name                       : 01_0116.jpg
Directory                       : /Users/peterneubauer/Downloads/colombia/01
File Size                       : 126 kB
File Modification Date/Time     : 2015:07:19 18:11:12+02:00
File Access Date/Time           : 2015:08:07 10:06:05+02:00
File Inode Change Date/Time     : 2015:08:07 10:06:05+02:00
File Permissions                : rw-r--r--
File Type                       : JPEG
MIME Type                       : image/jpeg
Exif Byte Order                 : Little-endian (Intel, II)
Date/Time Original              : 2015:07:19 11:13:09
GPS Version ID                  : 2.3.0.0
GPS Latitude Ref                : North
GPS Longitude Ref               : West
GPS Altitude Ref                : Above Sea Level
GPS Time Stamp                  : 16:11:12
GPS Speed Ref                   : km/h
GPS Speed                       : 21.73915678
GPS Date Stamp                  : 2015:07:19
Comment                         : Lavc56.26.100
Image Width                     : 1920
Image Height                    : 1080
Encoding Process                : Baseline DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 3
Y Cb Cr Sub Sampling            : YCbCr4:2:0 (2 2)
GPS Altitude                    : 1591.2 m Above Sea Level
GPS Date/Time                   : 2015:07:19 16:11:12Z
GPS Latitude                    : 4 deg 43' 26.79" N
GPS Longitude                   : 75 deg 42' 11.08" W
GPS Position                    : 4 deg 43' 26.79" N, 75 deg 42' 11.08" W
Image Size                      : 1920x1080

Try to create the Mapillary EXIF tag from the EXIF information

Check what's missing

Try to execute

MAPILLARY_USERNAME=peterneubauer MAPILLARY_EMAIL=neubauer.peter@gmail.com MAPILLARY_PASSWORD=xxx python add_mapillary_tag_from_exif.py   ~/Downloads/colombia

Gets the response:

Processing /Users/peterneubauer/Downloads/colombia/01/01_0016.jpg
Missing required EXIF tag: Exif.Image.Orientation

Add image orientation to EXIF

This means the image orientation tag is missing from the image. Easiest is to process all images in that folder and add it with exiftool. If the image is in landscape mode, the orientation value i 1:

exiftool -Orientation=1 -n ~/Downloads/colombia/01/*
1 image files updated

Checking the tags with exiftool gives us:

exiftool /Users/peterneubauer/Downloads/colombia/01/01_0016.jpg
ExifTool Version Number         : 9.76
File Name                       : 01_0016.jpg
...
Orientation                     : Horizontal (normal)
...
GPS Position                    : 4 deg 43' 32.32" N, 75 deg 41' 40.90" W
Image Size                      : 1920x1080

So the Orientation tag is there now.

Checking the tag creation again, we can see it's ok now:

MAPILLARY_USERNAME=peterneubauer MAPILLARY_EMAIL=neubauer.peter@gmail.com MAPILLARY_PASSWORD=xxx python add_mapillary_tag_from_exif.py   ~/Downloads/colombia
Processing /Users/peterneubauer/Downloads/colombia/01/01_0016.jpg
tag: {"MAPSequenceUUID": "2812055a-4155-4bb0-aa4e-972178a33da6", "MAPSettingsEmail": "neubauer.peter@gmail.com", "MAPOrientation": 1, "MAPPhotoUUID": "31084511-d968-4321-a569-339131fca280", "MAPDeviceMake": "none", "MAPDeviceModel": "none", "MAPLongitude": -75.694694, "MAPSettingsUsername": "peterneubauer", "MAPCaptureTime": "2015_07_19_11_04_56_000", "MAPLatitude": 4.725645, "MAPSettingsUploadHash": "8d5302b0bced0e7523e436718d5777118c37fd80231bf36646b889ff8b4b7f70", "MAPCompassHeading": {"TrueHeading": 0, "MagneticHeading": 0}}
...

Check and add image direction to EXIF

This is good, however, the MAPCompassHeading is 0 since it is missing from the EXIF (the action camera did not have a compass). Let's adjust the EXIF to add the direction.

In order to interpolate the direction from the previous images position with an offset of 270 degress (the images are pointing out of the left window of a driving car, catching the highway shoulder)

python interpolate_direction.py   ~/Downloads/colombia/01  270 
Added direction to: /Users/peterneubauer/Downloads/colombia/01/01_0016.jpg (25.4 degrees)
Added direction to: /Users/peterneubauer/Downloads/colombia/01/01_0017.jpg (22.4 degrees)
Added direction to: /Users/peterneubauer/Downloads/colombia/01/01_0018.jpg (22.4 degrees)

And a short check with exiftool confirms the new Direction ag in EXIF:

exiftool /Users/peterneubauer/Downloads/colombia/01/01_0016.jpg
File Name                       : 01_0016.jpg
...
Orientation                     : Horizontal (normal)
GPS Img Direction Ref           : True North
GPS Img Direction               : 25.4
...

Now adding the tag again will write that into the Mapillary Tag of the images in the folder:

MAPILLARY_USERNAME=peterneubauer MAPILLARY_EMAIL=neubauer.peter@gmail.com MAPILLARY_PASSWORD=xxx python add_mapillary_tag_from_exif.py   ~/Downloads/colombia
Processing /Users/peterneubauer/Downloads/colombia/01/01_0016.jpg
tag: {"MAPSequenceUUID": "b386a86e-7da9-4703-9c2d-46053b0b8042", "MAPSettingsEmail": "neubauer.peter@gmail.com", "MAPOrientation": 1, "MAPPhotoUUID": "1ba62b31-47ea-412a-8daa-407be766d8e4", "MAPDeviceMake": "none", "MAPDeviceModel": "none", "MAPLongitude": -75.694694, "MAPSettingsUsername": "peterneubauer", "MAPCaptureTime": "2015_07_19_11_04_56_000", "MAPLatitude": 4.725645, "MAPSettingsUploadHash": "8d5302b0bced0e7523e436718d5777118c37fd80231bf36646b889ff8b4b7f70", "MAPCompassHeading": {"TrueHeading": 25.4, "MagneticHeading": 25.4}}
Processing /Users/peterneubauer/Downloads/colombia/01/01_0017.jpg
tag: {"MAPSequenceUUID": "e4826195-6874-4671-988d-c379319c1046", "MAPSettingsEmail": "neubauer.peter@gmail.com", "MAPOrientation": 1, "MAPPhotoUUID": "153e94bd-c6f4-4590-b4d9-d647a7d8dd9a", "MAPDeviceMake": "none", "MAPDeviceModel": "none", "MAPLongitude": -75.69465600000001, "MAPSettingsUsername": "peterneubauer", "MAPCaptureTime": "2015_07_19_11_04_57_000", "MAPLatitude": 4.725627, "MAPSettingsUploadHash": "4bc6e2fd3c64f801247d57cdac066b29658a1ad786c5e49bbb48e642e768405c", "MAPCompassHeading": {"TrueHeading": 22.4, "MagneticHeading": 22.4}}
...

Adjust the Mapillary tag to make one sequence per folder

As you can see, the MAPSequenceUUID is unique and different for every image. In order to set it to the same for all images in a folder, do this:

MAPILLARY_USERNAME=peterneubauer MAPILLARY_EMAIL=neubauer.peter@gmail.com MAPILLARY_PASSWORD=xxx python convert_each_folder_into_one_sequence.py   ~/Downloads/colombia/01 
Processing folder /Users/peterneubauer/Downloads/colombia/01 with sequence_id 87a44693-5085-4b46-b14a-209ad3763a09.
Processing /Users/peterneubauer/Downloads/colombia/01/01_0016.jpg
tag: {"MAPSequenceUUID": "87a44693-5085-4b46-b14a-209ad3763a09", "MAPSettingsEmail": "neubauer.peter@gmail.com", "MAPOrientation": 1, "MAPPhotoUUID": "c50bdd23-d917-4418-a2ba-9396bd1c4a4e", "MAPDeviceMake": "none", "MAPDeviceModel": "none", "MAPLongitude": -75.694694, "MAPSettingsUsername": "peterneubauer", "MAPCaptureTime": "2015_07_19_11_04_56_000", "MAPLatitude": 4.725645, "MAPSettingsUploadHash": "8d5302b0bced0e7523e436718d5777118c37fd80231bf36646b889ff8b4b7f70", "MAPCompassHeading": {"TrueHeading": 25.4, "MagneticHeading": 25.4}}
Processing /Users/peterneubauer/Downloads/colombia/01/01_0017.jpg
tag: {"MAPSequenceUUID": "87a44693-5085-4b46-b14a-209ad3763a09", "MAPSettingsEmail": "neubauer.peter@gmail.com", "MAPOrientation": 1, "MAPPhotoUUID": "bb357525-89fc-4e54-9d14-d23962821955", "MAPDeviceMake": "none", "MAPDeviceModel": "none", "MAPLongitude": -75.69465600000001, "MAPSettingsUsername": "peterneubauer", "MAPCaptureTime": "2015_07_19_11_04_57_000", "MAPLatitude": 4.725627, "MAPSettingsUploadHash": "4bc6e2fd3c64f801247d57cdac066b29658a1ad786c5e49bbb48e642e768405c", "MAPCompassHeading": {"TrueHeading": 22.4, "MagneticHeading": 22.4}}
...

As you can see, all images in the same folder now have the MAPSequenceUUID of 87a44693-5085-4b46-b14a-209ad3763a09, makeing them join the same sequence in Mapillary.

Upload the images

Now you are ready to upload the images to mapillary, simply by pointing upload.py to the root folder of your material:

python upload.py ~/Downloads/colombia/   
Uploading: 01_0016.jpg
Uploading: 01_0017.jpg
Uploading: 01_0018.jpg

/peter

@Blackbird27
Copy link

How come when inspecting original image from GoPro it already has tags in exif header:

GPS Altitude : 1591.2 m Above Sea Level
GPS Date/Time : 2015:07:19 16:11:12Z
GPS Latitude : 4 deg 43' 26.79" N
GPS Longitude : 75 deg 42' 11.08" W
GPS Position : 4 deg 43' 26.79" N, 75 deg 42' 11.08" W

GoPro doesn't have built in GPS unit. It would be wise to add to instruction that images were previously tagged with GPS info from GPX file and how exactly it was done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment