Package: mapillary-tools
mapillary_tools is a command line tool that uploads geotagged images and videos to Mapillary.# Install mapillary_toolspipinstallmapillary_tools# Process and upload images and videos in the directorymapillary_toolsprocess_and_uploadMY_CAPTURE_DIR# List all commandsmapillary_tools--helpSupported File FormatsInstallationUsageProcess and UploadProcessUploadAdvanced UsageLocal Video ProcessingGeotagging with GPXAuthenticateImage DescriptionZip ImagesDevelopmentSupported File Formatsmapillary_tools can upload both images and videos.Image Formatsmapillary_tools supports JPG/JEPG images (.jpg, .jpeg), with the following EXIF tags minimally required:GPS LongitudeGPS LatitudeDate/Time Original or GPS Date/TimeVideo Formatsmapillary_tools supports videos (.mp4, .360) that contain any of the following telemetry structures:GPMF: mostly GoPro videosGoPro HERO series(from 5 to 11)GoPro MAXCAMM: an open-standard telemetry spec supported by a number of camerasInsta360 Pro2Insta360 TitanRicoh Theta XLabpanoand more...BlackVuevideosDR900S-1CHDR900X PlusInstallationStandalone ExecutableDownload the latest executable for your platform from thereleases.Move the executable to your system$PATHNOTE:If you see the error "mapillary_tools is damaged and can’t be opened" on macOS, try to clear the extended attributes:xattr -c mapillary_toolsInstalling via pipTo install or upgrade to the latest stable version:pipinstall--upgrademapillary_toolsIf you can't wait for the latest features in development, install it from GitHub:pipinstall--upgradegit+https://github.com/mapillary/mapillary_toolsNOTE:If you see "Permission Denied" error, try to run the command above withsudo, or install it in your
localvirtualenv(recommended).Installing on Android DevicesA command line program such as Termux is required. Installation can be done without root privileges. The following
commands will install Python 3, pip3, git, and all required libraries for mapillary_tools on Termux:pkginstallpythongitbuild-essentiallibgeosopenssllibjpeg-turbo
pipinstall--upgradepipwheel
pipinstall--upgrademapillary_toolsTermux must access the device's internal storage to process and upload images. To do this, use the following command:termux-setup-storageFinally, on devices running Android 11, using a command line program, mapillary_tools will process images very slowly if
they are in shared internal storage during processing. It is advisable to first move images to the command line
program’s native directory before running mapillary_tools. For an example using Termux, if imagery is stored in the
folderInternal storage/DCIM/mapillaryimagesthe following command will move that folder from shared storage to
Termux:mv-vstorage/dcim/mapillaryimagesmapillaryimagesUsageProcess and UploadFor most users,process_and_uploadis the command to go:# Process and upload all images and videos in MY_CAPTURE_DIR and its subfolders, and all videos under MY_VIDEO_DIRmapillary_toolsprocess_and_uploadMY_CAPTURE_DIRMY_VIDEO_DIR/*.mp4If any process error occurs, e.g. GPS not found in an image, mapillary_tools will exit with non-zero status code.
To ignore these errors and continue uploading the rest:# Skip process errors and upload to the specified user and organizationmapillary_toolsprocess_and_uploadMY_CAPTURE_DIRMY_VIDEO_DIR/*.mp4\--skip_process_errors\--user_name"my_username"\--organization_key"my_organization_id"Theprocess_and_uploadcommand will run theprocessand theuploadcommands consecutively with combined required and optional arguments.
The command above is equivalent to:mapillary_toolsprocessMY_CAPTURE_DIRMY_VIDEO_DIR/*.mp4\--skip_process_errors\--desc_path/tmp/mapillary_description_file.json

mapillary_toolsuploadMY_CAPTURE_DIRMY_VIDEO_DIR/*.mp4\--desc_path/tmp/mapillary_description_file.json\--user_name"my_username"\--organization_key"my_organization_id"ProcessTheprocesscommand is an intermediate step that extracts the metadata from images and videos,
and writes them in animage description file. Users should pass it to theuploadcommand.mapillary_toolsprocessMY_CAPTURE_DIRMY_VIDEO_DIR/*.mp4Duplicate check with custom distance and angle:# Mark images that are 3 meters closer to its previous one as duplicates.# Duplicates won't be uploadedmapillary_toolsprocessMY_CAPTURE_DIR\--duplicate_distance3\--duplicate_angle360# Set 360 to disable angle checkSplit sequences with the custom cutoff distance or custom capture time gap:# If two successive images are 100 meters apart,# OR their capture times are 120 seconds apart,# then split the sequence from theremapillary_toolsprocessMY_CAPTURE_DIR\--offset_angle90\--cutoff_distance100\--cutoff_time120\UploadAfter processing you should get theimage description file. Pass it to theuploadcommand to upload them:# Upload processed images and videos to the specified user account and organizationmapillary_toolsuploadMY_CAPTURE_DIR\--desc_path/tmp/mapillary_image_description.json\--user_name"my_username"\--organization_key"my_organization_id"Advanced UsageLocal Video ProcessingLocal video processing samples a video into a sequence of sample images and ensures the images are geotagged and ready for uploading.
It gives users more control over the sampling process, for example, you can specify the sampling distance to control the density.
Also, the sample images have smaller file sizes than videos, hence saving bandwidth.Install FFmpegFFmpegis required for local video processing.
You can downloadffmpegandffprobefromhere,
or install them with your favorite package manager.Video Processingmapillary_tools first extracts the GPS track from the video's telemetry structure, and then locates video frames along the GPS track.
When all are located, it then extracts one frame (image) every 3 meters by default.# Sample videos in MY_VIDEO_DIR and write the sample images in MY_SAMPLES with a custom sampling distancemapillary_toolsvideo_processMY_VIDEO_DIRMY_SAMPLES--video_sample_distance5# The command above is equivalent tomapillary_toolssample_videoMY_VIDEO_DIRMY_SAMPLES--video_sample_distance5mapillary_toolsprocessMY_SAMPLESTo process and upload the sample images consecutively, run:mapillary_toolsvideo_process_and_uploadMY_VIDEO_DIRMY_SAMPLES--video_sample_distance5# The command above is equivalent tomapillary_toolsvideo_processMY_VIDEO_DIRMY_SAMPLES--video_sample_distance5--desc_path=/tmp/mapillary_description.json
mapillary_toolsuploadMY_SAMPLES--desc_path=/tmp/mapillary_description.jsonGeotagging with GPXIf you use external GPS devices for mapping, you will need to geotag your captures with the external GPS tracks.To geotag images with a GPX file, the capture time (extracted from EXIF tag "Date/Time Original" or "GPS Date/Time") is minimally required.
It is used to locate the images along the GPS tracks.mapillary_toolsprocessMY_IMAGE_DIR--geotag_source"gpx"--geotag_source_pathMY_EXTERNAL_GPS.gpxTo geotag videos with a GPX file, video start time (video creation time minus video duration) is required to locate the sample images along the GPS tracks.# Geotagging with GPX works with interval-based sampling only,# the two options --video_sample_distance -1 --video_sample_interval 2 are therefore required# to switch from the default distance-based sampling to the legacy interval-based samplingmapillary_toolsvideo_processMY_VIDEO_DIR\--geotag_source"gpx"\--geotag_source_pathMY_EXTERNAL_GPS.gpx\--video_sample_distance-1--video_sample_interval2Ideally, the GPS device and the capture device should use the same clock to get the timestamps synchronized.
If not, as is often the case, the image locations will be shifted. To solve that, mapillary_tools provides an
option--interpolation_offset_time Nthat adds N seconds to image capture times for synchronizing the timestamps.# The capture device's clock is 8 hours (i.e. -8 * 3600 = -28800 seconds) ahead of the GPS device's clockmapillary_toolsprocessMY_IMAGE_DIR\--geotag_source"gpx"\--geotag_source_pathMY_EXTERNAL_GPS.gpx\--interpolation_offset_time-28800Another option--interpolation_use_gpx_start_timemoves your images to align with the beginning of the GPS track.
This is useful when you can confirm that you start GPS recording and capturing at the same time, or with a known delay.# Start capturing 2.5 seconds after start GPS recordingmapillary_toolsvideo_processMY_VIDEO_DIR\--geotag_source"gpx"\--geotag_source_pathMY_EXTERNAL_GPS.gpx\--interpolation_use_gpx_start_time\--interpolation_offset_time2.5\--video_sample_distance-1--video_sample_interval2New video geotagging features (experimental)As experimental features, mapillary_tools can now:Geotag videos from tracks recorded in GPX and NMEA filesInvokeexiftoolinternally, if available on the system.exiftoolcan extract geolocation data from a wide
range of video formats, allowing us to support more cameras with less trouble for the end user.Try several geotagging sources sequentially, until proper data is found.These features apply to theprocesscommand, which analyzes the video for direct upload instead of sampling it
into images. They are experimental and will be subject to change in future releases.UsageThe new video processing is triggered with the--video_geotag_source SOURCEoption. It can be specified multiple times:
In this case, each source will be tried in turn, until one returns good quality data.SOURCEcan be:the plain name of the source - one ofvideo, camm, gopro, blackvue, gpx, nmea, exiftool_xml, exiftool_runtimea JSON object that includes optional parameters{
  "source": "SOURCE",
  "pattern": "FILENAME_PATTERN" // optional
}PATTERN specifies how the data source file is named, starting from the video filename:%f: the full video filename%g: the video filename without extension%e: the video filename extensionSupported sources and their default pattern are:video: parse the video, in order, ascamm, gopro, blackvue. Pattern:%fcamm: parse the video looking for a CAMM track. Pattern:%fgopro: parse the video looking for geolocation in GoPro format. Pattern:%fblackvue: parse the video looking for geolocation in BlackVue format. Pattern:%fgpx: external GPX file. Pattern:%g.gpxnmea: external NMEA file. Pattern:%g.nmeaexiftool_xml: external XML file generated by exiftool. Pattern:%g.xmlexiftool_runtime: execute exiftool on the video file. Pattern:%fNotes:exiftool_runtimeonly works if exiftool is installed on the system. You can find it athttps://exiftool.org/or through
your software manager. If exiftool is installed, but is not in the default execution path, it is
possible to specify its location by setting the environment variableMAPILLARY_TOOLS_EXIFTOOL_PATH.Pattern are case-sensitive or not depending on the filesystem - in Windows,%g.gpxwill match bothbasename.gpxandbasename.GPX, in MacOs, Linux or other Unix systems no.If both--video_geotag_sourceand--geotag_sourceare specified,--video_geotag_sourcewill apply to video files
and--geotag_sourceto image files.ExamplesGeneric supported videosProcess all videos in a directory, trying to parse them as CAMM, GoPro or BlackVue:mapillary_toolsprocess--video_geotag_sourcevideoVIDEO_DIR/External GPXProcess all videos in a directory, taking geolocation data from GPX files. A video namedfoo.mp4will be associated
with a GPX file calledfoo.gpx.mapillary_toolsprocess--video_geotag_sourcegpxVIDEO_DIR/Insta360 stitched videosThe videos to process have been stitched by Insta360 Studio; the geolocation data is in the original
videos in the parent directory, and there may be GPX files alongside the stitched video.
First look for GPX, then fallback to running exiftool against the original videos.mapillary_toolsprocess\--video_geotag_sourcegpx\--video_geotag_source'{"source": "exiftool_runtime", "pattern": "../%g.insv"}'\VIDEO_DIR/Limitations of--video_geotag_sourceExternal geolocation sources will be aligned with the start of video, there is
currently no way of applying offsets or scaling the time.This means, for instance, that GPX tracks must begin precisely
at the instant of the video, and that timelapse videos are supported only for sourcescamm, gopro, blackvue.AuthenticateThe commandauthenticatewill update the user credentials stored in the config file.ExamplesAuthenticate new user:mapillary_toolsauthenticateAuthenticate for usermy_username. If the user is already authenticated, it will update the credentials in the config:mapillary_toolsauthenticate--user_name"my_username"Image DescriptionThe output of theprocesscommand is a JSON array of objects that describes metadata for each image or video.
The metadata is validated by theimage description schema.
Here is a minimal example:[{"MAPLatitude":58.5927694,"MAPLongitude":16.1840944,"MAPCaptureTime":"2021_02_13_13_24_41_140","filename":"/MY_IMAGE_DIR/IMG_0291.jpg"},{"error":{"type":"MapillaryGeoTaggingError","message":"Unable to extract GPS Longitude or GPS Latitude from the image"},"filename":"/MY_IMAGE_DIR/IMG_0292.jpg"}]Users may create or manipulate the image description file before passing them to theuploadcommand. Here are a few examples:# Remove images outside the bounding box and map matching the rest images on the road networkmapillary_toolsprocessMY_IMAGE_DIR|\./filter_by_bbox.py5.9559,45.818,10.4921,47.8084|\./map_match.py>/tmp/mapillary_image_description.json# Upload the processed imagesmapillary_toolsuploadMY_IMAGE_DIR--desc_path/tmp/mapillary_image_description.json# Converts captures.csv to an image description file./custom_csv_to_description.shcaptures.csv|mapillary_toolsuploadMY_IMAGE_DIR--desc_path-Zip ImagesWhenuploadingan image directory, internally theuploadcommand will zip sequences in the temporary
directory (TMPDIR) and then upload these zip files.mapillary_tools provideszipcommand that allows users to specify where to store the zip files, usually somewhere with
faster IO or more free space.# Zip processed images in MY_IMAGE_DIR and write zip files in MY_ZIPFILESmapillary_toolszipMY_IMAGE_DIRMY_ZIPFILES# Upload all the zip files (*.zip) in MY_ZIPFILES:mapillary_toolsupload--file_typeszipMY_ZIPFILESDevelopmentSetupClone the repository:gitclonegit@github.com:mapillary/mapillary_tools.gitcdmapillary_toolsSet up the virtual environment. It is optional but recommended:pipinstallpipenvInstall dependencies:pipenvinstall-rrequirements.txt
pipenvinstall-rrequirements-dev.txtEnter the virtualenv shell:pipenvshellRun the code from the repository:python3-mmapillary_tools.commands--versionTestsRun tests:# test all casespython3-mpytest-s-vvtests# or test a single case specificallypython3-mpytest-s-vvtests/unit/test_camm_parser.py::test_build_and_parseRun linting:# format codeblackmapillary_toolstests# sort importsusortformatmapillary_toolstestsRelease and Build# Assume you are releasing v0.9.1a2 (alpha2)# Tag your local branch# Use -f here to replace the existing onegittag-fv0.9.1a2# Push the tagged commit first if it is not there yetgitpushorigin# Push ALL local tags (TODO: How to push a specific tag?)# Use -f here to replace the existing tags in the remote repogitpushorigin--tags-f# The last step will trigger CI to publish a draft release with binaries built# in https://github.com/mapillary/mapillary_tools/releases