python - 使用 Exif 元数据存储 JPEG 图像的 sha224 哈希
问题描述
我必须存储大量由机器人显微镜生成的科学图像。在存储过程中,我想在 Exif 元数据中存储图像数据的哈希值,以便使每个图像都可识别并确定它是否在之后被修改。图像数据以 16 位 uint 的二维数组形式出现。我尝试使用的代码是:
import math,png,io,hashlib, numpy as np
import piexif
import piexif.helper
from PIL import Image
def MOEDAL_IMGWR_JPG_h(img,fname,q,js='{}',exif_ifd ={}):
y=np.asarray(img);
z = (65535*((y - y.min())/y.ptp())).astype(np.uint16)
a=(np.array(z)//256).astype("uint8");
im = Image.fromarray(a)
im.save(fname, format='JPEG', quality=q) # save the image
im=Image.open(fname) # reload it
img_byte_arr = io.BytesIO()
im.save(img_byte_arr,format='PNG') # write the image content in memory
jdc=json.loads(js)
jdc['sha244']=hashlib.sha224(img_byte_arr.getvalue()).hexdigest()
a=json.dumps(jdc)
exif_dict = {"Exif":exif_ifd}
exif_dict["Exif"][piexif.ExifIFD.UserComment] = piexif.helper.UserComment.dump(a)
exif_bytes = piexif.dump(exif_dict)
piexif.insert(exif_bytes,fname) # This method is supposed to work (but does not)
# im.save(fname, exif=exif_bytes) #
如您所见,我尝试在使用所需压缩保存图像后重新加载图像数据,计算哈希并将其(作为 JSON 键)存储在 exif 元数据的 UserComment 字段中。在第二次保存中,我尝试使用压缩
但是当我尝试从 Python CLI 重新加载图像并再次计算哈希时,我获得了不同的值。
>>> im=Image.open('Test.jpg')
>>> img_byte_arr = io.BytesIO()
>>> im.save(img_byte_arr,format='PNG')
>>> exif_dict=piexif.load('TEST.jpg')
>>> print(exif_dict)
{'0th': {34665: 26}, 'Exif': {37510: b'ASCII\x00\x00\x00{"sha244": "94ae6bcfbb94c75c8adf65536993a03a107aa076cb94e20ef6bdff12"}'}, 'GPS': {}, 'Interop': {}, '1st': {}, 'thumbnail': None}
>>> hashlib.sha224(img_byte_arr.getvalue()).hexdigest()
'ef5966d665aaefc0d5b48c293957f66007c8dcaab7afc39f85a3964e'
也许我对最后一个 im.save 有误,但我也尝试指定 format='JPEG' 和 quality=100 这样我就不会再次重复压缩。有什么建议么 ?谢谢, GL
解决方案
这是行不通的,不是这样。你计算图像的哈希值,然后将其保存为 JPEG 流,JPEG 是有损的。所以你的形象会立即改变。
您需要做的是将图像保存为JPEG,重新加载并计算重新加载图像的哈希值,然后更新EXIF元数据而不进一步改变图像(通常EXIF工具不会改变图像流,但我不熟悉使用 Python 库;您应该检查)。
推荐阅读
- java - Apache POI HWPFDocument 帮助插入超链接
- r - Ggplot:如何以给定的顺序显示箱线图?
- html - 带有 jQuery 的 Asp Mvc 视图
- ruby - 无法使 ruby omniauth-ebay-oauth gem 示例代码正常工作
- mysql - Mariadb 数据库被 wordpress “创建排序索引”卡住了
- laravel - 如何阻止 Laravel 队列缓存所有内容?
- python - 运行 python selenium 代码时在 Heroku cli 中显示类型错误
- c++ - 为什么我要对这个对象进行大括号初始化(值初始化)以使其成为 constexpr?
- java - JPA @Transactional 会导致竞争条件吗?
- bash - Bash - 如果 yaml 文件中存在值,则执行某些操作