The Mapillary Blog


Upload Scripts

by Jan Erik Solem, Posted on 21 Jul 2014

Jan Erik Solem

Here's a post for those of you who upload from a computer, because you use other cameras like GoPro or Garmin Virb, or because you offload photos when your phone is getting full. In our Mapillary Tools repository we have the tools you need. Just clone or download to get started.

There are two cases and two different kinds of uploads. The first is when you upload photos taken with the Mapillary app. The second is when you upload photos from other cameras. Let's look at each of them.

Photos from the Mapillary app

This is the easy case. Because the apps embed all information needed in the photo's EXIF information (inside the Image Description tag) all you need to do is to get the photo to the right server. Since the photos are self-contained it doesn't matter who does the uploading. You can collect photos from many users to one computer and upload all at once. They will be correctly sorted in sequences and assigned the right photographer.

Just run the script upload.py with the folder containing your photos as argument, like this:

$ python upload.py path

After successful upload the photo will be moved to a subfolder of where you run the script (named 'success'). This is so that in case you loose your connection or have to abort, you can just start again and not worry about uploading the same photo twice. Tip: run the script from a separate folder.

Photos from other cameras

With photos from other cameras, the photos don't contain all the information we need. For example, there is no sequence id indicating which photos belong together, and there is no information on which user took the photos.

One option is to use the web uploader and select photos sequence-by-sequence. Since you are logged in to the Mapillary website, and select which photos go together, we have everything that's needed. Using the web uploader is a liitle cumbersome if you have a lot of photos.

The second option is to use the upload_with_authentication.py script. As the name says, you need to authenticate so Mapillary can see who uploaded. To do this, you first need to go to this page while you are logged in in your browser. Then take the two hashes and save them as environment variables together with your Mapillary username. For example:

$ export MAPILLARY_SIGNATURE_HASH="your signature hash"
$ export MAPILLARY_PERMISSION_HASH="your permission hash"
$ export MAPILLARY_USERNAME="jesolem"

Next you need to group the photos into folders of sequences. Just copy manually or use the time_split.py script, also part of the tools you downloaded. See here on how to use that.

Finally, you can upload each sequence by supplying the path to the folder. Like this:

$ python upload_with_authentication.py path

The photos are also moved to a subfolder 'success' after sucessful upload.

Dependencies

In both scripts there are checks for the necessary EXIF tags. You will have to install the exifread module. For example using pip:

$ pip install exifread

Happy mapping with your GoPros and Garmins!

/Jan Erik


Introducing Places and Regional Stats

by Johan Gyllenspetz, Posted on 24 Jun 2014

Johan Gyllenspetz

We are continuing our work on showing all the great data that we have. Recently we added connections and notifications to connect mappers.

We have now added a new places page on our website with stats on who's mapping and where. We have so many great contributors and this is a nice way to show who is mapping a particular region.

The map looks like this:

alt toplists

From the main map you can drill down by clicking a specific region, for example Italy:

alt italy

Some countries have sub-regions, for example Germany, Sweden, and the United States. We will add more sub-regions when a region has enough data for that to make sense. Every country and region has its own url so you can share and bookmark.

For each of these views, we are also showing who the top contributors are. For example, for Italy:

alt fulltoplists

The number one contributor also gets a special spot on the map too.

Take a moment and browse around, see whos active in areas you care about and look at their fantastic contributions.


Making Connections and New Profile Pages

by Jan Erik Solem, Posted on 22 Jun 2014

Jan Erik Solem

At Mapillary, our main task is connecting the many photos uploaded to the service. We do this all the time, in the background, using computer vision and reasoners.

Besides showing connections when you are actively looking at a photo and navigating, we haven't really exposed this data. That is changing now.

Weekly Connections

Some of you may have noticed the weekly activity email that went out last week. At the top there are stats on how many new photos you added, how many new connections were made between your contributions and others', and your ranking on some relevent top lists of contributors. Then there is a section called "Close and similar to yours", these are the new connections between you and other mappers made in that week.

alt similar

In the screenshot above, you can see that my uploads were matched to other users' uploads. In the top row, the other photo (from a bus camera) is from a later point in time. You can see that the building under construction has several floors added. On the second row, you see a difference in seasons for two photos taken at the same exact spot.

Connections on Profile Pages

Johan made a major update to the profile pages. These show your bio and your basic stats at the top, just like before. Then, next to your uploads, are the connections. Here we are showing which users you are connected to through your uploads. The counter next to the name is how many connections you have. Click a user and the view expands so you can see all the connections.

