python获取原图GPS位置信息,轻松得到你的活动轨迹

一、图像EXIF信息

介绍

EXIF(Exchangeable image file format,可交换图像文件格式)是专门为数码相机的照片设定的,可以记录数码照片的属性信息和拍摄数据,如拍摄时间、图像分辨率、感光值、GPS坐标等。

Exif最初由日本电子工业发展协会在1996年制定,版本为1.0。1998年,升级到2.1,增加了对音频文件的支持。2002年3月,发表了2.2版。

Exif可以附加于JPEG、TIFF、RIFF等文件之中,为其增加有关数码相机拍摄信息的内容和索引图或图像处理软件的版本信息。

Exif信息是可以被任意编辑的,因此只有参考的功能。Exif信息以0xFFE1作为开头标记,后两个字节表示Exif信息的长度。所以Exif信息最大为64 kb,而内部采用TIFF格式。

查看EXIF信息

windows文件属性

  • :本文处理图片针对原图

Windows7以上操作系统具备对Exif的原生支持,Windows系统下,可以通过鼠标右键点击图片打开菜单,点击属性并切换到详细信息标签下,即可直接获取图片的EXIF信息。

在线查看器

exifread 库

exifread模块为python读取图片EXIF信息的库。

exifread模块的下载地址:https://pypi.python.org/pypi/ExifRead

安装exifread库

pip install exifread

主要使用process_file函数进行解析,传入图片文件对象,返回一个包含图片信息的字典。其中,exif中GPS格式为DMS格式,即:D(degree,度)、M(minute,分)、S(second,秒),因此要进行转换才能得到常见的double类型的经纬度值。下面就用python + exifread读取图片的详细信息。

import exifread

with open(‘IMG_20190618_163339.jpg‘, ‘rb‘) as f:
    exif_dict = exifread.process_file(f)
    print(‘拍摄时间:‘, exif_dict[‘EXIF DateTimeOriginal‘])
    print(‘照相机制造商:‘, exif_dict[‘Image Make‘])
    print(‘照相机型号:‘, exif_dict[‘Image Model‘])
    print(‘照片尺寸:‘, exif_dict[‘EXIF ExifImageWidth‘], exif_dict[‘EXIF ExifImageLength‘])

    # 经度
    lon_ref = exif_dict["GPS GPSLongitudeRef"].printable
    lon = exif_dict["GPS GPSLongitude"].printable[1:-1].replace(" ", "").replace("/", ",").split(",")
    lon = float(lon[0]) + float(lon[1]) / 60 + float(lon[2]) / float(lon[3]) / 3600
    if lon_ref != "E":
        lon = lon * (-1)

    # 纬度
    lat_ref = exif_dict["GPS GPSLatitudeRef"].printable
    lat = exif_dict["GPS GPSLatitude"].printable[1:-1].replace(" ", "").replace("/", ",").split(",")
    lat = float(lat[0]) + float(lat[1]) / 60 + float(lat[2]) / float(lat[3]) / 3600
    if lat_ref != "N":
        lat = lat * (-1)
    print(‘照片的经纬度:‘, (lat, lon))

    for key in exif_dict:
        print("%s: %s" % (key, exif_dict[key]))

输出:

拍摄时间: 2019:06:18 16:33:40
照相机制造商: HUAWEI
照相机型号: HRY-AL00Ta
照片尺寸: 3968 2976
照片的经纬度: (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]
............................省略

二、经纬度转地址

要想将图片中的经纬度信息转换为详细地址,同样也有很多方法,比如在线查询、地图API或者利用python的地理位置信息库:geopy

在线查询

没错,这张图片是我在泰国拍的??

地图API

这里以百度地图API为例,需要去官网注册创建应用获取AK码。

百度地图:http://lbsyun.baidu.com

这里以我之前拍的重庆彩车照进行试验,从输出结果上看算是非常精准定位了。

import json
import requests
import exifread

with open(‘IMG_20191019_164726.jpg‘, ‘rb‘) as f:
    exif_dict = exifread.process_file(f)

    # 经度
    lon_ref = exif_dict["GPS GPSLongitudeRef"].printable
    lon = exif_dict["GPS GPSLongitude"].printable[1:-1].replace(" ", "").replace("/", ",").split(",")
    lon = float(lon[0]) + float(lon[1]) / 60 + float(lon[2]) / float(lon[3]) / 3600
    if lon_ref != "E":
        lon = lon * (-1)

    # 纬度
    lat_ref = exif_dict["GPS GPSLatitudeRef"].printable
    lat = exif_dict["GPS GPSLatitude"].printable[1:-1].replace(" ", "").replace("/", ",").split(",")
    lat = float(lat[0]) + float(lat[1]) / 60 + float(lat[2]) / float(lat[3]) / 3600
    if lat_ref != "N":
        lat = lat * (-1)
    print(‘照片的经纬度:‘, (lat, lon))

    # 调用百度地图api转换经纬度为详细地址
    secret_key = ‘MAsVGINLNyTGiM4UulcaeluCekGnAFxj‘ # 百度地图api 需要注册创建应用
    baidu_map_api = ‘http://api.map.baidu.com/reverse_geocoding/v3/?ak={}&output=json&coordtype=wgs84ll&location={},{}‘.format(secret_key, lat, lon)
    content = requests.get(baidu_map_api).text
    gps_address = json.loads(content)
    # 结构化的地址
    formatted_address = gps_address["result"]["formatted_address"]
    # 国家(若需访问境外POI,需申请逆地理编码境外POI服务权限)
    country = gps_address["result"]["addressComponent"]["country"]
    # 省
    province = gps_address["result"]["addressComponent"]["province"]
    # 市
    city = gps_address["result"]["addressComponent"]["city"]
    # 区
    district = gps_address["result"]["addressComponent"]["district"]
    # 语义化地址描述
    sematic_description = gps_address["result"]["sematic_description"]

    print(formatted_address)
    print(gps_address["result"]["business"])

输出

照片的经纬度: (29.564165115277778, 106.54840087888888)
重庆市渝中区学田湾正街2号11楼
大礼堂,上清寺,大溪沟

geopy库

geopy使python开发人员能够使用第三方地理编码程序和其他数据源(包括谷歌地图,必应地图,Nominatim等),轻松定位全球各地的地址、城市、国家和地标的坐标。

安装

pip install geopy

通过geopy进行经纬度查询

import exifread
from geopy.geocoders import Nominatim

with open(‘IMG_20190618_163339.jpg‘, ‘rb‘) as f:
    exif_dict = exifread.process_file(f)

    # 经度
    lon_ref = exif_dict["GPS GPSLongitudeRef"].printable
    lon = exif_dict["GPS GPSLongitude"].printable[1:-1].replace(" ", "").replace("/", ",").split(",")
    lon = float(lon[0]) + float(lon[1]) / 60 + float(lon[2]) / float(lon[3]) / 3600
    if lon_ref != "E":
        lon = lon * (-1)

    # 纬度
    lat_ref = exif_dict["GPS GPSLatitudeRef"].printable
    lat = exif_dict["GPS GPSLatitude"].printable[1:-1].replace(" ", "").replace("/", ",").split(",")
    lat = float(lat[0]) + float(lat[1]) / 60 + float(lat[2]) / float(lat[3]) / 3600
    if lat_ref != "N":
        lat = lat * (-1)
    print(‘照片的经纬度:‘, (lat, lon))

    reverse_value = str(lat) + ‘, ‘ + str(lon)
    geolocator = Nominatim()
    location = geolocator.reverse(reverse_value)

    print(‘照片的经纬度信息:‘)
    print((location.latitude, location.longitude))

    print(‘照片的地址信息:‘)
    print(location.address)

输出

