|The final product. You click on a pin and a balloon with the |
image taken at that location pops up.
So I got a bunch of pictures at work that turned out to be Geotagged. "Pretty cool" I thought to myself, "but clearly I need to see these on a map to know where they were taken!" Deciding to leap before actually looking, I missed the fact that Picassa can generate KMZ files for use in Google Earth directly, and instead went about making a script to do it manually. Doing it like this does have the slight advantage of being able to control the output KMZ much more precisely - so you can have bigger pictures or different icons or show different info in the balloons.
To do this, I used a couple of third party libraries for Python. Simplekml is a package that lets you write kml and kmz files. Although there were a couple of things that seemed to be bugs, it worked pretty well.
To extract the GPS coordinates, I needed a package to read exif data. At first I tried to use PIL, but I couldn't get it to work on my work computer (didn't have a c compiler set up correctly) so I ended up using pyexiv2. The page said it was deprecated and I should use Gexiv2 instead. That seemed to add more complications, so I just used pyexiv and it worked fine (note I did this in Python 2.7, if I had used Python 3.x pyexiv2 wouldn't have worked).
This outputs a KMZ file which includes all the pictures zipped up within it. In other words, it's making a copy of all your pictures in a file that could get pretty big if you have lots of them. Anyway, without further ado, here is the script that goes through a given folder and generates a kmz file with the locations of each.
point.style.balloonstyle.text = balstylestring
kml.savekmz(OutputFile, format = False)
Please note that the "balstylestring= "..." should be one line, the Blogger formatter thing screws it up and I can't figure out how to fix it. Also note that I had to put a space on either side of the tag between the < and >, so remove those if you cut and paste it.
import os, simplekml, datetime as dt, pyexiv2 as pex path = r'C:\Users\aschmitt\Desktop\testpics' OutputFile = "Map with Sweetcroft Pictures.kmz" def GetLatLong(fn): metadata = pex.ImageMetadata(fn) metadata.read() Lat = metadata['Exif.GPSInfo.GPSLatitude'].human_value Long = metadata['Exif.GPSInfo.GPSLongitude'].human_value Alt = metadata['Exif.GPSInfo.GPSAltitude'].human_value DateTime = metadata['Exif.Image.DateTime'].human_value #string DT = dt.datetime.strptime(DateTime, '%Y:%m:%d %H:%M:%S') #Datetime object return (Lat, Long, Alt, DT) def FormatLatLong(LatLongString): d = LatLongString.find('deg') Degrees = float(LatLongString[:d]) m = LatLongString.find("'") Minutes = float(LatLongString[d+4:m]) s = LatLongString.find('"') Seconds = float(LatLongString[m+2:s]) decCoords = Degrees + Minutes/60.0 + Seconds/3600.0 return decCoords kml = simplekml.Kml() for (dirpath, dirnames, filenames) in os.walk(path): for filename in filenames: fullpath = os.path.join(dirpath, filename) try: Lat, Long, Alt, DT = GetLatLong(fullpath) except: Lat, Long, Alt, DT = (None, None, None, None) print '%s: Lat: %s, Long: %s, Alt: %s' % (fullpath, Lat, Long, Alt) if Lat: x, y = (FormatLatLong(Lat), FormatLatLong(Long)) point = kml.newpoint(name = filename , coords = [(y,x)]) picpath = kml.addfile(fullpath) print picpath fn = 'files/'+ os.path.splitext(filename) + '.jpg' #Note: will not work if .JPG is used, must be lower case. balstylestring = "< ![CDATA[
Date: " + DT.strftime('%a, %B %d, %Y') + "
Time: " + DT.strftime("%I:%M:%S %p") + "