利用Python實現(xiàn)讀取照片的Exif信息
今天要水的文章是,用 Python 讀取照片的 Exif 信息?,F(xiàn)如今的智能手機在拍攝照片時,都含有 Exif(可交換圖像文件格式,Exchangeable image file format)信息,通過該信息可以獲取拍照時的位置、時間,以及手機品牌等信息。那么下面就看看如何使用 Python 去獲取這些信息吧。
Python 想要讀取 Exif 信息需要安裝一個第三方庫,直接 pip install exifread 即可。
import exifread with open("1.jpg", 'rb') as f: # 直接可以拿到里面的信息,內(nèi)容非常多 # 但如果無法讀取,那么返回值 exif 就是 None exif = exifread.process_file(f) # 這里我們選一些常用的,里面的 value 需要轉(zhuǎn)成字符串 # 不轉(zhuǎn)成字符串的話看起來會比較費勁 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("經(jīng)度:", str(exif["GPS GPSLongitude"])) print("東經(jīng)還是西經(jīng):", 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 經(jīng)度: [116, 28, 5973999/100000] 東經(jīng)還是西經(jīng): E 緯度: [39, 59, 1255371/200000] 南緯還是北緯: N """
還是比較簡單的,但是里面的經(jīng)度和緯度比較怪,我們還需要再對其轉(zhuǎn)化一下。
lng = str(exif["GPS GPSLongitude"]) # 經(jīng)度 lat = str(exif["GPS GPSLatitude"]) # 緯度 print(lng) # [116, 28, 5973999/100000] print(lat) # [39, 59, 1255371/200000] # 轉(zhuǎn)成列表 lng = lng[1: -1].replace("/", ",").split(",") lat = lat[1: -1].replace("/", ",").split(",") print(lat) # ['39', ' 59', ' 1255371', '200000'] print(lng) # ['116', ' 28', ' 5973999', '100000'] # 然后得到具體的經(jīng)緯度 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
這里得到的經(jīng)緯度永遠是正數(shù),如果是西經(jīng),那么得到的經(jīng)度要乘上 -1;同理如果是南緯,那么緯度要乘上 -1。
另外需要注意,并非所有的照片都能夠進行解析,必須是攜帶 Exif 信息的原始圖片。如果中間進行了壓縮、或者 P 圖,那么就無法識別了。
當然像一些社交平臺也會專門針對 Exif 進行處理,比如微信,你發(fā)在朋友圈的圖片會自動壓縮,所以是不會暴露位置信息的。
方法補充
除了上文的方法,小編還為大家整理了其他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): """經(jīng)緯度轉(zhuǎn)換""" 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) # 經(jīng)度 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 : 上海市黃浦區(qū)中山南路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): """ 獲取經(jīng)度或緯度 """ 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 # 調(diào)用百度地圖API通過經(jīng)緯度獲取位置 def getlocation(lat, lng): """ exif里面的經(jīng)緯度是度分秒形式傳入的,需要轉(zhuǎn)換為小數(shù)形式,然后根據(jù)傳入的經(jīng)緯度,調(diào)用百度接口去查詢詳細地址 """ 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') # 經(jīng)度 print('緯度:{0} 經(jīng)度:{1}'.format(lat, lng)) location = getlocation(str(lat), str(lng)) print('位置:{0}'.format(location))
到此這篇關(guān)于利用Python實現(xiàn)讀取照片的Exif信息的文章就介紹到這了,更多相關(guān)python讀取照片Exif信息內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Win10操作系統(tǒng)中PyTorch虛擬環(huán)境配置+PyCharm配置
本文主要介紹了Win10操作系統(tǒng)中PyTorch虛擬環(huán)境配置+PyCharm配置,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09python人工智能使用RepVgg實現(xiàn)圖像分類示例詳解
這篇文章主要介紹了python人工智能使用RepVgg實現(xiàn)圖像分類示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-10-10Python While循環(huán)語句實例演示及原理解析
這篇文章主要介紹了Python While循環(huán)語句實例演示及原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-01-01python?dataframe獲得指定行列實戰(zhàn)代碼
對于一個DataFrame,常常需要篩選出某列為指定值的行,下面這篇文章主要給大家介紹了關(guān)于python?dataframe獲得指定行列的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2023-12-12Python使用asyncio異步時的常見問題總結(jié)
這篇文章主要為大家整理了開發(fā)人員在?Python?中使用?asyncio?時提出的常見問題以及解決方法,文中的示例代碼講解詳細,感興趣的可以學習一下2023-04-04