通过Python在图像上写入复杂的自定义元数据

18 投票
2 回答
24036 浏览
提问于 2025-04-17 08:45

我想在图片上写一些自定义的元数据(主要是jpeg格式,但可能还有其他格式)。到目前为止,我还没能通过PIL做到这一点(我在使用centos 5,没法安装pyexiv)。

我知道我可以更新一些预定义的标签,但我需要创建自定义的字段或标签!这能做到吗?

这些数据是用户创建的,所以我事先并不知道这些标签是什么,也不知道它们包含什么内容。我需要让用户能够创建标签和子标签,然后为它们写入数据。例如,有人可能想在某个特定的图片上创建这样的元数据:

Category : Human

Physical :
    skin_type : smooth
    complexion : fair
    eye_color: blue
    beard: yes
    beard_color: brown
    age: mid

Location :
    city: london
    terrain: grass
    buildings: old

我还发现,通过PIL的JpegImagePlugin保存jpeg时,所有之前的元数据都会被新的数据覆盖,而这些新数据是你无法编辑的?这算不算一个bug?

谢谢,

S

2 个回答

3

你可以试着安装一下piexif这个包,这样可以把你自定义的数据保存到ExifIFD.UserComment这个字段里。

示例数据:

userdata = {
    'Category': 'Human',
    'Physical': {
        'skin_type': 'smooth',
        'complexion': 'fair'
    },
    'Location': {
        'city': 'london'
    }
}

把数据编码到图片里:

import json
import piexif
import piexif.helper

# %% Write out exif data
# load existing exif data from image
exif_dict = piexif.load(filename)
# insert custom data in usercomment field
exif_dict["Exif"][piexif.ExifIFD.UserComment] = piexif.helper.UserComment.dump(
    json.dumps(userdata),
    encoding="unicode"
)
# insert mutated data (serialised into JSON) into image
piexif.insert(
    piexif.dump(exif_dict),
    filename
)

从图片中解码数据:

# %% Read in exif data
exif_dict = piexif.load(filename)
# Extract the serialized data
user_comment = piexif.helper.UserComment.load(exif_dict["Exif"][piexif.ExifIFD.UserComment])
# Deserialize
d = json.loads(user_comment)
print("Read in exif data: %s" % d)

注意,只有JPEG、WebP和TIFF格式的图片是支持的。

26

Python的pyexiv2模块可以用来读取和写入图片的元数据。

我觉得有效的EXIF标签是有限的。我不太清楚是否可以创建自己的自定义标签。不过,你可以使用Exif.Photo.UserComment这个标签,并把它填充为JSON格式:

import pyexiv2
import json

metadata = pyexiv2.ImageMetadata(filename)
metadata.read()
userdata={'Category':'Human',
          'Physical': {
              'skin_type':'smooth',
              'complexion':'fair'
              },
          'Location': {
              'city': 'london'
              }
          }
metadata['Exif.Photo.UserComment']=json.dumps(userdata)
metadata.write()

然后要读取这个内容,可以这样做:

import pprint
filename='/tmp/image.jpg'
metadata = pyexiv2.ImageMetadata(filename)
metadata.read()
userdata=json.loads(metadata['Exif.Photo.UserComment'].value)
pprint.pprint(userdata)

结果会是

{u'Category': u'Human',
 u'Location': {u'city': u'london'},
 u'Physical': {u'complexion': u'fair', u'skin_type': u'smooth'}}

撰写回答