照片的经纬度: (13.787098884444445, 100.62936401361111)
照片的经纬度信息:
(13.787094791472175, 100.6293647961708)
照片的地址信息:
?????????????, ?????????????, 10310, ?????????

三、搞事情

一张图片可以暴露你什么时间在什么地方,甚至体现了你当时在做什么,想想有多可怕,不信可以看看这个:

不过对于个人来说,图片exif信息可以让我们更好地管理自己拍摄的图片库。比如说:

按时间归类

可以通过exif时间信息,将图片归类到不同时间命名的文件夹下。

import os
import exifread
import shutil

imgs_path = ‘E:\泰国游‘
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年下半年的手机图片数据进行统计分析,并结合pyecharts和Mapbox进行展示。

  • pyecharts可视化

    pyecharts:一个大神创建的轮子,将python与echarts结合的强大的数据可视化工具。注意版本不同,有些接口调用是有区别的。

pip install pyecharts
pip install echarts-countries-pypkg
pip install pyecharts-jupyter-installer==0.0.3

统计和转换地址的代码,输出为csv文件:

import os
import json
import requests
import pandas as pd
import exifread
from geopy.geocoders import Nominatim

secret_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 dd

def 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‘].printable
        img_dict[‘length‘] = image_map[‘Image ImageLength‘].printable

        # 图片的经度
        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_latitude

        altitude = image_map[‘GPS GPSAltitude‘].printable
        if ‘/‘ in altitude:
            altitude = float(altitude.split(‘/‘)[0]) / float(altitude.split(‘/‘)[1])
        img_dict[‘altitude‘] = altitude

        # 照片拍摄时间
        img_dict[‘date‘] = image_map["EXIF DateTimeOriginal"].printable

        img_file.close()

        # 返回经纬度元组
        return img_dict

    except Exception as e:
        img_file.close()
        print(‘ERROR:图片中不包含Gps信息‘)
        return None

def 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).text
    gps_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"]
            # 区
            info_dict[‘district‘] = gps_address_dict["addressComponent"]["district"]
            info_dict[‘formatted_address‘] = gps_address_dict["formatted_address"]
            info_list.append(info_dict)
        # break

    img_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)

可视化,主要是通过pyecharts进行绘图。

import pandas as pd
from pyecharts.charts import Bar

df = pd.read_csv(‘imgInfo.csv‘,sep=‘,‘)
data = df["province"].value_counts()

