手机和数码相机拍的照片里除了我们能看到的RGB像元数据,还包含了拍摄时间、图像分辨率、感光值、GPS坐标等属性,记录在Exif(Exchangeable image file format)模块里。
随着手机像素越来越高,用手机记录身边的事(和自拍)已经变成很自然的动作,在一年里我们的手机肯定存了很多照片,照片和Exif数据块中的位置可以做哪些有趣的事情?一张图片和对应的拍摄位置如果没那么多可能性,那一系列照片和位置呢?
我们可以直观看近些年都去了哪里;可以制作和(男/女)朋友一起出去玩的地图故事;可以根据拍照时间和位置动态可视化游览路线;可以基于坐标的聚类整理照片,如拍了800张照片,把每个城市的照片批量整理到各自文件夹;……
地理位置属于个人隐私数据,相关应用需要注意隐私问题,之前挺火的一个谣言是可以根据别人朋友圈发的图知道别人的具体位置,但实际上微信会对朋友圈的图片进行压缩,Exif里的坐标数据是会删除掉的,所以朋友圈的图片是提取不了坐标的。以下实践基于部分自己这些年拍的照片,避免侵犯其他人隐私。
本文主要做的:批量提照片中的坐标->可视化照片位置->制作游历故事地图
所用到的工具:
- Python和exifread库
- Leaflet和两个插件
1,批量提照片中的坐标
照片中的地理坐标记录在Exif块里,Exif信息以0xFFE1作为开头标记,采用TIFF格式,可以自己解析或直接用轮子exifread库,exifread是一个很方便使用的读取tiff和jpeg格式图片的Python库,在pypi上的介绍是:
Easy to use Python module to extract Exif metadata from tiff and jpeg files.
通过 pip install exifread
安装后就可以使用了,我们现在只关心照片的坐标和拍摄时间,根据其教程探索参数和用法。
写代码提取这部分数据:
def extractExif(fpath):#提取坐标
try:
with open(fpath,'rb') as rf:
exif=exifread.process_file(rf)
eDate=exif['EXIF DateTimeOriginal'].printable
eLon=exif['GPS GPSLongitude'].printable
eLat=exif['GPS GPSLatitude'].printable
lon=eLon[1:-1].replace(' ','').replace('/',',').split(',')
#'[116, 29, 10533/500]' to [116,29,10533,500] type==(list)
lon=float(lon[0])+float(lon[1])/60+float(lon[2])/float(lon[3])/3600
lat=eLat[1:-1].replace(' ','').replace('/',',').split(',')
lat=float(lat[0])+float(lat[1])/60+float(lat[2])/float(lat[3])/3600
return [lon,lat,eDate] #经度,纬度,拍摄时间
except Exception as e:
print(e,fpath)
return None
注意的是如果拍照时没有读取地理位置权限那就不好记录拍照时的坐标了,所以使用时需要做一个判断。调用上面的函数批量取一个文件夹下照片的坐标:
wpt='J:/DS_refine/SQL-lyn/exifExtract/image'
latLons=[]
for root, dirs, files in os.walk(wpt):
print(len(files))
for f in files:
exif=extractExif('{0}/{1}'.format(wpt,f))
if exif:
exif[2]=exif[2]+' '+f
latLons.append(exif)
else:
print(f,'exif is None')
有了照片和对应的位置,可以做可视化讲故事了。下面的实践需要了解一些前端HTML和JavaScript知识。
2,在地图中展示坐标
直接展示地理点坐标有很多工具,百度/高德地图的API、Ech