Skip to content

Instantly share code, notes, and snippets.

@smsm1
Last active August 29, 2015 14:27
Show Gist options
  • Save smsm1/8c1ab74229d0ca7c5937 to your computer and use it in GitHub Desktop.
Save smsm1/8c1ab74229d0ca7c5937 to your computer and use it in GitHub Desktop.
Tweaks to Mapilary python upload scripts which make it easier to upload multiple folders. See readme below.

Tweaks to Mapilary python upload scripts which make it easier to upload multiple folders. The upload_with_authentication.py script has been modified so that it automatically confirms all uploads. Occasionally there are upload connection errors, in which case a control+c will cancel the blocked thread and move on to the next upload. Assumes you have the python scripts checked out from Github.

Github scripts: https://github.com/mapillary/mapillary_tools/tree/master/python

Mapillary blog post at http://blog.mapillary.com/technology/2014/07/21/upload-scripts.html

#!/bin/bash -ex
for FOLDER in $1/*/ ; do
echo $FOLDER
python time_split.py $FOLDER
done
#!/bin/bash -e
# Ensure that you have recently logged into the Mapillary website
# Go to http://api.mapillary.com/v1/u/uploadhashes
# Then use the parameters to fill in the following parameters:
export MAPILLARY_SIGNATURE_HASH="..."
export MAPILLARY_PERMISSION_HASH="..."
export MAPILLARY_USERNAME="..."
for FOLDER in $1/*/ ; do
#FOLDER=$1
for SUBFOLDER in $FOLDER*/ ; do
echo $SUBFOLDER
python upload_with_authentication.py $SUBFOLDER
done
done
#!/usr/bin/python
import sys
import urllib2, urllib
import os
from Queue import Queue
import uuid
import exifread
import time
from upload import create_dirs, UploadThread, upload_file
'''
Script for uploading images taken with other cameras than
the Mapillary iOS or Android apps.
Intended use is for when you have used an action camera such as a GoPro
or Garmin VIRB, or any other camera where the location is included in the image EXIF.
The following EXIF tags are required:
-GPSLongitude
-GPSLatitude
-(GPSDateStamp and GPSTimeStamp) or DateTimeOriginal or DateTimeDigitized or DateTime
-Orientation
Before uploading put all images that belong together in a sequence, in a
specific folder, for example using 'time_split.py'. All images in a session
will be considered part of a single sequence.
NB: DO NOT USE THIS SCRIPT ON IMAGE FILES FROM THE MAPILLARY APPS,
USE UPLOAD.PY INSTEAD.
(assumes Python 2.x, for Python 3.x you need to change some module names)
'''
MAPILLARY_UPLOAD_URL = "https://mapillary.uploads.manual.images.s3-eu-west-1.amazonaws.com"
NUMBER_THREADS = 4
def upload_done_file(params):
print("Upload a DONE file to tell the backend that the sequence is all uploaded and ready to submit.")
if not os.path.exists('DONE'):
open("DONE", 'a').close()
#upload
upload_file("DONE", **params)
#remove
os.remove("DONE")
def verify_exif(filename):
'''
Check that image file has the required EXIF fields.
Incompatible files will be ignored server side.
'''
# required tags in IFD name convention
required_exif = [["GPS GPSLongitude"], ["GPS GPSLatitude"], ["EXIF DateTimeOriginal","EXIF DateTimeDigitized","Image DateTime","GPS GPSDate"], ["Image Orientation"]]
description_tag = "Image ImageDescription"
with open(filename, 'rb') as f:
tags = exifread.process_file(f)
# make sure no Mapillary tags
if description_tag in tags:
if "MAPSequenceUUID" in tags[description_tag].values:
print("File contains Mapillary EXIF tags, use upload.py instead.")
return False
# make sure all required tags are there
for rexif in required_exif:
vflag = False
for subrexif in rexif:
if subrexif in tags:
vflag = True
if not vflag:
print("Missing required EXIF tag: {0}".format(rexif[0]))
return False
return True
if __name__ == '__main__':
'''
Use from command line as: python upload_with_authentication.py path
You need to set the environment variables MAPILLARY_USERNAME,
MAPILLARY_PERMISSION_HASH and MAPILLARY_SIGNATURE_HASH to your
unique values.
You also need upload.py in the same folder or in your PYTHONPATH since this
script uses pieces of that.
'''
if len(sys.argv) > 2:
print("Usage: python upload_with_authentication.py path")
raise IOError("Bad input parameters.")
path = sys.argv[1]
# if no success/failed folders, create them
create_dirs()
if path.lower().endswith(".jpg"):
# single file
file_list = [path]
else:
# folder(s)
file_list = []
for root, sub_folders, files in os.walk(path):
file_list += [os.path.join(root, filename) for filename in files if filename.lower().endswith(".jpg")]
# get env variables
try:
MAPILLARY_USERNAME = os.environ['MAPILLARY_USERNAME']
MAPILLARY_PERMISSION_HASH = os.environ['MAPILLARY_PERMISSION_HASH']
MAPILLARY_SIGNATURE_HASH = os.environ['MAPILLARY_SIGNATURE_HASH']
except KeyError:
print("You are missing one of the environment variables MAPILLARY_USERNAME, MAPILLARY_PERMISSION_HASH or MAPILLARY_SIGNATURE_HASH. These are required.")
sys.exit()
# generate a sequence UUID
sequence_id = uuid.uuid4()
# S3 bucket
s3_bucket = MAPILLARY_USERNAME+"/"+str(sequence_id)+"/"
print("Uploading sequence {0}.".format(sequence_id))
# set upload parameters
params = {"url": MAPILLARY_UPLOAD_URL, "key": s3_bucket,
"permission": MAPILLARY_PERMISSION_HASH, "signature": MAPILLARY_SIGNATURE_HASH,
"move_files":False}
# create upload queue with all files
q = Queue()
for filepath in file_list:
if verify_exif(filepath):
q.put(filepath)
else:
print("Skipping: {0}".format(filepath))
# create uploader threads with permission parameters
uploaders = [UploadThread(q, params) for i in range(NUMBER_THREADS)]
# start uploaders as daemon threads that can be stopped (ctrl-c)
try:
for uploader in uploaders:
uploader.daemon = True
uploader.start()
for uploader in uploaders:
uploaders[i].join(1)
while q.unfinished_tasks:
time.sleep(1)
q.join()
except (KeyboardInterrupt, SystemExit):
print("\nBREAK: Stopping upload.")
sys.exit()
# ask user if finalize upload to check that everything went fine
# print("===\nFinalizing upload will submit all successful uploads and ignore all failed.\nIf all files were marked as successful, everything is fine, just press 'y'.")
# ask 3 times if input is unclear
# for i in range(3):
# proceed = raw_input("Finalize upload? [y/n]: ")
# if proceed in ["y", "Y", "yes", "Yes"]:
# upload an empty DONE file
upload_done_file(params)
print("Done uploading.")
# break
# elif proceed in ["n", "N", "no", "No"]:
# print("Aborted. No files were submitted. Try again if you had failures.")
# break
# else:
# if i==2:
# print("Aborted. No files were submitted. Try again if you had failures.")
# else:
# print('Please answer y or n. Try again.')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment