Ich benutze PIL. Wie verwandle ich die EXIF-Daten in ein Wörterbuch?
Ich benutze PIL. Wie verwandle ich die EXIF-Daten in ein Wörterbuch?
Antworten:
Versuche dies:
import PIL.Image
img = PIL.Image.open('img.jpg')
exif_data = img._getexif()
Dies sollte Ihnen ein Wörterbuch geben, das durch numerische EXIF-Tags indiziert ist. Wenn Sie möchten, dass das Wörterbuch durch die tatsächlichen EXIF-Tag-Namenszeichenfolgen indiziert wird, versuchen Sie Folgendes:
import PIL.ExifTags
exif = {
PIL.ExifTags.TAGS[k]: v
for k, v in img._getexif().items()
if k in PIL.ExifTags.TAGS
}
import ExifTags
(ohne das PIL
Präfix).
Sie können auch das ExifRead- Modul verwenden:
import exifread
# Open image file for reading (binary mode)
f = open(path_name, 'rb')
# Return Exif tags
tags = exifread.process_file(f)
Ich benutze das:
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)
oder um ein bestimmtes Feld zu erhalten:
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')
name2tagnum = dict((name, num) for num, name in TAGS.iteritems())
und dann tun name2tagnum['ExposureTime']
.
exif.iteritems()
zuexif.items()
Für Python3.x und beginnen Pillow==6.0.0
, Image
bieten Objekte nun ein getexif()
Verfahren , dass die Rendite <class 'PIL.Image.Exif'>
oder None
wenn das Bild keine EXIF - Daten.
Ab Pillow 6.0.0 Versionshinweise :
getexif()
wurde hinzugefügt, wodurch eineExif
Instanz zurückgegeben wird. Werte können wie ein Wörterbuch abgerufen und festgelegt werden. Beim Speichern von JPEG, PNG oder WEBP kann die Instanz alsexif
Argument übergeben werden, um Änderungen im Ausgabebild aufzunehmen.
Die Exif
Ausgabe kann einfach in a umgewandelt werden dict
, so dass auf die EXIF-Daten als reguläre Schlüssel-Wert-Paare von a zugegriffen werden kann dict
. Die Schlüssel sind 16-Bit-Ganzzahlen, die mithilfe des ExifTags.TAGS
Moduls ihren Zeichenfolgennamen zugeordnet werden können.
from PIL import Image, ExifTags
img = Image.open("sample.jpg")
img_exif = img.getexif()
print(type(img_exif))
# <class 'PIL.Image.Exif'>
if img_exif is None:
print("Sorry, image has no exif data.")
else:
img_exif_dict = dict(img_exif)
print(img_exif_dict)
# { ... 42035: 'FUJIFILM', 42036: 'XF23mmF2 R WR', 42037: '75A14188' ... }
for key, val in img_exif_dict.items():
if key in ExifTags.TAGS:
print(f"{ExifTags.TAGS[key]}:{repr(val)}")
# ExifVersion:b'0230'
# ...
# FocalLength:(2300, 100)
# ColorSpace:1
# FocalLengthIn35mmFilm:35
# ...
# Model:'X-T2'
# Make:'FUJIFILM'
# ...
# DateTime:'2019:12:01 21:30:07'
# ...
Getestet mit Python 3.6.8 und Pillow==6.0.0
.
import sys
import PIL
import PIL.Image as PILimage
from PIL import ImageDraw, ImageFont, ImageEnhance
from PIL.ExifTags import TAGS, GPSTAGS
class Worker(object):
def __init__(self, img):
self.img = img
self.exif_data = 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
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
if __name__ == '__main__':
try:
img = PILimage.open(sys.argv[1])
image = Worker(img)
lat = image.lat
lon = image.lon
date = image.date
print(date, lat, lon)
except Exception as e:
print(e)
Ich habe festgestellt, dass die Verwendung ._getexif
in höheren Python-Versionen nicht funktioniert. Außerdem ist sie eine geschützte Klasse und sollte nach Möglichkeit vermieden werden. Nachdem ich mich im Debugger umgesehen hatte, stellte ich fest, dass dies der beste Weg ist, um die EXIF-Daten für ein Bild zu erhalten:
from PIL import Image
def get_exif(path):
return Image.open(path).info['parsed_exif']
Dies gibt ein Wörterbuch aller EXIF-Daten eines Bildes zurück.
Hinweis: Verwenden Sie für Python3.x Pillow anstelle von PIL
info['parsed_exif']
erfordert Pillow 6.0 oder neuer. info['exif']
ist in 5.4 verfügbar, dies ist jedoch ein roher Bytestring.
info['parsed_exif']
in Version 7.0.0; nur info['exif']
.
Hier ist die, die vielleicht etwas einfacher zu lesen ist. Hoffe das ist hilfreich.
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
Normalerweise verwende ich pyexiv2, um Exif-Informationen in JPG-Dateien festzulegen, aber wenn ich die Bibliothek in ein Skript importiere, stürzt das QGIS-Skript ab.
Ich habe eine Lösung mit der Bibliothek exif gefunden:
https://pypi.org/project/exif/
Es ist so einfach zu bedienen und mit Qgis habe ich kein Problem.
In diesem Code füge ich GPS-Koordinaten in eine Momentaufnahme des Bildschirms ein:
from exif import Image
with open(file_name, 'rb') as image_file:
my_image = Image(image_file)
my_image.make = "Python"
my_image.gps_latitude_ref=exif_lat_ref
my_image.gps_latitude=exif_lat
my_image.gps_longitude_ref= exif_lon_ref
my_image.gps_longitude= exif_lon
with open(file_name, 'wb') as new_image_file:
new_image_file.write(my_image.get_file())