Mapping every place i’ve been: Extracting Photo location Data

I was on reddit one day looking at Data is beautiful subreddit, and i came across a post by Geoff Boeing about mapping every place that he’s ever been in his life. And i thought this was cool and something i’d like to try to code my self. In his example he shows how he got the data from Google and Foursquare. I didn’t want to start in the same place so i’ve decided to start with my Photos. For the last 6-7 years every camera i’ve own has had built in GPS and my Phone all have GPS as well. So i have plenty of data to start with.

Before we look in to the code here is what the end product looks like. And here a web version that can be played with

Where i've been

Where i’ve been

First Getting the Exif data out of a JPG

There is a great Package for this called ExifRead which you can install here. I created the function read_image, which get the data we needs.
First we check to see if the image is a JPG or not, if it not we skip it. Next we try to see if it has the 4 variables that we need. The Latitude, Longitude and Direction for each (N,S or W,E). We then return a string in the following format longitude,Latitude. I use this as a key for my dictionary so that we only plot each location once


def read_image(image, full_path):
    """
    Read an Image, and get the EXIF data that include the GPS data
    """
    with open(os.path.join(full_path, image), 'rb') as f:
        if image.find('JPG') == -1:
            return
        tags = exifread.process_file(f)
        try:
            lat = tags['GPS GPSLatitude']
            long = tags['GPS GPSLongitude']
            lat_directions = tags['GPS GPSLatitudeRef']
            long_direction = tags['GPS GPSLongitudeRef']
                
            lat_degree = convert_to_degree(lat)
            if str(lat_directions) == "S":
                lat_degree = -lat_degree
            long_degree = convert_to_degree(long)
            if str(long_direction) == "W":
                long_degree = -long_degree
            return str(long_degree) + ',' + str(lat_degree)
        except:
            return

For my Sony Cybershot, and my current iPhone both store the Latitude and Longitude in the following format. Degree Minute Second\. To plot thing on most maps you need to convert to degree to a Decimal. To do that you need to use the following equation.

Degree + Minute\60 + (second\)\3600

In my code i also round to 4 decimal places. Which greatly cut the number of point drop, The closest point can be at this point is roughly 1 meter, which for this map is still way way more than we need.


def convert_to_degree(number):
    """
    Takes a Degree in the Degree min second format and covert it to a decimal
    """
    #convert from IfdTag to a string so we can parse it
    number = str(number)
    #Remove [] from the ends
    number = number[1:-1]
    degree, min, sec = number.split(',')
    s_t, s_b = sec.split('/')
    sec = (float(s_t) / float(s_b)) / 3600
    dd = Decimal(degree) + Decimal(min)/60 + Decimal(sec)
    #Limit us to 4 places after the point
    dd = round(dd, 4)
    return dd

The last 2 function in the code just put everything together.
Create_GeoJson create the json file needed by Leaflet (the mapping software i’m using)
Get_photos which goes in to an iphoto library and find all the photos

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>