从数码照片中读取定位信息
摘要:数码照片在拍摄时会记录照片的拍摄信息,如果拍照时开启了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 输出的点数据
从数码照片中读取定位信息相关推荐
- Failed to introspect Class [com.controller.HardWareController] from ClassLoa在ssm中读取串口信息
标题:Failed to introspect Class [com.controller.HardWareController] from ClassLoa在ssm中读取串口信息 之前使用java程 ...
- 从属性资源文件中读取连接数据库信息
从属性资源文件中读取连接数据库信息 jdbc.properties 属性配置文件 driver=com.mysql.jdbc.Driver url=jdbc:mysql://127.0.0.1:330 ...
- JavaWEB中读取配置信息
第一种方法是使用java.io和java.util包,缺点是路径的概念要清晰, 例子: Properties prop = new Properties(); InputStream in = get ...
- jpg中读取GPS信息
需要读取EXIF信息,自己阅读了一些资料,现在共享一下 需要注意的是,由于EXIF是一种可交换的文件格式,所以可以用在Intel系列和Motorola系列的CPU上(至于两者CPU的区别,大家可以到网 ...
- python中读取word信息_Python实现批量读取word中表格信息的方法
本文实例讲述了Python实现批量读取word中表格信息的方法.分享给大家供大家参考.具体如下: 单位收集了很多word格式的调查表,领导需要收集表单里的信息,我就把所有调查表放一个文件里,写了个py ...
- 从 ADNI 的 XML 文件中读取临床信息
本文配合手把手式介绍 ADNI 影像数据下载使用. 仅给出了如下读取XML文件中的project和subject信息的部分代码,读取其他内容采用一样的写法即可. 只适合自己批量读取一下XML文件,所以 ...
- brit用脚本JavaScript用报表创建数据源,并从配置文件中读取数据库信息
可以定义一个参数去指定properties文件的路径,然后创建datasource. 在datasource的script中编辑beforeOpen事件,参考下面的代码: ============== ...
- java 获取 邮箱联系人_在android中读取联系人信息的程序,包括读取联系人姓名、手机号码和邮箱...
/** 读取联系人的信息*/ public voidtestReadAllContacts() { Cursor cursor= this.getContext().getContentResolve ...
- 从照片中读取经纬度信息
引入依赖 <dependency> <groupId>com.drewnoakes</groupId> <artifactId>metadata-ext ...
最新文章
- linux 内核 初始化失败,300分求内核初始化及启动中出现的问题,
- LeetCode: 13. Roman to Integer
- python 高阶函数
- 你知道event库吗?教你如何写一个自己的event库
- java condition详解_Java使用Condition控制线程通信的方法实例详解
- 如何从零开始搭建 CI/CD 流水线
- 数据库-优化-数据库结构的优化-拆分优化
- 关于telnet: connect to address 190.168.6.6: No route to host 报错处理
- Android 系统(269)---native保活5.0以上方案推演过程以及代码详述
- java idle 机制_深入springboot原理——一步步分析springboot启动机制(starter机制)...
- IBM建立大中华区云计算中心供验证测试
- mac安装appium时执行appium-doctor命令提示command not found: appium-doctor
- Python将单一数字标签进行one-hot编码
- cdh6.1,cdh6.2 hue sqoop组件提交异常
- 【并发编程系列6】Condition队列原理及await和singal(等待/唤醒)机制源码分析
- 利用Qt制作QQ的登录及主界面
- 高分子聚合物过滤器折叠滤芯
- #1.8程式化自动化交易
- python 智能识别 超市商品 python人工智能 图像识别可以检测图片,视频流,有界面
- 150ms流畅体验 NBA2KOnline如何网络同步优化
热门文章
- 微信小程序头脑风暴2答题辅助
- Boost PFC参数计算——PFC电感
- 煤矿企业对无人值守称重系统性能有什么要求
- 洛谷 P4707 重返现世
- 互联网行业对标——阿里,腾讯,百度,滴滴,美团,头条,京东,网易,亚马逊等等...
- 转: std::string用法详解
- java并发编程实战wwj----------------------第一阶段--------------11-12-13-14-15
- java基础知识——流式计算Stream API
- usb转串口驱动ch341安装及安装后无效的处理办法
- 43種能創造「被動收入」的方法,收藏起來吧!