Wednesday, February 22, 2012

Plotting photo location data with Bing

A couple weeks ago, the Girl, Unallocated blog published an article called "Geolocation From Photos = Good Stuff." Her post got me thinking about writing a little bash one-liner to use exiftool to extract GPS coordinates and submit them to an online mapping service to pin the location where the photo was taken. In few minutes, I had a working solution and decided I'd blog about it as soon as I had time.

Time was short.

A little more reading, and I saw that Cheeky4n6Monkey was similarly inspired and accordingly, worked up a better solution than my bash one-liner. Very nice.

Over the last few evenings, I had some time to read up on GeoRSS, an XML document format that can be read by Microsoft's Bing Maps. In turn, Bing can drop pushpins in the GPS coordinates provided from the file. I have a working prototype for this. Now, right off, I have to say, I barely know enough to make this work, the solution is not robust. I did use the word "prototype."

But, I did get it working and I think it may be useful to investigators who want to take images off of a phone or GPS equipped camera and create a map showing where all the images were taken. Here's a walk through.

First, I started with SIFT 2.12 and wrote a Python script that would parse out the EXIF metadata from a collection of photos and write them to a GeoRSS file. The script borrows a bunch of code from http://stackoverflow.com/questions/208120/how-to-read-and-write-multiple-files and http://eran.sandler.co.il/2011/05/20/extract-gps-latitude-and-longitude-data-from-exif-using-python-imaging-library-pil/.

I turned on "Location Services" for the camera on my phone and snapped a bunch of pictures over a few days, then copied these to my SIFT system. Here's the directory listing:

Figure 1: Directory listing of a bunch of images from an iPhone and the script to parse them

To create the GeoRSS file, simply run the "photo_map.py" script with the files as an argument, like so:

Figure 2: Running the photo_map.py script against all the JPG files and redirecting the output to the xml file

Update: the code in photo_map.py is available in my git repo as exif2georss.py. Again, it is nearly all based on code taken from the links mentioned previously.

Now, here's where a good developer is really needed, someone like the guy behind "Ricky's Bing Maps Blog". He's done all the heavy lifting, creating a tool that can read our GeoRSS file and put pushpins on a Bing map for each set of GPS coordinates. You can download his code and build your own tool for doing this, but if you just want a quick solution that works, open Internet Explorer and go to maps.bing.com:

Figure 3: Internet Explorer with maps.bing.com loaded

Notice under the stylized "bing" logo in blue where it says "Maps" in orange? Right below that there is an image of a car and a row of menu options, one of which is "Map apps." If you click on "Map apps," you'll see this:
Figure 4: What you should see after clicking on the "Map apps" button

At the top of this window there is a search box. In that box, type in "georss" without the quotes. Duh. You should be presented with this:
Figure 5: Showing Ricky's Data Viewer, which will read our GeoRSS xml file and plot the GPS coordinates!

Click on "Ricky's Data Viewer" and you'll see something like this:
Figure 6: Bing's map now has Ricky's Data Viewer on the side. Note the "GeoRSS" tab.

Click on the "GeoRSS" tab and you'll see this:
Figure 7: Enough screen shots yet? Now we can select our GeoRSS file that we created earlier.

Select your file:
Figure 8: Navigate to your file (it's on my SIFT share) and click Open. Here comes the magic...

Now we can see a pushpin for every location where a photo was taken:
Figure 9: Pushpins representing locations where photos were taken. Mousing over the pin shows the photo file name.

That's it for my prototype code. Again, this could be taken further with more time and effort. According to the docs for Bing, these mouseover events can be modified to show more data. For example, it may be possible to add the timestamp information to the pushpins and have that appear on the mouseover. And of course you can zoom in to the map and get a better idea of where a cluster of photos was taken, by default Ricky's code centers the map over the collection.

6 comments:

  1. I was just thinking about how to plot multiple locations on a map too!
    Nice work!
    Have you been coding in Python long? I'm just starting Perl (mainly to look at RegRipper plugins) and was curious about how Python compares to Perl.

    ReplyDelete
    Replies
    1. I used to do everything in Perl, years ago. It's a really powerful language, especially for any text processing. My problem was when I went back to look at code I'd written six months or more ago, I couldn't make sense of it. This is less of a problem for me with Python. However, Perl is a more mature language with more established libraries and therefore is probably more capable, off the shelf. I decided a year or so ago that going forward, I would stick with Python exclusively until I felt I'd "mastered" it. I do so little dev work that it will be years before that will happen, if ever. I will try and get the Python script released later this week, but as I mentioned, I borrowed heavily from the code linked in the post, I hardly had to write anything.

      Delete
  2. I forgot to ask about the bash one-liner?

    PS I feel your pain on those screenshots too ;)

    ReplyDelete
    Replies
    1. I used to work with a guy who hated screen shots in documentation, he said they confused the issue. I think a picture is worth a thousand words, but how many is too many? Meh. As for the bash one liner, it creates a single HTML file for each photo, less than ideal. I think having one map with all the images plotted may be more useful. But here's the one liner:

      for i in $(exiftool\(-k\).exe photo* 2>/dev/null | grep "GPS Pos" | sed 's/deg//g' | awk -F":" '{print $2}' | sed 's/ /+/g' | sed "s/'/%27/g" | sed 's/"/%22/g'); do wget -O $i.html --no-check-certificate https://maps.google.com/maps?q=$i; done

      It's ugly, but last I tried it, it worked in Cygwin on a system with exiftool in the path, renamed as exiftool(-k).exe.

      Delete
  3. Dave,

    Excellent work. I was wondering if you know of a way how I may recursively scan a mounted hard drive image starting at C:\ and locate all GPS tagged pictures and add them into one georss.xml or other file that can be uploaded to Google Maps or Bing maps?

    Thanks for sharing your work.

    Gerald

    ReplyDelete
  4. GParsons, apologies for the delayed response. I haven't checked in here for a few months. :)

    Take a look at this post:
    http://computer-forensics.sans.org/blog/2008/11/12/more-command-line-forensics-fu

    It may provide some useful info for doing this.

    ReplyDelete

Paperclip Maximizers, Artificial Intelligence and Natural Stupidity

Existential risk from AI Some believe an existential risk accompanies the development or emergence of artificial general intelligence (AGI)...