Geolocating photos

Photos taken with GPS-enabled cameras including smartphones store location information in the header of the file in a format called exchangeable image file format (EXIF) tags. These tags are based largely on the same header tags used by the TIFF image standard. In this example, we'll use those tags to create a shapefile with point locations for the photos and file paths to the photos as attributes.

We'll use the Python Imaging Library in this example because it has the ability to extract EXIF data. Most photos taken with smartphones are geotagged images; however, you can download the set used in this example from the following URL:

http://git.io/vczR0

First, we'll import the libraries we need including PIL for the image metadata and PyShp for the shapefiles:

import glob
import os
try:
    import Image
    import ImageDraw
except:
    from PIL import Image
    from PIL.ExifTags import TAGS
import shapefile

Now, we'll need three functions. The first extracts the EXIF data. The second function converts degree, minutes, seconds (DMS) coordinates to decimal degrees. EXIF data stores GPS data as DMS coordinates. The third function extracts the GPS data and performs the coordinate conversion:

def exif(img): # extract exif data.
    exif_data = {}
    try:    
        i = Image.open(img)
        tags = i._getexif()
        for tag, value in tags.items():
            decoded = TAGS.get(tag, tag)
            exif_data[decoded] = value
    except:
        pass
    return exif_data

def dms2dd(d, m, s, i): # convert degrees, min, sec to decimal degrees
    
    sec = float((m * 60) + s)
    dec = float(sec / 3600)
    deg = float(d + dec)
    if i.upper() == 'W':
        deg = deg * -1
    elif i.upper() == 'S':
        deg = deg * -1
    return float(deg)

def gps(exif): # get gps data from exif
    lat = None
    lon = None
    if exif['GPSInfo']:        
        # Lat
        coords = exif['GPSInfo']
        i = coords[1]
        d = coords[2][0][0]
        m = coords[2][1][0]
        s = coords[2][2][0]
        lat = dms2dd(d, m, s, j)
        # Lon
        i = coords[3]
        d = coords[4][0][0]
        m = coords[4][1][0]
        s = coords[4][2][0]
        lon = dms2dd(d, m, s, i)
    return lat, lon

Next, we will loop through the photos, extract the coordinates, and store the coordinates and filename in a dictionary:

photos = {}
photo_dir = "./photos"
files = glob.glob(os.path.join(photo_dir, "*.jpg"))
for f in files:
    e = exif(f)
    lat, lon = gps(e)
    photos[f] = [lon, lat]

Now, we will save the photo information as a shapefile:

w = shapefile.Writer(shapefile.POINT)
w.field("NAME", "C", 80)
for f, coords in photos.items():
    w.point(*coords)
    w.record(f)
w.save("photos")

The filenames of the photos in the shapefile are now attributes of the point locations where the photos were taken. GIS programs including QGIS and ArcGIS have tools to turn those attributes into links when you click on the photo path or the point. The following screenshot from QGIS shows one of the photos opening after clicking on the associated point using the Run feature action tool:

Geolocating photos
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset