利用Python实现读取照片的Exif信息
作者:古明地觉的编程教室
今天要水的文章是,用 Python 读取照片的 Exif 信息。现如今的智能手机在拍摄照片时,都含有 Exif(可交换图像文件格式,Exchangeable image file format)信息,通过该信息可以获取拍照时的位置、时间,以及手机品牌等信息。那么下面就看看如何使用 Python 去获取这些信息吧。
Python 想要读取 Exif 信息需要安装一个第三方库,直接 pip install exifread 即可。
import exifread with open("1.jpg", 'rb') as f: # 直接可以拿到里面的信息,内容非常多 # 但如果无法读取,那么返回值 exif 就是 None exif = exifread.process_file(f) # 这里我们选一些常用的,里面的 value 需要转成字符串 # 不转成字符串的话看起来会比较费劲 print("图片宽度:", str(exif["Image ImageWidth"])) print("图片高度:", str(exif["Image ImageLength"])) print("手机品牌:", str(exif["Image Make"])) print("手机型号:", str(exif["Image Model"])) print("拍摄时间:", str(exif["Image DateTime"])) print("经度:", str(exif["GPS GPSLongitude"])) print("东经还是西经:", str(exif["GPS GPSLongitudeRef"])) print("纬度:", str(exif["GPS GPSLatitude"])) print("南纬还是北纬:", str(exif["GPS GPSLatitudeRef"])) """ 图片宽度: 3968 图片高度: 2976 手机品牌: HUAWEI 手机型号: EML-AL00 拍摄时间: 2021:07:08 19:52:23 经度: [116, 28, 5973999/100000] 东经还是西经: E 纬度: [39, 59, 1255371/200000] 南纬还是北纬: N """
还是比较简单的,但是里面的经度和纬度比较怪,我们还需要再对其转化一下。
lng = str(exif["GPS GPSLongitude"]) # 经度 lat = str(exif["GPS GPSLatitude"]) # 纬度 print(lng) # [116, 28, 5973999/100000] print(lat) # [39, 59, 1255371/200000] # 转成列表 lng = lng[1: -1].replace("/", ",").split(",") lat = lat[1: -1].replace("/", ",").split(",") print(lat) # ['39', ' 59', ' 1255371', '200000'] print(lng) # ['116', ' 28', ' 5973999', '100000'] # 然后得到具体的经纬度 lng = float(lng[0]) + float(lng[1]) / 60 + float(lng[2]) / float(lng[3]) / 3600 lat = float(lat[0]) + float(lat[1]) / 60 + float(lat[2]) / float(lat[3]) / 3600 print(lng) # 116.48326110833334 print(lat) # 39.98507690416667
这里得到的经纬度永远是正数,如果是西经,那么得到的经度要乘上 -1;同理如果是南纬,那么纬度要乘上 -1。
另外需要注意,并非所有的照片都能够进行解析,必须是携带 Exif 信息的原始图片。如果中间进行了压缩、或者 P 图,那么就无法识别了。
当然像一些社交平台也会专门针对 Exif 进行处理,比如微信,你发在朋友圈的图片会自动压缩,所以是不会暴露位置信息的。
方法补充
除了上文的方法,小编还为大家整理了其他Python读取图片Exif信息的方法,需要的可以收藏一下
方法一:
示例代码
import exifread import requests class PhotoExifInfo(): def __init__(self,photo_path): self.photo_path = photo_path self.baidu_map_ak = "your baidu map api key" self.image_info_dict={} self.tags ={} self.interested_keys = [ 'EXIF ExposureMode', 'EXIF ExposureTime', 'EXIF Flash', 'EXIF ISOSpeedRatings', 'Image Model', 'EXIF ExifImageWidth', 'EXIF ExifImageLength', 'Image DateTime', 'EXIF DateTimeOriginal', 'Image Make', # lens # jiaoju ] def get_tags(self): """ 获取照片信息 """ image_content = open(self.photo_path, 'rb') tags = exifread.process_file(image_content) self.tags = tags for item in self.interested_keys: try: info = tags[item] self.image_info_dict[item] = info except: print(f'{self.photo_path} has no attribute of {item}') continue # 遍历获取照片所有信息 #for j, k in tags.items(): #print(f"{j} : {k}") #print('拍摄时间:', tags['EXIF DateTimeOriginal']) #print('照相机制造商:', tags['Image Make']) #print('照相机型号:', tags['Image Model']) #print('照片尺寸:', tags['EXIF ExifImageWidth'], tags['EXIF ExifImageLength']) image_content.close() def get_lng_lat(self): """经纬度转换""" tags = self.tags try: # 纬度 LatRef = tags["GPS GPSLatitudeRef"].printable Lat = tags["GPS GPSLatitude"].printable[1:-1].replace(" ", "").replace("/", ",").split(",") Lat = float(Lat[0]) + float(Lat[1]) / 60 + float(Lat[2]) / 3600 if LatRef != "N": Lat = Lat * (-1) # 经度 LonRef = tags["GPS GPSLongitudeRef"].printable Lon = tags["GPS GPSLongitude"].printable[1:-1].replace(" ", "").replace("/", ",").split(",") Lon = float(Lon[0]) + float(Lon[1]) / 60 + float(Lon[2]) / 3600 if LonRef != "E": Lon = Lon * (-1) return Lat,Lon except: print('Unable to get') def get_city_info(self): result = self.get_lng_lat() if result: Lat, Lon = result url = "https://api.map.baidu.com/reverse_geocoding/v3/?ak="+self.baidu_map_ak+"&output=json&coordtype=wgs84ll&location=" + str(Lat) + ',' + str(Lon) #url = "https://api.map.baidu.com/reverse_geocoding/v3/?ak="+self.baidu_map_ak+"&output=json&coordtype=wgs84ll&location=31.225696563611,121.49884033194" response = requests.get(url).json() status = response['status'] if status == 0: address = response['result']['formatted_address'] if address != "": self.image_info_dict['Position'] = address else: print('baidu_map error') def get_image_info(self): self.get_tags() self.get_city_info() return self.image_info_dict if __name__ == '__main__': result = PhotoExifInfo("test.jpeg").get_image_info() for j, k in result.items(): print(f"{j} : {k}")
示例输出
EXIF ExposureMode : Auto Exposure
EXIF ExposureTime : 10/24723
EXIF Flash : Flash did not fire, auto mode
EXIF ISOSpeedRatings : 50
Image Model : vivo Z1
EXIF ExifImageWidth : 4144
EXIF ExifImageLength : 1968
Image DateTime : 2019:11:03 11:34:24
EXIF DateTimeOriginal : 2019:11:03 11:34:24
Image Make : vivo
Position : 上海市黄浦区中山南路187
方法二
示例代码
import exifread import json import urllib.request f = open('1.jpg', 'rb') tags = exifread.process_file(f) print(tags) # 打印所有照片信息,会以键值对的方法保存 for tag in tags.keys(): print("Key: {0}, value {1}".format(tag, tags[tag])) # 打印照片其中一些信息 print('拍摄时间:', tags['EXIF DateTimeOriginal']) print('照相机制造商:', tags['Image Make']) print('照相机型号:', tags['Image Model']) print('照片尺寸:', tags['EXIF ExifImageWidth'], tags['EXIF ExifImageLength']) def getLatOrLng(refKey, tudeKey): """ 获取经度或纬度 """ if refKey not in tags: return None ref = tags[refKey].printable LatOrLng = tags[tudeKey].printable[1:-1].replace(" ", "").replace("/", ",").split(",") print(LatOrLng) LatOrLng = float(LatOrLng[0]) + float(LatOrLng[1]) / 60 + float(LatOrLng[2]) / 3600 if refKey == 'GPS GPSLatitudeRef' and tags[refKey].printable != "N": LatOrLng = LatOrLng * (-1) if refKey == 'GPS GPSLongitudeRef' and tags[refKey].printable != "E": LatOrLng = LatOrLng * (-1) return LatOrLng # 调用百度地图API通过经纬度获取位置 def getlocation(lat, lng): """ exif里面的经纬度是度分秒形式传入的,需要转换为小数形式,然后根据传入的经纬度,调用百度接口去查询详细地址 """ url = "http://api.map.baidu.com/reverse_geocoding/v3/?ak=百度API的AK信息,需要自己去申请&output=json&coordtype=wgs84ll&language_auto=1&extensions_town=true&location=" + lat + "," + lng req = urllib.request.urlopen(url) res = req.read().decode("utf-8") print(res) str1 = json.loads(res) jsonResult = str1.get('result') formatted_address = jsonResult.get('formatted_address') return formatted_address lat = getLatOrLng('GPS GPSLatitudeRef', 'GPS GPSLatitude') # 纬度 lng = getLatOrLng('GPS GPSLongitudeRef', 'GPS GPSLongitude') # 经度 print('纬度:{0} 经度:{1}'.format(lat, lng)) location = getlocation(str(lat), str(lng)) print('位置:{0}'.format(location))
到此这篇关于利用Python实现读取照片的Exif信息的文章就介绍到这了,更多相关python读取照片Exif信息内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!