摘要:数码照片在拍摄时会记录照片的拍摄信息,如果拍照时开启了GPS定位服务功能,则就会记录拍摄时的经纬度坐标及高程信息。本文介绍如何读取数码照片中的位置信息,以及根据位置信息转换成shapefile格式点数据。

1、目标

数码照片在拍摄时会产生一个Exif数据(Exchangeable image file format),该数据记录了照片的拍摄信息,并附加于JPEG、TIFF、RIFF等文件之中,如果拍照时开启了GPS定位服务功能,则Exif数据就会记录照片拍摄时的位置数据(经纬度坐标及高程)。打开照片的属性对话框可以看到Exif数据。

图1 照片属性对话框

通过从数码照片中读取位置信息,则可以产生拍摄点的点数据,进一步根据多个照片的拍摄时间可以产生拍摄点的轨迹数据。

2、方法

照片中的Exif数据读取可利用PIL(新的版本称为Pillow)图像处理包。PIL图像对象的_getexif()方法以字典形式返回照片的Exif数据,形式如下:

{271: 'HUAWEI',

272: 'HUAWEI B199',

282: (72, 1),

283: (72, 1),

296: 2,

531: 1,

33434: (1, 1089),

34665: 146,

……

字典中的键用整数表示,可利用ExitTags模块中的TAGS字典查看每个键对应的描述字符串,代码及输出结果如下:

from PIL.ExifTags import TAGS
for item in TAGS.items():print(item)

(11, 'ProcessingSoftware')

(254, 'NewSubfileType')

(255, 'SubfileType')

(256, 'ImageWidth')

(257, 'ImageLength')

……

从输出结果中可以查看到记录GPS信息的键为34853。以下代码是输出一个照片的GPS信息:

from PIL import Image
fname = "20160828042149.jpg"
img = Image.open(fname)
exifinfo = img._getexif()
GPSinfo = exifinfo[34853]
GPSinfo

输出结果如下:

{1: 'N',

2: ((30, 1), (18, 1), (417659, 10000)),

3: 'E',

4: ((119, 1), (26, 1), (394445, 10000)),

5: b'\x00',

6: (296000, 1000),

7: ((8, 1), (22, 1), (30, 1)),

27: 'ASCII\x00\x00\x00GPS',

29: '2016:08:28'}

GPS信息的值是一个字典,字典中的键用整数表示,可利用ExitTags模块中的GPSTAGS字典查看每个键对应的描述字符串,代码及输出结果如下:

from PIL.ExifTags import GPSTAGS
for item in GPSTAGS.items():print(item)

(0, 'GPSVersionID')

(1, 'GPSLatitudeRef')

(2, 'GPSLatitude')

(3, 'GPSLongitudeRef')

(4, 'GPSLongitude')

(5, 'GPSAltitudeRef')

……

GPS信息中最主要的信息是经度和纬度坐标,经度坐标的键为2,纬度坐标的键为4,这两个键对应的值都是元组,元组中有三个元素,分别记录坐标的度、分、秒数据,元素的类型也是元组,由两个元素组成,前一个元素和后一个元素的比值为实际数据。

由于GPS信息中的坐标单位是度分秒,如要把照片的位置转换为点数据,需要把坐标的单位转成十进制度。

3、示例

以下示例是输出一个照片的经纬度坐标(十进制度),考虑到有些照片没有记录经纬度坐标,GPS信息字典中没有相应的键,通过键去获取经纬度坐标时就会出错,因此,在代码中增加了try语句。

import os
from PIL import Imagedef photo_lonlat(fname):img = Image.open(fname)exifinfo = img._getexif()try:GPSinfo = exifinfo[34853]lat_d = GPSinfo[2][0][0]/GPSinfo[2][0][1]lat_m = GPSinfo[2][1][0]/GPSinfo[2][1][1]lat_s = GPSinfo[2][2][0]/GPSinfo[2][2][1]lon_d = GPSinfo[4][0][0]/GPSinfo[4][0][1]lon_m = GPSinfo[4][1][0]/GPSinfo[4][1][1]lon_s = GPSinfo[4][2][0]/GPSinfo[4][2][1]lat = lat_d + lat_m/60.0 + lat_s/3600.0lon = lon_d + lon_m/60.0 + lon_s/3600.0return (lon,lat)except:return Nonefname = "20160828042149.jpg"
lon = photo_lonlat(fname)[0]
lat = photo_lonlat(fname)[1]
print(f"Longitude: {lon}")
print(f"Latitude:  {lat}")

输出结果如下:

Longitude: 119.44429013888889

Latitude:  30.311601638888888

以下示例是读取某个文件夹下面所有jpg和tif文件的经纬度以及时间信息,并产生shapefile格式的点数据,示例使用shapely包创建点几何对象,利用geopandas包产生shapefile格式数据。

import os
from PIL import Image
from shapely.geometry import Point
import geopandas as gpddef photo_lonlat(fname):img = Image.open(fname)exifinfo = img._getexif()DateTimeOriginal = exifinfo[36867]try:GPSinfo = exifinfo[34853]      lat_d = GPSinfo[2][0][0]/GPSinfo[2][0][1]lat_m = GPSinfo[2][1][0]/GPSinfo[2][1][1]lat_s = GPSinfo[2][2][0]/GPSinfo[2][2][1]lon_d = GPSinfo[4][0][0]/GPSinfo[4][0][1]lon_m = GPSinfo[4][1][0]/GPSinfo[4][1][1]lon_s = GPSinfo[4][2][0]/GPSinfo[4][2][1]lat = lat_d + lat_m/60.0 + lat_s/3600.0lon = lon_d + lon_m/60.0 + lon_s/3600.0return (lon,lat,DateTimeOriginal)except:return Nonefnames = []
dirpath = "photos"
for filename in os.listdir(dirpath):if os.path.splitext(filename)[1] in ('.tiff', '.tif', '.jpg', '.jpeg'):fnames.append(os.path.join(dirpath, filename))data = []
for fname in fnames:if photo_lonlat(fname) == None:print(f"{fname} hasn't GPSinfo")else:lon = photo_lonlat(fname)[0]lat = photo_lonlat(fname)[1]DateTimeOriginal = photo_lonlat(fname)[2]basename = os.path.basename(fname)point = Point([lon,lat])data.append([basename,DateTimeOriginal,point])gdf = gpd.GeoDataFrame(data,columns=["name","time","geometry"])
gdf.to_file("photo_point.shp")

图2是输出结果。

图2 输出的点数据

从数码照片中读取定位信息相关推荐

  1. Failed to introspect Class [com.controller.HardWareController] from ClassLoa在ssm中读取串口信息

    标题:Failed to introspect Class [com.controller.HardWareController] from ClassLoa在ssm中读取串口信息 之前使用java程 ...

  2. 从属性资源文件中读取连接数据库信息

    从属性资源文件中读取连接数据库信息 jdbc.properties 属性配置文件 driver=com.mysql.jdbc.Driver url=jdbc:mysql://127.0.0.1:330 ...

  3. JavaWEB中读取配置信息

    第一种方法是使用java.io和java.util包,缺点是路径的概念要清晰, 例子: Properties prop = new Properties(); InputStream in = get ...

  4. jpg中读取GPS信息

    需要读取EXIF信息,自己阅读了一些资料,现在共享一下 需要注意的是,由于EXIF是一种可交换的文件格式,所以可以用在Intel系列和Motorola系列的CPU上(至于两者CPU的区别,大家可以到网 ...

  5. python中读取word信息_Python实现批量读取word中表格信息的方法

    本文实例讲述了Python实现批量读取word中表格信息的方法.分享给大家供大家参考.具体如下: 单位收集了很多word格式的调查表,领导需要收集表单里的信息,我就把所有调查表放一个文件里,写了个py ...

  6. 从 ADNI 的 XML 文件中读取临床信息

    本文配合手把手式介绍 ADNI 影像数据下载使用. 仅给出了如下读取XML文件中的project和subject信息的部分代码,读取其他内容采用一样的写法即可. 只适合自己批量读取一下XML文件,所以 ...

  7. brit用脚本JavaScript用报表创建数据源,并从配置文件中读取数据库信息

    可以定义一个参数去指定properties文件的路径,然后创建datasource. 在datasource的script中编辑beforeOpen事件,参考下面的代码: ============== ...

  8. java 获取 邮箱联系人_在android中读取联系人信息的程序,包括读取联系人姓名、手机号码和邮箱...

    /** 读取联系人的信息*/ public voidtestReadAllContacts() { Cursor cursor= this.getContext().getContentResolve ...

  9. 从照片中读取经纬度信息

    引入依赖 <dependency> <groupId>com.drewnoakes</groupId> <artifactId>metadata-ext ...

最新文章

  1. linux 内核 初始化失败,300分求内核初始化及启动中出现的问题,
  2. LeetCode: 13. Roman to Integer
  3. python 高阶函数
  4. 你知道event库吗?教你如何写一个自己的event库
  5. java condition详解_Java使用Condition控制线程通信的方法实例详解
  6. 如何从零开始搭建 CI/CD 流水线
  7. 数据库-优化-数据库结构的优化-拆分优化
  8. 关于telnet: connect to address 190.168.6.6: No route to host 报错处理
  9. Android 系统(269)---native保活5.0以上方案推演过程以及代码详述
  10. java idle 机制_深入springboot原理——一步步分析springboot启动机制(starter机制)...
  11. IBM建立大中华区云计算中心供验证测试
  12. mac安装appium时执行appium-doctor命令提示command not found: appium-doctor
  13. Python将单一数字标签进行one-hot编码
  14. cdh6.1,cdh6.2 hue sqoop组件提交异常
  15. 【并发编程系列6】Condition队列原理及await和singal(等待/唤醒)机制源码分析
  16. 利用Qt制作QQ的登录及主界面
  17. 高分子聚合物过滤器折叠滤芯
  18. #1.8程式化自动化交易
  19. python 智能识别 超市商品 python人工智能 图像识别可以检测图片,视频流,有界面
  20. 150ms流畅体验 NBA2KOnline如何网络同步优化

热门文章

  1. 微信小程序头脑风暴2答题辅助
  2. Boost PFC参数计算——PFC电感
  3. 煤矿企业对无人值守称重系统性能有什么要求
  4. 洛谷 P4707 重返现世
  5. 互联网行业对标——阿里,腾讯,百度,滴滴,美团,头条,京东,网易,亚马逊等等...
  6. 转: std::string用法详解
  7. java并发编程实战wwj----------------------第一阶段--------------11-12-13-14-15
  8. java基础知识——流式计算Stream API
  9. usb转串口驱动ch341安装及安装后无效的处理办法
  10. 43種能創造「被動收入」的方法,收藏起來吧!