Tôi đang sử dụng PIL. Làm cách nào để biến dữ liệu EXIF thành một từ điển về nội dung?
Tôi đang sử dụng PIL. Làm cách nào để biến dữ liệu EXIF thành một từ điển về nội dung?
Câu trả lời:
Thử cái này:
import PIL.Image
img = PIL.Image.open('img.jpg')
exif_data = img._getexif()
Điều này sẽ cung cấp cho bạn một từ điển được lập chỉ mục bởi các thẻ số EXIF. Nếu bạn muốn từ điển được lập chỉ mục bởi các chuỗi tên thẻ EXIF thực tế, hãy thử một cái gì đó như:
import PIL.ExifTags
exif = {
PIL.ExifTags.TAGS[k]: v
for k, v in img._getexif().items()
if k in PIL.ExifTags.TAGS
}
import ExifTags
(không có PIL
tiền tố).
Bạn cũng có thể sử dụng mô-đun ExifRead :
import exifread
# Open image file for reading (binary mode)
f = open(path_name, 'rb')
# Return Exif tags
tags = exifread.process_file(f)
Tôi sử dụng cái này:
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)
hoặc để lấy một trường cụ thể:
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())
và sau đó làm name2tagnum['ExposureTime']
.
exif.iteritems()
thànhexif.items()
Đối với Python3.x và bắt đầu Pillow==6.0.0
, Image
các đối tượng hiện cung cấp một getexif()
phương thức trả về <class 'PIL.Image.Exif'>
hoặc None
nếu hình ảnh không có dữ liệu EXIF.
Từ ghi chú phát hành Pillow 6.0.0 :
getexif()
đã được thêm vào, trả về mộtExif
thể hiện. Các giá trị có thể được truy xuất và đặt giống như một từ điển. Khi lưu JPEG, PNG hoặc WEBP, thể hiện có thể được chuyển làmexif
đối số để bao gồm bất kỳ thay đổi nào trong hình ảnh đầu ra.
Đầu Exif
ra có thể đơn giản được chuyển thành a dict
, để dữ liệu EXIF sau đó có thể được truy cập dưới dạng các cặp khóa-giá trị thông thường của a dict
. Các khóa là các số nguyên 16 bit có thể được ánh xạ tới các tên chuỗi của chúng bằng cách sử dụng ExifTags.TAGS
mô-đun.
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'
# ...
Đã thử nghiệm với Python 3.6.8 và 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)
Tôi nhận thấy rằng việc sử dụng ._getexif
không hoạt động trong các phiên bản python cao hơn, hơn nữa, nó là một lớp được bảo vệ và người ta nên tránh sử dụng nó nếu có thể. Sau khi tìm hiểu về trình gỡ lỗi, đây là những gì tôi thấy là cách tốt nhất để lấy dữ liệu EXIF cho một hình ảnh:
from PIL import Image
def get_exif(path):
return Image.open(path).info['parsed_exif']
Điều này trả về một từ điển của tất cả dữ liệu EXIF của một hình ảnh.
Lưu ý: Đối với Python3.x, hãy sử dụng Pillow thay vì PIL
info['parsed_exif']
yêu cầu Pillow 6.0 hoặc mới hơn. info['exif']
có sẵn trong 5.4, nhưng đây là một bytestring thô.
info['parsed_exif']
trong phiên bản 7.0.0; duy nhất info['exif']
.
Đây là cái có thể dễ đọc hơn một chút. Hy vọng điều này là hữu ích.
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
Tôi thường sử dụng pyexiv2 để đặt thông tin exif trong tệp JPG, nhưng khi tôi nhập thư viện trong sự cố tập lệnh QGIS tập lệnh.
Tôi đã tìm thấy một giải pháp bằng cách sử dụng thư viện exif:
https://pypi.org/project/exif/
Nó rất dễ sử dụng và với Qgis I don’t have any problem.
Trong mã này, tôi chèn tọa độ GPS vào ảnh chụp nhanh màn hình:
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())