alt profile

Now you can easily see who else is mapping where you are. Who knows, you might make new friends or new rivals this way ;)

We love this way of connecting our contributors, not just the photos. You are not alone out there. When your uploads become connected with others and become part of something bigger, we want to let you know. Hopefully you will find that as rewarding as we do.

/Jan Erik


Using an Action Camera with GPS

by Jan Erik Solem, Posted on 16 Jun 2014

Jan Erik Solem

Here's another workflow posts for you, this time about action cameras that have GPS. I have had my eyes on the Garmin Virb after seeing it at bike races and finally gave it a try.

We have written about flying drones, about working with GoPro cameras, where you have to sync the photos to locations recorded with an external GPS or phone. (There is a script for that, see this post.)

With a GPS enabled action camera you can skip all that. I'll use a bike handle bar as example.

alt bike
A Garmin Virb attached to a bike with the GoPro bike mount.

Here's the process:

  • Attach the camera (I like the GoPro bike mount kit, you can also try 3D printing these).
  • Check the preview to see that the photos are straight and the horizon is where you want it (I like mine in the middle).
  • Set the camera to 2s interval time lapse. On the Garmin Virb, you can turn on wide angle straightening, this is a good idea.
  • Start riding and start the camera.
  • Stop and start when it makes sense to do so, at natual sequence gaps or when there is sometheing you don't want to capture.
  • When you are done riding, copy the photos over to your computer. Look through them quickly and delete the bad ones.
  • Before uploading the photos using the web uploader, it is useful to organize them in sequences since the uploader needs all photos in a sequence at the same time. I made a script for that, just download it here. Run it like this:
$ python time_split.py virb_test 
Organizing into 15 groups.
Moved 32 photos to virb_test/0
Moved 42 photos to virb_test/1
Moved 10 photos to virb_test/2
Moved 36 photos to virb_test/3
Moved 46 photos to virb_test/4
Moved 30 photos to virb_test/5
Moved 11 photos to virb_test/6
Moved 25 photos to virb_test/7
Moved 154 photos to virb_test/8
Moved 54 photos to virb_test/9
Moved 29 photos to virb_test/10
Moved 84 photos to virb_test/11
Moved 70 photos to virb_test/12
Moved 59 photos to virb_test/13
Moved 27 photos to virb_test/14
Done grouping photos.
  • With photos captured in time lapse mode the script automatically finds the cutoff points and copies the photos into subfolders for you.
  • Open the web uploader, click "Choose Files" and select everything in one of those folders. You will then see them on a map, where you can check that everything is ok and remove unwanted photos. alt uploader
  • Click "Upload To Server" and when all markers are green, push to Mapillary.
  • Repeat until all folders are uploaded.

Hope this is useful for our bikers and motorcyclists out there. If you have other workflow tips, blog, tweet or email us.

/Jan Erik


Privacy Blurring - Now in the Editor

by Johan Gyllenspetz, Posted on 25 May 2014

Johan Gyllenspetz

At Mapillary we do a lot of things with the photos you upload. One thing we do is to automatically blur license plates and peoples faces for privacy purposes. No license plate detector or face detector is perfect and sometimes we will incorrectly blur areas, sometimes we will miss important areas that needed blurring.


Example of incorrect blurring

Enabling manual correction of blurring is one of the most requested features that we have had so far. It is a great thing that our users are concerned about privacy. We promised to do something about it and now we have.

As of now, any user can manually add and remove blur in the editor. This is how it works (a video says more than a thousand words):

Blurring/Unblurring Mapillary from Mapillary on Vimeo.

That means that even though our automatic detectors sometimes fail, together we can make Mapillary a place where privacy is respected.

This looks like an easy feature to build but we actually had to make deep changes in how we handle the results of the detectors for blurring. We are very happy to finally have the feature out and we hope you will like it too.

/johan


Flying Drones, Capturing Mapillary Tracks

by Peter Neubauer, Posted on 20 May 2014

Peter Neubauer

The task

A few days ago, we tested what it would take to capture tracks using professional equipment like the awesome drones by Intuitive Aerial in Linköping, Sweden.

The hardware

For the flight, we used a smaller variant of the drone, and attached a normal cell phone to capture the GPS position while flying with a GoPro camera, following the same technique as described in Craig Taverner's blog post for time lapsed GoPro pictures.

The quadcopter was a lesser variant of the real devices produced by the company, with an Ardupilot central unit and for propellers. Thank you Torkel Danielsson of Intuitive Aerial for taking the time to make this possible!


Torkel Danielsson of Intuitive Aerials and his quadcopter

Also, we had the fortune to have a prototype of a stabilizing handheld wig for GoPro available, big thanks to Patrick St-Arnaud from Shape for spending the time to makes this possible!

Patrick St-Arnaud demoing the GoPro stabilization device

The process

Now, it is "just" a matter of directing the drone automatically along GPX tracks, or manually control it to take the desired footage in GoPro sequence mode.


The Quadcopter rig flying

The resulting pictures are transferred from the GoPro to a computer together with the GPX track form the phone, and then correlated and uploaded to Mapillary.

Here is the result - aerial coverage around the university of Linköping!

Summary:

With the right equipment, it is entirely possible to capture aerial footage using drones and Mapillary, and without big effort this can be scaled up for a municipality or infrastructure company. This experiment took about 2 hours - not a lot of time considering this was the first time.

Safe flying,

/peter


A Mapillary Windows Phone App!

by Tommy Ovesen, Posted on 15 May 2014

Tommy Ovesen

Today Mapillary - the project to provide a street level view of the world - arrived at the Windows Phone platform with the first release of the app for Windows Phone 8 / 8.1.

This is not an official app from Mapillary, but it was developed by me in cooperation with the Mapillary team.

The Windows Phone app is quite similar to the iPhone and Android apps. Here are a few screenshots:


The Welcome Screen


The Camera View.


Edit/Delete pictures before upload.


Upload pictures.

The Mapillary app for Windows Phone can be downloaded for free here:

Mapillary for Windows Phone is developed by Ovesen.net. The person behind Ovesen.net is me, Tommy Ovesen, an experienced senior software developer from Bodø, Norway. I develop apps for the Windows 8 and Windows Phone platform as a hobby besides my full time job as a developer.

Please try out the app if you have a Windows Phone. If you have any suggestions or issues with the Windows Phone app, contact me at my Facebook page

Your community member

Tommy Ovesen


A Capture Workflow

by Jan Erik Solem, Posted on 15 May 2014

Jan Erik Solem

This past weekend we captured some data for the upcoming Traffic Jam Session hackathon here in Malmö. Since the event is about hacking public transportation data, we mapped some of the local bus lines. We used six Android phones running the Mapillary app that captured a total of 50GB of photos.

alt devices
The red things are TI Sensor Tags that recorded some additional data.

With this blog post I just wanted to share the workflow we used for this type of organized "large scale" capture session.

  • Meet up with all devices charged and plan who goes where. In our case we had coffee and waited for the rain to clear.
  • Turn off automatic syncing if you use Android.
  • Go out and capture. Depending on your mode of transportation, hold the phone in your hand, use a mount, whatever works in the situation. For vertical windows like a bus or tram, double-sided tape directly against the window works great.
  • Empty the phones at regular intervals. If you want to capture 10-20GB per device, you most likely will have to do it in several sessions and copy your photos over to a laptop.
    • On iOS you can do this in iTunes. Open the Apps tab and scroll down until you see the Mapillary app at the bottom. You can copy the photos from there.
    • On Android you can access the files over USB cable or if they are on an external SD card, you can put the card in a reader on your laptop.
  • Review the photos. When you are done capturing and have collected all photos it is much easier to go over thousands of photos on your laptop on a good screen. Just delete all photos you don't want.
  • Upload. The easiest way is to run our command line upload script. Just point it at the folder with all your photos and it should do the rest. If you cannot run the script, you can also copy photos back to the app and upload from there but that's a little messy. Don't worry about giving credit to the right photographer, all capture information is contained in the photo's EXIF. Anyone can upload a photo you took from anywhere, it will show as your upload.

The same process applies if you capture over long times with no WiFi to upload. Just copy the photos over to a laptop at regular intervals and review them in peace before bulk uploading.

Here's one of the routes. alt route

Here's a photo of Peter and a happy busdriver. alt devices


Weekend Hack - a Mapillary GoPro Bike Mount

by Peter Neubauer, Posted on 05 May 2014

Peter Neubauer

After we sent out the car mounts after our survey, we received a lot of positive feedback. However, there are not many mounts for bikes that are suitable for Mapillary.

So, last weekend's project was to start building one. First, my friend Martin Wolff did a great first iteration with a 3D printer:

alt test

There are many interested Mapillary users wanting to import images from GoPro cameras. I thought it might be a good idea to build on that ecosystem and design a bicycle phone mount that is compatible with the GoPro accessories.

Searching at Thingiverse, I found this nice starting point. Loading it into OpenSCAD, I got

alt test

Cool! So, I could use the GoPro 2-legged mount and edited Martins Phone-mount, corrected for my Sony Xperia Z1, resulting in this code:

use <gopro_mounts_mooncactus.scad>
include <write.scad>

// Create a "triple" gopro connector
translate([0,-10.5,0])
gopro_connector("double");


ph_width     = 147;
ph_height    = 74;
ph_thick     = 9.5;
wall             = 2;
camera_hole_to_top_edge = 11.5;
camera_hole_to_side_edge = 10;
camera_hole_diameter = 15;
side_edge_to_screen = 10;
bottom_edge_to_screen = 10;
lift_holes_diameter= 20;


color([0.6,0.6,0.6])
translate([-ph_thick/2,0,-ph_width/2])
difference (){
    union() {
        cube([ph_thick+wall*2,ph_height+wall*2,ph_width+wall*2]);

    }
    union() {
        translate([wall,wall,wall])
        //phone body
        cube([ph_thick,ph_height+10,ph_width]);

        //camera hole
        translate([0,ph_height-camera_hole_to_top_edge,ph_width-camera_hole_to_side_edge]) {
            rotate([90,0,90])   cylinder(3*wall,d=camera_hole_diameter,center=true);
        }

        rotate([90,0,90])   cylinder(30,d=lift_holes_diameter,center=true);
        translate([0,0,ph_width]) {
            rotate([90,0,90]) cylinder(30,d=lift_holes_diameter,center=true);
            translate([0, ph_height/2, -ph_height])
            rotate([270,270,90])
                write("Mapillary",h=10,t=wall/2,center=true);
        }
        translate([wall*2+ph_thick/2,side_edge_to_screen,bottom_edge_to_screen]) cube([wall*6,ph_height*0.8,ph_width*0.8]);



    }
}

Which looks something like:

alt test

The code is here, feel free to fork and improve, and adjust the dimensions to your phone model. Once it is good enough, we will upload it to Thingiverse.

This took about two hours (I am a bit slow on CAD, just starting). After that, just export the STL file and print it on your nearest 3D printer - I went to my local hacker space STPLN where we printed the mount in ABS on a RepRap variant:

alt test

The walls are a bit thin, and I printed with only 40% material fill which is wrong but the dimensions seem to work:

alt test

alt test

So, next iteration will be on a printshop-printer, printing the GoPro handlebar-mount, and off we go!

/peter


License Update: Now Creative Commons Share Alike

by Jan Erik Solem, Posted on 29 Apr 2014

Jan Erik Solem

It has been six weeks since we announced that we were licensing our photos with Creative Commons. The license we chose was the Creative Commons Attribution-NonCommercial 4.0 License (CC BY-NC). Our reasoning was explained in the accompanying blog post.

Today we are making modifications to the license and are switching to a Creative Commons Attribution-ShareAlike 4.0 License (CC BY-SA).

Creative Commons License

Our updated legal summary page has the details.

This now means we have a true open data license and that we are welcoming people to use our photos. Our guiding principle remains the same: maximize sharing and use of all our photos without totally compromising us building a sustainable business.

We are in this to build something great and we have many cool features to come. As a commercial business we are still in the early phases but we plan to build some great products on these photos and the data we create using our algorithms. Stay tuned.

Now let's map this world.

/Jan Erik

If you came here without knowing what Mapillary is, take a look at our manifesto.


Bulk Editing Compass Angles - Yay!

by Peter Neubauer, Posted on 28 Apr 2014

Peter Neubauer

Today, we finally got around to implement one of the most requested editing operations for Mapillary - the bulk-straightening for all images in a sequence.

When you take pictures in cars, busses and other vehicles, the phones compass directions tends to be off by non-trivial angles. Now, in the editor, you can just click on the button "Camera was pointing forward" and we will make a changeset for all pictures in the sequence with their compass direction pointing to the next picture as calculated from the GPS positions instead of the phones data. Very handy and being applicable in 95% of all sequences in Riding mode!

Here is a few seconds video showing this:

Happy editing!

/peter


A Startup Dashboard with Google Spreadsheet

by Peter Neubauer, Posted on 04 Apr 2014

Peter Neubauer

When you are a startup, you don't have much time. In our case, we want to track some of our KPIs, as the numbers of users, images and power users over time (lots of other historic KPIs like user retention too, but that's another blog). We also want have a nice dashboard but not build a system for that.

Since we needed a JSON API call anyway, we decided to implement a sliding backwards-scale JSON endpoint that looks something like

{
    "date":["12/19/2013","12/26/2013","01/02/2014","01/09/2014","01/16/2014","01/23/2014","01/30/2014","02/06/2014","02/13/2014","02/20/2014","02/27/2014","03/06/2014","03/13/2014","03/20/2014","03/27/2014","04/03/2014"],
    "users":[104,109,112,113,121,131,152,164,185,198,215,574,738,786,843,956],
    "photos":[24889,28435,34919,36599,40255,43388,51790,60306,68490,74641,78413,91207,120284,138000,165583,192208],
    "sequences":[923,1034,1171,1228,1358,1471,1776,2085,2483,2729,3177,3907,5034,5729,6635,8019],
    "edges":[128752,140619,181738,217009,247674,284711,315260,462161,612369,874701,1127074,1268489,1808776,2232907,2829353,3508281],
    "uploading_users":[31,34,36,38,39,41,45,51,53,61,66,110,154,181,203,234],
    "uploading_users_10":[26,29,30,32,33,35,37,42,43,49,53,76,108,133,154,181],
    "uploading_users_100":[14,15,17,17,17,18,18,21,24,29,31,44,56,62,74,100]
}

Now, you can build your own visualization on top of this with authentication, Heroku hosting and so on. However, there is Google Spreadsheet and Google AppScript, an extremely powerful and productive combination. In our case, we added a script to a Google Calc spreadsheet to interpret the JSON response and return an array of cell values:

function fetchStats() {

  var url = "https://api.mapillary.com/xxx";
  var urlFetch = UrlFetchApp.fetch(url, null);
  //fetch the data (with a secret token or authentication)
  var json = JSON.parse(urlFetch.getContentText());
  var cells = [];
  for (key in json) {
    var values = [];
    values.push(key)
    for (var i = 0; i < json[key].length; i++) {
      values.push(json[key][i]);
    }
    cells.push(values);
  }
  //the resulting 2-dimensional cell range
  return cells;
}

Once we have this, we can simply have a cell with =fetchStats() and have a cell range filled in from the endpoint anywhere in the spreadsheet. After that, diagrams and calculations are trivial. This could result in a spreadsheet like

alt trace

And we get the whole sharing, charting and other spreadsheet benefits instead of yet another system to maintain.

I like pragmatic - thought you might be interested.

/peter


The Disqus Integration is Working - Let's Start Talking!

by Peter Neubauer, Posted on 19 Mar 2014

Peter Neubauer

Hi there, you probably have seen the disqus footers under the Mapillary pictures. While this has been working for a while (we are talking days here :), we now have integrated a polling on new blog posts that will mail the photographer of the image with any new updates on the discussions.

In other words - you will now be notified when someone comments on your pictures. Start commenting and replying. Now the photographer can actually hear you!

/peter


An Angular.js Confirm Dialog Directive ftw!

by Peter Neubauer, Posted on 18 Mar 2014

Peter Neubauer

We got a complaint from a user who flagged an image by accident, see this issue. As we are now entering a phase of Complaint Driven Development, this morning I found a great little fix to this. Angular.js which we use for the web client, does not come with a built-in confirmation dialogue. However, here is a great little generic confirm-button directive that avoids the onClick method and can be reused.

This is how it turned out:

angular.module('mapapp')
  .directive 'ngConfirmClick', [() ->
    restrict: 'A'
    replace: false
    link: ($scope, $element, $attr) ->
      msg = $attr.ngConfirmClick || "Are you sure?"
      clickAction = $attr.confirmedClickAction;
      $element.bind('click',(event) ->
        if window.confirm(msg)
          $scope.$eval(clickAction)
      )
      ]

Having done this, we can now just change the HAML-template code from

%span.set_flag{'ng-show' => '!flagged', 'ng-click' => 'flagImage(nav.currentImage)'}

to something like

%span.set_flag{'ng-show' => '!flagged', 'confirmed-click-action' => 'flagImage(nav.currentImage)', 'ng-confirm-click'=>'Are you sure to flag this image?'}

Resulting in this:

Voilá, another closed issue :)

/peter


Mapillary Goes Creative Commons

by Jan Erik Solem, Posted on 17 Mar 2014

Jan Erik Solem

One thing we have been struggling with since starting Mapillary is the issue of licensing Mapillary photos.

On one hand, the reality of the situation is that we are a startup with a small hard-working team, trying to build something we think is important. With that comes operational cost for salaries, servers, office space etc. At the same time, we are strong proponents of Open Source and Open Data and feel we have a responsibility for sharing and contributing as much as we can.

In our discussions we went over many scenarios of users opting in, or opting out, to sharing specific photos or specific uploads. It never felt right. Complicated and contrived. Hard to explain.

We decided to go for something simple instead. Maximize sharing and use of all our photos without completely shooting us in the foot (head?) when it comes to making a sustainable future business. Something truly sustainable that will let us work on this challenging thing we love for many years to come.

Today we are happy to announce that all public photos on Mapillary are free to use for non-commercial work under the Creative Commons Attribution-NonCommercial 4.0 International License (CC BY-NC).

Creative Commons License

Take a look at our legal summary page for the full details.

If you came here without knowing what Mapillary is, take a look at our manifesto.


Thanks!

While trying to sort out licensing, we have received a lot of feedback, questions, and comments over twitter, email, and our public GitHub issues, and really appreciated all of it. Lots of great advice from lots of smart people. Members of the Swedish and German OSM communities have been very supportive and helped a lot. Thanks everyone!

Now let's map this world.

Update: We are revising the license and going from CC-BY-NC to CC-BY-SA on April 29, 2014. See this blog post.


Embed a Mapillary View

by Johan Gyllenspetz, Posted on 04 Mar 2014

Johan Gyllenspetz

As Mapillary is starting to grow in popularity, we got a number of requests to be able to embed the Mapillary view into other web pages. So, we built it! This is how it goes - for details, see the developer page:

  • import the Mapillary Javascript lib
  • have a <div id='mapillary'>l tag somewhere on your site where you want the widget
  • initialize the Mapillary Javascript after the site is loaded fully.

The code is quite simple:

    <!-- pull in the script -->
    <script src="//dga406zepc8gy.cloudfront.net/javascripts/mapillary.js" type="text/javascript"></script>

    <!-- This is where the widget will appear-->
    <div id='mapillary'></div>

    <!-- Initialize the Widget with a start image and a width-->
    <script>
      (function() {
        Mapillary.init('mapillary', {image: 'RdGqCZOGpRTzFII4i7swYg', width: 320});
      })();
    </script>

With this, you can now start at any image you find on Mapillary. Of course, we want to add more things to it, like the ability to give a longitude/latitude to start with, but it's a start. Please let us know how you like it. As always, comment below, and report issues.

Looking forward to seeing Mapillary on a website near you!


Making the Static Dynamic

by Johan Gyllenspetz, Posted on 26 Feb 2014

Johan Gyllenspetz

The right stack for the job

Here at Mapillary we believe in dividing our services into small maintainable parts. We use the right stack at the right place. We force ourselves to write clear API:s between our services, no cheating. Our iPhone app uses the same API as our website. A feature developed in one of our server APIs can instantly be used by both our javascript front-end guy as well as our iPhone and Android developers.

The static problem

Our website http://mapillary.com uses the middleman framework and is hosted on heroku, this prevents us from cheating with the APIs. To communicate with our servers we use angularjs, the whole web page is static which is awesome.

