本文最后更新于:2024年5月17日 晚上

JPG 图像中经常会保存相机记录的图像拍摄位置的 GPS 信息,本文记录 Python 获取、保存图像拍摄位置信息的方法。

简介

EXIF(Exchangeable Image File Format)是一种用于存储图像拍摄相关信息的标准,这些信息包括相机设置、拍摄时间、地点等。EXIF信息通常嵌入在JPEG、TIFF和RAW图像文件中,以便于软件和设备(如数字相机、手机、扫描仪)能够读取和使用这些信息。

在EXIF信息中,GPS信息是一个重要的组成部分,它可以提供关于图像拍摄位置的详细数据。以下是GPS信息可能包含的内容:

  1. GPS版本信息:表示EXIF中GPS信息的版本号。
  2. GPS国界:标识图像拍摄位置所在的国家或地区。
  3. GPS定位日期和时间:记录图像拍摄时的日期和时间。
  4. GPS卫星信息:显示在图像拍摄时,哪些卫星参与了GPS定位。
  5. GPS经度:表示图像拍摄位置的经度,通常以度、分、秒的形式表示。
  6. GPS纬度:表示图像拍摄位置的纬度,同样以度、分、秒的形式表示。
  7. GPS高度:以米为单位,表示图像拍摄位置相对于海平面的高度。
  8. GPS速度:表示图像拍摄时的移动速度,通常以千米/小时为单位。

通过这些GPS信息,我们可以了解到图像的拍摄位置、时间和拍摄时的运动状态。这些信息对于图片的归档、分享和地理信息系统(GIS)分析等方面非常有用。

Python 获取路线

可以在 Python 中很容易地获取到图像的 exif 信息,并从中提取 gps 信息,本质上都是从文件中读取 exif 信息字段,将其解析成我们可读的 gps 信息。

这里介绍三种实现方法:

  1. Pillow 路线
  2. piexif
  3. exifread

经度、纬度概念

  • 经度 Longitude , 本初子午线 位置 为 0 度经线 , 相当于水平 x 轴 的坐标 , 经度的取值范围 -180 度 ~ +180 度 ;

  • 纬度 Latitude , 相当于 垂直 y 轴 的坐标 , 纬度的取值范围 -90 度 ~ + 90 度 ;

  • 西经 和 南纬 是负数 ;

Pillow

安装

1
pip install Pillow

使用

上源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from PIL import Image, ExifTags

def pillow_get_exif_data(image_path):
image = Image.open(image_path)
# 获取图片的exif信息
exif_data = image._getexif()
if exif_data is not None:
# 使用自定义的函数转换exif标签
exif_data = {
ExifTags.TAGS[k]: v
for k, v in exif_data.items()
if k in ExifTags.TAGS
}
return exif_data

if __name__ == '__main__':
image_path = 'demo.jpg'
exif_data = pillow_get_exif_data(image_path)
print(exif_data['GPSInfo'])

输出:

1
{0: b'\x02\x03\x00\x00', 1: 'N', 2: (31.0, 5.0, 37.6518), 3: 'E', 4: (121.0, 14.0, 54.4151), 5: b'\x00', 6: 93.606, 7: (2.0, 32.0, 54.0), 9: 'A', 18: 'WGS-84\x00', 29: '2024:05:04'}

含义:

  • 1 —— 南北
  • 2 —— 纬度(度分秒)
  • 3 —— 东西
  • 4 —— 经度(度分秒)
  • 6 —— 高度(米)

piexif

安装

1
pip install piexif

使用

上源码:

1
2
3
4
5
6
7
8
9
10
import piexif

def piexif_get_exif_data(image_path):
exif_dict = piexif.load(image_path)
return exif_dict

