手指印刷的图像比较

时间:2016-10-15 10:13:05

标签: image-processing hash image-comparison fingerprinting

我正在寻找通过指纹识别来查找图像重复的方法。我知道这是通过在图像上应用哈希函数来完成的,每个图像都有一个唯一的哈希值。

我对图像处理相当新,对哈希不太了解。我应该如何应用哈希函数并生成哈希值?

提前致谢

3 个答案:

答案 0 :(得分:3)

你需要注意散列,一些图像格式,如JPEG和PNG,在图像中存储日期/时间和其他信息,这将使两个相同的图像看起来与普通工具不同,例如{{1} }和md5

这是一个例子。使用 ImageMagick

在终端的命令行中制作两个相同的128x128红色正方形图像
cksum

enter image description here enter image description here

现在检查他们的MD5总和:

convert -size 128x128 xc:red a.png
convert -size 128x128 xc:red b.png

或他们的校验和:

md5 [ab].png
MD5 (a.png) = b4b82ba217f0b36e6d3ba1722f883e59
MD5 (b.png) = 6aa398d3aaf026c597063c5b71b8bd1a

哎呀,根据cksum [ab].png 4158429075 290 a.png 3657683960 290 b.png md5,它们是不同的。为什么?因为日期相隔1秒。

我建议您使用 ImageMagick 来校验和“只是图像数据”而不是元数据 - 当然,除非日期对您很重要:

cksum

现在它们都是相同的,因为图像是相同的 - 只是元数据不同。

当然,您可能对“Perceptual Hashing”更感兴趣,您可以在其中了解两个图像“看起来相似”。如果是,请查看here

或者你可能有兴趣在亮度,方向或裁剪方面略有不同 - 这是另一个主题。

答案 1 :(得分:0)

有很多方法可以实现这一点,但最简单的方法是将图像转换为base64字符串,然后使用标准的散列库。在python中它看起来像:

import base64
import md5



with open("foo.png", "rb") as image_file:
    encoded_string = base64.b64encode(image_file.read())
    m = md5.new()
    m.update(encoded_string)
    fingerprint = m.hexdigest()
    print(fingerprint)

如果您只是将哈希函数视为将一个(可能很大的)字符串转换为另一个字符串,那么您应该没问题。在上面的代码中,m.update()只是将encoded_string(一个非常大的base64字符串)转换为一个较小的十六进制字符串,我们通过调用m.hexdigest()得到它。

你可以阅读md5库here的python文档,但是你使用的语言应该有类似的东西。

答案 2 :(得分:0)

如果您有兴趣找到 near 重复项(包括已调整大小的图片),则可以应用差异哈希。有关哈希here的更多信息。下面的代码是从Real Python博客文章编辑的,以使其在python 3中工作。它使用链接到上面的散列库,其中包含有关不同类型散列的信息。您应该只需复制并粘贴脚本,并直接从命令行运行它们,而无需编辑脚本。

第一个脚本(index.py)为每个图像创建一个差异哈希值,然后将哈希值放在一个架子或持久字典中,以后可以像数据库一样访问该字典,以及图像文件名有那个哈希:

from PIL import Image
import imagehash
import argparse
import shelve
import glob

# This is just so you can run it from the command line
ap = argparse.ArgumentParser()
ap.add_argument('-d', '--dataset', required = True,
                help = 'path to imput dataset of images')

ap.add_argument('-s', '--shelve', required = True,
                help = 'output shelve database')
args = ap.parse_args()

# open the shelve database
db = shelve.open(args.shelve, writeback = True)

# loop over the image dataset
for imagePath in glob.glob(args.dataset + '/*.jpg'):
    # load the image and compute the difference in hash
    image = Image.open(imagePath)
    h = str(imagehash.dhash(image))
    print(h)

    # extract the filename from the path and update the database using the hash
    # as the key and the filename append to the list of values

    filename = imagePath[imagePath.rfind('/') + 1:]
    db[h] = db.get(h, []) + [filename]

db.close()

在命令行上运行:

python index.py --dataset ./image_directory --shelve db.shelve

在Jupyter笔记本中运行

%run index.py --dataset ./image_directory --shelve db.shelve

现在所有内容都存储在一个书架中,您可以使用要检查的图像文件名查询书架,它将打印出匹配的图像的文件名,并打开匹配的图像(search.py ):

from PIL import Image
import imagehash
import argparse
import shelve

# arguments for command line
ap = argparse.ArgumentParser()
ap.add_argument("-d", "--dataset", required=True,
            help="path to dataset of images")
ap.add_argument("-s", "--shelve", required=True,
            help="output the shelve database")
ap.add_argument("-q", "--query", required=True,
            help="path to the query image")
args = ap.parse_args()

# open the shelve database
db = shelve.open(args.shelve)

# Load the query image, compute the difference image hash, and grab the images
# from the database that have the same hash value
query = Image.open(args.query)
h = str(imagehash.dhash(query))
filenames = db[h]
print("found {} images".format(len(filenames)))

# loop over the images
for filename in filenames:
    print(filename)
    image = Image.open(args.dataset + "/" + filename)
    image.show()

# close the shelve database
db.close()

在命令行上运行以查看image_directory./directory/someimage.jpg具有相同哈希值的图片

python search.py —dataset ./image_directory —shelve db.shelve —query ./directory/someimage.jpg

同样,这是从上面链接的Real Python博客文章修改的,这是为python2.7编写的,应该可以解决这个问题!只需根据需要更改命令行即可。如果我没记错的话,python 2/3问题只与argparse有关,而不是图像库。