However we just recently bumped into a problem. We want some of our links to be socially shareable. If a user finds a beautiful image in our archives (such as this one http://www.mapillary.com/map/im/pXA7tF-BIYMM2gStoOBMrQ) we want them to be able to share that link with their friends. This requires that we fill in our meta tags on the site accordingly. This is where rack is the best of friends.

Rack

Rack lets you write middlewares. A middleware is a piece of code that has access to everything in the HTML request by the user and the HTML response from the server. This is what we came up with. Add the following to your config.ru file.

    # Datamapper is awesome for accesing your database in ruby
    require 'data_mapper'

    # Create an Image object
    class Image
      include DataMapper::Resource
      property :k, String
      property :title, String
    end

    # Setup Database
    DataMapper.setup(:default, ENV['DATABASE_URL'])

    class DYNAMIC_META
      def initialize(app)
        @app = app
      end

      def call(env)
        status, headers, body = @app.call env

        # Check for request path
        if env['REQUEST_PATH']
          # Match it to our specific path
          match = env['REQUEST_PATH'].match(/^\/map\/im\/([^\/]*)$/)
          if match
            key = match[1]
            # If there is a match lookup up the image in our database
            image = Image.all(k: key).first
            if body
              body.each do |line|
                # Replace static content with dynamic content
                if line =~ /.*twitter:.*/
                  line.gsub!(/<meta content='' name='twitter:image:src'>/, "<meta content='https://example.com/#{key}/image.jpg' name='twitter:image:src'>")
                  line.gsub!(/<meta content='' name='twitter:title'>/, "<meta content='#{image.title}' name='twitter:title'>")
                  body = [line]
                end
              end
            end
          end
        end

        [status, headers, body]
      end
    end

    use DYNAMIC_META

Why is this piece of code so magical. Well its the easiest smallest piece of server side include I can think of. It enables us to use middleman and all of the features we love yet having a tiny part of our website to be dynamic.


Manual Upload

by Jan Erik Solem, Posted on 21 Feb 2014

Jan Erik Solem

One question we get a lot is if you can upload photos that you have taken with another camera, outside of our apps. Maybe you have some great street sequences taken with your DSLR or older photos that you would like to add.

Today we added manual uploads as an experimental feature. If you are signed in, you can find it in the drop down menu here:

alt upload menu

Just click the "Choose files" button and select all photos that should go together as a sequence. Once uploaded they will go through our regular pipeline.

We are working to support different EXIF tag formats. Right now we require latitude, longitude, image direction, and time.

alt upload menu
Example EXIF tags (photo from ubahnverleih)

Let us know if you have photos, EXIF, camera models that you would like us to support (twitter or email).


Mapillary to OpenStreetMap

by Johan Gyllenspetz, Posted on 20 Feb 2014

Johan Gyllenspetz

We have been working with the OpenStreetMap community lately and we wanted to investigate how Mapillary can be used as a tool for some serious mapping.

First of all I needed to find a possible candidate area for mapping. After some investigation I found this little park in West Hollywood, called West Hollywood park. The park was under construction on the Bing images in the Id editor and nobody has traced the park yet.

alt before map

I headed out a Saturday equiped with my iPhone and my Garmin GLO GPS connected with bluetooth for better GPS accuracy. After some (not too rigorous) testing we have found that the Garmin GLO gives really good accuracy.

alt garmin

I went around the park and used the Mapillary app to take photos of every path. When I came home I uploaded the images directly from the app over WiFi. When the upload finished, I went to My Uploads.

alt my uploads

Every sequence taken has a link where I can get the corresponding GPX file.

alt gpx

I downloaded all the gpx files and added them to the excellent application Adze. Here I can import several traces, merge them into one, and save the merged file.

alt editor

Next step was to locate the park in the Id editor and drag that file to the editor. Id will now show an overlay of my trace.

alt overlay

I traced the tracks and set them to be “walking path”.

alt trace

Press save button and, voila, a few minutes later the track was visible on openstreetmap.org.

alt done map

Check out the final result on Mapillary and on OpenStreetMap.

Some of these steps can probably be done more effectively, but this first test shows that we can easily use Mapillary for OpenStreetMap tracing. Try it yourself!


Photo Capture Modes

by Jan Erik Solem, Posted on 13 Feb 2014

Jan Erik Solem

With our latest update to the iPhone and Android apps today, we made some changes in how you capture photos. Where before, you selected "photo" or "sequences" when launching the camera, we now added three capture modes:

alt iphone modes

Walking

Walking mode is for when you are walking, or moving slow, and want to manually control when photos are taken. Take as many photos as you like and try to get lots of overlap between photos. When you turn or change direction, try to do it gradually, taking overlapping photos. That way the photos will be better connected and you get a nicer viewing experience.

Riding (bike/car)

In riding mode, photos are taken automatically in 2s intervals. Hold the camera straight and point it in the direction you are riding. Bikes are great for this! If you are in a car, make sure your view is clear of dashboards and other car parts.

Panorama

The panorama mode is for when you are in a location where you want people to be able to look around in many directions. For example, in fromt of landmarks, interesting buildings, at intersections, where there is a beautiful view. Stand in one place and take as many photos you like while panning the camera around. Make sure to get lots of overlap between photos.

alt screenshot alt screenshot
iPhone app in walking mode and Android app in riding mode.

In all modes, we recommend shooting with the camera in landscape orientation.

The reason for introducing these modes is that we want to help users take better photos. Some were confused when to use sequences before and we felt that although people did take panoramas, we wanted to handle panoramas differently. The capture mode will also determine how your photos are processed and what rules and reasoners are applied to the resulting data which also improves the end result.

We hope you will like our new apps. As always, send us your feedback on twitter or email.


Editing Uploads

by Johan Gyllenspetz, Posted on 31 Jan 2014

Johan Gyllenspetz

Starting out Mapillary with the idea of crowdsourcing street view photos using smartphones we were fully aware of the limitations of the devices used. Typically, your phone will at best give position within a few meters accuracy, sometimes a lot more than a few meters.

To help users take photos with good positioning, we added GPS icons to the camera view in the apps that would show when it is safe to take photos. We also prevent photo capture in the apps if the accuracy is too low. Despite this, things go wrong and we wanted the ability to crowdsource the correction of uploads.

Today we launched the next step in improving our data quality, editing of uploads.

When you are signed in and looking at a photo (or sequence) you will see an "Edit" button, like this:

alt edit button

Clicking that button will take you into edit mode where you can drag to change the position of photos and edit other details. Once you are done, review and save your edits. Once saved, your edits will generate a change set that is queued for approval by Mapillary users that have the extra powers to approve changes. We aim to update all incoming change sets within 24h.

alt edit before
An example with poor GPS accuracy.

alt edit after
The same after editing. (modified photos are marked with red)

Next time you see a Mapillary upload that has errors, we hope you will give editing a try. Not just on your own uploads, you can help improve everyone's uploads.

Have fun editing!


Mapillary for Android

by Jan Erik Solem, Posted on 24 Jan 2014

Jan Erik Solem

The number one thing people have been asking us during our short history is "when will you have an Android app"?

We are happy to announce that exactly 9 weeks after the Mapillary iPhone app went live on the App Store, we have now released Mapillary for Android!

The two apps are essentially the same. Android allows background activities so our Android app has automatic background upload when you connect to WiFi. There is also sharing of uploads, something we will add to the iPhone version soon.

alt android screenshot

With Android comes a wide range of devices to support. While we have tested on a few models (recent Samsung, HTC and Sony models), it is still a small sample set. Let us know if you find issues with your device so we can fix them. The easiest way is twitter or email.

Download Mapillary for Android and try it out!


A Graph of Images

by Jan Erik Solem, Posted on 21 Jan 2014

Jan Erik Solem

Yesterday we updated the site with some major changes. Some of you may have noticed that loading the photos after clicking the map took a long time for certain locations with lots of photos.

This is because internally, we are actually building up a connected model of how images relate to all their possible neighbors - both in terms of location, direction, overlap and time, amongst others. Our master database is Postgres - very robust and with great tooling, but poor on performance in smart rule-based traversals of our image graph.

Just a few days back, we internally launched a graph search service built on top of the awesome graph database neo4j - also lovingly built in Malmö, Sweden! This graph search service exposes an API that we are now using for the site and that we will open up for developers soon. Even with hundreds of images, the performance is now back to where it needs to be (<100ms, compared to 15s+ in some really bad cases on Postgres).

We will use this as a platform for building new features around browsing photos and navigation. Stay tuned for a number of cool things we can do now that the bottleneck of the database performance is removed.

alt image with links

A photo is connected to other photos based on location and image features. The arrows show the most important connections for user navigation.

What does this mean for you?

  • The site is faster
  • Your applications will have better and faster search
  • Later on, you will be able to do queries for photos in specific directions or with specific properties.

Right now it’s winter over here in Sweden - help take some sunny photos to brighten the database and the front page. Happy mapping!


Welcome to Mapillary!

by Jan Erik Solem, Posted on 01 Jan 2014

Jan Erik Solem

With this post we are starting our company blog to share long-form content on topics that we are passionate about and topics that relate to Mapillary. For announcements and short-style content, follow us on twitter.

Why are we doing this?

In short: we want to create a photo representation of the world, a map with photos of every place on earth.

A somewhat longer answer is that we want to collect street view and map photos and make them available for users and developers because we believe:

  • that in order to extend the coverage and improve the freshness and level of detail of today's street view and map photos, we need to move from a top-down model (cars with a rig on the roof) to a bottom-up model where users contribute.
  • that users are good at deciding what is important and useful to photograph. Local knowledge is hard to beat.
  • that there is no limit to the focus and depth of people's interests, and there should be no limit to the level of detail users can contribute.
  • that the best way to crowdsource is to make super simple apps for data collection and move the intelligence to the server side, away from the user.
  • that a crowdsourced solution should improve with every new photo contributed, immediately.
  • that users and customers using the data provide a natural prioritization of what areas to cover first and how.
  • that there is a place for an independent neutral provider of map photos.

What can you do?

Browse photos online at mapillary.com.

Download the app. Try it out. Take photos of your neighborhood, take photos on your next vacation, your next hike, your next bike ride.

Use the API to build something.

Send us your feedback. These days are early days and we appreciate all feedback that can help us understand what you need and how.

Join us! It will be an adventure.