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
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\
Degree + Minute\60 + (second\
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