if __name__ == '__main__':
image_path = 'demo.jpg'
exif_data = piexif_get_exif_data(image_path)
print(exif_data['GPS'])

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
0:
(2, 3, 0, 0)
1:
b'N'
2:
((31, 1), (5, 1), (376518, 10000))
3:
b'E'
4:
((121, 1), (14, 1), (544151, 10000))
5:
0
6:
(93606, 1000)
7:
((2, 1), (32, 1), (54, 1))
9:
b'A'
18:
b'WGS-84\x00'

含义:

其中的 tuple 需要第一个数除以第二个数

  • 1 —— 南北
  • 2 —— 纬度(度分秒)
  • 3 —— 东西
  • 4 —— 经度(度分秒)
  • 6 —— 高度(米)

exifread

安装

1
pip install exifread

使用

上源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
import exifread

def exifread_get_exif_data(image_path):
f = open(image_path,'rb')
contents = exifread.process_file(f)
f.close()
return contents

if __name__ == '__main__':
image_path = 'demo.jpg'

contents = exifread_get_exif_data(image_path)
print(contents["GPS GPSLongitude"], contents['GPS GPSLongitudeRef'], contents["GPS GPSLatitude"], contents['GPS GPSLatitudeRef'], contents["GPS GPSAltitude"])

输出:

1
[121, 14, 544151/10000] E [31, 5, 188259/5000] N 46803/500

性能评估

连续运行一千次,统计时间:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
from PIL import Image, ExifTags
import mtutils as mt
import numpy as np
import piexif
import exifread
import time


def piexif_get_exif_data(image_path):
exif_dict = piexif.load(image_path)
return exif_dict

def pillow_get_exif_data(image_path):
image = Image.open(image_path)
# 获取图片的exif信息
exif_data = image._getexif()
if exif_data is not None:
# 使用自定义的函数转换exif标签
exif_data = {
ExifTags.TAGS[k]: v
for k, v in exif_data.items()
if k in ExifTags.TAGS
}
return exif_data

def exifread_get_exif_data(image_path):
f = open(image_path,'rb')
contents = exifread.process_file(f)
f.close()
return contents

if __name__ == '__main__':
image_path = 'demo.JPG'

times = 1000

start = time.time()
for _ in range(times):
exif_data = pillow_get_exif_data(image_path)
end = time.time()
print(f'pillow_get_exif_data: {end - start}')

start = time.time()
for _ in range(times):
exif_data2 = piexif_get_exif_data(image_path)
end = time.time()
print(f'piexif_get_exif_data: {end - start}')

start = time.time()
for _ in range(times):
exifread_get_exif_data(image_path)
end = time.time()
print(f'exifread_get_exif_data: {end - start}')

pass

输出:

1
2
3
pillow_get_exif_data: 0.94569993019104
piexif_get_exif_data: 0.17222881317138672
exifread_get_exif_data: 0.8518986701965332

结论piexif 又快又好用。

写入exif信息

当需要用Python 保存图像并附带 exif 信息时,就只能用到 Pillow 库了,exif信息这里两种方式:

  1. pillow 自带信息

    1
    2
    3
    4
    5
    from PIL import Image
    image_path = 'demo.jpg'

    pil_img = Image.open(image_path)
    pil_img.save('target.jpg', exif=pil_img.info['exif'])
  2. piexif 信息压缩成字符串送入 pil 写图像中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    from PIL import Image
    import piexif

    image_path = 'demo.jpg'
    pil_img = Image.open(image_path)

    exif_dict = piexif.load(img.info['exif'])
    exif_bytes = piexif.dump(exif_dict)

    pil_img.save('target.jpg', exif=exif_bytes)

参考资料



文章链接:
https://www.zywvvd.com/notes/coding/python/get-jpg-img-gps-info/get-jpg-img-gps-info/


“觉得不错的话,给点打赏吧 ୧(๑•̀⌄•́๑)૭”

微信二维码

微信支付

支付宝二维码

支付宝支付

Python 读写图像 GPS 信息
https://www.zywvvd.com/notes/coding/python/get-jpg-img-gps-info/get-jpg-img-gps-info/
作者
Yiwei Zhang
发布于
2024年5月11日
许可协议