【华为云技术分享】Python解析照片EXIF信息,获取坐标位置

1、背景

每张图片都包含EXIF信息,它是可交换图像文件的缩写,是专门为数码相机的照片设定的,可以记录数码照片的属性信息和拍摄数据。EXIF可以附加于JPEG、TIFF、RIFF等文件之中,为其增加有关数码相机拍摄信息的内容和索引图或图像处理软件的版本信息。总结来说EXIF信息包含着该照片的拍照基本信息。

网上有很多的EXIF信息查看器,这里上传一张十月一日和朋友去观看的我和我的祖国这部电影的照片,没有任何的标志建筑背景,使用该工具进行尝试,可以很直观的看到拍照时间、手机型号、地理位置等信息,具体如下所示:

接下来通过Python exifread库函数解析照片,它可以解析图片的EXIF信息,进而依托百度地图开放平台将GPS坐标信息转换为具体的位置,若想达到理想效果需要满足以下几点要求:

他人通过选择原图的方式,发送照片;
相机拍照时,默认设置了GPS定位;
图片没P过;

2、云端部署

第1步:登录百度地图开放平台,进入控制台,这里说明一下,百度地图开放平台的定位有Web开发、Android开发
iOS开发等不同的服务,最终均会生成服务密钥(AK),我们的Python调用就是依托于服务密钥,所以创建什么业务影响不大,故不看开发文档也可以很方便开发。

第2步:创建应用,这里我选择应用类型为:服务端(什么类型都不影响接下来的操作,重点是获取服务密钥)。

这样就操作完成了,使用获取的服务密钥就可以实现访问。

最后拓展学习,看一下开发文档 ,主要是不同终端设备的SDK说明文档,有需要的小伙伴可以针对学习。

3、照片分析

依旧使用该照片做测试。

分析代码如下:

 1 import requests
 2 import exifread
 3  
 4 class GetPhotoInfo:
 5     def __init__(self, photo):
 6         self.photo = photo
 7         # 百度地图ak  请替换为自己申请的ak
 8         self.ak = 'nYPs4LQ9a4VhVxj55AD69K6zgsRy9o4z'
 9         self.location = self.get_photo_info()
10  
11     def get_photo_info(self, ):
12         with open(self.photo, 'rb') as f:
13             tags = exifread.process_file(f)
14         try:
15             # 打印照片其中一些信息
16             print('拍摄时间:', tags['EXIF DateTimeOriginal'])
17             print('照相机制造商:', tags['Image Make'])
18             print('照相机型号:', tags['Image Model'])
19             print('照片尺寸:', tags['EXIF ExifImageWidth'], tags['EXIF ExifImageLength'])
20             # 纬度
21             lat_ref = tags["GPS GPSLatitudeRef"].printable
22             lat = tags["GPS GPSLatitude"].printable[1:-1].replace(" ", "").replace("/", ",").split(",")
23             lat = float(lat[0]) + float(lat[1]) / 60 + float(lat[2]) / float(lat[3]) / 3600
24             if lat_ref != "N":
25                 lat = lat * (-1)
26             # 经度
27             lon_ref = tags["GPS GPSLongitudeRef"].printable
28             lon = tags["GPS GPSLongitude"].printable[1:-1].replace(" ", "").replace("/", ",").split(",")
29             lon = float(lon[0]) + float(lon[1]) / 60 + float(lon[2]) / float(lon[3]) / 3600
30             if lon_ref != "E":
31                 lon = lon * (-1)
32         except KeyError:
33             return "ERROR:请确保照片包含经纬度等EXIF信息。"
34         else:
35             print("经纬度:", lat, lon)
36             return lat, lon
37  
38     def get_location(self):
39         url = 'http://api.map.baidu.com/reverse_geocoding/v3/?ak={}&output=json' \
40               '&coordtype=wgs84ll&location={},{}'.format(self.ak, *self.location)
41         response = requests.get(url).json()
42         status = response['status']
43         if status == 0:
44             address = response['result']['formatted_address']
45             print('详细地址:', address)
46         else:
47             print('baidu_map error')
48  
49  
50 if __name__ == '__main__':
51     Main = GetPhotoInfo('im1.jpg')
52     Main.get_location()

虽然地理位置和实际看电影的地点存在一些偏差,但是基本信息是挺准的,和EXIF信息查看器解析一致,分析结果如下:

作者:华为云特约供稿开发者 不脱发的程序猿