【问题标题】:Python: Extract Metadata from PNGPython:从 PNG 中提取元数据
【发布时间】:2020-10-16 02:03:26
【问题描述】:

我可以使用 R 提取必要的信息,但为了整个项目的一致性,我希望能够使用 Python(最好是 Python3)来完成。我需要一个名为“设置”的标签的内容。此标记包含 XML,然后需要对其进行解析。

在 R 中获取元数据非常简单:

library(exifr)
library(XML)

path = file.path('path', 'to', 'file')

x = read_exif(file.path(path,'image.png'))
x$Settings

看起来 Python 做不到,这让我大吃一惊。或者这样做需要我比现在拥有更多的 Python 和 PNG 知识。如何使用 Python 提取 PNG 元数据?


这是我尝试过的事情的清单:

PyPng PyPNG 似乎很有希望。检查每个块的长度,“设置”标签似乎存在于 zTXt 块中。

import png

filename = "C:\\path\\to\\image.png"

im = png.Reader(filename)

for c in im.chunks():
    print(c[0], len(c[1]))

>>>
IHDR 13
tIME 7
pHYs 9
IDAT 47775
zTXt 714
IEND 0

以上内容来自this post。但是,目前还不清楚如何提取 zTXt 数据。

hachoir3

使用hachoir3 包,我尝试了以下操作:

from hachoir.parser import createParser
from hachoir.metadata import extractMetadata

filename = "C:\\path\\to\\file\\image.png"
parser = createParser(filename)
metadata = extractMetadata(parser)

for line in metadata.exportPlaintext():
    print(line)

这给了我以下信息:

Metadata:
- Image width: 1024 pixels
- Image height: 46 pixels
- Bits/pixel: 16
- Pixel format: RGB
- Compression rate: 2.0x
- Image DPI width: 1 DPI
- Image DPI height: 1 DPI
- Creation date: 2016-07-13 19:09:28
- Compression: deflate
- MIME type: image/png
- Endianness: Big endian

我似乎无法找到我需要的字段,即 R 代码中引用的“设置”。我对其他方法没有运气,例如metadata.get。据我所知,这似乎是解析 PNG 元数据的两个选项。文档阅读,

一些好的(但不是完美的;-))解析器:

Matroska 视频 Microsoft RIFF(AVI 视频、WAV 音频、CDA 文件)PNG 图片 TAR 和 ZIP 存档

也许它只是没有我需要的功能?

枕头

遵循post 中给出的建议:

from PIL import Image
filename = "C:\\path\\to\\file\\image.png"
im = Image.open(filename)

这会读入图像,但 im.info 只返回 {'aspect': (1, 1)}。通读文档,看起来没有任何方法可以获取元数据。我通读了帖子中提供的PNG description。老实说,我不知道如何利用它的信息,也不知道 Pillow 如何为我提供便利。

有些帖子暗示我需要的东西可以完成,但它们不起作用。例如,this post 建议使用 ExifTags 库:

from PIL import Image, ExifTags
filename = "C:\\path\\to\\file\\image.png"
im = Image.open(filename)
exif = { ExifTags.TAGS[k]: v for k, v in im._getexif().items() if k in ExifTags.TAGS}

问题是,AttributeError: 'PngImageFile' object has no attribute '_getexif'。根据documentation._getexif 功能是实验性的,仅适用于 JPG。

通读整个Pillow documentation,确实只讲了JPG和TIFF。处理 PNG 文件似乎根本不是包的一部分。那么像hachoir,可能做不到吧?

PIL

Pillow 显然是从另一个包 PIL 中分叉出来的。好像在 2009 年就被废弃了。

【问题讨论】:

  • PNG 标签只有四个字符长,所以那些“设置”实际上并不是一个标签。你是对的,它看起来像是压缩数据。你有这样一个PNG文件的链接吗?如果是这样,我可能可以调整我的 PyPNG 代码来提取它。
  • .. 好的,这里有一些坏消息。我发现了一个 R-created PNG with a zTXt 块,它只包含该块中的一个配置文件,没有元数据。所以我仍然需要一个包含你的设置。

标签: python png metadata


【解决方案1】:

您可以通过访问已加载图像的 info dict 来使用 Pillow 获取 EXIF 元数据。

从 Pillow 6.0 开始,可以从 PNG 图像中读取 EXIF 数据。 但是,与其他图像格式不同,在调用load() 之前,不能保证 EXIF 数据出现在 info 中。 https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#png

from PIL import Image

filename = 'path/to/img'
im = Image.open(filename)
im.load()  # Needed only for .png EXIF data (see citation above)
print(im.info['meta_to_read'])

我正在使用来自 conda repo 的 Python 3.7 和枕头 7.1.2。

【讨论】:

    【解决方案2】:

    这是一个不雅且笨拙但有效的解决方案。

    改编自这里:https://motherboard.vice.com/en_us/article/aekn58/hack-this-extra-image-metadata-using-python

    您可以在 python 中调用命令行 exiftools 应用程序,然后解析结果。

    以下是在 Ubuntu 16.04 下的 Python 3.6.3 中运行的代码:

    import subprocess
    
    result = subprocess.run(['exiftool', '-h', '/home/jason/Pictures/kitty_mask.png'], stdout=subprocess.PIPE)
    print (type(result))
    print ("\n\n",result.stdout)
    normal_string = result.stdout.decode("utf-8")
    print("\n\n", normal_string)
    

    它为我的测试图像产生以下结果:

    > <class 'subprocess.CompletedProcess'>
    > 
    > 
    >  b'<!-- /home/jason/Pictures/kitty_mask.png
    > -->\n<table>\n<tr><td>ExifTool Version Number</td><td>10.80</td></tr>\n<tr><td>File
    > Name</td><td>kitty_mask.png</td></tr>\n<tr><td>Directory</td><td>/home/jason/Pictures</td></tr>\n<tr><td>File
    > Size</td><td>25 kB</td></tr>\n<tr><td>File Modification
    > Date/Time</td><td>2018:07:02 09:35:00+01:00</td></tr>\n<tr><td>File
    > Access Date/Time</td><td>2018:07:09
    > 16:23:24+01:00</td></tr>\n<tr><td>File Inode Change
    > Date/Time</td><td>2018:07:02 09:35:00+01:00</td></tr>\n<tr><td>File
    > Permissions</td><td>rw-r--r--</td></tr>\n<tr><td>File
    > Type</td><td>PNG</td></tr>\n<tr><td>File Type
    > Extension</td><td>png</td></tr>\n<tr><td>MIME
    > Type</td><td>image/png</td></tr>\n<tr><td>Image
    > Width</td><td>2448</td></tr>\n<tr><td>Image
    > Height</td><td>3264</td></tr>\n<tr><td>Bit
    > Depth</td><td>8</td></tr>\n<tr><td>Color
    > Type</td><td>RGB</td></tr>\n<tr><td>Compression</td><td>Deflate/Inflate</td></tr>\n<tr><td>Filter</td><td>Adaptive</td></tr>\n<tr><td>Interlace</td><td>Noninterlaced</td></tr>\n<tr><td>Image
    > Size</td><td>2448x3264</td></tr>\n<tr><td>Megapixels</td><td>8.0</td></tr>\n</table>\n'
    > 
    > 
    >  <!-- /home/jason/Pictures/kitty_mask.png --> <table> <tr><td>ExifTool
    > Version Number</td><td>10.80</td></tr> <tr><td>File
    > Name</td><td>kitty_mask.png</td></tr>
    > <tr><td>Directory</td><td>/home/jason/Pictures</td></tr> <tr><td>File
    > Size</td><td>25 kB</td></tr> <tr><td>File Modification
    > Date/Time</td><td>2018:07:02 09:35:00+01:00</td></tr> <tr><td>File
    > Access Date/Time</td><td>2018:07:09 16:23:24+01:00</td></tr>
    > <tr><td>File Inode Change Date/Time</td><td>2018:07:02
    > 09:35:00+01:00</td></tr> <tr><td>File
    > Permissions</td><td>rw-r--r--</td></tr> <tr><td>File
    > Type</td><td>PNG</td></tr> <tr><td>File Type
    > Extension</td><td>png</td></tr> <tr><td>MIME
    > Type</td><td>image/png</td></tr> <tr><td>Image
    > Width</td><td>2448</td></tr> <tr><td>Image
    > Height</td><td>3264</td></tr> <tr><td>Bit Depth</td><td>8</td></tr>
    > <tr><td>Color Type</td><td>RGB</td></tr>
    > <tr><td>Compression</td><td>Deflate/Inflate</td></tr>
    > <tr><td>Filter</td><td>Adaptive</td></tr>
    > <tr><td>Interlace</td><td>Noninterlaced</td></tr> <tr><td>Image
    > Size</td><td>2448x3264</td></tr>
    > <tr><td>Megapixels</td><td>8.0</td></tr> </table>
    

    【讨论】:

    • 如果您要调用 exiftool,那么我建议删除 -h 选项。这将为您提供原始输出,因此您无需解析 html,只需解析您需要的标签。
    猜你喜欢
    • 2013-01-09
    • 2011-01-12
    • 2019-07-14
    • 2019-06-13
    • 2016-04-29
    • 1970-01-01
    • 1970-01-01
    • 2017-07-24
    相关资源
    最近更新 更多