这个想法其实在这篇博客中早就已经实现了,只不过那时候实在Android手机上做的。这次利用Google Earth作为展示平台,在电脑上实现。 在电脑上实现主要流程和思路都是一样的,唯一不同的是这次以KML文件作为数据存储格式,利用Google Earth打开。 读取EXIF中的GPS信息这里就不再赘述了,新增的部分就是根据读取的位置信息生成KML文件。
KML文件本质上是XML文件,KML是标记语言(Keyhole Markup Language)的缩写,最初由Keyhole公司开发,是一种基于XML语法与格式的、用于描述和保存地理信息(如点、线、图像、多边形和模型等)的编码规范,可以被Google Earth和Google Maps识别并显示。 Google也提供了一个KML文件的Sample,可以下载学习。KML教程可以看这里。 再简单说一下KMZ和KML的差别,KMZ可以理解为是压缩的KML,把KML压缩成zip文件,然后将后缀名改成kmz即可。同理,如果想查看kmz对应的kml,直接把kmz解压即可。 下面就直接放代码。
1.代码
# coding=utf-8
from PIL import Image
from PIL.ExifTags import TAGS
import os
def findAllFiles(root_dir, filter):
"""
遍历搜索文件
:param root_dir:搜索目录
:param filter: 搜索文件类型
:return: 路径、文件名、路径+文件名
"""
print("Finding files ends with \'" + filter + "\' ...")
separator = os.path.sep
paths = []
names = []
files = []
# 遍历
for parent, dirname, filenames in os.walk(root_dir):
for filename in filenames:
if filename.endswith(filter):
paths.append(parent + separator)
names.append(filename)
for i in range(paths.__len__()):
files.append(paths[i] + names[i])
print (names.__len__().__str__() + " files have been found.")
paths.sort()
names.sort()
files.sort()
return paths, names, files
def get_exif_data(fname):
"""
获取EXIF信息
:param fname: 影像文件路径
:return: 字典类型的EXIF信息
"""
ret = {}
try:
img = Image.open(fname)
if hasattr(img, '_getexif'):
exifinfo = img._getexif()
if exifinfo != None:
for tag, value in exifinfo.items():
decoded = TAGS.get(tag, tag)
ret[decoded] = value
else:
ret = 'no exif'
except IOError:
print 'IOERROR ' + fname
return ret
if __name__ == '__main__':
directory = raw_input("Input directory of images('.' as default):\n")
file_type = raw_input("Input image type('.jpg' as default):\n")
if directory is "":
directory = "."
if file_type is "":
file_type = ".jpg"
paths, names, files = findAllFiles(directory, file_type)
photo_info = []
for i in range(files.__len__()):
print "reading ", (i + 1), "/", files.__len__()
exif = get_exif_data(files[i])
if exif != "no exif":
if exif.get('FocalLength') is not None:
focalLength = exif.get('FocalLength')[0] * 1.0 / exif.get('FocalLength')[1]
else:
focalLength = 0
if exif.get("ISOSpeedRatings") is not None:
iso = exif.get("ISOSpeedRatings")
else:
iso = 0
if exif.get("Model") is not None:
model = exif.get("Model")
else:
model = "default"
if exif.get("ShutterSpeedValue") is not None:
if exif.get("ShutterSpeedValue")[0] == 0:
shutter = (exif.get("ShutterSpeedValue")[0] * 1.0).__str__()
else:
shutter = "1/" + int(
1000 / (exif.get("ShutterSpeedValue")[0] * 1.0 /
exif.get("ShutterSpeedValue")[1])).__str__()
else:
shutter = "1/0"
time_info = exif.get("DateTime")
if exif.has_key('GPSInfo'):
info = exif.get('GPSInfo')
if info.has_key(1) and info.has_key(3):
lat = info[2]
lon = info[4]
lat_deg = lat[0][0] * 1.0 / lat[0][1]
lat_min = lat[1][0] * 1.0 / lat[1][1]
lat_sec = lat[2][0] * 1.0 / lat[2][1]
lon_deg = lon[0][0] * 1.0 / lon[0][1]
lon_min = lon[1][0] * 1.0 / lon[1][1]
lon_sec = lon[2][0] * 1.0 / lon[2][1]
lat_decimal = lat_deg + lat_min / 60.0 + lat_sec / 3600.0
lon_decimal = lon_deg + lon_min / 60.0 + lon_sec / 2600.0
if info[1] is u'S':
lat_decimal = -lat_decimal
if info[3] is u'W':
lon_decimal = -lon_decimal
photo_info.append((focalLength, iso, model, shutter, time_info, (lat_decimal, lon_decimal)))
else:
photo_info.append("no info")
else:
photo_info.append("no info")
mean_lon = 0
mean_lat = 0
counter = 0
placemarks = []
for i in range(photo_info.__len__()):
if photo_info[i] is not "no info":
line1 = "\t\t\t<Placemark>\n"
line2 = "\t\t\t\t<name>" + names[i] + "</name>\n"
line3 = "\t\t\t\t<description>\n"
line4 = "\t\t\t\t<img style=\"max-width:500px;\" src=\"file:///" + files[i] + "\"></img>\n"
line5 = "\t\t\t\tISO:" + photo_info[i][1].__str__() + \
" ShutterSpeed:" + photo_info[i][3].__str__() + \
" FocalLength:" + photo_info[i][0].__str__() + \
"<br />Datetime:" + photo_info[i][4] + \
" Camera:" + photo_info[i][2] + "\n"
line6 = "\t\t\t\t</description>\n"
line7 = "\t\t\t\t<Point>\n"
line8 = "\t\t\t\t\t<coordinates>" + photo_info[i][5][1].__str__() + "," + photo_info[i][5][
0].__str__() + ",0</coordinates>\n"
line9 = "\t\t\t\t</Point>\n"
line10 = "\t\t\t</Placemark>\n"
counter += 1
mean_lon = mean_lon + photo_info[i][5][1]
mean_lat = mean_lat + photo_info[i][5][0]
item = line1 + line2 + line3 + line4 + line5 + line6 + line7 + line8 + line9 + line10
placemarks.append(item)
mean_lon = mean_lon / counter
mean_lat = mean_lat / counter
photos = open(directory + os.path.sep + "photos.kml", 'w+')
photos.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
photos.write("<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n")
photos.write("\t<Document>\n")
photos.write("\t\t<name>Photos</name>\n")
photos.write("\t\t<open>1</open>\n")
photos.write("\t\t<description>KML file created by PhotoLocator.</description>\n")
photos.write("\t\t<Folder>\n")
photos.write("\t\t\t<name>Placemarks</name>\n")
photos.write("\t\t\t<description>Your photos with geo-info are listed here.</description>\n")
photos.write("\t\t\t<LookAt>\n")
photos.write("\t\t\t\t<longitude>" + mean_lon.__str__() + "</longitude>\n")
photos.write("\t\t\t\t<latitude>" + mean_lat.__str__() + "</latitude>\n")
photos.write("\t\t\t\t<altitude>0</altitude>\n")
photos.write("\t\t\t\t<tilt>10</tilt>\n")
photos.write("\t\t\t</LookAt>\n")
for item in placemarks:
photos.write(item)
photos.write("\t\t</Folder>\n")
photos.write("\t</Document>\n")
photos.write("</kml>")
print "Result has been saved at:", directory + os.path.sep + "photos.kml"
photos.close()
运行上面的代码,在Google Earth上展示的效果如下。 项目放在了Github上,点击查看。
本文作者原创,未经许可不得转载,谢谢配合