python获取原图GPS位置信息,轻松得到你的活动轨迹
點(diǎn)擊上方“AI搞事情”關(guān)注我們
一、圖像EXIF信息
介紹
EXIF(Exchangeable image file format,可交換圖像文件格式)是專門(mén)為數(shù)碼相機(jī)的照片設(shè)定的,可以記錄數(shù)碼照片的屬性信息和拍攝數(shù)據(jù),如拍攝時(shí)間、圖像分辨率、感光值、GPS坐標(biāo)等。
Exif最初由日本電子工業(yè)發(fā)展協(xié)會(huì)在1996年制定,版本為1.0。1998年,升級(jí)到2.1,增加了對(duì)音頻文件的支持。2002年3月,發(fā)表了2.2版。
Exif可以附加于JPEG、TIFF、RIFF等文件之中,為其增加有關(guān)數(shù)碼相機(jī)拍攝信息的內(nèi)容和索引圖或圖像處理軟件的版本信息。
Exif信息是可以被任意編輯的,因此只有參考的功能。Exif信息以0xFFE1作為開(kāi)頭標(biāo)記,后兩個(gè)字節(jié)表示Exif信息的長(zhǎng)度。所以Exif信息最大為64 kb,而內(nèi)部采用TIFF格式。
參考自百度百科查看EXIF信息
windows文件屬性
注:本文處理圖片針對(duì)原圖
Windows7以上操作系統(tǒng)具備對(duì)Exif的原生支持,Windows系統(tǒng)下,可以通過(guò)鼠標(biāo)右鍵點(diǎn)擊圖片打開(kāi)菜單,點(diǎn)擊屬性并切換到詳細(xì)信息標(biāo)簽下,即可直接獲取圖片的EXIF信息。
在線查看器
圖蟲(chóng)EXIF查看器
https://exif.tuchong.com/
改圖寶
https://www.gaitubao.com/exif
我愛(ài)斗圖(一個(gè)表情包網(wǎng)站????)
https://www.52doutu.cn/tools/exif
exifread 庫(kù)
exifread模塊為python讀取圖片EXIF信息的庫(kù)。
exifread模塊的下載地址:https://pypi.python.org/pypi/ExifRead
安裝exifread庫(kù)
主要使用process_file函數(shù)進(jìn)行解析,傳入圖片文件對(duì)象,返回一個(gè)包含圖片信息的字典。其中,exif中GPS格式為DMS格式,即:D(degree,度)、M(minute,分)、S(second,秒),因此要進(jìn)行轉(zhuǎn)換才能得到常見(jiàn)的double類型的經(jīng)緯度值。下面就用python + exifread讀取圖片的詳細(xì)信息。
import exifreadwith open('IMG_20190618_163339.jpg', 'rb') as f:exif_dict = exifread.process_file(f)print('拍攝時(shí)間:', exif_dict['EXIF DateTimeOriginal'])print('照相機(jī)制造商:', exif_dict['Image Make'])print('照相機(jī)型號(hào):', exif_dict['Image Model'])print('照片尺寸:', exif_dict['EXIF ExifImageWidth'], exif_dict['EXIF ExifImageLength'])# 經(jīng)度lon_ref = exif_dict["GPS GPSLongitudeRef"].printablelon = exif_dict["GPS GPSLongitude"].printable[1:-1].replace(" ", "").replace("/", ",").split(",")lon = float(lon[0]) + float(lon[1]) / 60 + float(lon[2]) / float(lon[3]) / 3600if lon_ref != "E":lon = lon * (-1)# 緯度lat_ref = exif_dict["GPS GPSLatitudeRef"].printablelat = exif_dict["GPS GPSLatitude"].printable[1:-1].replace(" ", "").replace("/", ",").split(",")lat = float(lat[0]) + float(lat[1]) / 60 + float(lat[2]) / float(lat[3]) / 3600if lat_ref != "N":lat = lat * (-1)print('照片的經(jīng)緯度:', (lat, lon))for key in exif_dict:print("%s: %s" % (key, exif_dict[key]))輸出:
拍攝時(shí)間:2019:06:18 16:33:40 照相機(jī)制造商:HUAWEI 照相機(jī)型號(hào):HRY-AL00Ta 照片尺寸:3968 2976 照片的經(jīng)緯度:(13.787098884444445, 100.62936401361111) Image ImageWidth: 3968 Image ImageLength: 2976 Image BitsPerSample: [8, 8, 8] Image Make: HUAWEI Image Model: HRY-AL00Ta Image Orientation: 0 Image XResolution: 72 Image YResolution: 72 Image ResolutionUnit: Pixels/Inch Image Software: HRY-AL00Ta 9.0.1.130(C00E130R4P1) Image DateTime: 2019:06:18 16:33:40 Image YCbCrPositioning: Centered Image ExifOffset: 290 GPS GPSVersionID: [2, 2, 0, 0] GPS GPSLatitudeRef: N GPS GPSLatitude: [13, 47, 847249/62500] GPS GPSLongitudeRef: E GPS GPSLongitude: [100, 37, 45710449/1000000] ............................省略二、經(jīng)緯度轉(zhuǎn)地址
要想將圖片中的經(jīng)緯度信息轉(zhuǎn)換為詳細(xì)地址,同樣也有很多方法,比如在線查詢、地圖API或者利用python的地理位置信息庫(kù):geopy。
在線查詢
GPS查詢網(wǎng)址1
http://www.gpsspg.com/maps.htm
GPS查詢網(wǎng)址2
http://www.gzhatu.com/dingwei.html
地球在線
https://www.earthol.com/
沒(méi)錯(cuò),這張圖片是我在泰國(guó)拍的????
地圖API
這里以百度地圖API為例,需要去官網(wǎng)注冊(cè)創(chuàng)建應(yīng)用獲取AK碼。
百度地圖:http://lbsyun.baidu.com 這里以我之前拍的重慶彩車照進(jìn)行試驗(yàn),從輸出結(jié)果上看算是非常精準(zhǔn)定位了。
輸出
照片的經(jīng)緯度:(29.564165115277778, 106.54840087888888) 重慶市渝中區(qū)學(xué)田灣正街2號(hào)11樓 大禮堂,上清寺,大溪溝geopy庫(kù)
geopy使python開(kāi)發(fā)人員能夠使用第三方地理編碼程序和其他數(shù)據(jù)源(包括谷歌地圖,必應(yīng)地圖,Nominatim等),輕松定位全球各地的地址、城市、國(guó)家和地標(biāo)的坐標(biāo)。
安裝
pip install geopy通過(guò)geopy進(jìn)行經(jīng)緯度查詢
import exifread from geopy.geocoders import Nominatimwith open('IMG_20190618_163339.jpg', 'rb') as f:exif_dict = exifread.process_file(f)# 經(jīng)度lon_ref = exif_dict["GPS GPSLongitudeRef"].printablelon = exif_dict["GPS GPSLongitude"].printable[1:-1].replace(" ", "").replace("/", ",").split(",")lon = float(lon[0]) + float(lon[1]) / 60 + float(lon[2]) / float(lon[3]) / 3600if lon_ref != "E":lon = lon * (-1)# 緯度lat_ref = exif_dict["GPS GPSLatitudeRef"].printablelat = exif_dict["GPS GPSLatitude"].printable[1:-1].replace(" ", "").replace("/", ",").split(",")lat = float(lat[0]) + float(lat[1]) / 60 + float(lat[2]) / float(lat[3]) / 3600if lat_ref != "N":lat = lat * (-1)print('照片的經(jīng)緯度:', (lat, lon))reverse_value = str(lat) + ', ' + str(lon)geolocator = Nominatim()location = geolocator.reverse(reverse_value)print('照片的經(jīng)緯度信息:')print((location.latitude, location.longitude))print('照片的地址信息:')print(location.address)輸出
照片的經(jīng)緯度:(13.787098884444445, 100.62936401361111) 照片的經(jīng)緯度信息: (13.787094791472175, 100.6293647961708) 照片的地址信息: ?????????????, ?????????????, 10310, ?????????三、搞事情
一張圖片可以暴露你什么時(shí)間在什么地方,甚至體現(xiàn)了你當(dāng)時(shí)在做什么,想想有多可怕,不信可以看看這個(gè):
21歲日本女星慘遭猥褻,只因自拍瞳孔倒影暴露住址? | 一張照片是怎么出賣你的!
不過(guò)對(duì)于個(gè)人來(lái)說(shuō),圖片exif信息可以讓我們更好地管理自己拍攝的圖片庫(kù)。比如說(shuō):
按時(shí)間歸類
可以通過(guò)exif時(shí)間信息,將圖片歸類到不同時(shí)間命名的文件夾下。
import os import exifread import shutilimgs_path = 'E:\泰國(guó)游' for img in os.listdir(imgs_path):img_path = os.path.join(imgs_path, img)img_file = open(img_path, 'rb')exif_dict = exifread.process_file(img_file)date = exif_dict['EXIF DateTimeOriginal']date = date.values.replace(':', '_')year_month_day = date[:10]target_path = os.path.join('E:\旅游', year_month_day)if not os.path.exists(target_path):os.mkdir(target_path)shutil.copy(img_path, target_path)旅游地圖
下面以本人2019年下半年的手機(jī)圖片數(shù)據(jù)進(jìn)行統(tǒng)計(jì)分析,并結(jié)合pyecharts和Mapbox進(jìn)行展示。
pyecharts可視化
pyecharts:一個(gè)大神創(chuàng)建的輪子,將python與echarts結(jié)合的強(qiáng)大的數(shù)據(jù)可視化工具。注意版本不同,有些接口調(diào)用是有區(qū)別的。
統(tǒng)計(jì)和轉(zhuǎn)換地址的代碼,輸出為csv文件:
import os import json import requests import pandas as pd import exifread from geopy.geocoders import Nominatimsecret_key = '###################'def convert_dms2dd(coord_arr):arr = str(coord_arr).replace('[', '').replace(']', '').split(', ')d = float(arr[0])m = float(arr[1])s = float(arr[2].split('/')[0]) / float(arr[2].split('/')[1])dd = float(d) + (float(m) / 60) + (float(s) / 3600)return dddef get_img_infor_tup(photo):img_file = open(photo, 'rb')image_map = exifread.process_file(img_file)img_dict = {}img_dict['Image Name'] = os.path.basename(photo)try:img_dict['width'] = image_map['Image ImageWidth'].printableimg_dict['length'] = image_map['Image ImageLength'].printable# 圖片的經(jīng)度img_longitude = convert_dms2dd(image_map["GPS GPSLongitude"].printable)if image_map["GPS GPSLongitudeRef"].printable != "E":img_longitude = img_longitude * (-1)img_dict['longitude'] = img_longitude# 圖片的緯度img_latitude = convert_dms2dd(image_map["GPS GPSLatitude"].printable)if image_map["GPS GPSLatitudeRef"].printable != "N":img_latitude = img_latitude * (-1)img_dict['latitude'] = img_latitudealtitude = image_map['GPS GPSAltitude'].printableif '/' in altitude:altitude = float(altitude.split('/')[0]) / float(altitude.split('/')[1])img_dict['altitude'] = altitude# 照片拍攝時(shí)間img_dict['date'] = image_map["EXIF DateTimeOriginal"].printableimg_file.close()# 返回經(jīng)緯度元組return img_dictexcept Exception as e:img_file.close()print('ERROR:圖片中不包含Gps信息')return Nonedef get_detail_infor_by_baidu(lat, lon):baidu_map_api = 'http://api.map.baidu.com/reverse_geocoding/v3/?ak={0}&output=json&coordtype=wgs84ll&location={1},' \'{2}'.format(secret_key, lat, lon)content = requests.get(baidu_map_api).textgps_address = json.loads(content)return gps_address["result"]def img_data_statistic(imgs_path):info_list = []for file_name in os.listdir(imgs_path):img_path = os.path.join(imgs_path, file_name)info_dict = get_img_infor_tup(img_path)if info_dict is not None:gps_address_dict = get_detail_infor_by_baidu(info_dict['latitude'], info_dict['longitude'])# 省info_dict['province'] = gps_address_dict["addressComponent"]["province"]# 市info_dict['city'] = gps_address_dict["addressComponent"]["city"]# 區(qū)info_dict['district'] = gps_address_dict["addressComponent"]["district"]info_dict['formatted_address'] = gps_address_dict["formatted_address"]info_list.append(info_dict)# breakimg_df = pd.DataFrame(info_list)img_df.to_csv('imgInfo.csv', index=False, encoding='utf-8')if __name__ == '__main__':imgs_path = 'E:/photo'img_data_statistic(imgs_path)可視化,主要是通過(guò)pyecharts進(jìn)行繪圖。
import pandas as pd from pyecharts.charts import Bardf = pd.read_csv('imgInfo.csv',sep=',') data = df["province"].value_counts()bar = (Bar().add_xaxis(data.index.tolist()).add_yaxis("圖片數(shù)量", data.values.tolist()).set_global_opts(title_opts=opts.TitleOpts(title="各省分布情況", subtitle='19年下半年去了哪兒'),xaxis_opts=opts.AxisOpts(name="省份",axislabel_opts={"rotate":45})) ) bar.render_notebook()同理,各個(gè)城市的統(tǒng)計(jì)圖。
以及,在地圖上進(jìn)行可視化。
import json import pandas as pd from pyecharts import options as opts from pyecharts.charts import Geo from pyecharts.globals import CurrentConfig, NotebookType CurrentConfig.NOTEBOOK_TYPE = NotebookType.JUPYTER_NOTEBOOKdef is_Chinese(word):for ch in word:if '\u4e00' <= ch <= '\u9fff':return Truereturn Falsedf = pd.read_csv('imgInfo.csv',sep=',') data = df["city"].value_counts() # 找出國(guó)外地址,Geo添加自定義點(diǎn) thailand_address = [] json_data= {} for city in data.index:if not is_Chinese(city):json_data[city] = df[['longitude','latitude']][df["city"] == city].mean().values.tolist()thailand_address.append(city) json_str = json.dump(json_data, open('thailand.json', 'w', encoding='utf-8'), ensure_ascii=False,indent=4)# 鏈?zhǔn)秸{(diào)用 c = (Geo().add_schema(maptype="world").add_coordinate_json(json_file='thailand.json').add("去過(guò)的城市", [list(z) for z in zip(data.index.tolist(), data.values.tolist())],symbol_size = 30, large_threshold = 2000, symbol="pin").set_series_opts(label_opts=opts.LabelOpts(is_show=False)).set_global_opts(title_opts=opts.TitleOpts(title="2019下半年你去過(guò)哪兒")) ) c.render_notebook()國(guó)內(nèi)地圖展示
Mapbox可視化
可以直接將包含經(jīng)度和維度的統(tǒng)計(jì)數(shù)據(jù)(csv格式)拖入到網(wǎng)站:
https://www.mapbox.cn/labs/mbxdataexplorer/
綜上,要想自己信息不被泄露,盡量少發(fā)原圖(●'?'●)。
長(zhǎng)按二維碼關(guān)注我們
有趣的靈魂在等你
留言請(qǐng)摁
總結(jié)
以上是生活随笔為你收集整理的python获取原图GPS位置信息,轻松得到你的活动轨迹的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: PaddleHub人像分割模型:AI人像
- 下一篇: 利用python分析了下乘风破浪的姐姐