我正在 python 中使用 PIL 来提取图像的元数据。
这是我的代码:
import json
from PIL import Image, TiffImagePlugin
import PIL.ExifTags
img = Image.open("/home/user/DSCN0010.jpg")
dct = {
PIL.ExifTags.TAGS[k]: float(v) if isinstance(v, TiffImagePlugin.IFDRational) else v
for k, v in img._getexif().items()
if k in PIL.ExifTags.TAGS
}
print(json.dumps(dct))
我收到以下错误:
Error processing EXIF data: Object of type IFDRational is not JSON serializable
正如您在代码中看到的,我将
IFDRational
类型的所有值都转换为 float
但我仍然收到错误。
这是图像的链接:https://github.com/ianare/exif-samples/blob/master/jpg/gps/DSCN0010.jpg
问题是您只是将float
转换为直接位于EXIF项根中的
IFDRational
值。但是,看起来 GPSInfo
数据是一个 dict
,内部包含更多 IFDRational
值。您需要一个函数来清理这些值,理想情况下,该函数会递归地迭代所有可能的嵌套数据,以便在所有级别上完成转换。
最初的想法是这样做:
import json
import PIL.ExifTags
from PIL import Image, TiffImagePlugin
img = Image.open("/home/user/DSCN0010.jpg")
def sanitise_value(value):
# Base case: IFDRational to float
if isinstance(value, TiffImagePlugin.IFDRational):
return float(value)
# Dict case: sanitise all values
if isinstance(value, dict):
for k, v in value.items():
value[k] = sanitise_value(v)
# List/tuple case: sanitise all values and convert to list,
# as a tuple in JSON will anyway be a list
elif isinstance(value, (list, tuple)):
value = [sanitise_value(i) for i in value]
# Extra case: some values are byte-strings, so you have to
# decode them in order to make them JSON serializable. I
# decided to use 'replace' in case some bytes cannot be
# decoded, but there are other options
elif isinstance(value, (bytes, bytearray)):
value = value.decode("utf-8", "replace")
return value
dct = {
PIL.ExifTags.TAGS[k]: sanitise_value(v) # <-- We use here the sanitising function
for k, v in img._getexif().items()
if k in PIL.ExifTags.TAGS
}
print(json.dumps(dct))
这适用于该图像,但请随意测试其他场景,以防万一它仍然不是通用解决方案。
另外,请记住有关
byte-strings
的评论,因为您可能需要根据您的需要以不同的方式对它们进行解码。 例如,您可能更愿意将其解码为
latin-1
而不是 utf-8
,或者使用此处所述的其他类型的错误处理。 希望这有帮助!