PIL图像的简单哈希
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PIL图像的简单哈希相关的知识,希望对你有一定的参考价值。
背景
我想将PIL图像的信息存储在键值存储中。为此,我散列图像并使用哈希作为键。
我尝试了什么
我一直在使用以下代码来计算哈希值:
def hash(img):
return hashlib.md5(img.tobytes()).hexdigest()
但似乎这不稳定。我还没弄清楚为什么,但是对于不同机器上的相同图像,我会得到不同的哈希值。
题
是否有一种简单的散列图像方式,只取决于图像本身(而不是时间戳,系统架构等)?
请注意,我不需要类似的图像来获得类似/相同的哈希,就像在image hashing中一样。实际上,我希望不同的图像具有不同的散列,例如改变图像的亮度应改变其散列。
我猜你的目标是在Python中执行图像散列(这与经典散列有很大的不同,因为图像的字节表示取决于格式,分辨率等)
其中一种图像散列技术是平均散列。确保这不是100%准确,但在大多数情况下它可以正常工作。
首先,我们通过减小图像的尺寸和颜色来简化图像,降低图像的复杂性,大大有助于提高其他图像之间的比较精度:
缩小尺寸:
img = img.resize((10, 10), Image.ANTIALIAS)
减少颜色:
img = img.convert("L")
然后,我们找到图像的平均像素值(这显然是平均散列的主要组成部分之一):
pixel_data = list(img.getdata())
avg_pixel = sum(pixel_data)/len(pixel_data)
最后计算哈希值,我们将图像中的每个像素与平均像素值进行比较。如果像素大于或等于平均像素,那么我们得到1,否则它是0.然后我们将这些位转换为基数16表示:
bits = "".join(['1' if (px >= avg_pixel) else '0' for px in pixel_data])
hex_representation = str(hex(int(bits, 2)))[2:][::-1].upper()
如果要将此图像与其他图像进行比较,则执行上述操作,并找出平均散列图像的十六进制表示之间的相似性。您可以使用像hamming distance这样简单的东西或更复杂的算法,如Levenshtein distance,Ratcliff/Obershelp pattern recognition(SequenceMatcher),Cosine Similarity等。
认识到你对时间戳的看法,ImageMagick就是这样一个功能。首先,一个例子。
在这里,我创建两个具有相同像素的图像,但时间戳至少为1秒不同:
convert -size 600x100 gradient:magenta-cyan 1.png
sleep 2
convert -size 600x100 gradient:magenta-cyan 2.png
如果我在macOS上对它们进行校验,它会告诉我它们因嵌入的时间戳而不同:
md5 -r [12].png
c7454aa225e3e368abeb5290b1d7a080 1.png
66cb4de0b315505de528fb338779d983 2.png
但是,如果我使用ImageMagick校验像素,(其中%#
是像素校验和),它知道像素是相同的,我得到:
identify -format '%# - %f
' 1.png 2.png
70680e2827ad671f3732c0e1c2e1d33acb957bc0d9e3a43094783b4049225ea5 - 1.png
70680e2827ad671f3732c0e1c2e1d33acb957bc0d9e3a43094783b4049225ea5 - 2.png
事实上,如果我使用相同的图像内容制作TIFF
文件,无论是使用Motorola还是Intel字节顺序,还是使用NetPBM PPM
文件:
convert -size 600x100 gradient:magenta-cyan -define tiff:endian=msb 3motorola.tif
convert -size 600x100 gradient:magenta-cyan -define tiff:endian=lsb 3intel.tif
convert -size 600x100 gradient:magenta-cyan 3.ppm
尽管文件格式,CPU架构和时间戳不同,ImageMagick知道它们是相同的,但是:
identify -format '%# - %f
' 1.png 3.ppm 3{motorola,intel}.tif
70680e2827ad671f3732c0e1c2e1d33acb957bc0d9e3a43094783b4049225ea5 - 1.png
70680e2827ad671f3732c0e1c2e1d33acb957bc0d9e3a43094783b4049225ea5 - 3.ppm
70680e2827ad671f3732c0e1c2e1d33acb957bc0d9e3a43094783b4049225ea5 - 3motorola.tif
70680e2827ad671f3732c0e1c2e1d33acb957bc0d9e3a43094783b4049225ea5 - 3intel.tif
所以,在回答你的问题时,我建议你使用Python子进程模块向ImageMagick发送shell并使用ImageMagick。
以上是关于PIL图像的简单哈希的主要内容,如果未能解决你的问题,请参考以下文章