利用相片位置生成KML并在Google Earth显示

该代码示例演示如何使用Python读取图片的EXIF数据,特别是GPS信息,然后生成KML文件,这些文件可以在GoogleEarth中用来定位和展示图片的位置。KML是一种用于描述地理信息的XML格式。程序首先遍历指定目录下的指定类型图片,获取其EXIF信息,包括经纬度,并最终创建一个包含图片位置信息的KML文档。
摘要由CSDN通过智能技术生成

一、思路

这次利用Google Earth作为展示平台,在电脑上实现。 利用Google Earth打开。 读取EXIF中的GPS信息这里就不再赘述了,新增的部分就是根据读取的位置信息生成KML文件。

KML文件本质上是XML文件,KML是标记语言(Keyhole Markup Language)的缩写,最初由Keyhole公司开发,是一种基于XML语法与格式的、用于描述和保存地理信息(如点、线、图像、多边形和模型等)的编码规范,可以被Google Earth和Google Maps识别并显示。 再简单说一下KMZ和KML的差别,KMZ可以理解为是压缩的KML,把KML压缩成zip文件,然后将后缀名改成kmz即可。同理,如果想查看kmz对应的kml,直接把kmz解压即可。 下面就直接放代码。

二、代码

# 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上展示的效果如下。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

倾城一少

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值