bar = (
    Bar()
    .add_xaxis(data.index.tolist())
    .add_yaxis("图片数量", 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()

同理,各个城市的统计图。

以及,在地图上进行可视化。

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_NOTEBOOK

def is_Chinese(word):
    for ch in word:
        if ‘\u4e00‘ <= ch <= ‘\u9fff‘:
            return True
    return False

df = pd.read_csv(‘imgInfo.csv‘,sep=‘,‘)
data = df["city"].value_counts()
# 找出国外地址,Geo添加自定义点
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)

# 链式调用
c = (
        Geo()
        .add_schema(maptype="world")
        .add_coordinate_json(json_file=‘thailand.json‘)
        .add("去过的城市", [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下半年你去过哪儿"))
)
c.render_notebook()

国内地图展示

参考:

python第三方库之exifread库使用

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

Python-根据照片信息获取用户详细信息(微信发原图或泄露位置信息)

基于Python获取照片的GPS位置信息

Python获取照片的位置信息并进行可视化

【原创】某少儿不宜网站图片拍摄位置分析 (python批量读取图片GPS位置信息)

原文地址:https://www.cnblogs.com/fahaihappy/p/12702162.html

时间: 2024-12-27 18:40:37

python获取原图GPS位置信息,轻松得到你的活动轨迹的相关文章

通过IP地址获取省份城市位置信息

private String mResult = null; private String mProvinceName; //省份 private String mChCityName; //城市 private int GET_CITY_SUCCESS = 1; private int GET_CITY_FAILURE = 2; //Handler接收到消息进行处理,取出需要的信息 privateHandler mHandler = new Handler() { public void ha

H5、微信 获取用户当前位置信息

在之前的 调用百度地图API的总结 中获取当前位置信息我用的是 H5 ,其实微信也提供了获取用户地理位置的方法,现将这两种方法都贴出来,看情况选择使用. 一.H5 获取当前地理位置得到经纬度 // H5 获取当前位置经纬度 var location_lon = '',location_lat = ''; // 经度,纬度 if (navigator.geolocation){ navigator.geolocation.getCurrentPosition(function (position)

淘宝(新浪)API获取IP地址位置信息

1 package com.parse; 2 3 import java.io.BufferedReader; 4 import java.io.DataOutputStream; 5 import java.io.IOException; 6 import java.io.InputStreamReader; 7 import java.io.UnsupportedEncodingException; 8 import java.net.HttpURLConnection; 9 import

nagios通过python获取ESXi硬盘SMART信息

ESXi可以在相关面板上看见smart信息, 我这边公司用的是组装的服务器,然后不支持,只好用SSH的办法去获取了.Nagios监控是按退出的状态代码来显示相关信息的.退出代码如下:0 ok; 1 warning; 2 critical; 3 unknown python可以用 paramiko 去实现SSH连接并执行命令这一过程.paramiko 下载位置pypi.python.org/pypi/paramiko #!/usr/bin/env python import paramiko im

python 获取linux的内存信息

1.安装psutil源码 https://pypi.python.org/pypi?:action=display&name=psutil#downloads 找到psutil-5.2.2.tar.gz 点击即可下载 shell # tar xzvf psutil-5.2.2.tar.gz shell # cd psutil-5.2.2 shell # python setup.py install 2.使用psutil获取内存信息 终端输入python shell # python Pytho

使用python获取CPU和内存信息的思路与实现(linux系统)

linux里一切皆为文件,在linux/unix的根目录下,有个/proc目录,这个/proc 是一种内核和内核模块用来向进程(process)发送信息的机制(所以叫做"/proc"),这个伪文件系统允许与内核内部数据结构交互,获取有关进程的有用信息,在运行中(on the fly)改变设置(通过改变内核参数).与其他文件系统不同,/proc 存在于内存而不是硬盘中.proc 文件系统提供的信息如下: ?进程信息:系统中的任何一个进程,在 proc 的子目录中都有一个同名的进程 ID,

使用 python 获取 Linux 的 IP 信息(通过 ifconfig 命令)

我们可以使用 python 代码通过调用 ifconfig 命令来获取 Linux 主机的 IP 相关信息,包括:网卡名称.MAC地址.IP地址等. 第一种实现方式: 1 #!/usr/bin/python 2 #encoding: utf-8 3 4 from subprocess import Popen, PIPE 5 6 def getIfconfig(): 7 p = Popen(['ifconfig'], stdout = PIPE) 8 data = p.stdout.read()

根据经纬度调用百度地图获取详细的位置信息

访问类似下面的网址: http://api.map.baidu.com/geocoder/v2/?ak=A1758accd4ec22544bc2f200e5c83a76&location=39,116&output=json&pois=0 location代表坐标的位置,前面是纬度,后面的是经度,中间用逗号隔开. output表示返回的格式,这里用的是json. 返回结果如下:

android通过gps获取到当前位置

定位有GPS定位和基站定位:GPS定位是基于卫星进行定位,要求头顶要空旷,定位误差在2-10米,基站网络定位是根据距离手机的距离进行定位,误差较大,只要手机有信号即可定位:获取gps信息分为以下几步: 1)获取与位置相关的服务  服务都是通过上下文获取出来的 manager =(LocationManager) context.getSystemService(Context.LOCATION_SERVICE); 2)选择一种目前状态下最好的定位方式 gps定位或者基站定位 /** * * @p