【问题标题】:Image Comparison by Finger Printing指纹图像比较
【发布时间】:2017-02-24 17:55:43
【问题描述】:

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

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

提前致谢

【问题讨论】:

    标签: image-processing hash image-comparison fingerprinting


    【解决方案1】:

    如果您有兴趣查找 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 而不是图像库。

    【讨论】:

      【解决方案2】:

      您需要小心散列,某些图像格式(例如 JPEG 和 PNG)会在图像中存储日期/时间和其他信息,这会使两个相同的图像看起来与普通工具(例如 md5cksum.

      这是一个例子。使用 ImageMagick

      在终端的命令行中制作两张相同的 128x128 红色方块
      convert -size 128x128 xc:red a.png
      convert -size 128x128 xc:red b.png
      

      现在检查他们的 MD5 和:

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

      或者他们的校验和:

      cksum [ab].png
      4158429075 290 a.png
      3657683960 290 b.png
      

      糟糕,根据md5cksum,它们是不同的。为什么?因为日期相差 1 秒。

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

      identify -format %# a.png
      e74164f4bab2dd8f7f612f8d2d77df17106bac77b9566aa888d31499e9cf8564
      
      identify -format %# b.png
      e74164f4bab2dd8f7f612f8d2d77df17106bac77b9566aa888d31499e9cf8564
      

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

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

      或者您可能对允许亮度、方向或裁剪的细微差异感兴趣 - 这完全是另一个主题。

      【讨论】:

        【解决方案3】:

        有很多方法可以实现这一点,但最简单的方法是将图像转换为 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 文档,但无论您使用什么语言,都应该有类似的内容。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-11-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-08
          • 1970-01-01
          相关资源
          最近更新 更多