在Python中,如何读取图像的exif数据?

In Python, how do I read the exif data for an image?

我用的是PIL。如何将exif数据转换成一本字典?


试试这个:

1
2
3
import PIL.Image
img = PIL.Image.open('img.jpg')
exif_data = img._getexif()

这将为您提供一个由exif数字标记索引的字典。如果要使用实际的exif标记名字符串对字典进行索引,请尝试如下操作:

1
2
3
4
5
6
import PIL.ExifTags
exif = {
    PIL.ExifTags.TAGS[k]: v
    for k, v in img._getexif().items()
    if k in PIL.ExifTags.TAGS
}


您还可以使用exifrad模块:

1
2
3
4
5
6
import exifread
# Open image file for reading (binary mode)
f = open(path_name, 'rb')

# Return Exif tags
tags = exifread.process_file(f)


我用这个:

1
2
3
4
5
6
import os,sys
from PIL import Image
from PIL.ExifTags import TAGS

for (k,v) in Image.open(sys.argv[1])._getexif().iteritems():
        print '%s = %s' % (TAGS.get(k), v)

或获取特定字段:

1
2
3
4
5
6
7
def get_field (exif,field) :
  for (k,v) in exif.iteritems():
     if TAGS.get(k) == field:
        return v

exif = image._getexif()
print get_field(exif,'ExposureTime')


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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
try:
    import PIL
    import PIL.Image as PILimage
    from PIL import ImageDraw, ImageFont, ImageEnhance
    from PIL.ExifTags import TAGS, GPSTAGS
except ImportError as err:
    exit(err)


class Worker(object):
    def __init__(self, img):
        self.img = img
        self.get_exif_data()
        self.lat = self.get_lat()
        self.lon = self.get_lon()
        self.date =self.get_date_time()
        super(Worker, self).__init__()

    @staticmethod
    def get_if_exist(data, key):
        if key in data:
            return data[key]
        return None

    @staticmethod
    def convert_to_degress(value):
       """Helper function to convert the GPS coordinates
        stored in the EXIF to degress in float format"""

        d0 = value[0][0]
        d1 = value[0][1]
        d = float(d0) / float(d1)
        m0 = value[1][0]
        m1 = value[1][1]
        m = float(m0) / float(m1)

        s0 = value[2][0]
        s1 = value[2][1]
        s = float(s0) / float(s1)

        return d + (m / 60.0) + (s / 3600.0)

    def get_exif_data(self):
       """Returns a dictionary from the exif data of an PIL Image item. Also
        converts the GPS Tags"""

        exif_data = {}
        info = self.img._getexif()
        if info:
            for tag, value in info.items():
                decoded = TAGS.get(tag, tag)
                if decoded =="GPSInfo":
                    gps_data = {}
                    for t in value:
                        sub_decoded = GPSTAGS.get(t, t)
                        gps_data[sub_decoded] = value[t]

                    exif_data[decoded] = gps_data
                else:
                    exif_data[decoded] = value
        self.exif_data = exif_data
        # return exif_data

    def get_lat(self):
       """Returns the latitude and longitude, if available, from the
        provided exif_data (obtained through get_exif_data above)"""

        # print(exif_data)
        if 'GPSInfo' in self.exif_data:
            gps_info = self.exif_data["GPSInfo"]
            gps_latitude = self.get_if_exist(gps_info,"GPSLatitude")
            gps_latitude_ref = self.get_if_exist(gps_info, 'GPSLatitudeRef')
            if gps_latitude and gps_latitude_ref:
                lat = self.convert_to_degress(gps_latitude)
                if gps_latitude_ref !="N":
                    lat = 0 - lat
                lat = str(f"{lat:.{5}f}")
                return lat
        else:
            return None

    def get_lon(self):
       """Returns the latitude and longitude, if available, from the
        provided exif_data (obtained through get_exif_data above)"""

        # print(exif_data)
        if 'GPSInfo' in self.exif_data:
            gps_info = self.exif_data["GPSInfo"]
            gps_longitude = self.get_if_exist(gps_info, 'GPSLongitude')
            gps_longitude_ref = self.get_if_exist(gps_info, 'GPSLongitudeRef')
            if gps_longitude and gps_longitude_ref:
                lon = self.convert_to_degress(gps_longitude)
                if gps_longitude_ref !="E":
                    lon = 0 - lon
                lon = str(f"{lon:.{5}f}")
                return lon
        else:
            return None

    def get_date_time(self):
        if 'DateTime' in self.exif_data:
            date_and_time = self.exif_data['DateTime']
            return date_and_time


def main():
    date = image.date
    print(date)

if __name__ == '__main__':
    try:
        img = PILimage.open(path + filename)
        image = Worker(img)
        lat = image.lat
        lon = image.lon
        date = image.date
        print(date)

    except Exception as e:
        print(e)


这是一个可能更容易阅读的。希望这是有帮助的。

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

exifData = {}
img = Image.open(picture.jpg)
exifDataRaw = img._getexif()
for tag, value in exifDataRaw.items():
    decodedTag = ExifTags.TAGS.get(tag, tag)
    exifData[decodedTag] = value


我发现使用._getexif在较高的Python版本中不起作用,而且它是一个受保护的类,如果可能的话,应该避免使用它。在深入研究了调试器之后,我发现这是获取图像的exif数据的最佳方法:

1
2
3
4
from PIL import Image

def get_exif(path):
    return Image.open(path).info['parsed_exif']

这将返回图像的所有exif数据的字典。

注:对于python3.x,使用枕头代替pil。